Hyperiso 1.0.3
Modular flavour-physics calculations, Wilson coefficients and statistical inference
Loading...
Searching...
No Matches
JsonParser.cpp
Go to the documentation of this file.
1#include "JsonParser.h"
2
3std::shared_ptr<DBNode> JSONParser::parse(const std::string& input) const {
4 size_t index = 0;
5 return parseObject(input, index);
6
7}
8
9std::shared_ptr<DBNode> JSONParser::parseObject(const std::string& input, size_t& index) const {
10 auto root = std::make_shared<DBNode>();
11 if (input[index] != '{') throw std::runtime_error("Invalid JSON");
12 ++index;
13
14 while (index < input.size()) {
15 skipWhitespace(input, index);
16 if (input[index] == '}') { ++index; break; }
17
18 std::string key = parseString(input, index);
19 skipWhitespace(input, index);
20 if (input[index] != ':') throw std::runtime_error("Expected ':' in JSON");
21 ++index;
22 skipWhitespace(input, index);
23
24 root->set(parseValue(input, index), key);
25 skipWhitespace(input, index);
26 if (input[index] == ',') ++index;
27 }
28 return root;
29}
30
31std::string JSONParser::parseString(const std::string& input, size_t& index) const {
32 if (input[index] != '\"') throw std::runtime_error("Expected '\"' in JSON");
33 ++index;
34 std::string result;
35 while (index < input.size() && input[index] != '\"') {
36 result += input[index++];
37 }
38 if (input[index] != '\"') throw std::runtime_error("Expected closing '\"'");
39 ++index;
40 return result;
41}
42
43DBNode::Value JSONParser::parseValue(const std::string& input, size_t& index) const {
44 skipWhitespace(input, index);
45
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; }
52
53 throw std::runtime_error("Invalid value in JSON");
54}
55
56
57std::shared_ptr<DBNode> JSONParser::parseArray(const std::string& input, size_t& index) const {
58 auto listDBNode = std::make_shared<DBNode>();
59 ++index; // Skip '['
60
61 int elementIndex = 0;
62 while (index < input.size()) {
63 skipWhitespace(input, index);
64 if (input[index] == ']') { ++index; break; }
65
66 listDBNode->set(parseValue(input, index), std::to_string(elementIndex++));
67 skipWhitespace(input, index);
68
69 if (input[index] == ',') ++index;
70 }
71 return listDBNode;
72}
73
74double JSONParser::parseNumber(const std::string& input, size_t& index) const {
75 std::string num;
76 bool hasDecimal = false;
77 bool hasExponent = false;
78
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;
82 hasDecimal = true;
83 } else if (input[index] == 'e' || input[index] == 'E') {
84 if (hasExponent) break;
85 hasExponent = true;
86 if (index + 1 < input.size() && (input[index + 1] == '-' || input[index + 1] == '+')) {
87 num += input[index++];
88 }
89 }
90 num += input[index++];
91 }
92 try {
93 return std::stod(num);
94 } catch (...) {
95 throw std::runtime_error("Invalid number format in JSON");
96 }
97}
98
99void JSONParser::skipWhitespace(const std::string& input, size_t& index) const {
100 while (index < input.size() && isspace(input[index])) ++index;
101}
102
103void JSONParser::writeToFile(const std::string& filename, const std::shared_ptr<DBNode>& root) const {
104 std::ofstream file(filename);
105 if (!file.is_open()) throw std::runtime_error("Unable to open file for writing");
106
107 std::ostringstream oss;
108 root->printJSONToStream(oss);
109 file << oss.str();
110 file.close();
111}
112
113std::shared_ptr<DBNode> JSONParser::readFromFile(const std::string& filename) const {
114 std::ifstream file(filename);
115 LOG_DEBUG("File path:", filename);
116 if (!file.is_open()) throw std::runtime_error("Unable to open file for reading");
117
118 std::ostringstream oss;
119 oss << file.rdbuf();
120 return parse(oss.str());
121}
Lightweight JSON parser/serializer for DBNode trees.
#define LOG_DEBUG(...)
Macro for logging debug messages.
Definition Logger.h:45
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.
Definition DBNode.h:45
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.
Definition JsonParser.cpp:9
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.
Definition JsonParser.cpp:3
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.