#ifndef PORYGONLANG_DIAGNOSTICSHOLDER_HPP #define PORYGONLANG_DIAGNOSTICSHOLDER_HPP #include #include #include "DiagnosticSeverity.hpp" #include "DiagnosticCode.hpp" #include "Diagnostic.hpp" using namespace std; namespace Porygon::Diagnostics { class DiagnosticsHolder { bool _hasErrors; vector _diagnostics; vector _lineStarts; vector _lineLength; public: explicit DiagnosticsHolder(const u16string& str) { _hasErrors = false; _lineStarts = vector{0}; size_t lineLength = 0; for (size_t i = 0; i < str.size(); i++){ lineLength++; if (str[i] == '\n'){ _lineStarts.push_back(i + 1); _lineLength.push_back(lineLength); lineLength = 0; } } } ~DiagnosticsHolder() { _diagnostics.clear(); } void Log(DiagnosticSeverity severity, DiagnosticCode code, unsigned int start, unsigned int length); void LogError(DiagnosticCode code, unsigned int start, unsigned int length); void LogWarning(DiagnosticCode code, unsigned int start, unsigned int length); void LogInfo(DiagnosticCode code, unsigned int start, unsigned int length); bool HasErrors(); vector GetDiagnostics(); int DiagnosticsCount(); Diagnostic *GetDiagnosticAt(int position); size_t GetLineFromPosition(size_t i){ size_t topLimit = _lineStarts.size() - 1; size_t bottomLimit = 0; while (true){ if (bottomLimit == topLimit){ return bottomLimit; } size_t half = (topLimit - bottomLimit) / 2; size_t pos = _lineStarts[half]; size_t length = _lineLength[half]; if (pos < i && pos + length > i){ return half; } if (pos > i){ bottomLimit = half; } else if (pos < i){ topLimit = half; } else{ return half; } } } }; } #endif //PORYGONLANG_DIAGNOSTICSHOLDER_HPP