| Bsoft 2.0.5 Bernard's software package

json.h
Go to the documentation of this file.
1
8 #include <ostream>
9 #include <iostream>
10 #include <fstream>
11 #include <sstream>
12 #include <vector>
13 #include <map>
14 #include <type_traits>
15
16 using namespace std;
17
18 #ifndef _JSON_
19 #define _JSON_
20
21 enum JStype {
22 JSstring,
23 JSbool,
24 JSinteger,
25 JSreal,
26 JSobject,
27 JSarray,
28 JSnull
29 };
30
31 // Prototypes
32 class JSvalue;
33 ostream& operator<<(ostream& output, JStype t);
34 ostream& operator<<(ostream& output, JSvalue& jsv);
35
36 /*
37 The string s contains eiher the tag if the type is a pair
38 or the value if the type is a number or string.
39 The list v contains elements that could be:
40 a single value if type is a pair
41 an array of values if type is an array
42 an array of pairs if type is an object.
43 The last three types are the barewords: true, false and null
44 Type Str/Val Vec/Map
45 JSstring value -
46 JSbool t/f -
47 JSinteger long -
48 JSreal double -
49 JSobject - map
50 JSarray - vec
51 JSnull - -
52 */
53 class JSvalue { // 104
54 private:
55 JStype t; // 4 - aligned on 8
56 string s; // 24
57 bool b; // 1 - aligned on 8
58 long i; // 8
59 double r; // 8
60 vector<JSvalue> v; // 24
61 map<string, JSvalue> m; // 24
62 void clean_string(string val) {
63 if ( val.front() == '"' ) {
64 if ( val.back() == '"' ) s = val.substr(1,val.length() - 2);
65 else s = val.substr(1);
66 } else s = val;
67 }
68 void fail(string msg) {
69 cerr << "JSON error! " << msg << " (" << t << ")" << endl;
70 show_value(*this);
71 cerr << "array:" << endl;
72 for ( auto it = v.begin(); it != v.end(); ++it )
73 show_value(*it);
74 cerr << "object:" << endl;
75 for ( auto it = m.begin(); it != m.end(); ++it ) {
76 cerr << "tag: " << it->first << endl;
77 show_value(it->second);
78 }
79 // exit(-1);
80 }
81 void show_value(JSvalue& val) {
82 cerr << "string: \"" << s << "\"" << endl;
83 cerr << "boolean: " << b << endl;
84 cerr << "integer: " << i << endl;
85 cerr << "real: " << r << endl;
86 }
87 public:
88 JSvalue() : t(JSnull) { }
89 JSvalue(JStype tp) : t(tp) { }
90 JSvalue(bool tf) : t(JSbool), b(tf) { }
91 JSvalue(const char* val) : t(JSstring) { clean_string(val); }
92 JSvalue(const string& val) : t(JSstring) { clean_string(val); }
93 JSvalue(const int& val) : t(JSinteger) { i = val; }
94 JSvalue(const unsigned int& val) : t(JSinteger) { i = val; }
95 JSvalue(const long& val) : t(JSinteger) { i = val; }
96 JSvalue(const unsigned long& val) : t(JSinteger) { i = val; }
97 JSvalue(const float& val) : t(JSreal) { r = val; }
98 JSvalue(const double& val) : t(JSreal) { r = val; }
99 template <typename T>
100 JSvalue(const vector<T>& arr) : t(JSarray) {
101 v.clear();
102 for ( auto it = arr.begin(); it != arr.end(); ++it )
103 v.push_back(*it);
104 }
105 JSvalue(const map<string, JSvalue>& mp) : t(JSobject) { m = mp; }
106 const JStype& type() const { return t; }
107 // Size
108 size_t size() {
109 if ( t == JSarray ) return v.size();
110 else if ( t == JSobject ) return m.size();
111 else if ( t == JSstring ) return s.size();
112 else if ( t == JSnull ) return 0;
113 return 1;
114 }
115 void clear() {
116 if ( t == JSarray ) return v.clear();
117 else if ( t == JSobject ) return m.clear();
118 else if ( t == JSstring ) return s.clear();
119 }
120 long memory() {
121 long n(sizeof(JSvalue));
122 if ( t == JSarray ) for ( auto it: v ) n += it.memory();
123 else if ( t == JSobject ) for ( auto it: m ) n += it.first.size() + it.second.memory();
124 else if ( t == JSstring ) n += s.size();
125 return n;
126 }
127 // Access
128 string& value() {
129 if ( t != JSstring ) fail("value: Expected a string.");
130 return s;
131 }
132 bool& boolean() {
133 if ( t != JSbool ) fail("boolean: Expected a boolean.");
134 return b;
135 }
136 long& integer() {
137 if ( t != JSinteger ) {
138 if ( t != JSreal ) fail("integer: Expected an integer.");
139 else i = r;
140 }
141 return i;
142 }
143 double& real() {
144 if ( t != JSreal ) {
145 if ( t != JSinteger ) fail("real: Expected a real number.");
146 else r = i;
147 }
148 return r;
149 }
150 // Array access
151 vector<JSvalue>& array() {
152 if ( t != JSarray ) fail("array: Expected an array.");
153 return v;
154 }
155 JSvalue& operator[](long j) {
156 if ( t != JSarray ) fail("Expected an array.");
157 return v.at(j);
158 }
159 vector<long> array_integer() {
160 if ( t != JSarray ) fail("array_integer: Expected an array.");
161 vector<long> vec;
162 for ( auto it = v.begin(); it != v.end(); ++it )
163 vec.push_back(it->integer());
164 return vec;
165 }
166 vector<double> array_real() {
167 if ( t != JSarray ) fail("array_real: Expected an array.");
168 vector<double> vec;
169 for ( auto it = v.begin(); it != v.end(); ++it )
170 vec.push_back(it->real());
171 return vec;
172 }
173 JSvalue& front() {
174 if ( t != JSarray ) fail("front: Expected an array.");
175 return v.front();
176 }
177 JSvalue& back() {
178 if ( t != JSarray ) fail("back: Expected an array.");
179 return v.back();
180 }
181 vector<JSvalue>::iterator begin() { return v.begin(); }
182 vector<JSvalue>::iterator end() { return v.end(); }
183 vector<JSvalue>::iterator erase(long j) {
184 if ( t != JSarray ) fail("erase: Expected an array.");
185 return v.erase(v.begin()+j);
186 }
187 vector<JSvalue>::iterator erase(vector<JSvalue>::iterator first, vector<JSvalue>::iterator last) {
188 if ( t != JSarray ) fail("erase: Expected an array.");
189 return v.erase(v.begin(), v.end());
190 }
191 void push_back(const JSvalue& val) {
192 if ( t != JSarray ) fail("push_back: Expected an array.");
193 v.push_back(val);
194 }
195 // Object access
196 map<string, JSvalue>& object() {
197 if ( t != JSobject ) fail("Expected an object.");
198 return m;
199 }
200 JSvalue& operator[](string tag) {
201 if ( t != JSobject ) fail("Expected an object with tag " + tag + ".");
202 if ( m.find(tag) == m.end() ) m[tag] = JSvalue();
203 return m[tag];
204 }
205 JSvalue& object(string tag) {
206 if ( t != JSobject ) fail("object: Expected an object with tag " + tag + ".");
207 if ( m.find(tag) == m.end() ) fail("Tag " + tag + " not found.");
208 return m[tag];
209 }
210 JSvalue& at(string tag) {
211 if ( t != JSobject ) fail("at: Expected an object with tag " + tag + ".");
212 if ( m.find(tag) == m.end() ) fail("Tag " + tag + " not found.");
213 return m[tag];
214 }
215 bool exists(string tag) {
216 if ( t != JSobject ) fail("exists: Expected an object with tag " + tag + ".");
217 if ( m.find(tag) == m.end() ) return false;
218 return true;
219 }
220 long erase(string tag) {
221 if ( t != JSobject ) fail("erase: Expected an object with tag " + tag + ".");
222 return m.erase(tag);
223 }
224 map<string, JSvalue>::iterator object_begin() { return m.begin(); }
225 map<string, JSvalue>::iterator object_end() { return m.end(); }
226 map<string, JSvalue>::iterator erase(map<string, JSvalue>::iterator first, map<string, JSvalue>::iterator last) {
227 if ( t != JSobject ) fail("erase: Expected an object.");
228 return m.erase(first, last);
229 }
230 map<string, JSvalue>::iterator lower_bound(string& s) { return m.lower_bound(s); }
231 map<string, JSvalue>::iterator upper_bound(string& s) { return m.upper_bound(s); }
232 // Simple type access
233 bool& boolean(string& tag) {
234 return object(tag).boolean();
235 }
236 long& integer(string& tag) {
237 return object(tag).integer();
238 }
239 double& real(string& tag) {
240 return object(tag).real();
241 }
242 vector<JSvalue>& array(string& tag) {
243 return object(tag).array();
244 }
245 // Relational operators
246 bool operator==(string val) {
247 return s == val;
248 }
249 bool operator!=(string val) {
250 return s != val;
251 }
252 // Computational operators
253 void operator*=(double d) {
254 if ( t == JSinteger ) i *= d;
255 else if ( t == JSreal ) r *= d;
256 else if ( t == JSarray )
257 for ( auto it = this->begin(); it != this->end(); ++it ) *it *= d;
258 }
259 // Queries
260 vector<JSvalue*> operator()(string& jsonpath) {
261 cout << "Parsing path: " << jsonpath << endl;
262 vector<JSvalue*> qarr;
263 if ( jsonpath.find_first_of(".") < 2 ) qdots(jsonpath, qarr);
264 else qbrackets(jsonpath, qarr);
265 cout << "Query size: " << qarr.size() << endl;
266 return qarr;
267 }
268 void qdots(string& jsonpath, vector<JSvalue*>& qarr) {
269 // cout << "jsonpath=" << jsonpath << endl;
270 size_t b1(jsonpath.find_first_of("."));
271 size_t b2(jsonpath.find_first_of("["));
272 // cout << b1 << "\t" << b2 << endl;
273 if ( b2 < b1 ) {
274 b1 = b2;
275 b2 = jsonpath.find_first_of("]", b1);
276 } else {
277 size_t b3(jsonpath.find_first_of(".", b1+1));
278 if ( b3 < b2 ) b2 = b3;
279 }
280 if ( b1 >= string::npos ) {
281 qarr.push_back(this);
282 return;
283 }
284 // cout << b1 << "\t" << b2 << endl;
285 if ( b2 >= string::npos ) b2 = jsonpath.length();
286 string tag(jsonpath.substr(b1+1,b2-b1-1));
287 string nupath(jsonpath.substr(b2)); // new path starts with '.' or '['
288 // cout << "tag=" << tag << endl;
289 // cout << "nupath=" << nupath << endl;
290 if ( t == JSarray ) {
291 if ( tag == "*" ) {
292 for ( auto it = begin(); it != end(); ++it )
293 it->qdots(nupath, qarr);
294 } else {
295 try { i = stol(tag); }
296 catch (...) { fail("No conversion to an integer."); }
297 v[i].qdots(nupath, qarr);
298 }
299 } else if ( t == JSobject ) {
300 if ( tag == "*" ) {
301 for ( auto it = object_begin(); it != object_end(); ++it )
302 it->second.qdots(nupath, qarr);
303 } else {
304 if ( tag[0] == '\'' )
305 tag = tag.substr(1, tag.find_last_of("'") - 1);
306 if ( tag[0] == '"' )
307 tag = tag.substr(1, tag.find_last_of("\"") - 1);
308 m[tag].qdots(nupath, qarr);
309 }
310 } else fail("Tag " + tag + " not found.");
311 }
312 void qbrackets(string& jsonpath, vector<JSvalue*>& qarr) {
313 // cout << "jsonpath=" << jsonpath << endl;
314 size_t b1(jsonpath.find_first_of("["));
315 if ( b1 == string::npos ) {
316 qarr.push_back(this);
317 return;
318 }
319 size_t b2(jsonpath.find_first_of("]"));
320 string tag(jsonpath.substr(b1+1,b2-b1-1));
321 string nupath(jsonpath.substr(b2+1));
322 // cout << "tag=" << tag << endl;
323 if ( t == JSarray ) {
324 if ( tag == "*" ) {
325 for ( auto it = begin(); it != end(); ++it )
326 it->qbrackets(nupath, qarr);
327 } else {
328 try { i = stol(tag); }
329 catch (...) { fail("No conversion to an integer."); }
330 v[i].qbrackets(nupath, qarr);
331 }
332 } else if ( t == JSobject ) {
333 if ( tag == "*" ) {
334 for ( auto it = object_begin(); it != object_end(); ++it )
335 it->second.qbrackets(nupath, qarr);
336 } else {
337 if ( tag[0] == '\'' )
338 tag = tag.substr(1, tag.find_last_of("'") - 1);
339 if ( tag[0] == '"' )
340 tag = tag.substr(1, tag.find_last_of("\"") - 1);
341 m[tag].qbrackets(nupath, qarr);
342 }
343 } else fail("Tag " + tag + " not found.");
344 }
345 void write(string& filename) {
346 ofstream fjs(filename);
347 fjs << *this << endl;
348 fjs.close();
349 }
350 };
351
352 /*
353 The following incorrect syntax is ignored:
354 Any content after the top-level closing bracket
355 Any fields before or after commas that only contain white space
356 Any white space within numeric fields or leading zeroes
357 */
358 class JSparser {
359 private:
360 string content;
361 string::iterator it;
362 void read(string filename) {
363 // cout << "Reading " << filename << endl;
364 ifstream f(filename);
365 if ( f.fail() ) {
366 cerr << "Error: File " << filename << " not opened" << endl;
367 return;
368 }
369 f.seekg(0, ios::end);
370 content.resize(f.tellg());
371 // cout << "Length = " << content.size() << endl;
372 f.seekg(0, ios::beg);
373 f.read(&content[0], content.size());
374 f.close();
375 }
376 void fail(string msg) {
377 long i;
378 cerr << "JSON parser error! " << msg << " (";
379 for ( i=0; it!=content.end() && i<10 ; ++it, ++i ) cerr << *it;
380 if ( i >= 10 ) cerr << "...";
381 cerr << ")" << endl;
382 exit(-1);
383 }
384 public:
385 JSparser() {};
386 JSparser(string filename) { read(filename); }
387 JSparser(const char* buf, size_t n) { content = string(buf, n); }
388 JSvalue parse() {
389 JSvalue val;
390 for ( it=content.begin(); it!=content.end(); ++it ) {
391 if ( *it == '{' ) return parseJSobject();
392 else if ( *it == '[' ) return parseJSarray();
393 else if ( !isspace(*it) ) break;
394 }
395 fail("No { or [ found at the start.");
396 return val;
397 }
398 JSvalue parse(string filename) {
399 read(filename);
400 return parse();
401 }
402 private:
403 JSvalue parseJSvalue() {
404 JSvalue val;
405 for ( ; it!=content.end() && *it != '}' && *it != ']' && *it != ','; ++it ) {
406 if ( *it == '{' ) {
407 return parseJSobject();
408 } else if ( *it == '[' ) {
409 return parseJSarray();
410 } else if ( *it == '"' ) {
411 return parseJSstring();
412 } else if ( isdigit(*it) || *it == '.' || *it == '+' || *it == '-' ) {
413 return parseJSnumber();
414 } else if ( *it == 't' || *it == 'f' || *it == 'n' ) {
415 return parseJSbare();
416 } else if ( !isspace(*it) ) {
417 fail("Found an unquoted string.");
418 }
419 }
420 return val;
421 }
422 string parseString() {
423 string s;
424 for ( ; it!=content.end() && *it != '"'; ++it )
425 if ( !isspace(*it) ) fail("Unquoted string.");
426 if ( *it != '"' ) fail("No opening quote on a string.");
427 for ( ++it; it!=content.end(); ++it ) {
428 if ( *it == '\\' ) { s += *it; ++it; s += *it; }
429 else if ( *it == '"' ) break;
430 else s += *it;
431 // cout << *it;
432 }
433 // cout << s << " \"" << *it << "\"" << endl;
434 if ( *it != '"' ) fail("No closing quote on a string.");
435 ++it;
436 return s;
437 }
438 JSvalue parseJSstring() {
439 string s(parseString());
440 return JSvalue(s);
441 }
442 JSvalue parseJSnumber() {
443 string s;
444 int ft(0);
445 for ( ; it!=content.end() && *it != '}' && *it != ']'
446 && *it != ',' && !isspace(*it); ++it ) {
447 if ( *it == '.' ) ft = 1;
448 if ( *it == 'x' ) fail("Numbers cannot be hex");
449 s += *it;
450 }
451 long l;
452 double d;
453 if ( ft ) {
454 try { d = stod(s); }
455 catch (...) { fail("No conversion to a real number."); }
456 return JSvalue(d);
457 } else {
458 try { l = stol(s); }
459 catch (...) { fail("No conversion to an integer."); }
460 return JSvalue(l);
461 }
462 }
463 JSvalue parseJSbare() {
464 string s;
465 for ( ; it!=content.end() && !isspace(*it) && *it != ',' && *it != '}'; ++it )
466 s += *it;
467 if ( s.compare("true") == 0 ) {
468 return JSvalue(true);
469 } else if ( s.compare("false") == 0 ) {
470 return JSvalue(false);
471 } else if ( s.compare("null") == 0 ) {
472 return JSvalue();
473 } else fail("Bare word " + s + " not allowed!");
474 return JSvalue();
475 }
476 JSvalue parseJSarray() {
477 it++;
478 JSvalue arr(JSarray);
479 for ( ; it!=content.end() && *it != ']'; ++it ) {
480 // cout << *it << endl;
481 if ( !isspace(*it) && *it != '}' && *it != ',' )
482 arr.push_back(parseJSvalue());
483 // cout << "parseJSarray:'" << *it << "'" << endl;
484 if ( *it == ':' ) fail("Unexpected colon.");
485 if ( it==content.end() || *it == ']' ) break;
486 }
487 if ( *it != ']' ) fail("No closing bracket on an array.");
488 it++;
489 // cout << "Parsing array" << *it << endl;
490 return arr;
491 }
492 JSvalue parseJSobject() {
493 it++;
494 string tag;
495 JSvalue obj(JSobject);
496 for ( ; it!=content.end() && *it != '}'; ++it ) {
497 if ( !isspace(*it) && *it != ']' && *it != ',' ) {
498 tag = parseString();
499 for ( ; it!=content.end() && isspace(*it); ++it ) ;
500 if ( *it != ':' ) fail("Expected a colon.");
501 it++;
502 obj[tag] = parseJSvalue();
503 }
504 if ( it==content.end() || *it == '}' ) break;
505 }
506 if ( *it != '}' ) fail("No closing bracket on an object.");
507 it++;
508 return obj;
509 }
510 };
511
512 #endif // _JSON_
513
514
515
516
JSvalue::erase
long erase(string tag)
Definition: json.h:220
JSvalue::object_begin
map< string, JSvalue >::iterator object_begin()
Definition: json.h:224
JSvalue::JSvalue
JSvalue(const char *val)
Definition: json.h:91
JSvalue::erase
vector< JSvalue >::iterator erase(long j)
Definition: json.h:183
JSvalue::integer
long & integer()
Definition: json.h:136
JSvalue::clear
void clear()
Definition: json.h:115
JSvalue::qbrackets
void qbrackets(string &jsonpath, vector< JSvalue * > &qarr)
Definition: json.h:312
JSvalue::front
JSvalue & front()
Definition: json.h:173
JSstring
Definition: json.h:22
operator *=
void operator *=(vector< T1 > &v1, T2 v2)
Definition: Vector3.h:456
JSvalue::qdots
void qdots(string &jsonpath, vector< JSvalue * > &qarr)
Definition: json.h:268
JSvalue::JSvalue
JSvalue(const double &val)
Definition: json.h:98
JSvalue::memory
long memory()
Definition: json.h:120
JSvalue::object_end
map< string, JSvalue >::iterator object_end()
Definition: json.h:225
JSvalue::object
JSvalue & object(string tag)
Definition: json.h:205
JSinteger
Definition: json.h:24
JSvalue::array
vector< JSvalue > & array(string &tag)
Definition: json.h:242
JSvalue::upper_bound
map< string, JSvalue >::iterator upper_bound(string &s)
Definition: json.h:231
JSvalue::real
double & real()
Definition: json.h:143
JSvalue::type
const JStype & type() const
Definition: json.h:106
JSvalue::real
double & real(string &tag)
Definition: json.h:239
JSvalue::JSvalue
JSvalue(const unsigned int &val)
Definition: json.h:94
JSvalue::array
vector< JSvalue > & array()
Definition: json.h:151
JSvalue::at
JSvalue & at(string tag)
Definition: json.h:210
JSvalue::JSvalue
JSvalue(bool tf)
Definition: json.h:90
JSvalue::array_real
vector< double > array_real()
Definition: json.h:166
JSvalue::JSvalue
JSvalue(const long &val)
Definition: json.h:95
JSvalue::JSvalue
JSvalue(const map< string, JSvalue > &mp)
Definition: json.h:105
JSvalue::boolean
bool & boolean()
Definition: json.h:132
JSvalue::erase
map< string, JSvalue >::iterator erase(map< string, JSvalue >::iterator first, map< string, JSvalue >::iterator last)
Definition: json.h:226
JSvalue::JSvalue
JSvalue(const float &val)
Definition: json.h:97
JSvalue::JSvalue
JSvalue(const unsigned long &val)
Definition: json.h:96
JSbool
Definition: json.h:23
JSvalue::write
void write(string &filename)
Definition: json.h:345
JStype
JStype
Definition: json.h:21
JSobject
Definition: json.h:26
JSvalue::operator[]
JSvalue & operator[](long j)
Definition: json.h:155
JSvalue
Definition: json.h:53
JSvalue::operator[]
JSvalue & operator[](string tag)
Definition: json.h:200
operator<<
ostream & operator<<(ostream &output, JStype t)
Definition: json.cpp:10
JSvalue::end
vector< JSvalue >::iterator end()
Definition: json.h:182
JSreal
Definition: json.h:25
JSvalue::boolean
bool & boolean(string &tag)
Definition: json.h:233
JSvalue::begin
vector< JSvalue >::iterator begin()
Definition: json.h:181
JSparser::JSparser
JSparser()
Definition: json.h:385
JSvalue::operator==
bool operator==(string val)
Definition: json.h:246
JSparser::parse
JSvalue parse(string filename)
Definition: json.h:398
JSvalue::exists
bool exists(string tag)
Definition: json.h:215
JSvalue::operator()
vector< JSvalue * > operator()(string &jsonpath)
Definition: json.h:260
JSvalue::JSvalue
JSvalue(const int &val)
Definition: json.h:93
JSparser::JSparser
JSparser(const char *buf, size_t n)
Definition: json.h:387
JSvalue::JSvalue
JSvalue(const vector< T > &arr)
Definition: json.h:100
JSvalue::object
map< string, JSvalue > & object()
Definition: json.h:196
JSvalue::back
JSvalue & back()
Definition: json.h:177
JSvalue::array_integer
vector< long > array_integer()
Definition: json.h:159
JSarray
Definition: json.h:27
JSparser
Definition: json.h:358
JSvalue::lower_bound
map< string, JSvalue >::iterator lower_bound(string &s)
Definition: json.h:230
JSvalue::value
string & value()
Definition: json.h:128
JSparser::parse
JSvalue parse()
Definition: json.h:388
JSvalue::JSvalue
JSvalue()
Definition: json.h:88
JSvalue::size
size_t size()
Definition: json.h:108
JSvalue::push_back
void push_back(const JSvalue &val)
Definition: json.h:191
JSvalue::JSvalue
JSvalue(const string &val)
Definition: json.h:92
JSparser::JSparser
JSparser(string filename)
Definition: json.h:386
JSvalue::operator!=
bool operator!=(string val)
Definition: json.h:249
JSnull
Definition: json.h:28
JSvalue::erase
vector< JSvalue >::iterator erase(vector< JSvalue >::iterator first, vector< JSvalue >::iterator last)
Definition: json.h:187
JSvalue::JSvalue
JSvalue(JStype tp)
Definition: json.h:89
JSvalue::integer
long & integer(string &tag)
Definition: json.h:236