diff --git a/Source/cmJSONState.cxx b/Source/cmJSONState.cxx index c01aa01232..348349e64e 100644 --- a/Source/cmJSONState.cxx +++ b/Source/cmJSONState.cxx @@ -3,6 +3,7 @@ #include "cmJSONState.h" +#include #include #include #include @@ -27,37 +28,12 @@ cmJSONState::cmJSONState(std::string jsonFile, Json::Value* root) // 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(fin), - std::istreambuf_iterator()); - if (this->doc.empty()) { - this->AddError("A JSON document cannot be empty"); - return; - } - fin.seekg(finBegin); + this->ReadJSONStream(fin, root); +} - Json::CharReaderBuilder builder; - Json::CharReaderBuilder::strictMode(&builder.settings_); - std::string errMsg; - -#if JSONCPP_VERSION_HEXA >= 0x01090600 - // Has StructuredError - std::unique_ptr const reader(builder.newCharReader()); - reader->parse(doc.data(), doc.data() + doc.size(), root, &errMsg); - std::vector structuredErrors = - reader->getStructuredErrors(); - for (auto const& structuredError : structuredErrors) { - this->AddErrorAtOffset(structuredError.message, - structuredError.offset_start); - } -#else - // No StructuredError Available, Use error string from jsonCpp - if (!Json::parseFromStream(builder, fin, root, &errMsg)) { - errMsg = cmStrCat("JSON Parse Error: ", this->Filename, ":\n", errMsg); - this->AddError(errMsg); - } -#endif +cmJSONState::cmJSONState(std::istream& jsonIStream, Json::Value* root) +{ + this->ReadJSONStream(jsonIStream, root); } void cmJSONState::AddError(std::string const& errMsg) @@ -144,6 +120,46 @@ void cmJSONState::pop_stack() this->parseStack.pop_back(); } +void cmJSONState::ReadJSONStream(std::istream& jsonIStream, Json::Value* root) +{ + // Save the entire document. + std::streampos inBegin = jsonIStream.tellg(); + this->doc = std::string(std::istreambuf_iterator(jsonIStream), + std::istreambuf_iterator()); + if (this->doc.empty()) { + this->AddError("A JSON document cannot be empty"); + return; + } + jsonIStream.seekg(inBegin); + + Json::CharReaderBuilder builder; + Json::CharReaderBuilder::strictMode(&builder.settings_); + std::string errMsg; + +#if JSONCPP_VERSION_HEXA >= 0x01090600 + // Has StructuredError + std::unique_ptr const reader(builder.newCharReader()); + reader->parse(this->doc.data(), this->doc.data() + this->doc.size(), root, + &errMsg); + std::vector structuredErrors = + reader->getStructuredErrors(); + for (auto const& structuredError : structuredErrors) { + this->AddErrorAtOffset(structuredError.message, + structuredError.offset_start); + } +#else + // No StructuredError Available, Use error string from jsonCpp + if (!Json::parseFromStream(builder, jsonIStream, root, &errMsg)) { + if (this->Filename.empty()) { + errMsg = cmStrCat("JSON Parse Error:\n ", errMsg); + } else { + errMsg = cmStrCat("JSON Parse Error: ", this->Filename, ":\n", errMsg); + } + this->AddError(errMsg); + } +#endif +} + std::string cmJSONState::GetJsonContext(Location loc) { std::string line; diff --git a/Source/cmJSONState.h b/Source/cmJSONState.h index 8d5731d5e5..a4edc9f8c4 100644 --- a/Source/cmJSONState.h +++ b/Source/cmJSONState.h @@ -5,6 +5,7 @@ #include "cmConfigure.h" // IWYU pragma: keep #include +#include #include #include #include @@ -25,6 +26,7 @@ public: using JsonPair = std::pair; cmJSONState() = default; cmJSONState(std::string jsonFile, Json::Value* root); + cmJSONState(std::istream& jsonIStream, Json::Value* root); void AddError(std::string const& errMsg); void AddErrorAtValue(std::string const& errMsg, Json::Value const* value); void AddErrorAtOffset(std::string const& errMsg, std::ptrdiff_t offset); @@ -58,6 +60,7 @@ public: bool allowComments = false; private: + void ReadJSONStream(std::istream& jsonIStream, Json::Value* root); std::string GetJsonContext(Location loc); Location LocateInDocument(ptrdiff_t offset); std::string Filename;