Guitar
jstream.h
Go to the documentation of this file.
1 #ifndef JSTREAM_H_
2 #define JSTREAM_H_
3 
4 #include <cmath>
5 #include <cstdint>
6 #include <cstring>
7 #include <functional>
8 #include <string>
9 #include <string_view>
10 #include <vector>
11 #include <variant>
12 #include <assert.h>
13 
14 // #include <charconv> // C++17
15 
16 namespace jstream {
17 
18 static inline std::vector<char> encode_json_string(std::string_view const &in)
19 {
20  std::vector<char> ret;
21  char const *ptr = in.data();
22  char const *end = ptr + in.size();
23  ret.reserve(end - ptr + 10);
24  while (ptr < end) {
25  int c = (unsigned char)*ptr;
26  ptr++;
27  switch (c) {
28  case '\"': ret.push_back('\\'); ret.push_back('\"'); break;
29  case '\\': ret.push_back('\\'); ret.push_back('\\'); break;
30  case '\b': ret.push_back('\\'); ret.push_back('b'); break;
31  case '\f': ret.push_back('\\'); ret.push_back('f'); break;
32  case '\n': ret.push_back('\\'); ret.push_back('n'); break;
33  case '\r': ret.push_back('\\'); ret.push_back('r'); break;
34  case '\t': ret.push_back('\\'); ret.push_back('t'); break;
35  default:
36  if (c >= 0x20 && c < 0x7f) {
37  ret.push_back(c);
38  } else {
39  uint32_t u = 0;
40  if ((c & 0xe0) == 0xc0 && ptr < end) {
41  if ((ptr[0] & 0xc0) == 0x80) {
42  int d = (unsigned char)ptr[0];
43  u = ((c & 0x1f) << 6) | (d & 0x3f);
44  }
45  } else if ((c & 0xf0) == 0xe0 && ptr + 1 < end) {
46  if ((ptr[0] & 0xc0) == 0x80 && (ptr[1] & 0xc0) == 0x80) {
47  int d = (unsigned char)ptr[0];
48  int e = (unsigned char)ptr[1];
49  u = ((c & 0x0f) << 12) | ((d & 0x3f) << 6) | (e & 0x3f);
50  }
51  } else if ((c & 0xf8) == 0xf0 && ptr + 2 < end) {
52  if ((ptr[0] & 0xc0) == 0x80 && (ptr[1] & 0xc0) == 0x80 && (ptr[2] & 0xc0) == 0x80) {
53  int d = (unsigned char)ptr[0];
54  int e = (unsigned char)ptr[1];
55  int f = (unsigned char)ptr[2];
56  u = ((c & 0x0f) << 18) | ((d & 0x3f) << 12) | ((e & 0x3f) << 6) | (f & 0x3f);
57  }
58  }
59  if (u != 0) {
60  char tmp[20];
61  if (u >= 0x10000 && u < 0x110000) {
62  uint16_t h = (u - 0x10000) / 0x400 + 0xd800;
63  uint16_t l = (u - 0x10000) % 0x400 + 0xdc00;
64  sprintf(tmp, "\\u%04X\\u%04X", h, l);
65  ret.insert(ret.end(), tmp, tmp + 12);
66  } else {
67  sprintf(tmp, "\\u%04X", u);
68  ret.insert(ret.end(), tmp, tmp + 6);
69  }
70  }
71  }
72  }
73  }
74  return ret;
75 }
76 
77 class misc {
78 private:
89  static double pow10_int(int exp)
90  {
91  // Pre‑computed powers for |exp| ≤ 16
92  static const double tbl[] = {
93  1e+00, 1e+01, 1e+02, 1e+03, 1e+04, 1e+05, 1e+06,
94  1e+07, 1e+08, 1e+09, 1e+10, 1e+11, 1e+12, 1e+13,
95  1e+14, 1e+15, 1e+16
96  };
97  if (exp >= 0 && exp < static_cast<int>(sizeof tbl / sizeof *tbl))
98  return tbl[exp];
99  if (exp <= 0 && exp > -static_cast<int>(sizeof tbl / sizeof *tbl))
100  return 1.0 / tbl[-exp];
101  // Rare case: delegate to libm
102  return std::pow(10.0, exp);
103  }
104 public:
120  static double my_strtod(const char *nptr, char **endptr)
121  {
122  const char *s = nptr;
123  bool sign = false;
124  bool saw_digit = false;
125  int frac_digits = 0;
126  long exp_val = 0;
127  bool exp_sign = false;
128  double value = 0.0;
129 
130  // Skip leading white‑space
131  while (std::isspace((unsigned char)*s)) ++s;
132 
133  // Parse optional sign
134  if (*s == '+' || *s == '-') {
135  if (*s == '-') sign = true;
136  s++;
137  }
138 
139  // Integer part
140  while (std::isdigit((unsigned char)*s)) {
141  saw_digit = true;
142  value = value * 10.0 + (*s - '0');
143  s++;
144  }
145 
146  // Fractional part
147  if (*s == '.') {
148  s++;
149  while (std::isdigit((unsigned char)*s)) {
150  saw_digit = true;
151  value = value * 10.0 + (*s - '0');
152  s++;
153  frac_digits++;
154  }
155  }
156 
157  // No digits at all -> conversion failure
158  if (!saw_digit) {
159  if (endptr) *endptr = const_cast<char *>(nptr);
160  return 0.0;
161  }
162 
163  // Exponent part
164  if (*s == 'e' || *s == 'E') {
165  s++;
166  const char *exp_start = s;
167  if (*s == '+' || *s == '-') {
168  if (*s == '-') exp_sign = true;
169  s++;
170  }
171  if (std::isdigit((unsigned char)*s)) {
172  while (std::isdigit((unsigned char)*s)) {
173  exp_val = exp_val * 10 + (*s - '0');
174  s++;
175  }
176  if (exp_sign) {
177  exp_val = -exp_val;
178  }
179  } else {
180  // Roll back if 'e' is not followed by a valid exponent
181  s = exp_start - 1;
182  }
183  }
184 
185  // Scale by 10^(exponent − #fractional‑digits)
186  int total_exp = exp_val - frac_digits;
187  if (total_exp != 0) {
188  value *= pow10_int(total_exp);
189  }
190 
191  // Apply sign
192  if (sign) {
193  value = -value;
194  }
195 
196  // Set errno on overflow/underflow
197  if (!std::isfinite(value)) {
198  // errno = ERANGE;
199  value = sign ? -HUGE_VAL : HUGE_VAL;
200  } else if (value == 0.0 && saw_digit && total_exp != 0) {
201  // errno = ERANGE; // underflow
202  }
203 
204  // Report where parsing stopped
205  if (endptr) *endptr = const_cast<char *>(s);
206  return value;
207  }
208 
209  static std::string format_double(double val, bool allow_nan)
210  {
211  int precision = 15;
212  bool trim_zeros = true;
213  bool plus = false;
214 
215  if (std::isnan(val)) {
216  if (allow_nan) {
217  return "NaN";
218  }
219  return {};
220  }
221  if (std::isinf(val)) {
222  if (allow_nan) {
223  bool sign = std::signbit(val);
224  if (sign) {
225  return "-Infinity";
226  } else {
227  return "Infinity";
228  }
229  }
230  return {};
231  }
232 
233  char *ptr, *end;
234 
235  char *dot = nullptr;
236 
237  bool sign = val < 0;
238  if (sign) {
239  val = -val;
240  }
241 
242  double intval = floor(val);
243  val -= intval;
244 
245  int intlen = 0;
246  if (intval == 0) {
247  ptr = end = (char *)alloca(precision + 10) + 5;
248  } else {
249  double t = intval;
250  do {
251  t = floor(t / 10);
252  intlen++;
253  } while (t != 0);
254  ptr = end = (char *)alloca(intlen + precision + 10) + intlen + 5;
255  }
256 
257  if (precision > 0) {
258  dot = end;
259  *end++ = '.';
260  double v = val;
261  int e = 0;
262  while (v > 0 && v < 1) {
263  v *= 10;
264  e++;
265  }
266  while (v >= 1) {
267  v /= 10;
268  e--;
269  }
270  double add = 0.5;
271  for (int i = 0; i < precision - e; i++) {
272  add /= 10;
273  }
274  v += add;
275  double t = floor(v);
276  intval += t;
277  v -= t;
278  int i = 0;
279  int n = intlen;
280  int r = std::min(e, precision);
281  while (i < r) {
282  *end++ = '0';
283  if (n != 0) {
284  n++;
285  }
286  i++;
287  }
288  while (i < precision) {
289  if (n < 16) {
290  v *= 10;
291  double m = floor(v);
292  v -= m;
293  *end++ = (char)m + '0';
294  } else {
295  *end++ = '0';
296  }
297  n++;
298  i++;
299  }
300  } else {
301  intval += floor(val + 0.5);
302  }
303 
304  intlen = 0;
305  double t = intval;
306  do {
307  t = floor(t / 10);
308  intlen++;
309  } while (t != 0);
310 
311  if (intval == 0) {
312  *--ptr = '0';
313  } else {
314  double t = intval;
315  for (int i = 0; i < intlen; i++) {
316  t /= 10;
317  double u = floor(t);
318  *--ptr = (char)((t - u) * 10 + 0.49) + '0';
319  t = u;
320  }
321  }
322 
323  if (sign) {
324  *--ptr = '-';
325  } else if (plus) {
326  *--ptr = '+';
327  }
328 
329  if (trim_zeros && dot) {
330  while (dot < end) {
331  char c = end[-1];
332  if (c == '.') {
333  end--;
334  break;
335  }
336  if (c != '0') {
337  break;
338  }
339  end--;
340  }
341  }
342 
343  return std::string(ptr, end - ptr);
344  }
345 };
346 
347 enum StateType {
348  // Symbols
349  None = 0,
353  // States
354  Key = 100,
362 };
363 
364 class Reader {
365 public:
366  struct Error {
367  std::string what_;
368  std::string what() const { return what_; }
369  };
370 private:
371  static std::string to_stdstr(std::vector<char> const &vec)
372  {
373  if (!vec.empty()) {
374  char const *begin = &vec[0];
375  char const *end = begin + vec.size();
376  return std::string(begin, end);
377  }
378  return std::string();
379  }
380 
381  int scan_space(char const *begin, char const *end)
382  {
383  char const *ptr = begin;
384  while (ptr < end) {
385  if (std::isspace((unsigned char)*ptr)) {
386  ptr++;
387  continue;
388  }
389  if (d.allow_comment && *ptr == '/' && ptr + 1 < end) {
390  if (ptr[1] == '/') {
391  ptr += 2;
392  while (ptr < end && *ptr != '\r' && *ptr != '\n') {
393  ptr++;
394  }
395  continue;
396  }
397  if (ptr[1] == '*') {
398  ptr += 2;
399  while (ptr + 1 < end) {
400  if (*ptr == '*' && ptr[1] == '/') {
401  ptr += 2;
402  break;
403  }
404  ptr++;
405  }
406  continue;
407  }
408  }
409  break;
410  }
411  return ptr - begin;
412  }
413 
414  int parse_symbol(char const *begin, char const *end, std::string *out)
415  {
416  char const *ptr = begin;
417  ptr += scan_space(ptr, end);
418  std::vector<char> vec;
419  while (ptr < end) {
420  if (!isalnum((unsigned char)*ptr) && *ptr != '_') break;
421  vec.push_back(*ptr);
422  ptr++;
423  }
424  if (ptr > begin && !vec.empty()) {
425  *out = to_stdstr(vec);
426  return ptr - begin;
427  }
428  out->clear();
429  return 0;
430  }
431 
432  int parse_number(char const *begin, char const *end, double *out)
433  {
434  *out = 0;
435  char const *ptr = begin;
436  ptr += scan_space(ptr, end);
437 
438  std::vector<char> vec;
439 
440  if (d.allow_hexadicimal) {
441  char const *p = ptr;
442  bool sign = false;
443  if (p + 1 < end && *p == '-') {
444  p++;
445  sign = true;
446  }
447  if (p + 1 < end && *p == '0' && (p[1] == 'x' || p[1] == 'X')) {
448  p += 2;
449  while (p < end && isxdigit((unsigned char)*p)) {
450  vec.push_back(*p);
451  p++;
452  }
453  vec.push_back(0);
454  long long v = strtoll(vec.data(), nullptr, 16);
455  *out = sign ? -v : v;
456  return p - begin;
457  }
458  }
459 
461  char const *p = ptr;
462  bool sign = false;
463  if (p < end && *p == '-') {
464  p++;
465  sign = true;
466  }
467  while (p < end && isalpha((unsigned char)*p)) {
468  vec.push_back(*p);
469  p++;
470  }
471  vec.push_back(0);
472  if (strcmp(vec.data(), "Infinity") == 0) {
473  ptr = p;
474  *out = sign ? -INFINITY : INFINITY;
475  } else if (strcmp(vec.data(), "NaN") == 0) {
476  ptr = p;
477  *out = NAN;
478  }
479  if (ptr > begin) {
480  return ptr - begin;
481  }
482  }
483 
484  while (ptr < end) {
485  char c = *ptr;
486  if (isdigit((unsigned char)c) || c == '.' || c == '+' || c == '-' || c == 'e' || c == 'E') {
487  // thru
488  } else {
489  break;
490  }
491  vec.push_back(c);
492  ptr++;
493  }
494  vec.push_back(0);
495 
496  // use my_strtod instead of strtod, because strtod is locale dependent
497  // *out = strtod(vec.data(), nullptr);
498  // std::from_chars(vec.data(), vec.data() + vec.size(), *out); // C++17
499  *out = misc::my_strtod(vec.data(), nullptr);
500 
501  return ptr - begin;
502  }
503 
504  int parse_string(char const *begin, char const *end, std::string *out)
505  {
506  char const *ptr = begin;
507  ptr += scan_space(ptr, end);
508  if (*ptr == '\"') {
509  ptr++;
510  std::vector<char> vec;
511  while (ptr < end) {
512  if (*ptr == '\"') {
513  *out = to_stdstr(vec);
514  ptr++;
515  return ptr - begin;
516  } else if (*ptr == '\\') {
517  ptr++;
518  if (ptr < end) {
519  auto push = [&](char c){ vec.push_back(c); ptr++;};
520  switch (*ptr) {
521  case 'b': push('\b'); break;
522  case 'n': push('\n'); break;
523  case 'r': push('\r'); break;
524  case 'f': push('\f'); break;
525  case 't': push('\t'); break;
526  case 'v': push('\v'); break;
527  case '\\':
528  case '\"':
529  push(*ptr);
530  break;
531  case 'u':
532  ptr++;
533  if (ptr + 3 < end) {
534  char tmp[5];
535  tmp[0] = ptr[0];
536  tmp[1] = ptr[1];
537  tmp[2] = ptr[2];
538  tmp[3] = ptr[3];
539  tmp[4] = 0;
540  ptr += 4;
541  uint32_t unicode = (uint32_t)strtol(tmp, nullptr, 16);
542  if (unicode >= 0xd800 && unicode < 0xdc00) {
543  if (ptr + 5 < end && ptr[0] == '\\' && ptr[1] == 'u') {
544  tmp[0] = ptr[2];
545  tmp[1] = ptr[3];
546  tmp[2] = ptr[4];
547  tmp[3] = ptr[5];
548  uint32_t surrogate = (uint32_t)strtol(tmp, nullptr, 16);
549  if (surrogate >= 0xdc00 && surrogate < 0xe000) {
550  ptr += 6;
551  unicode = ((unicode - 0xd800) << 10) + (surrogate - 0xdc00) + 0x10000;
552  }
553  }
554  }
555  if (unicode < (1 << 7)) {
556  vec.push_back(unicode & 0x7f);
557  } else if (unicode < (1 << 11)) {
558  vec.push_back(((unicode >> 6) & 0x1f) | 0xc0);
559  vec.push_back((unicode & 0x3f) | 0x80);
560  } else if (unicode < (1 << 16)) {
561  vec.push_back(((unicode >> 12) & 0x0f) | 0xe0);
562  vec.push_back(((unicode >> 6) & 0x3f) | 0x80);
563  vec.push_back((unicode & 0x3f) | 0x80);
564  } else if (unicode < (1 << 21)) {
565  vec.push_back(((unicode >> 18) & 0x07) | 0xf0);
566  vec.push_back(((unicode >> 12) & 0x3f) | 0x80);
567  vec.push_back(((unicode >> 6) & 0x3f) | 0x80);
568  vec.push_back((unicode & 0x3f) | 0x80);
569  }
570  }
571  break;
572  default:
573  vec.push_back(*ptr);
574  ptr++;
575  break;
576  }
577  }
578  } else {
579  vec.push_back(*ptr);
580  ptr++;
581  }
582  }
583  }
584  return 0;
585  }
586 private:
587  struct StateItem {
589  char const *ptr = nullptr;
590  StateItem() = default;
591  StateItem(StateType type, char const *ptr = nullptr)
592  : type(type)
593  , ptr(ptr)
594  {
595  }
596  };
597  struct ParserData {
598  char const *begin = nullptr;
599  char const *end = nullptr;
600  char const *ptr = nullptr;
601  std::vector<StateItem> states;
602  bool hold = false;
603  std::string key;
604  std::string string;
605  double number = 0;
606  bool is_array = false;
607  bool allow_comment = false;
608  bool allow_ambiguous_comma = false;
609  bool allow_unquoted_key = false;
610  bool allow_hexadicimal = false;
612  std::vector<std::string> depth;
613  std::vector<int> depth_stack;
615  std::vector<Error> errors;
616  };
618 
619  void push_error(std::string const &what)
620  {
621  d.states.clear();
622 
623  Error err;
624  err.what_ = what;
625  d.errors.push_back(err);
626  }
627 
629  {
630  if (state() == Key || state() == Comma || state() == EndObject) {
631  d.states.pop_back();
632  }
633  d.states.push_back(s);
634 
635  if (isarray()) {
636  d.key.clear();
637  }
638 
639  switch (s.type) {
640  case StartArray:
641  d.is_array = true;
642  break;
643  case StartObject:
644  case Key:
645  d.is_array = false;
646  break;
647  }
648  }
649 
650  bool pop_state()
651  {
652  bool f = false;
653  if (!d.states.empty()) {
654  d.last_state = d.states.back();
655  d.states.pop_back();
656  size_t i = d.states.size();
657  while (i > 0) {
658  i--;
659  auto s = d.states[i];
660  if (s.type == StartArray) {
661  d.is_array = true;
662  break;
663  }
664  if (s.type == StartObject || s.type == Key) {
665  d.is_array = false;
666  break;
667  }
668  }
669  f = true;
670  if (state() == Key) {
671  d.states.pop_back();
672  }
673  }
674  d.key.clear();
675  return f;
676  }
677 
678  void parse(char const *begin, char const *end)
679  {
680  reset();
681  d = {};
682  d.begin = begin;
683  d.end = end;
684  d.ptr = d.begin;
685  }
686 
687  void parse(std::string_view const &sv)
688  {
689  parse(sv.data(), sv.data() + sv.size());
690  }
691 
692  void parse(char const *ptr, int len = -1)
693  {
694  if (len < 0) {
695  len = strlen(ptr);
696  }
697  parse(ptr, ptr + len);
698  }
699 
701  {
702  while (d.ptr < d.end) {
703  {
704  auto n = scan_space(d.ptr, d.end);;
705  if (n > 0) {
706  d.ptr += n;
707  continue;
708  }
709  }
710  if (*d.ptr == '}') {
711  d.ptr++;
712  d.string.clear();
713  std::string key;
714  if (!d.depth.empty()) {
715  key = d.depth.back();
716  auto n = key.size();
717  if (n > 0) {
718  if (key[n - 1] == '{') {
719  key = key.substr(0, n - 1);
720  }
721  }
722  d.depth.pop_back();
723  }
724  while (1) {
725  bool f = (state() == StartObject);
726  if (!pop_state()) break;
727  if (f) {
729  d.key = key;
730  return true;
731  }
732  }
733  }
734  if (*d.ptr == ']') {
735  d.ptr++;
736  d.string.clear();
737  std::string key;
738  if (!d.depth.empty()) {
739  key = d.depth.back();
740  auto n = key.size();
741  if (n > 0) {
742  if (key[n - 1] == '[') {
743  key = key.substr(0, n - 1);
744  }
745  }
746  d.depth.pop_back();
747  }
748  while (1) {
749  bool f = (state() == StartArray);
750  if (!pop_state()) break;
751  if (f) {
753  d.key = key;
754  return true;
755  }
756  }
757  }
758  if (*d.ptr == ',') {
759  d.ptr++;
760  if (state() == Key) {
761  push_state(Null);
762  return true;
763  }
764  d.ptr += scan_space(d.ptr, d.end);
765  if (isobject() || isvalue()) {
766  pop_state();
767  }
768  push_state(Comma);
769  if (d.allow_ambiguous_comma) {
770  continue;
771  } else {
772  // if not allow_ambiguous_comma, fall through
773  }
774  }
775  if (*d.ptr == '{') {
776  char const *p = d.ptr++;
777  if (state() != Key) {
778  d.key.clear();
779  d.string.clear();
780  }
781  d.depth.push_back(d.key + '{');
782  push_state({StartObject, p});
783  return true;
784  }
785  if (*d.ptr == '[') {
786  char const *p = d.ptr++;
787  if (state() != Key) {
788  d.key.clear();
789  d.string.clear();
790  }
791  d.depth.push_back(d.key + '[');
792  push_state({StartArray, p});
793  return true;
794  }
795  if (*d.ptr == '\"') {
796  switch (state()) {
797  case None:
798  case StartObject:
799  case StartArray:
800  case Key:
801  case Comma:
802  // thru
803  break;
804  default:
805  if (d.allow_ambiguous_comma) {
806  break; // consider as a virtual comma is exists
807  }
808  push_error("unexpected double quote");
809  return false;
810  }
811 
812  auto n = parse_string(d.ptr, d.end, &d.string);
813  if (n > 0) {
814  if (isarray()) {
815  d.ptr += n;
817  return true;
818  }
819  if (state() == Key) {
820  d.ptr += n;
822  return true;
823  }
824  n += scan_space(d.ptr + n, d.end);
825  if (d.ptr[n] == ':') {
826  d.ptr += n + 1;
827  d.key = d.string;
828  push_state(Key);
829  return true;
830  }
831  }
832  }
833  if (state() == Key || isarray()) {
834  auto n = parse_number(d.ptr, d.end, &d.number);
835  if (n > 0) {
836  d.string.assign(d.ptr, n);
837  d.ptr += n;
839  return true;
840  }
841  if (isalpha((unsigned char)*d.ptr)) {
842  auto n = parse_symbol(d.ptr, d.end, &d.string);
843  if (n > 0) {
844  if (state() == Key || state() == Comma || state() == StartArray) {
845  d.ptr += n;
846  if (d.string == "false") {
847  push_state(False);
848  return true;
849  }
850  if (d.string == "true") {
851  push_state(True);
852  return true;
853  }
854  if (d.string == "null") {
855  push_state(Null);
856  return true;
857  }
858  }
859  }
860  }
861  } else if (d.allow_unquoted_key) {
862  auto n = parse_symbol(d.ptr, d.end, &d.string);
863  if (n > 0) {
864  n += scan_space(d.ptr + n, d.end);
865  if (d.ptr[n] == ':') {
866  d.ptr += n + 1;
867  d.key = d.string;
868  push_state(Key);
869  return true;
870  }
871  }
872  }
873  push_error("syntax error");
874  break;
875  }
876  return false;
877  }
878 public:
879  Reader(std::string_view const &sv)
880  {
881  parse(sv);
882  }
883  Reader(char const *begin, char const *end)
884  {
885  parse(begin, end);
886  }
887  Reader(char const *ptr, int len = -1)
888  {
889  parse(ptr, len);
890  }
891  void allow_comment(bool allow)
892  {
893  d.allow_comment = allow;
894  }
895  void allow_ambiguous_comma(bool allow)
896  {
897  d.allow_ambiguous_comma = allow;
898  }
899  void allow_unquoted_key(bool allow)
900  {
901  d.allow_unquoted_key = allow;
902  }
903  void allow_hexadicimal(bool allow)
904  {
905  d.allow_hexadicimal = allow;
906  }
907  void allow_special_constant(bool allow)
908  {
909  d.allow_special_constant = allow;
910  }
911  void reset()
912  {
913  d.errors.clear();
914  }
915  void hold()
916  {
917  d.hold = true;
918  }
919  void nest()
920  {
921  d.depth_stack.push_back(depth());
922  }
923  bool next()
924  {
925  if (d.hold) {
926  d.hold = false;
927  return true;
928  }
929  if (_internal_next()) {
930  if (d.depth_stack.empty()) return true;
931  if (this->depth() >= d.depth_stack.back()) {
932  return true;
933  }
934  d.depth_stack.pop_back();
935  hold();
936  }
937  return false;
938  }
939 
940  StateType state() const
941  {
942  return d.states.empty() ? None : d.states.back().type;
943  }
944 
945  bool has_error() const
946  {
947  return !d.errors.empty();
948  }
949 
950  std::vector<Error> const &errors() const
951  {
952  return d.errors;
953  }
954 
955  bool is_start_object() const
956  {
957  return state() == StartObject;
958  }
959 
960  bool is_end_object() const
961  {
962  return state() == EndObject;
963  }
964 
965  bool is_start_array() const
966  {
967  return state() == StartArray;
968  }
969 
970  bool is_end_array() const
971  {
972  return state() == EndArray;
973  }
974 
975  bool isobject() const
976  {
977  switch (state()) {
978  case StartObject:
979  case StartArray:
980  return true;
981  case EndObject:
982  case EndArray:
983  if (d.states.size() > 1) {
984  auto s = d.states[d.states.size() - 2];
985  switch (s.type) {
986  case StartObject:
987  case StartArray:
988  return true;
989  }
990  }
991  break;
992  }
993  return false;
994  }
995 
996  bool isvalue() const
997  {
998  switch (state()) {
999  case String:
1000  case Number:
1001  case Null:
1002  case False:
1003  case True:
1004  return true;
1005  }
1006  return false;
1007  }
1008 
1009  std::string key() const
1010  {
1011  return d.key;
1012  }
1013 
1014  std::string string() const
1015  {
1016  return d.string;
1017  }
1018 
1020  {
1021  StateType s = state();
1022 
1023  switch (s) {
1024  case Null:
1025  case False:
1026  case True:
1027  return s;
1028  }
1029  return None;
1030  }
1031 
1032  bool isnull() const
1033  {
1034  return symbol() == Null;
1035  }
1036 
1037  bool isfalse() const
1038  {
1039  return symbol() == False;
1040  }
1041 
1042  bool istrue() const
1043  {
1044  return symbol() == True;
1045  }
1046 
1047  bool isnumber() const
1048  {
1049  return state() == Number;
1050  }
1051 
1052  bool isstring() const
1053  {
1054  return state() == String;
1055  }
1056 
1057  double number() const
1058  {
1059  return d.number;
1060  }
1061 
1062  bool isarray() const
1063  {
1064  return d.is_array;
1065  }
1066 
1067  int depth() const
1068  {
1069  return d.depth.size();
1070  }
1071 
1072  std::string path() const
1073  {
1074  std::string path;
1075  for (std::string const &s : d.depth) {
1076  path += s;
1077  }
1079  return path;
1080  }
1081  return path + d.key;
1082  }
1083 
1084  std::string_view raw()
1085  {
1086  if (d.last_state.ptr) {
1087  size_t n = d.ptr - d.last_state.ptr;
1088  return std::string_view(d.last_state.ptr, n);
1089  }
1090  return {};
1091  }
1092 
1093  bool match(char const *path, std::vector<std::string> *vals = nullptr, bool clear = true) const
1094  {
1095  if (vals && clear) {
1096  vals->clear();
1097  }
1098  if (!isobject() && !isarray() && !isvalue()) return false;
1099  size_t i;
1100  for (i = 0; i < d.depth.size(); i++) {
1101  std::string const &s = d.depth[i];
1102  if (s.empty()) break;
1103  if (path[0] == '*' && path[1] == '*' && path[2] == 0) {
1104  return true;
1105  }
1106  if (path[0] == '*' && s.c_str()[s.size() - 1] == '{') {
1107  if (path[1] == 0) {
1108  if (state() == StartObject) {
1109  if (i + 1 == d.depth.size()) {
1110  if (vals) {
1111  std::string t;
1112  while (i < d.depth.size()) {
1113  t += d.depth[i];
1114  i++;
1115  }
1116  if (isvalue()) {
1117  t += d.key;
1118  }
1119  vals->push_back(t);
1120  }
1121  return true;
1122  }
1123  }
1124  return false;
1125  } else if (path[1] == '{') {
1126  path += 2;
1127  continue;
1128  }
1129  }
1130  if (strncmp(path, s.c_str(), s.size()) != 0) return false;
1131  path += s.size();
1132  }
1133  if (path[0] == '*' && path[1] == '*' && path[2] == 0) {
1134  return true;
1135  }
1136  if (path[0] == '*') {
1137  if (path[1] == 0 && i == d.depth.size() && (isvalue() || state() == EndObject || state() == EndArray)) {
1138  if (vals) {
1139  std::string t;
1140  if (isvalue()) {
1141  t = d.key;
1142  }
1143  vals->push_back(t);
1144  }
1145  return true;
1146  }
1147  return false;
1148  }
1149  if (path == d.key) {
1150  if (vals && isvalue()) {
1151  vals->push_back(string());
1152  }
1153  return true;
1154  }
1155  return false;
1156  }
1157 
1158  bool match_start_object(char const *path) const
1159  {
1160  return state() == StartObject && match(path);
1161  }
1162 
1163  bool match_end_object(char const *path) const
1164  {
1165  return state() == EndObject && match(path);
1166  }
1167 
1168  bool match_start_array(char const *path) const
1169  {
1170  return state() == StartArray && match(path);
1171  }
1172 
1173  bool match_end_array(char const *path) const
1174  {
1175  return state() == EndArray && match(path);
1176  }
1177 };
1178 
1179 class Writer {
1180 protected:
1181  void print(char const *p, int n)
1182  {
1183  if (output_fn) {
1184  output_fn(p, n);
1185  } else {
1186  for (size_t i = 0; i < n; i++) {
1187  putchar(p[i]);
1188  }
1189  }
1190  }
1191 
1192  void print(char c)
1193  {
1194  print(&c, 1);
1195  }
1196 
1197  void print(char const *p)
1198  {
1199  print(p, strlen(p));
1200  }
1201 
1202  void print(std::string const &s)
1203  {
1204  print(s.c_str(), s.size());
1205  }
1206 private:
1207  std::vector<int> stack;
1208  std::function<void (char const *p, int n)> output_fn;
1209 
1210  bool enable_indent_ = true;
1211  bool enable_newline_ = true;
1212  bool allow_nan_ = false;
1213 
1215  {
1216  if (!enable_newline_) return;
1217 
1218  print('\n');
1219  }
1220 
1222  {
1223  if (!enable_indent_) return;
1224 
1225  size_t n = stack.size() - 1;
1226  for (size_t i = 0; i < n; i++) {
1227  print(' ');
1228  print(' ');
1229  }
1230  }
1231 
1232  bool print_number(double v)
1233  {
1234  std::string s = misc::format_double(v, allow_nan_);
1235  if (s.empty()) {
1236  print("null");
1237  return false;
1238  }
1239  print(s);
1240  return true;
1241  }
1242 
1243  void print_string(std::string const &s)
1244  {
1245  std::vector<char> buf = encode_json_string(s);
1246 
1247  print('\"');
1248  if (!buf.empty()) {
1249  print(buf.data(), buf.size());
1250  }
1251  print('\"');
1252  }
1253 
1254  bool print_value(std::string const &name, std::function<bool ()> const &fn)
1255  {
1256  print_name(name);
1257 
1258  bool ok = fn();
1259 
1260  if (!stack.empty()) stack.back()++;
1261 
1262  return ok;
1263  }
1264 
1265  void print_object(std::string const &name = {}, std::function<void ()> const &fn = {})
1266  {
1267  print_name(name);
1268  print('{');
1269  stack.push_back(0);
1270  if (fn) {
1271  fn();
1272  end_object();
1273  }
1274  }
1275 
1276  void print_array(std::string const &name = {}, std::function<void ()> const &fn = {})
1277  {
1278  print_name(name);
1279  print('[');
1280  stack.push_back(0);
1281  if (fn) {
1282  fn();
1283  end_array();
1284  }
1285  }
1286 
1287  void end_block()
1288  {
1289  print_newline();
1290  if (!stack.empty()) {
1291  stack.pop_back();
1292  if (!stack.empty()) stack.back()++;
1293  }
1294  print_indent();
1295  }
1296 public:
1297  Writer(std::function<void (char const *p, int n)> fn = {})
1298  {
1299  output_fn = fn;
1300  stack.push_back(0);
1301  }
1302 
1304  {
1305  if (!stack.empty() && stack.front() > 0) {
1306  print_newline();
1307  }
1308  }
1309 
1310  void enable_indent(bool enabled)
1311  {
1312  enable_indent_ = enabled;
1313  }
1314 
1315  void enable_newline(bool enabled)
1316  {
1317  enable_newline_ = enabled;
1318  }
1319 
1320  void allow_nan(bool allow)
1321  {
1322  allow_nan_ = allow;
1323  }
1324 
1325  void print_name(std::string const &name)
1326  {
1327  if (!stack.empty()) {
1328  if (stack.back() > 0) {
1329  print(',');
1330  }
1331  }
1332  if (stack.size() > 1) {
1333  print_newline();
1334  }
1335  print_indent();
1336  if (!name.empty()) {
1337  print_string(name);
1338  print(':');
1339  if (enable_indent_) {
1340  print(' ');
1341  }
1342  }
1343  }
1344 
1345  void start_object(std::string const &name = {})
1346  {
1347  print_object(name);
1348  }
1349 
1350  void end_object()
1351  {
1352  end_block();
1353  print('}');
1354  }
1355 
1356  void object(std::string const &name, std::function<void ()> const &fn)
1357  {
1358  print_object(name, fn);
1359  }
1360 
1361  void start_array(std::string const &name = {})
1362  {
1363  print_array(name, {});
1364  }
1365 
1366  void end_array()
1367  {
1368  end_block();
1369  print(']');
1370  }
1371 
1372  void array(std::string const &name, std::function<void ()> const &fn)
1373  {
1374  print_array(name, fn);
1375  }
1376 
1377  bool number(std::string const &name, double v)
1378  {
1379  return print_value(name, [&](){
1380  return print_number(v);
1381  });
1382  }
1383 
1384  void number(double v)
1385  {
1386  number({}, v);
1387  }
1388 
1389  void string(std::string const &name, std::string const &s)
1390  {
1391  print_value(name, [&](){
1392  print_string(s);
1393  return true;
1394  });
1395  }
1396 
1397  void string(std::string const &s)
1398  {
1399  string({}, s);
1400  }
1401 
1402  void symbol(std::string const &name, StateType v)
1403  {
1404  print_value(name, [&](){
1405  switch (v) {
1406  case False:
1407  print("false");
1408  break;
1409  case True:
1410  print("true");
1411  break;
1412  default:
1413  print("null");
1414  }
1415  return true;
1416  });
1417  }
1418 
1419  void boolean(std::string const &name, bool b)
1420  {
1421  symbol(name, b ? True : False);
1422  }
1423 
1424  void null()
1425  {
1426  symbol({}, Null);
1427  }
1428 };
1429 
1430 typedef std::nullptr_t null_t;
1431 constexpr std::nullptr_t null = nullptr;
1432 
1433 struct Array;
1434 struct KeyValue;
1435 typedef std::vector<KeyValue> _Object;
1436 typedef std::variant<null_t, bool, double, std::string, _Object, Array> Variant;
1437 struct Array {
1438  std::vector<Variant> a;
1439  size_t size() const
1440  {
1441  return a.size();
1442  }
1443  bool empty() const
1444  {
1445  return a.empty();
1446  }
1447  Variant &operator[](size_t i)
1448  {
1449  return a[i];
1450  }
1451  Variant const &operator[](size_t i) const
1452  {
1453  return a[i];
1454  }
1455  template <typename T> T &get(size_t i)
1456  {
1457  assert(i < a.size());
1458  return std::get<T>(a[i]);
1459  }
1460  template <typename T> T const &get(size_t i) const
1461  {
1462  assert(i < a.size());
1463  return std::get<T>(a[i]);
1464  }
1465  void push_back(Variant const &v)
1466  {
1467  a.push_back(v);
1468  }
1470  {
1471  push_back(v);
1472  return *this;
1473  }
1474 };
1475 struct KeyValue {
1476  std::string key;
1478  KeyValue() = default;
1479  KeyValue(std::string const &k, Variant const &v)
1480  : key(k), value(v)
1481  {
1482  }
1483 };
1484 struct VariantRef {
1487  : var(&v)
1488  {
1489  }
1490  void operator = (Variant const &v)
1491  {
1492  *var = v;
1493  }
1494  operator Variant &()
1495  {
1496  return *var;
1497  }
1498 };
1499 struct Object {
1501  Object() : p(nullptr)
1502  {
1503  }
1505  : p(&o)
1506  {
1507  }
1509  {
1510  if (!std::holds_alternative<_Object>(v)) {
1511  v = _Object();
1512  }
1513  p = &std::get<_Object>(v);
1514  }
1515  size_t size() const
1516  {
1517  return p ? p->size() : 0;
1518  }
1519  bool empty() const
1520  {
1521  return size() == 0;
1522  }
1523  Variant *find(std::string const &key)
1524  {
1525  if (p) {
1526  for (auto &kv : *p) {
1527  if (kv.key == key) {
1528  return &kv.value;
1529  }
1530  }
1531  }
1532  return nullptr;
1533  }
1534  Variant const *find(std::string const &key) const
1535  {
1536  return const_cast<Object *>(this)->find(key);
1537  }
1538  Variant &value(std::string const &key)
1539  {
1540  Variant *v = find(key);
1541  assert(v);
1542  return *v;
1543  }
1544  Variant const &value(std::string const &key) const
1545  {
1546  return const_cast<Object *>(this)->value(key);
1547  }
1548  template <typename T> T const &get(std::string const &key) const
1549  {
1550  Variant const *v = find(key);
1551  assert(v);
1552  return std::get<T>(*v);
1553  }
1554  VariantRef operator [] (std::string const &key)
1555  {
1556  p->emplace_back(key, Variant());
1557  return p->back().value;
1558  }
1559 };
1560 
1561 static inline bool is_null(Variant const &v)
1562 {
1563  return std::holds_alternative<null_t>(v);
1564 }
1565 static inline bool is_boolean(Variant const &v)
1566 {
1567  return std::holds_alternative<bool>(v);
1568 }
1569 static inline bool is_number(Variant const &v)
1570 {
1571  return std::holds_alternative<double>(v);
1572 }
1573 static inline bool is_string(Variant const &v)
1574 {
1575  return std::holds_alternative<std::string>(v);
1576 }
1577 static inline bool is_object(Variant const &v)
1578 {
1579  return std::holds_alternative<_Object>(v);
1580 }
1581 static inline bool is_array(Variant const &v)
1582 {
1583  return std::holds_alternative<Array>(v);
1584 }
1585 static inline bool is_nan(Variant const &v)
1586 {
1587  return std::holds_alternative<double>(v) && std::isnan(std::get<double>(v));
1588 }
1589 static inline bool is_infinite(Variant const &v)
1590 {
1591  return std::holds_alternative<double>(v) && std::isinf(std::get<double>(v));
1592 }
1593 static inline Array &arr(Array &a)
1594 {
1595  return a;
1596 }
1597 static inline Array &arr(Variant &v)
1598 {
1599  if (!std::holds_alternative<Array>(v)) {
1600  v = Array();
1601  }
1602  return std::get<Array>(v);
1603 }
1604 static inline Object obj(Variant &v)
1605 {
1606  if (!std::holds_alternative<_Object>(v)) {
1607  v = _Object();
1608  }
1609  return Object(std::get<_Object>(v));
1610 }
1611 
1612 static inline Variant var(jstream::Reader const &reader)
1613 {
1614  if (reader.isnull()) {
1615  return null;
1616  } else if (reader.isfalse()) {
1617  return false;
1618  } else if (reader.istrue()) {
1619  return true;
1620  } else if (reader.isnumber()) {
1621  return reader.number();
1622  } else if (reader.isstring()) {
1623  return reader.string();
1624  }
1625  return null;
1626 }
1627 
1628 using std::get;
1629 
1630 } // namespace jstream
1631 
1632 #endif // JSTREAM_H_
Definition: jstream.h:364
bool is_end_object() const
Definition: jstream.h:960
int depth() const
Definition: jstream.h:1067
bool isarray() const
Definition: jstream.h:1062
Reader(char const *begin, char const *end)
Definition: jstream.h:883
void allow_ambiguous_comma(bool allow)
Definition: jstream.h:895
void allow_hexadicimal(bool allow)
Definition: jstream.h:903
bool isnull() const
Definition: jstream.h:1032
bool is_end_array() const
Definition: jstream.h:970
ParserData d
Definition: jstream.h:617
bool has_error() const
Definition: jstream.h:945
bool pop_state()
Definition: jstream.h:650
static std::string to_stdstr(std::vector< char > const &vec)
Definition: jstream.h:371
bool isobject() const
Definition: jstream.h:975
bool match_start_object(char const *path) const
Definition: jstream.h:1158
bool match_end_array(char const *path) const
Definition: jstream.h:1173
double number() const
Definition: jstream.h:1057
void parse(char const *ptr, int len=-1)
Definition: jstream.h:692
bool isfalse() const
Definition: jstream.h:1037
void allow_comment(bool allow)
Definition: jstream.h:891
void hold()
Definition: jstream.h:915
bool istrue() const
Definition: jstream.h:1042
std::string path() const
Definition: jstream.h:1072
bool match_start_array(char const *path) const
Definition: jstream.h:1168
void push_error(std::string const &what)
Definition: jstream.h:619
std::vector< Error > const & errors() const
Definition: jstream.h:950
std::string_view raw()
Definition: jstream.h:1084
std::string key() const
Definition: jstream.h:1009
bool is_start_object() const
Definition: jstream.h:955
int scan_space(char const *begin, char const *end)
Definition: jstream.h:381
void reset()
Definition: jstream.h:911
int parse_number(char const *begin, char const *end, double *out)
Definition: jstream.h:432
bool isvalue() const
Definition: jstream.h:996
Reader(char const *ptr, int len=-1)
Definition: jstream.h:887
void parse(std::string_view const &sv)
Definition: jstream.h:687
void allow_unquoted_key(bool allow)
Definition: jstream.h:899
void push_state(StateItem s)
Definition: jstream.h:628
std::string string() const
Definition: jstream.h:1014
bool match_end_object(char const *path) const
Definition: jstream.h:1163
Reader(std::string_view const &sv)
Definition: jstream.h:879
bool _internal_next()
Definition: jstream.h:700
bool is_start_array() const
Definition: jstream.h:965
StateType state() const
Definition: jstream.h:940
int parse_symbol(char const *begin, char const *end, std::string *out)
Definition: jstream.h:414
bool isstring() const
Definition: jstream.h:1052
bool match(char const *path, std::vector< std::string > *vals=nullptr, bool clear=true) const
Definition: jstream.h:1093
bool isnumber() const
Definition: jstream.h:1047
void nest()
Definition: jstream.h:919
StateType symbol() const
Definition: jstream.h:1019
bool next()
Definition: jstream.h:923
void parse(char const *begin, char const *end)
Definition: jstream.h:678
int parse_string(char const *begin, char const *end, std::string *out)
Definition: jstream.h:504
void allow_special_constant(bool allow)
Definition: jstream.h:907
Definition: jstream.h:1179
void end_block()
Definition: jstream.h:1287
bool allow_nan_
Definition: jstream.h:1212
void print_string(std::string const &s)
Definition: jstream.h:1243
void array(std::string const &name, std::function< void()> const &fn)
Definition: jstream.h:1372
void boolean(std::string const &name, bool b)
Definition: jstream.h:1419
void symbol(std::string const &name, StateType v)
Definition: jstream.h:1402
void object(std::string const &name, std::function< void()> const &fn)
Definition: jstream.h:1356
std::vector< int > stack
Definition: jstream.h:1207
void print_indent()
Definition: jstream.h:1221
void string(std::string const &s)
Definition: jstream.h:1397
void start_object(std::string const &name={})
Definition: jstream.h:1345
void allow_nan(bool allow)
Definition: jstream.h:1320
void string(std::string const &name, std::string const &s)
Definition: jstream.h:1389
Writer(std::function< void(char const *p, int n)> fn={})
Definition: jstream.h:1297
bool number(std::string const &name, double v)
Definition: jstream.h:1377
void print(char c)
Definition: jstream.h:1192
bool print_value(std::string const &name, std::function< bool()> const &fn)
Definition: jstream.h:1254
void end_array()
Definition: jstream.h:1366
void number(double v)
Definition: jstream.h:1384
bool print_number(double v)
Definition: jstream.h:1232
void print(std::string const &s)
Definition: jstream.h:1202
void print_name(std::string const &name)
Definition: jstream.h:1325
void enable_newline(bool enabled)
Definition: jstream.h:1315
void print_array(std::string const &name={}, std::function< void()> const &fn={})
Definition: jstream.h:1276
void print(char const *p)
Definition: jstream.h:1197
bool enable_indent_
Definition: jstream.h:1210
~Writer()
Definition: jstream.h:1303
void start_array(std::string const &name={})
Definition: jstream.h:1361
bool enable_newline_
Definition: jstream.h:1211
void end_object()
Definition: jstream.h:1350
void print(char const *p, int n)
Definition: jstream.h:1181
std::function< void(char const *p, int n)> output_fn
Definition: jstream.h:1208
void print_newline()
Definition: jstream.h:1214
void print_object(std::string const &name={}, std::function< void()> const &fn={})
Definition: jstream.h:1265
void enable_indent(bool enabled)
Definition: jstream.h:1310
Definition: jstream.h:77
static std::string format_double(double val, bool allow_nan)
Definition: jstream.h:209
static double pow10_int(int exp)
Return 10 raised to an integer power.
Definition: jstream.h:89
static double my_strtod(const char *nptr, char **endptr)
Locale‑independent strtod clone.
Definition: jstream.h:120
Definition: jstream.h:16
static bool is_infinite(Variant const &v)
Definition: jstream.h:1589
static Variant var(jstream::Reader const &reader)
Definition: jstream.h:1612
static bool is_nan(Variant const &v)
Definition: jstream.h:1585
static bool is_null(Variant const &v)
Definition: jstream.h:1561
std::vector< KeyValue > _Object
Definition: jstream.h:1434
static bool is_boolean(Variant const &v)
Definition: jstream.h:1565
static Object obj(Variant &v)
Definition: jstream.h:1604
std::variant< null_t, bool, double, std::string, _Object, Array > Variant
Definition: jstream.h:1436
static bool is_object(Variant const &v)
Definition: jstream.h:1577
StateType
Definition: jstream.h:347
@ Null
Definition: jstream.h:350
@ String
Definition: jstream.h:360
@ EndObject
Definition: jstream.h:357
@ Comma
Definition: jstream.h:355
@ StartObject
Definition: jstream.h:356
@ EndArray
Definition: jstream.h:359
@ True
Definition: jstream.h:352
@ Number
Definition: jstream.h:361
@ StartArray
Definition: jstream.h:358
@ Key
Definition: jstream.h:354
@ False
Definition: jstream.h:351
@ None
Definition: jstream.h:349
static Array & arr(Array &a)
Definition: jstream.h:1593
static bool is_array(Variant const &v)
Definition: jstream.h:1581
static std::vector< char > encode_json_string(std::string_view const &in)
Definition: jstream.h:18
static bool is_number(Variant const &v)
Definition: jstream.h:1569
std::nullptr_t null_t
Definition: jstream.h:1430
static bool is_string(Variant const &v)
Definition: jstream.h:1573
Definition: jstream.h:1437
Variant const & operator[](size_t i) const
Definition: jstream.h:1451
Array & operator+=(Variant const &v)
Definition: jstream.h:1469
bool empty() const
Definition: jstream.h:1443
T & get(size_t i)
Definition: jstream.h:1455
Variant & operator[](size_t i)
Definition: jstream.h:1447
void push_back(Variant const &v)
Definition: jstream.h:1465
size_t size() const
Definition: jstream.h:1439
T const & get(size_t i) const
Definition: jstream.h:1460
std::vector< Variant > a
Definition: jstream.h:1438
Definition: jstream.h:1475
KeyValue(std::string const &k, Variant const &v)
Definition: jstream.h:1479
Variant value
Definition: jstream.h:1477
KeyValue()=default
std::string key
Definition: jstream.h:1476
Definition: jstream.h:1499
size_t size() const
Definition: jstream.h:1515
Object(Variant &v)
Definition: jstream.h:1508
Variant & value(std::string const &key)
Definition: jstream.h:1538
Variant const * find(std::string const &key) const
Definition: jstream.h:1534
Variant const & value(std::string const &key) const
Definition: jstream.h:1544
_Object * p
Definition: jstream.h:1500
Object(_Object &o)
Definition: jstream.h:1504
Object()
Definition: jstream.h:1501
T const & get(std::string const &key) const
Definition: jstream.h:1548
VariantRef operator[](std::string const &key)
Definition: jstream.h:1554
bool empty() const
Definition: jstream.h:1519
Variant * find(std::string const &key)
Definition: jstream.h:1523
Definition: jstream.h:366
std::string what_
Definition: jstream.h:367
std::string what() const
Definition: jstream.h:368
Definition: jstream.h:597
bool allow_comment
Definition: jstream.h:607
std::vector< Error > errors
Definition: jstream.h:615
std::vector< std::string > depth
Definition: jstream.h:612
bool allow_ambiguous_comma
Definition: jstream.h:608
char const * ptr
Definition: jstream.h:600
bool allow_unquoted_key
Definition: jstream.h:609
bool is_array
Definition: jstream.h:606
bool allow_special_constant
Definition: jstream.h:611
StateItem last_state
Definition: jstream.h:614
std::string string
Definition: jstream.h:604
std::vector< StateItem > states
Definition: jstream.h:601
bool hold
Definition: jstream.h:602
std::vector< int > depth_stack
Definition: jstream.h:613
bool allow_hexadicimal
Definition: jstream.h:610
double number
Definition: jstream.h:605
char const * begin
Definition: jstream.h:598
char const * end
Definition: jstream.h:599
std::string key
Definition: jstream.h:603
Definition: jstream.h:587
StateType type
Definition: jstream.h:588
char const * ptr
Definition: jstream.h:589
StateItem(StateType type, char const *ptr=nullptr)
Definition: jstream.h:591
Definition: jstream.h:1484
Variant * var
Definition: jstream.h:1485
void operator=(Variant const &v)
Definition: jstream.h:1490
VariantRef(Variant &v)
Definition: jstream.h:1486