10 auto root = std::make_shared<DBNode>();
11 if (input[index] !=
'{')
throw std::runtime_error(
"Invalid JSON");
14 while (index < input.size()) {
16 if (input[index] ==
'}') { ++index;
break; }
20 if (input[index] !=
':')
throw std::runtime_error(
"Expected ':' in JSON");
26 if (input[index] ==
',') ++index;
32 if (input[index] !=
'\"')
throw std::runtime_error(
"Expected '\"' in JSON");
35 while (index < input.size() && input[index] !=
'\"') {
36 result += input[index++];
38 if (input[index] !=
'\"')
throw std::runtime_error(
"Expected closing '\"'");
46 if (input[index] ==
'{')
return parseObject(input, index);
47 if (input[index] ==
'[')
return parseArray(input, index);
48 if (input[index] ==
'\"')
return parseString(input, index);
49 if (isdigit(input[index]) || input[index] ==
'-')
return parseNumber(input, index);
50 if (input.substr(index, 4) ==
"true") { index += 4;
return true; }
51 if (input.substr(index, 5) ==
"false") { index += 5;
return false; }
53 throw std::runtime_error(
"Invalid value in JSON");
58 auto listDBNode = std::make_shared<DBNode>();
62 while (index < input.size()) {
64 if (input[index] ==
']') { ++index;
break; }
66 listDBNode->set(
parseValue(input, index), std::to_string(elementIndex++));
69 if (input[index] ==
',') ++index;
76 bool hasDecimal =
false;
77 bool hasExponent =
false;
79 while (index < input.size() && (isdigit(input[index]) || input[index] ==
'.' || input[index] ==
'e' || input[index] ==
'E' || input[index] ==
'-' || input[index] ==
'+')) {
80 if (input[index] ==
'.') {
81 if (hasDecimal || hasExponent)
break;
83 }
else if (input[index] ==
'e' || input[index] ==
'E') {
84 if (hasExponent)
break;
86 if (index + 1 < input.size() && (input[index + 1] ==
'-' || input[index + 1] ==
'+')) {
87 num += input[index++];
90 num += input[index++];
93 return std::stod(num);
95 throw std::runtime_error(
"Invalid number format in JSON");
100 while (index < input.size() && isspace(input[index])) ++index;
104 std::ofstream file(filename);
105 if (!file.is_open())
throw std::runtime_error(
"Unable to open file for writing");
107 std::ostringstream oss;
108 root->printJSONToStream(oss);
114 std::ifstream file(filename);
116 if (!file.is_open())
throw std::runtime_error(
"Unable to open file for reading");
118 std::ostringstream oss;
120 return parse(oss.str());
Lightweight JSON parser/serializer for DBNode trees.
#define LOG_DEBUG(...)
Macro for logging debug messages.
std::variant< BlockName, int, double, bool, std::shared_ptr< DBNode >, std::vector< std::shared_ptr< DBNode > > > Value
Variant type used to store values in the tree.
void writeToFile(const std::string &filename, const std::shared_ptr< DBNode > &root) const override
Serializes a DBNode tree to a JSON file.
std::shared_ptr< DBNode > parseArray(const std::string &input, size_t &index) const
Parses a JSON array starting at the current position.
DBNode::Value parseValue(const std::string &input, size_t &index) const
Parses any JSON value at the current position.
std::shared_ptr< DBNode > parseObject(const std::string &input, size_t &index) const
Parses a JSON object starting at the given index.
std::shared_ptr< DBNode > readFromFile(const std::string &filename) const override
Reads a JSON file and parses it into a DBNode tree.
double parseNumber(const std::string &input, size_t &index) const
Parses a JSON number (integer or floating point).
std::shared_ptr< DBNode > parse(const std::string &input) const override
Parses a JSON document from an in-memory string.
std::string parseString(const std::string &input, size_t &index) const
Parses a JSON string literal.
void skipWhitespace(const std::string &input, size_t &index) const
Skips whitespace characters in the input string.