TazGraph Project v0.1.0
Loading...
Searching...
No Matches
JsonParser.h
1#pragma once
2
3#include <fstream>
4#include <iostream>
5#include <map>
6#include <vector>
7#include <string>
8#include <sstream>
9#include <cctype>
10#include <stdexcept>
11
12enum class JsonType {
13 Object, Array, String, Number, Boolean, Null
14};
15
17 bool operator()(const std::string& a, const std::string& b) const {
18 bool a_numeric = isNumeric(a);
19 bool b_numeric = isNumeric(b);
20
21 if (a_numeric && b_numeric) {
22 return std::stod(a) < std::stod(b);
23 }
24 return a < b; // fallback to alphabetical for non-numeric
25 }
26
27private:
28 bool isNumeric(const std::string& s) const {
29 char* end = nullptr;
30 std::strtod(s.c_str(), &end);
31 return end != s.c_str() && *end == '\0';
32 }
33};
34struct JsonValue {
35 JsonType type = JsonType::Object;
36 std::map<std::string, JsonValue, NumericStringCompare> obj;
37 std::vector<JsonValue> arr;
38 std::string str = "";
39 double num = -1;
40 bool boolean = false;
41};
42
44public:
45 explicit JsonParser(const std::string& input) : input(input), pos(0) {}
46
47 explicit JsonParser(std::ifstream& file) {
48 std::stringstream buffer;
49 buffer << file.rdbuf();
50 input = buffer.str();
51 pos = 0;
52
53 pos = input.find('{');
54 input = input.substr(pos);
55 pos = 0;
56 }
57
58 JsonValue parse() {
59 JsonValue value = parseValue();
60 skipWhitespace();
61 if (!eof()) {
62 throw std::runtime_error("Unexpected characters at end of input.");
63 }
64 return value;
65 }
66
67private:
68 std::string input;
69 size_t pos;
70
71 void skipWhitespace() {
72 while (!eof() && std::isspace(input[pos])) {
73 pos++;
74 }
75 }
76
77 bool eof() const {
78 return pos >= input.size();
79 }
80
81 char peek() const {
82 return input[pos];
83 }
84
85 char consume() {
86 return input[pos++];
87 }
88
89 JsonValue parseValue() {
90 skipWhitespace();
91 if (eof()) {
92 throw std::runtime_error("Unexpected end of input.");
93 }
94
95 char ch = peek();
96 if (ch == '{') return parseObject();
97 if (ch == '[') return parseArray();
98 if (ch == '\"' || ch == '\'') return parseString();
99 if (std::isdigit(ch) || ch == '-') return parseNumber();
100 if (ch == 't' || ch == 'T' || ch == 'f' || ch == 'F') return parseBoolean();
101 if (ch == 'n') return parseNull();
102
103 throw std::runtime_error("Unexpected character.");
104 }
105
106 JsonValue parseObject() {
107 consume(); // '{'
108 JsonValue obj;
109 obj.type = JsonType::Object;
110
111 skipWhitespace();
112 if (peek() == '}') {
113 consume();
114 return obj;
115 }
116
117 while (true) {
118 skipWhitespace();
119 JsonValue key;
120 if (std::isdigit(peek()) || peek() == '-') {
121 key = parseNumber();
122 key.type = JsonType::String;
123 key.str = std::to_string(key.num);
124 }
125 else if (peek() == '\"' || peek() == '\'') {
126 key = parseString();
127 }
128 skipWhitespace();
129 if (consume() != ':') {
130 throw std::runtime_error("Expected ':' after key in object.");
131 }
132 JsonValue value = parseValue();
133 obj.obj[key.str] = value;
134
135 skipWhitespace();
136 char ch = consume();
137 if (ch == '}' || ch == '\0') break;
138 if (ch != ',') {
139 throw std::runtime_error("Expected ',' or '}' in object.");
140 }
141 }
142 return obj;
143 }
144
145 JsonValue parseArray() {
146 consume(); // '['
147 JsonValue array;
148 array.type = JsonType::Array;
149
150 skipWhitespace();
151 if (peek() == ']') {
152 consume();
153 return array;
154 }
155
156 while (true) {
157 JsonValue value = parseValue();
158 array.arr.push_back(value);
159
160 skipWhitespace();
161 char ch = consume();
162 if (ch == ']') break;
163 if (ch != ',') {
164 throw std::runtime_error("Expected ',' or ']' in array.");
165 }
166 }
167 return array;
168 }
169
170 JsonValue parseString() {
171 std::ostringstream result;
172 consume(); // the initial '"'
173 while (true) {
174 if (eof()) throw std::runtime_error("Unexpected end of input during string parsing.");
175
176 char ch = consume();
177 if (ch == '\"' || ch == '\'') break; // end of string
178 if (ch == '\\') { // handle escapes
179 if (eof()) throw std::runtime_error("Unexpected end of input during escape sequence.");
180 char esc = consume();
181 switch (esc) {
182 case '\"': result << '\"'; break;
183 case '\'': result << '\''; break;
184 case '\\': result << '\\'; break;
185 case '/': result << '/'; break;
186 case 'b': result << '\b'; break;
187 case 'f': result << '\f'; break;
188 case 'n': result << '\n'; break;
189 case 'r': result << '\r'; break;
190 case 't': result << '\t'; break;
191 default: throw std::runtime_error("Invalid escape sequence.");
192 }
193 }
194 else {
195 result << ch;
196 }
197 }
198
199 JsonValue strValue;
200 strValue.type = JsonType::String;
201 strValue.str = result.str();
202 return strValue;
203 }
204
205 JsonValue parseNumber() {
206 std::ostringstream result;
207 if (peek() == '-') {
208 result << consume();
209 }
210
211 while (!eof() && (std::isdigit(peek()) || peek() == '.')) {
212 result << consume();
213 }
214 if (!eof() && (peek() == 'e' || peek() == 'E')) {
215 result << consume();
216
217 if (!eof() && (peek() == '+' || peek() == '-')) {
218 result << consume();
219 }
220
221 while (!eof() && std::isdigit(peek())) {
222 result << consume();
223 }
224 }
225
226 JsonValue number;
227 number.type = JsonType::Number;
228 number.num = std::stod(result.str());
229 return number;
230 }
231
232 JsonValue parseBoolean() {
233 std::ostringstream result;
234 for (int i = 0; i < 4 && !eof(); ++i) { // "true" or "fals"
235 result << consume();
236 }
237
238 JsonValue boolValue;
239 boolValue.type = JsonType::Boolean;
240 std::string res = result.str();
241 if (res == "true" || res == "True") {
242 boolValue.boolean = true;
243 }
244 else if (res == "false" || res == "False") {
245 boolValue.boolean = false;
246 }
247 else {
248 throw std::runtime_error("Invalid value for boolean.");
249 }
250 return boolValue;
251 }
252
253 JsonValue parseNull() {
254 std::string result;
255 for (int i = 0; i < 4 && !eof(); ++i) { // "null"
256 result += consume();
257 }
258 if (result != "null") {
259 throw std::runtime_error("Invalid value for null.");
260 }
261 JsonValue nullValue;
262 nullValue.type = JsonType::Null;
263 return nullValue;
264 }
265};
Definition JsonParser.h:43
Definition JsonParser.h:34
Definition JsonParser.h:16