cmJSONState: Allow input stream as input

This commit is contained in:
Tyler Yankee
2026-07-30 10:29:19 -04:00
parent ec0588416e
commit 397fcd4663
2 changed files with 49 additions and 30 deletions
+46 -30
View File
@@ -3,6 +3,7 @@
#include "cmJSONState.h"
#include <istream>
#include <iterator>
#include <memory>
#include <sstream>
@@ -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<char>(fin),
std::istreambuf_iterator<char>());
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<Json::CharReader> const reader(builder.newCharReader());
reader->parse(doc.data(), doc.data() + doc.size(), root, &errMsg);
std::vector<Json::CharReader::StructuredError> 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<char>(jsonIStream),
std::istreambuf_iterator<char>());
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<Json::CharReader> const reader(builder.newCharReader());
reader->parse(this->doc.data(), this->doc.data() + this->doc.size(), root,
&errMsg);
std::vector<Json::CharReader::StructuredError> 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;
+3
View File
@@ -5,6 +5,7 @@
#include "cmConfigure.h" // IWYU pragma: keep
#include <cstddef>
#include <istream>
#include <string>
#include <utility>
#include <vector>
@@ -25,6 +26,7 @@ public:
using JsonPair = std::pair<std::string const, Json::Value const*>;
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;