| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 | 
							- /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
 
-    file Copyright.txt or https://cmake.org/licensing for details.  */
 
- #include "cmJSONState.h"
 
- #include <sstream>
 
- #include <cm/memory>
 
- #include <cm3p/json/reader.h>
 
- #include <cm3p/json/value.h>
 
- #include "cmsys/FStream.hxx"
 
- #include "cmStringAlgorithms.h"
 
- cmJSONState::cmJSONState(const std::string& filename, Json::Value* root)
 
- {
 
-   cmsys::ifstream fin(filename.c_str(), std::ios::in | std::ios::binary);
 
-   if (!fin) {
 
-     this->AddError(cmStrCat("File not found: ", filename));
 
-     return;
 
-   }
 
-   // If there's a BOM, toss it.
 
-   cmsys::FStream::ReadBOM(fin);
 
-   // Save the entire document.
 
-   std::streampos finBegin = fin.tellg();
 
-   this->doc = std::string(std::istreambuf_iterator<char>(fin),
 
-                           std::istreambuf_iterator<char>());
 
-   if (this->doc.empty()) {
 
-     this->AddError("A JSON document cannot be empty");
 
-     return;
 
-   }
 
-   fin.seekg(finBegin);
 
-   // Parse the document.
 
-   Json::CharReaderBuilder builder;
 
-   Json::CharReaderBuilder::strictMode(&builder.settings_);
 
-   std::string errMsg;
 
-   if (!Json::parseFromStream(builder, fin, root, &errMsg)) {
 
-     errMsg = cmStrCat("JSON Parse Error: ", filename, ":\n", errMsg);
 
-     this->AddError(errMsg);
 
-   }
 
- }
 
- void cmJSONState::AddError(std::string const& errMsg)
 
- {
 
-   this->errors.push_back(Error(errMsg));
 
- }
 
- void cmJSONState::AddErrorAtValue(std::string const& errMsg,
 
-                                   const Json::Value* value)
 
- {
 
-   if (value && !value->isNull()) {
 
-     this->AddErrorAtOffset(errMsg, value->getOffsetStart());
 
-   } else {
 
-     this->AddError(errMsg);
 
-   }
 
- }
 
- void cmJSONState::AddErrorAtOffset(std::string const& errMsg,
 
-                                    std::ptrdiff_t offset)
 
- {
 
-   if (doc.empty()) {
 
-     this->AddError(errMsg);
 
-   } else {
 
-     Location loc = LocateInDocument(offset);
 
-     this->errors.push_back(Error(loc, errMsg));
 
-   }
 
- }
 
- std::string cmJSONState::GetErrorMessage(bool showContext)
 
- {
 
-   std::string message;
 
-   for (auto const& error : this->errors) {
 
-     message = cmStrCat(message, error.GetErrorMessage(), "\n");
 
-     if (showContext) {
 
-       Location loc = error.GetLocation();
 
-       if (loc.column > 0) {
 
-         message = cmStrCat(message, GetJsonContext(loc), "\n");
 
-       }
 
-     }
 
-   }
 
-   message = cmStrCat("\n", message);
 
-   message.pop_back();
 
-   return message;
 
- }
 
- std::string cmJSONState::key()
 
- {
 
-   if (!this->parseStack.empty()) {
 
-     return this->parseStack.back().first;
 
-   }
 
-   return "";
 
- }
 
- std::string cmJSONState::key_after(std::string const& k)
 
- {
 
-   for (auto it = this->parseStack.begin(); it != this->parseStack.end();
 
-        ++it) {
 
-     if (it->first == k && (++it) != this->parseStack.end()) {
 
-       return it->first;
 
-     }
 
-   }
 
-   return "";
 
- }
 
- const Json::Value* cmJSONState::value_after(std::string const& k)
 
- {
 
-   for (auto it = this->parseStack.begin(); it != this->parseStack.end();
 
-        ++it) {
 
-     if (it->first == k && (++it) != this->parseStack.end()) {
 
-       return it->second;
 
-     }
 
-   }
 
-   return nullptr;
 
- }
 
- void cmJSONState::push_stack(std::string const& k, const Json::Value* value)
 
- {
 
-   this->parseStack.push_back(JsonPair(k, value));
 
- }
 
- void cmJSONState::pop_stack()
 
- {
 
-   this->parseStack.pop_back();
 
- }
 
- std::string cmJSONState::GetJsonContext(Location loc)
 
- {
 
-   std::string line;
 
-   std::stringstream sstream(doc);
 
-   for (int i = 0; i < loc.line; ++i) {
 
-     std::getline(sstream, line, '\n');
 
-   }
 
-   return cmStrCat(line, '\n', std::string(loc.column - 1, ' '), '^');
 
- }
 
- cmJSONState::Location cmJSONState::LocateInDocument(ptrdiff_t offset)
 
- {
 
-   int line = 1;
 
-   int col = 1;
 
-   const char* beginDoc = doc.data();
 
-   const char* last = beginDoc + offset;
 
-   for (; beginDoc != last; ++beginDoc) {
 
-     switch (*beginDoc) {
 
-       case '\r':
 
-         if (beginDoc + 1 != last && beginDoc[1] == '\n') {
 
-           continue; // consume CRLF as a single token.
 
-         }
 
-         CM_FALLTHROUGH; // CR without a following LF is same as LF
 
-       case '\n':
 
-         col = 1;
 
-         ++line;
 
-         break;
 
-       default:
 
-         ++col;
 
-         break;
 
-     }
 
-   }
 
-   return { line, col };
 
- }
 
 
  |