#include "conf.h" #include #include #include #include #include #include #include void TYandexConfig::Clear() { delete[] FileData; FileData = nullptr; CurrentMemoryPtr = nullptr; Len = 0; while (!CurSections.empty()) CurSections.pop(); for (size_t i = 0; i < AllSections.size(); i++) { if (AllSections[i]->Owner) delete AllSections[i]->Cookie; delete AllSections[i]; } AllSections.clear(); Errors.clear(); EndLines.clear(); ConfigPath.remove(); } void TYandexConfig::PrintErrors(TLog* Log) { size_t sz = Errors.size(); if (sz) { Log->AddLog("Processing of \'%s\':\n", ConfigPath.data()); for (size_t i = 0; i < sz; i++) *Log << Errors[i]; Errors.clear(); } } void TYandexConfig::PrintErrors(TString& Err) { size_t sz = Errors.size(); if (sz) { char buf[512]; snprintf(buf, 512, "Processing of \'%s\':\n", ConfigPath.data()); Err += buf; for (size_t i = 0; i < sz; i++) Err += Errors[i]; Errors.clear(); } } void TYandexConfig::ReportError(const char* ptr, const char* err, bool warning) { if (ptr) { char buf[1024]; int line = 0, col = 0; if (!EndLines.empty()) { TVector::iterator I = UpperBound(EndLines.begin(), EndLines.end(), ptr); if (I == EndLines.end()) I = EndLines.end() - 1; line = int(I - EndLines.begin()); if (line) I--; col = int(ptr - (*I)); } if (warning) snprintf(buf, 1024, "Warning at line %d, col %d: %s.\n", line, col, err); else snprintf(buf, 1024, "Error at line %d, col %d: %s.\n", line, col, err); Errors.push_back(buf); } else Errors.push_back(err); } void TYandexConfig::ReportError(const char* ptr, bool warning, const char* format, ...) { va_list args; va_start(args, format); char buf[512]; vsnprintf(buf, 512, format, args); ReportError(ptr, buf, warning); } bool TYandexConfig::Read(const TString& path) { assert(FileData == nullptr); ConfigPath = path; //read the file to memory TFile doc(path, OpenExisting | RdOnly); if (!doc.IsOpen()) { Errors.push_back(TString("can't open file ") + path + "\n"); return false; } Len = (ui32)doc.GetLength(); FileData = new char[Len + 1]; doc.Load(FileData, Len); FileData[Len] = 0; doc.Close(); return PrepareLines(); } bool TYandexConfig::ReadMemory(const TStringBuf& buffer, const char* configPath) { assert(FileData == nullptr); if (configPath != nullptr) { ConfigPath = configPath; } Len = (ui32)buffer.size(); FileData = new char[Len + 1]; memcpy(FileData, buffer.data(), Len); FileData[Len] = 0; return PrepareLines(); } bool TYandexConfig::ReadMemory(const char* buffer, const char* configPath) { Y_ASSERT(buffer); return ReadMemory(TStringBuf(buffer), configPath); } bool TYandexConfig::PrepareLines() { //scan line breaks EndLines.push_back(FileData - 1); CurrentMemoryPtr = FileData; while (*CurrentMemoryPtr) { // Are you in a great hurry? I am not... :-) if (iscntrl((unsigned char)*CurrentMemoryPtr) && !isspace((unsigned char)*CurrentMemoryPtr)) { ReportError(CurrentMemoryPtr, "it's a binary file"); return false; } if (*CurrentMemoryPtr++ == '\n') EndLines.push_back(CurrentMemoryPtr - 1); } EndLines.push_back(CurrentMemoryPtr); // convert simple comments inceptive with '#' or '!' or ';' to blanks ProcessComments(); //convert the XML comments to blanks char* endptr = nullptr; CurrentMemoryPtr = strstr(FileData, ""); if (endptr) { endptr += 3; while (CurrentMemoryPtr != endptr) *CurrentMemoryPtr++ = ' '; CurrentMemoryPtr = strstr(endptr, "