FIMS  v0.8.0
Loading...
Searching...
No Matches
fims_json.hpp
Go to the documentation of this file.
1#ifndef FIMS_JSON_HPP
2#define FIMS_JSON_HPP
3
13#include <cctype>
14#include <iostream>
15#include <fstream>
16#include <map>
17#include <sstream>
18#include <string>
19#include <algorithm>
20#include <vector>
21
22namespace fims {
23class JsonValue;
24
28using JsonObject = std::map<std::string, JsonValue>;
29
33using JsonArray = std::vector<JsonValue>;
34
46
50class JsonValue {
51 public:
54
56 JsonValue(int num) : type(JsonValueType::Number), number(num) {}
57
59 JsonValue(double num) : type(JsonValueType::Number), number(num) {}
60
62 JsonValue(const std::string& str) : type(JsonValueType::String), str(str) {}
63
65 JsonValue(bool b) : type(JsonValueType::Bool), boolean(b) {}
66
68 JsonValue(const JsonObject& obj) : type(JsonValueType::Object), object(obj) {}
69
71 JsonValue(const JsonArray& arr) : type(JsonValueType::JArray), array(arr) {}
72
74 JsonValueType GetType() const { return type; }
75
77 int GetInt() const { return static_cast<int>(number); }
78
80 double GetDouble() const { return number; }
81
83 const std::string& GetString() const { return str; }
84
86 bool GetBool() const { return boolean; }
87
89 JsonObject& GetObject() { return object; }
90
92 JsonArray& GetArray() { return array; }
93
94 private:
95 JsonValueType type;
96 double number;
97 std::string str;
98 bool boolean;
99 JsonObject object;
100 JsonArray array;
101};
102
107 public:
109 JsonValue Parse(const std::string& json);
111 void WriteToFile(const std::string& filename, JsonValue jsonValue);
114
116 static std::string removeWhitespace(const std::string& input) {
117 std::string result = input;
118 result.erase(std::remove_if(result.begin(), result.end(), ::isspace),
119 result.end());
120 return result;
121 }
122
128 static std::string PrettyFormatJSON(const std::string& json) {
129 std::string result;
131 int indentLevel = 0;
132 bool inQuotes = false;
133
134 for (size_t i = 0; i < input.size(); ++i) {
135 char current = input[i];
136
137 switch (current) {
138 case '{':
139 case '[':
140 result += current;
141 if (!inQuotes) {
142 result += '\n';
143 indentLevel++;
144 result += std::string(indentLevel * 4, ' ');
145 }
146 break;
147
148 case '}':
149 case ']':
150 if (!inQuotes) {
151 result += '\n';
152 indentLevel--;
153 result += std::string(indentLevel * 4, ' ');
154 }
155 result += current;
156 break;
157
158 case ',':
159 result += current;
160 if (!inQuotes) {
161 result += '\n';
162 result += std::string(indentLevel * 4, ' ');
163 }
164 break;
165
166 case ':':
167 result += current;
168 if (!inQuotes) result += " ";
169 break;
170
171 case '"':
172 result += current;
173 // Toggle inQuotes when we encounter a double-quote
174 if (i == 0 || input[i - 1] != '\\') {
176 }
177 break;
178
179 default:
180 result += current;
181 break;
182 }
183 }
184 return result;
185 }
186
187 private:
189 void SkipWhitespace();
191 JsonValue ParseValue();
193 JsonValue ParseNumber();
195 JsonValue ParseString();
197 JsonValue ParseBool();
199 JsonValue ParseNull();
201 JsonValue ParseObject();
203 JsonValue ParseArray();
205 void WriteJsonValue(std::ofstream& outputFile, JsonValue jsonValue);
207 void PrintJsonValue(std::ostream& outputFile, JsonValue jsonValue);
209 void Indent(std::ostream& outputFile, int level);
211 void Indent(std::ofstream& outputFile, int level);
212
213 std::string data;
214 size_t position;
215};
216
222JsonValue JsonParser::Parse(const std::string& json) {
223 data = json;
224 position = 0;
225 return ParseValue();
226}
227
232void JsonParser::SkipWhitespace() {
233 while (position < data.size() && std::isspace(data[position])) {
234 position++;
235 }
236}
237
242JsonValue JsonParser::ParseValue() {
244 SkipWhitespace();
245 char current = data[position];
246 if (current == '{') {
247 return ParseObject();
248 } else if (current == '[') {
249 return ParseArray();
250 } else if (current == '"') {
251 return ParseString();
252 } else if (current == 't' || current == 'f') {
253 return ParseBool();
254 } else if (current == 'n') {
255 return ParseNull();
256 } else {
257 return ParseNumber();
258 }
259}
260
265JsonValue JsonParser::ParseNumber() {
266 size_t end_pos = position;
267 bool is_float = false;
268 while (end_pos < data.size() &&
269 (std::isdigit(data[end_pos]) || data[end_pos] == '.' ||
270 data[end_pos] == '-' || data[end_pos] == 'e' ||
271 data[end_pos] == 'E')) {
272 if (data[end_pos] == '.' || data[end_pos] == 'e' || data[end_pos] == 'E') {
273 is_float = true;
274 }
275 end_pos++;
276 }
277
278 std::string num_str = data.substr(position, end_pos - position);
279 position = end_pos;
280
281 if (is_float) {
282 double num;
283 std::istringstream(num_str) >> num;
284 return JsonValue(num);
285 } else {
286 int num;
287 std::istringstream(num_str) >> num;
288 return JsonValue(num);
289 }
290}
291
296JsonValue JsonParser::ParseString() {
297 position++; // Skip the initial '"'
298 size_t end_pos = data.find('"', position);
299 std::string str = data.substr(position, end_pos - position);
300 position = end_pos + 1;
301 return JsonValue(str);
302}
303
308JsonValue JsonParser::ParseBool() {
309 if (data.compare(position, 4, "true") == 0) {
310 position += 4;
311 return JsonValue(true);
312 } else if (data.compare(position, 5, "false") == 0) {
313 position += 5;
314 return JsonValue(false);
315 } else {
316 // Invalid boolean value
317 return JsonValue();
318 }
319}
320
325JsonValue JsonParser::ParseNull() {
326 if (data.compare(position, 4, "null") == 0) {
327 position += 4;
328 return JsonValue();
329 } else {
330 // Invalid null value
331 return JsonValue();
332 }
333}
334
339JsonValue JsonParser::ParseObject() {
341 position++; // Skip the initial '{'
342
343 while (data[position] != '}') {
344 SkipWhitespace();
345 std::string key = ParseString().GetString();
346
347 position++; // Skip the ':'
348 SkipWhitespace();
349 JsonValue value = ParseValue();
350 obj[key] = value;
351
352 SkipWhitespace();
353 if (data[position] == ',') {
354 position++;
355 }
356 }
357
358 position++; // Skip the trailing '}'
359 return JsonValue(obj);
360}
361
366JsonValue JsonParser::ParseArray() {
368 position++; // Skip the initial '['
369
370 while (data[position] != ']') {
371 SkipWhitespace();
372 JsonValue value = ParseValue();
373 arr.push_back(value);
374
375 SkipWhitespace();
376 if (data[position] == ',') {
377 position++;
378 }
379 }
380
381 position++; // Skip the trailing ']'
382 return JsonValue(arr);
383}
384
391 std::ofstream outputFile(filename);
392 if (!outputFile) {
393 std::cerr << "Error: Unable to open file " << filename << " for writing."
394 << std::endl;
395 return;
396 }
397
399 WriteJsonValue(outputFile, jsonValue);
400}
401
408void JsonParser::WriteJsonValue(std::ofstream& outputFile,
410 switch (jsonValue.GetType()) {
411 case JsonValueType::Null:
412 outputFile << "null";
413 break;
414 case JsonValueType::Number:
415 outputFile << jsonValue.GetDouble();
416 break;
417 case JsonValueType::String:
418 outputFile << "\"" << jsonValue.GetString() << "\"";
419 break;
420 case JsonValueType::Bool:
421 outputFile << (jsonValue.GetBool() ? "true" : "false");
422 break;
423 case JsonValueType::Object: {
424 JsonObject& obj = jsonValue.GetObject();
425 outputFile << "{";
426 bool first = true;
427 for (const auto& pair : obj) {
428 if (!first) {
429 outputFile << ",";
430 }
431 first = false;
432 outputFile << "\"" << pair.first << "\":";
433 WriteJsonValue(outputFile, pair.second);
434 }
435 outputFile << "}";
436 } break;
437 case JsonValueType::JArray: {
438 JsonArray& arr = jsonValue.GetArray();
439 outputFile << "[";
440 bool first = true;
441 for (const auto& value : arr) {
442 if (!first) {
443 outputFile << ",";
444 }
445 first = false;
446 WriteJsonValue(outputFile, value);
447 }
448 outputFile << "]";
449 } break;
450 }
451}
452
458 this->PrintJsonValue(std::cout, jsonValue);
459 std::cout << std::endl;
460}
461
467void JsonParser::PrintJsonValue(std::ostream& output, JsonValue jsonValue) {
468 switch (jsonValue.GetType()) {
469 case JsonValueType::Null:
470 output << "null";
471 break;
472 case JsonValueType::Number:
473 output << jsonValue.GetDouble();
474 break;
475 case JsonValueType::String:
476 output << "\"" << jsonValue.GetString() << "\"";
477 break;
478 case JsonValueType::Bool:
479 output << (jsonValue.GetBool() ? "true" : "false");
480 break;
481 case JsonValueType::Object: {
482 JsonObject& obj = jsonValue.GetObject();
483 output << "{";
484 bool first = true;
485 for (const auto& pair : obj) {
486 if (!first) {
487 output << ",";
488 }
489 first = false;
490 output << "\"" << pair.first << "\":";
491 PrintJsonValue(output, pair.second);
492 }
493 output << "}";
494 } break;
495 case JsonValueType::JArray: {
496 JsonArray& arr = jsonValue.GetArray();
497 output << "[";
498 bool first = true;
499 for (const auto& value : arr) {
500 if (!first) {
501 output << ",";
502 }
503 first = false;
504 PrintJsonValue(output, value);
505 }
506 output << "]";
507 } break;
508 }
509}
510} // namespace fims
511#endif
Definition fims_json.hpp:106
void Show(JsonValue jsonValue)
Definition fims_json.hpp:457
void WriteToFile(const std::string &filename, JsonValue jsonValue)
Definition fims_json.hpp:390
static std::string PrettyFormatJSON(const std::string &json)
Formats a JSON string.
Definition fims_json.hpp:128
JsonValue Parse(const std::string &json)
Definition fims_json.hpp:222
static std::string removeWhitespace(const std::string &input)
Definition fims_json.hpp:116
Definition fims_json.hpp:50
JsonValue(bool b)
Definition fims_json.hpp:65
JsonValue()
Definition fims_json.hpp:53
JsonValue(const JsonArray &arr)
Definition fims_json.hpp:71
double GetDouble() const
Definition fims_json.hpp:80
JsonArray & GetArray()
Definition fims_json.hpp:92
const std::string & GetString() const
Definition fims_json.hpp:83
JsonValue(const JsonObject &obj)
Definition fims_json.hpp:68
JsonValue(double num)
Definition fims_json.hpp:59
int GetInt() const
Definition fims_json.hpp:77
JsonObject & GetObject()
Definition fims_json.hpp:89
bool GetBool() const
Definition fims_json.hpp:86
JsonValue(const std::string &str)
Definition fims_json.hpp:62
JsonValueType GetType() const
Definition fims_json.hpp:74
JsonValue(int num)
Definition fims_json.hpp:56
std::vector< JsonValue > JsonArray
Definition fims_json.hpp:33
JsonValueType
Definition fims_json.hpp:38
@ Bool
Definition fims_json.hpp:42
@ Number
Definition fims_json.hpp:40
@ String
Definition fims_json.hpp:41
@ Object
Definition fims_json.hpp:43
@ Null
Definition fims_json.hpp:39
@ JArray
Definition fims_json.hpp:44
std::map< std::string, JsonValue > JsonObject
Definition fims_json.hpp:28
void clear_internal()
Clears the internal objects.
Definition rcpp_interface.hpp:279