WSL/SLF GitLab Repository

picojson.h 32.3 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
/*
 * Copyright 2009-2010 Cybozu Labs, Inc.
 * Copyright 2011-2014 Kazuho Oku
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
#ifndef picojson_h
#define picojson_h

#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cstddef>
#include <iostream>
#include <iterator>
#include <limits>
#include <map>
#include <stdexcept>
#include <string>
#include <vector>
#include <utility>

// for isnan/isinf
46
47
#if __cplusplus >= 201103L
#include <cmath>
48
49
#else
extern "C" {
50
51
52
53
54
55
56
#ifdef _MSC_VER
#include <float.h>
#elif defined(__INTEL_COMPILER)
#include <mathimf.h>
#else
#include <math.h>
#endif
57
58
59
60
}
#endif

#ifndef PICOJSON_USE_RVALUE_REFERENCE
61
62
63
64
65
66
#if (defined(__cpp_rvalue_references) && __cpp_rvalue_references >= 200610) || (defined(_MSC_VER) && _MSC_VER >= 1600)
#define PICOJSON_USE_RVALUE_REFERENCE 1
#else
#define PICOJSON_USE_RVALUE_REFERENCE 0
#endif
#endif // PICOJSON_USE_RVALUE_REFERENCE
67
68
69

// experimental support for int64_t (see README.mkdn for detail)
#ifdef PICOJSON_USE_INT64
70
71
72
#define __STDC_FORMAT_MACROS
#include <errno.h>
#include <inttypes.h>
73
74
75
76
#endif

// to disable the use of localeconv(3), set PICOJSON_USE_LOCALE to 0
#ifndef PICOJSON_USE_LOCALE
77
#define PICOJSON_USE_LOCALE 1
78
79
80
#endif
#if PICOJSON_USE_LOCALE
extern "C" {
81
#include <locale.h>
82
83
84
85
}
#endif

#ifndef PICOJSON_ASSERT
86
87
88
89
90
#define PICOJSON_ASSERT(e)                                                                                                         \
  do {                                                                                                                             \
    if (!(e))                                                                                                                      \
      throw std::runtime_error(#e);                                                                                                \
  } while (0)
91
92
93
#endif

#ifdef _MSC_VER
94
95
96
97
98
#define SNPRINTF _snprintf_s
#pragma warning(push)
#pragma warning(disable : 4244) // conversion from int to char
#pragma warning(disable : 4127) // conditional expression is constant
#pragma warning(disable : 4702) // unreachable code
99
#else
100
#define SNPRINTF snprintf
101
102
103
104
#endif

namespace picojson {

105
106
107
108
109
110
111
enum {
  null_type,
  boolean_type,
  number_type,
  string_type,
  array_type,
  object_type
112
#ifdef PICOJSON_USE_INT64
113
114
  ,
  int64_type
115
#endif
116
};
117

118
enum { INDENT_WIDTH = 2 };
119

120
struct null {};
121

122
123
124
125
126
127
128
class value {
public:
  typedef std::vector<value> array;
  typedef std::map<std::string, value> object;
  union _storage {
    bool boolean_;
    double number_;
129
#ifdef PICOJSON_USE_INT64
130
    int64_t int64_;
131
#endif
132
133
134
135
136
137
138
139
140
141
142
143
144
    std::string *string_;
    array *array_;
    object *object_;
  };

protected:
  int type_;
  _storage u_;

public:
  value();
  value(int type, bool);
  explicit value(bool b);
145
#ifdef PICOJSON_USE_INT64
146
  explicit value(int64_t i);
147
#endif
148
149
150
151
  explicit value(double n);
  explicit value(const std::string &s);
  explicit value(const array &a);
  explicit value(const object &o);
152
#if PICOJSON_USE_RVALUE_REFERENCE
153
154
155
  explicit value(std::string &&s);
  explicit value(array &&a);
  explicit value(object &&o);
156
#endif
157
158
159
160
161
  explicit value(const char *s);
  value(const char *s, size_t len);
  ~value();
  value(const value &x);
  value &operator=(const value &x);
162
#if PICOJSON_USE_RVALUE_REFERENCE
163
164
  value(value &&x) throw();
  value &operator=(value &&x) throw();
165
#endif
166
167
168
169
170
  void swap(value &x) throw();
  template <typename T> bool is() const;
  template <typename T> const T &get() const;
  template <typename T> T &get();
  template <typename T> void set(const T &);
171
#if PICOJSON_USE_RVALUE_REFERENCE
172
  template <typename T> void set(T &&);
173
#endif
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
  bool evaluate_as_boolean() const;
  const value &get(const size_t idx) const;
  const value &get(const std::string &key) const;
  value &get(const size_t idx);
  value &get(const std::string &key);

  bool contains(const size_t idx) const;
  bool contains(const std::string &key) const;
  std::string to_str() const;
  template <typename Iter> void serialize(Iter os, bool prettify = false) const;
  std::string serialize(bool prettify = false) const;

private:
  template <typename T> value(const T *); // intentionally defined to block implicit conversion of pointer to bool
  template <typename Iter> static void _indent(Iter os, int indent);
  template <typename Iter> void _serialize(Iter os, int indent) const;
  std::string _serialize(int indent) const;
  void clear();
};

typedef value::array array;
typedef value::object object;

inline value::value() : type_(null_type), u_() {
}
199

200
201
202
203
204
205
206
207
inline value::value(int type, bool) : type_(type), u_() {
  switch (type) {
#define INIT(p, v)                                                                                                                 \
  case p##type:                                                                                                                    \
    u_.p = v;                                                                                                                      \
    break
    INIT(boolean_, false);
    INIT(number_, 0.0);
208
#ifdef PICOJSON_USE_INT64
209
    INIT(int64_, 0);
210
#endif
211
212
213
    INIT(string_, new std::string());
    INIT(array_, new array());
    INIT(object_, new object());
214
#undef INIT
215
216
  default:
    break;
217
  }
218
}
219

220
221
222
inline value::value(bool b) : type_(boolean_type), u_() {
  u_.boolean_ = b;
}
223
224

#ifdef PICOJSON_USE_INT64
225
226
227
inline value::value(int64_t i) : type_(int64_type), u_() {
  u_.int64_ = i;
}
228
229
#endif

230
231
inline value::value(double n) : type_(number_type), u_() {
  if (
232
#ifdef _MSC_VER
233
234
235
      !_finite(n)
#elif __cplusplus >= 201103L || !(defined(isnan) && defined(isinf))
      std::isnan(n) || std::isinf(n)
236
#else
237
      isnan(n) || isinf(n)
238
#endif
239
240
          ) {
    throw std::overflow_error("");
241
  }
242
243
  u_.number_ = n;
}
244

245
246
247
inline value::value(const std::string &s) : type_(string_type), u_() {
  u_.string_ = new std::string(s);
}
248

249
250
251
inline value::value(const array &a) : type_(array_type), u_() {
  u_.array_ = new array(a);
}
252

253
254
255
inline value::value(const object &o) : type_(object_type), u_() {
  u_.object_ = new object(o);
}
256
257

#if PICOJSON_USE_RVALUE_REFERENCE
258
259
260
inline value::value(std::string &&s) : type_(string_type), u_() {
  u_.string_ = new std::string(std::move(s));
}
261

262
263
264
inline value::value(array &&a) : type_(array_type), u_() {
  u_.array_ = new array(std::move(a));
}
265

266
267
268
inline value::value(object &&o) : type_(object_type), u_() {
  u_.object_ = new object(std::move(o));
}
269
270
#endif

271
272
273
inline value::value(const char *s) : type_(string_type), u_() {
  u_.string_ = new std::string(s);
}
274

275
276
277
inline value::value(const char *s, size_t len) : type_(string_type), u_() {
  u_.string_ = new std::string(s, len);
}
278

279
280
281
282
283
284
285
286
287
inline void value::clear() {
  switch (type_) {
#define DEINIT(p)                                                                                                                  \
  case p##type:                                                                                                                    \
    delete u_.p;                                                                                                                   \
    break
    DEINIT(string_);
    DEINIT(array_);
    DEINIT(object_);
288
#undef DEINIT
289
290
  default:
    break;
291
  }
292
}
293

294
295
296
inline value::~value() {
  clear();
}
297

298
299
300
301
302
303
304
305
306
inline value::value(const value &x) : type_(x.type_), u_() {
  switch (type_) {
#define INIT(p, v)                                                                                                                 \
  case p##type:                                                                                                                    \
    u_.p = v;                                                                                                                      \
    break
    INIT(string_, new std::string(*x.u_.string_));
    INIT(array_, new array(*x.u_.array_));
    INIT(object_, new object(*x.u_.object_));
307
#undef INIT
308
309
310
  default:
    u_ = x.u_;
    break;
311
  }
312
}
313

314
315
316
317
inline value &value::operator=(const value &x) {
  if (this != &x) {
    value t(x);
    swap(t);
318
  }
319
320
  return *this;
}
321
322

#if PICOJSON_USE_RVALUE_REFERENCE
323
324
325
326
327
328
329
inline value::value(value &&x) throw() : type_(null_type), u_() {
  swap(x);
}
inline value &value::operator=(value &&x) throw() {
  swap(x);
  return *this;
}
330
#endif
331
332
333
334
inline void value::swap(value &x) throw() {
  std::swap(type_, x.type_);
  std::swap(u_, x.u_);
}
335

336
337
338
#define IS(ctype, jtype)                                                                                                           \
  template <> inline bool value::is<ctype>() const {                                                                               \
    return type_ == jtype##_type;                                                                                                  \
339
  }
340
341
IS(null, null)
IS(bool, boolean)
342
#ifdef PICOJSON_USE_INT64
343
IS(int64_t, int64)
344
#endif
345
346
347
IS(std::string, string)
IS(array, array)
IS(object, object)
348
#undef IS
349
350
template <> inline bool value::is<double>() const {
  return type_ == number_type
351
#ifdef PICOJSON_USE_INT64
352
         || type_ == int64_type
353
354
#endif
      ;
355
}
356

357
358
359
360
361
362
363
364
365
366
367
368
369
#define GET(ctype, var)                                                                                                            \
  template <> inline const ctype &value::get<ctype>() const {                                                                      \
    PICOJSON_ASSERT("type mismatch! call is<type>() before get<type>()" && is<ctype>());                                           \
    return var;                                                                                                                    \
  }                                                                                                                                \
  template <> inline ctype &value::get<ctype>() {                                                                                  \
    PICOJSON_ASSERT("type mismatch! call is<type>() before get<type>()" && is<ctype>());                                           \
    return var;                                                                                                                    \
  }
GET(bool, u_.boolean_)
GET(std::string, *u_.string_)
GET(array, *u_.array_)
GET(object, *u_.object_)
370
#ifdef PICOJSON_USE_INT64
371
372
373
374
GET(double,
    (type_ == int64_type && (const_cast<value *>(this)->type_ = number_type, const_cast<value *>(this)->u_.number_ = u_.int64_),
     u_.number_))
GET(int64_t, u_.int64_)
375
#else
376
GET(double, u_.number_)
377
378
379
#endif
#undef GET

380
381
382
383
384
385
386
387
388
389
390
#define SET(ctype, jtype, setter)                                                                                                  \
  template <> inline void value::set<ctype>(const ctype &_val) {                                                                   \
    clear();                                                                                                                       \
    type_ = jtype##_type;                                                                                                          \
    setter                                                                                                                         \
  }
SET(bool, boolean, u_.boolean_ = _val;)
SET(std::string, string, u_.string_ = new std::string(_val);)
SET(array, array, u_.array_ = new array(_val);)
SET(object, object, u_.object_ = new object(_val);)
SET(double, number, u_.number_ = _val;)
391
#ifdef PICOJSON_USE_INT64
392
SET(int64_t, int64, u_.int64_ = _val;)
393
394
395
396
#endif
#undef SET

#if PICOJSON_USE_RVALUE_REFERENCE
397
398
399
400
401
402
403
404
405
#define MOVESET(ctype, jtype, setter)                                                                                              \
  template <> inline void value::set<ctype>(ctype && _val) {                                                                       \
    clear();                                                                                                                       \
    type_ = jtype##_type;                                                                                                          \
    setter                                                                                                                         \
  }
MOVESET(std::string, string, u_.string_ = new std::string(std::move(_val));)
MOVESET(array, array, u_.array_ = new array(std::move(_val));)
MOVESET(object, object, u_.object_ = new object(std::move(_val));)
406
407
408
#undef MOVESET
#endif

409
410
411
412
413
414
415
416
inline bool value::evaluate_as_boolean() const {
  switch (type_) {
  case null_type:
    return false;
  case boolean_type:
    return u_.boolean_;
  case number_type:
    return u_.number_ != 0;
417
#ifdef PICOJSON_USE_INT64
418
419
  case int64_type:
    return u_.int64_ != 0;
420
#endif
421
422
423
424
  case string_type:
    return !u_.string_->empty();
  default:
    return true;
425
  }
426
}
427

428
429
430
431
432
inline const value &value::get(const size_t idx) const {
  static value s_null;
  PICOJSON_ASSERT(is<array>());
  return idx < u_.array_->size() ? (*u_.array_)[idx] : s_null;
}
433

434
435
436
437
438
inline value &value::get(const size_t idx) {
  static value s_null;
  PICOJSON_ASSERT(is<array>());
  return idx < u_.array_->size() ? (*u_.array_)[idx] : s_null;
}
439

440
441
442
443
444
445
inline const value &value::get(const std::string &key) const {
  static value s_null;
  PICOJSON_ASSERT(is<object>());
  object::const_iterator i = u_.object_->find(key);
  return i != u_.object_->end() ? i->second : s_null;
}
446

447
448
449
450
451
452
inline value &value::get(const std::string &key) {
  static value s_null;
  PICOJSON_ASSERT(is<object>());
  object::iterator i = u_.object_->find(key);
  return i != u_.object_->end() ? i->second : s_null;
}
453

454
455
456
457
inline bool value::contains(const size_t idx) const {
  PICOJSON_ASSERT(is<array>());
  return idx < u_.array_->size();
}
458

459
460
461
462
463
inline bool value::contains(const std::string &key) const {
  PICOJSON_ASSERT(is<object>());
  object::const_iterator i = u_.object_->find(key);
  return i != u_.object_->end();
}
464

465
466
467
468
469
470
inline std::string value::to_str() const {
  switch (type_) {
  case null_type:
    return "null";
  case boolean_type:
    return u_.boolean_ ? "true" : "false";
471
#ifdef PICOJSON_USE_INT64
472
473
474
475
476
  case int64_type: {
    char buf[sizeof("-9223372036854775808")];
    SNPRINTF(buf, sizeof(buf), "%" PRId64, u_.int64_);
    return buf;
  }
477
#endif
478
479
480
481
  case number_type: {
    char buf[256];
    double tmp;
    SNPRINTF(buf, sizeof(buf), fabs(u_.number_) < (1ULL << 53) && modf(u_.number_, &tmp) == 0 ? "%.f" : "%.17g", u_.number_);
482
#if PICOJSON_USE_LOCALE
483
484
485
486
487
488
    char *decimal_point = localeconv()->decimal_point;
    if (strcmp(decimal_point, ".") != 0) {
      size_t decimal_point_len = strlen(decimal_point);
      for (char *p = buf; *p != '\0'; ++p) {
        if (strncmp(p, decimal_point, decimal_point_len) == 0) {
          return std::string(buf, p) + "." + (p + decimal_point_len);
489
490
491
        }
      }
    }
492
493
494
495
496
497
498
499
500
501
502
#endif
    return buf;
  }
  case string_type:
    return *u_.string_;
  case array_type:
    return "array";
  case object_type:
    return "object";
  default:
    PICOJSON_ASSERT(0);
503
#ifdef _MSC_VER
504
    __assume(0);
505
#endif
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
  }
  return std::string();
}

template <typename Iter> void copy(const std::string &s, Iter oi) {
  std::copy(s.begin(), s.end(), oi);
}

template <typename Iter> struct serialize_str_char {
  Iter oi;
  void operator()(char c) {
    switch (c) {
#define MAP(val, sym)                                                                                                              \
  case val:                                                                                                                        \
    copy(sym, oi);                                                                                                                 \
    break
      MAP('"', "\\\"");
      MAP('\\', "\\\\");
      MAP('/', "\\/");
      MAP('\b', "\\b");
      MAP('\f', "\\f");
      MAP('\n', "\\n");
      MAP('\r', "\\r");
      MAP('\t', "\\t");
530
#undef MAP
531
532
533
534
535
536
537
    default:
      if (static_cast<unsigned char>(c) < 0x20 || c == 0x7f) {
        char buf[7];
        SNPRINTF(buf, sizeof(buf), "\\u%04x", c & 0xff);
        copy(buf, buf + 6, oi);
      } else {
        *oi++ = c;
538
      }
539
      break;
540
541
    }
  }
542
};
543

544
545
546
547
548
549
template <typename Iter> void serialize_str(const std::string &s, Iter oi) {
  *oi++ = '"';
  serialize_str_char<Iter> process_char = {oi};
  std::for_each(s.begin(), s.end(), process_char);
  *oi++ = '"';
}
550

551
552
553
template <typename Iter> void value::serialize(Iter oi, bool prettify) const {
  return _serialize(oi, prettify ? 0 : -1);
}
554

555
556
557
558
559
560
561
562
inline std::string value::serialize(bool prettify) const {
  return _serialize(prettify ? 0 : -1);
}

template <typename Iter> void value::_indent(Iter oi, int indent) {
  *oi++ = '\n';
  for (int i = 0; i < indent * INDENT_WIDTH; ++i) {
    *oi++ = ' ';
563
  }
564
}
565

566
567
568
569
570
571
572
573
574
575
576
577
578
template <typename Iter> void value::_serialize(Iter oi, int indent) const {
  switch (type_) {
  case string_type:
    serialize_str(*u_.string_, oi);
    break;
  case array_type: {
    *oi++ = '[';
    if (indent != -1) {
      ++indent;
    }
    for (array::const_iterator i = u_.array_->begin(); i != u_.array_->end(); ++i) {
      if (i != u_.array_->begin()) {
        *oi++ = ',';
579
580
      }
      if (indent != -1) {
581
        _indent(oi, indent);
582
      }
583
      i->_serialize(oi, indent);
584
    }
585
586
587
588
    if (indent != -1) {
      --indent;
      if (!u_.array_->empty()) {
        _indent(oi, indent);
589
      }
590
591
592
593
594
595
596
597
598
599
600
601
    }
    *oi++ = ']';
    break;
  }
  case object_type: {
    *oi++ = '{';
    if (indent != -1) {
      ++indent;
    }
    for (object::const_iterator i = u_.object_->begin(); i != u_.object_->end(); ++i) {
      if (i != u_.object_->begin()) {
        *oi++ = ',';
602
603
      }
      if (indent != -1) {
604
        _indent(oi, indent);
605
      }
606
607
608
609
610
611
      serialize_str(i->first, oi);
      *oi++ = ':';
      if (indent != -1) {
        *oi++ = ' ';
      }
      i->second._serialize(oi, indent);
612
    }
613
614
615
616
617
    if (indent != -1) {
      --indent;
      if (!u_.object_->empty()) {
        _indent(oi, indent);
      }
618
    }
619
620
    *oi++ = '}';
    break;
621
  }
622
623
624
625
626
627
  default:
    copy(to_str(), oi);
    break;
  }
  if (indent == 0) {
    *oi++ = '\n';
628
  }
629
}
630

631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
inline std::string value::_serialize(int indent) const {
  std::string s;
  _serialize(std::back_inserter(s), indent);
  return s;
}

template <typename Iter> class input {
protected:
  Iter cur_, end_;
  bool consumed_;
  int line_;

public:
  input(const Iter &first, const Iter &last) : cur_(first), end_(last), consumed_(false), line_(1) {
  }
  int getc() {
    if (consumed_) {
      if (*cur_ == '\n') {
        ++line_;
650
      }
651
      ++cur_;
652
    }
653
    if (cur_ == end_) {
654
      consumed_ = false;
655
      return -1;
656
    }
657
658
659
660
661
662
663
664
665
666
667
    consumed_ = true;
    return *cur_ & 0xff;
  }
  void ungetc() {
    consumed_ = false;
  }
  Iter cur() const {
    if (consumed_) {
      input<Iter> *self = const_cast<input<Iter> *>(this);
      self->consumed_ = false;
      ++self->cur_;
668
    }
669
670
671
672
673
674
675
676
677
678
679
    return cur_;
  }
  int line() const {
    return line_;
  }
  void skip_ws() {
    while (1) {
      int ch = getc();
      if (!(ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r')) {
        ungetc();
        break;
680
681
      }
    }
682
683
684
685
686
687
  }
  bool expect(const int expected) {
    skip_ws();
    if (getc() != expected) {
      ungetc();
      return false;
688
    }
689
690
691
692
693
694
695
    return true;
  }
  bool match(const std::string &pattern) {
    for (std::string::const_iterator pi(pattern.begin()); pi != pattern.end(); ++pi) {
      if (getc() != *pi) {
        ungetc();
        return false;
696
697
      }
    }
698
699
700
    return true;
  }
};
701

702
703
704
705
706
template <typename Iter> inline int _parse_quadhex(input<Iter> &in) {
  int uni_ch = 0, hex;
  for (int i = 0; i < 4; i++) {
    if ((hex = in.getc()) == -1) {
      return -1;
707
    }
708
709
710
711
712
713
714
715
716
717
718
    if ('0' <= hex && hex <= '9') {
      hex -= '0';
    } else if ('A' <= hex && hex <= 'F') {
      hex -= 'A' - 0xa;
    } else if ('a' <= hex && hex <= 'f') {
      hex -= 'a' - 0xa;
    } else {
      in.ungetc();
      return -1;
    }
    uni_ch = uni_ch * 16 + hex;
719
  }
720
721
  return uni_ch;
}
722

723
724
725
726
727
728
729
730
template <typename String, typename Iter> inline bool _parse_codepoint(String &out, input<Iter> &in) {
  int uni_ch;
  if ((uni_ch = _parse_quadhex(in)) == -1) {
    return false;
  }
  if (0xd800 <= uni_ch && uni_ch <= 0xdfff) {
    if (0xdc00 <= uni_ch) {
      // a second 16-bit of a surrogate pair appeared
731
732
      return false;
    }
733
734
735
736
737
738
739
740
    // first 16-bit of surrogate pair, get the next one
    if (in.getc() != '\\' || in.getc() != 'u') {
      in.ungetc();
      return false;
    }
    int second = _parse_quadhex(in);
    if (!(0xdc00 <= second && second <= 0xdfff)) {
      return false;
741
    }
742
743
744
745
746
747
748
749
    uni_ch = ((uni_ch - 0xd800) << 10) | ((second - 0xdc00) & 0x3ff);
    uni_ch += 0x10000;
  }
  if (uni_ch < 0x80) {
    out.push_back(static_cast<char>(uni_ch));
  } else {
    if (uni_ch < 0x800) {
      out.push_back(static_cast<char>(0xc0 | (uni_ch >> 6)));
750
    } else {
751
752
      if (uni_ch < 0x10000) {
        out.push_back(static_cast<char>(0xe0 | (uni_ch >> 12)));
753
      } else {
754
755
        out.push_back(static_cast<char>(0xf0 | (uni_ch >> 18)));
        out.push_back(static_cast<char>(0x80 | ((uni_ch >> 12) & 0x3f)));
756
      }
757
      out.push_back(static_cast<char>(0x80 | ((uni_ch >> 6) & 0x3f)));
758
    }
759
    out.push_back(static_cast<char>(0x80 | (uni_ch & 0x3f)));
760
  }
761
762
  return true;
}
763

764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
template <typename String, typename Iter> inline bool _parse_string(String &out, input<Iter> &in) {
  while (1) {
    int ch = in.getc();
    if (ch < ' ') {
      in.ungetc();
      return false;
    } else if (ch == '"') {
      return true;
    } else if (ch == '\\') {
      if ((ch = in.getc()) == -1) {
        return false;
      }
      switch (ch) {
#define MAP(sym, val)                                                                                                              \
  case sym:                                                                                                                        \
    out.push_back(val);                                                                                                            \
    break
        MAP('"', '\"');
        MAP('\\', '\\');
        MAP('/', '/');
        MAP('b', '\b');
        MAP('f', '\f');
        MAP('n', '\n');
        MAP('r', '\r');
        MAP('t', '\t');
789
#undef MAP
790
791
792
793
794
795
796
      case 'u':
        if (!_parse_codepoint(out, in)) {
          return false;
        }
        break;
      default:
        return false;
797
      }
798
799
    } else {
      out.push_back(static_cast<char>(ch));
800
801
    }
  }
802
803
  return false;
}
804

805
806
807
808
809
810
811
812
813
814
template <typename Context, typename Iter> inline bool _parse_array(Context &ctx, input<Iter> &in) {
  if (!ctx.parse_array_start()) {
    return false;
  }
  size_t idx = 0;
  if (in.expect(']')) {
    return ctx.parse_array_stop(idx);
  }
  do {
    if (!ctx.parse_array_item(in, idx)) {
815
816
      return false;
    }
817
818
819
820
    idx++;
  } while (in.expect(','));
  return in.expect(']') && ctx.parse_array_stop(idx);
}
821

822
823
824
825
826
827
828
829
830
831
template <typename Context, typename Iter> inline bool _parse_object(Context &ctx, input<Iter> &in) {
  if (!ctx.parse_object_start()) {
    return false;
  }
  if (in.expect('}')) {
    return true;
  }
  do {
    std::string key;
    if (!in.expect('"') || !_parse_string(key, in) || !in.expect(':')) {
832
833
      return false;
    }
834
835
    if (!ctx.parse_object_item(in, key)) {
      return false;
836
    }
837
838
839
  } while (in.expect(','));
  return in.expect('}');
}
840

841
842
843
844
845
846
847
template <typename Iter> inline std::string _parse_number(input<Iter> &in) {
  std::string num_str;
  while (1) {
    int ch = in.getc();
    if (('0' <= ch && ch <= '9') || ch == '+' || ch == '-' || ch == 'e' || ch == 'E') {
      num_str.push_back(static_cast<char>(ch));
    } else if (ch == '.') {
848
#if PICOJSON_USE_LOCALE
849
      num_str += localeconv()->decimal_point;
850
#else
851
      num_str.push_back('.');
852
#endif
853
854
855
    } else {
      in.ungetc();
      break;
856
857
    }
  }
858
859
  return num_str;
}
860

861
862
863
864
865
866
867
868
869
870
871
872
873
874
template <typename Context, typename Iter> inline bool _parse(Context &ctx, input<Iter> &in) {
  in.skip_ws();
  int ch = in.getc();
  switch (ch) {
#define IS(ch, text, op)                                                                                                           \
  case ch:                                                                                                                         \
    if (in.match(text) && op) {                                                                                                    \
      return true;                                                                                                                 \
    } else {                                                                                                                       \
      return false;                                                                                                                \
    }
    IS('n', "ull", ctx.set_null());
    IS('f', "alse", ctx.set_bool(false));
    IS('t', "rue", ctx.set_bool(true));
875
#undef IS
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
  case '"':
    return ctx.parse_string(in);
  case '[':
    return _parse_array(ctx, in);
  case '{':
    return _parse_object(ctx, in);
  default:
    if (('0' <= ch && ch <= '9') || ch == '-') {
      double f;
      char *endp;
      in.ungetc();
      std::string num_str(_parse_number(in));
      if (num_str.empty()) {
        return false;
      }
891
#ifdef PICOJSON_USE_INT64
892
893
894
895
896
897
      {
        errno = 0;
        intmax_t ival = strtoimax(num_str.c_str(), &endp, 10);
        if (errno == 0 && std::numeric_limits<int64_t>::min() <= ival && ival <= std::numeric_limits<int64_t>::max() &&
            endp == num_str.c_str() + num_str.size()) {
          ctx.set_int64(ival);
898
899
900
          return true;
        }
      }
901
902
903
904
905
906
907
#endif
      f = strtod(num_str.c_str(), &endp);
      if (endp == num_str.c_str() + num_str.size()) {
        ctx.set_number(f);
        return true;
      }
      return false;
908
    }
909
    break;
910
  }
911
912
913
  in.ungetc();
  return false;
}
914

915
916
917
918
919
920
921
922
class deny_parse_context {
public:
  bool set_null() {
    return false;
  }
  bool set_bool(bool) {
    return false;
  }
923
#ifdef PICOJSON_USE_INT64
924
925
926
  bool set_int64(int64_t) {
    return false;
  }
927
#endif
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
  bool set_number(double) {
    return false;
  }
  template <typename Iter> bool parse_string(input<Iter> &) {
    return false;
  }
  bool parse_array_start() {
    return false;
  }
  template <typename Iter> bool parse_array_item(input<Iter> &, size_t) {
    return false;
  }
  bool parse_array_stop(size_t) {
    return false;
  }
  bool parse_object_start() {
    return false;
  }
  template <typename Iter> bool parse_object_item(input<Iter> &, const std::string &) {
    return false;
  }
};
950

951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
class default_parse_context {
protected:
  value *out_;

public:
  default_parse_context(value *out) : out_(out) {
  }
  bool set_null() {
    *out_ = value();
    return true;
  }
  bool set_bool(bool b) {
    *out_ = value(b);
    return true;
  }
966
#ifdef PICOJSON_USE_INT64
967
968
969
970
  bool set_int64(int64_t i) {
    *out_ = value(i);
    return true;
  }
971
#endif
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
  bool set_number(double f) {
    *out_ = value(f);
    return true;
  }
  template <typename Iter> bool parse_string(input<Iter> &in) {
    *out_ = value(string_type, false);
    return _parse_string(out_->get<std::string>(), in);
  }
  bool parse_array_start() {
    *out_ = value(array_type, false);
    return true;
  }
  template <typename Iter> bool parse_array_item(input<Iter> &in, size_t) {
    array &a = out_->get<array>();
    a.push_back(value());
    default_parse_context ctx(&a.back());
    return _parse(ctx, in);
  }
  bool parse_array_stop(size_t) {
    return true;
  }
  bool parse_object_start() {
    *out_ = value(object_type, false);
    return true;
  }
  template <typename Iter> bool parse_object_item(input<Iter> &in, const std::string &key) {
    object &o = out_->get<object>();
    default_parse_context ctx(&o[key]);
    return _parse(ctx, in);
For faster browsing, not all history is shown. View entire blame