s2 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,42 @@
1
+
2
+ #ifndef PARSE_S2_HPP
3
+ #define PARSE_S2_HPP
4
+
5
+ /*
6
+ WARNING: This file is generated using ruco. Please modify the .ruco file if you wish to change anything
7
+ https://github.com/davidsiaw/ruco
8
+ */
9
+
10
+ #include <iostream>
11
+ #include <memory>
12
+ #include <fstream>
13
+ #include <sstream>
14
+ #include <string>
15
+ #include <vector>
16
+ #include <set>
17
+
18
+ #include "Scanner.h"
19
+ #include "Parser.h"
20
+
21
+ #include "picojson.hpp"
22
+
23
+ namespace S2
24
+ {
25
+ /**
26
+ * Exception thrown when the specified source file is not found
27
+ */
28
+ class FileNotFoundException {};
29
+
30
+ /**
31
+ * Parses a source file into the data structure of S2
32
+ */
33
+ S2Ptr Parse(std::string sourceFile);
34
+
35
+ /**
36
+ * Transforms the data structure of S2 to an abstract syntax tree in JSON format
37
+ */
38
+ picojson::value Jsonify(S2Ptr parseResult);
39
+ }
40
+
41
+ #endif // PARSE_S2_HPP
42
+
@@ -0,0 +1,1299 @@
1
+ /*
2
+ * Copyright 2009-2010 Cybozu Labs, Inc.
3
+ * Copyright 2011-2014 Kazuho Oku
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ *
9
+ * 1. Redistributions of source code must retain the above copyright notice,
10
+ * this list of conditions and the following disclaimer.
11
+ *
12
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
13
+ * this list of conditions and the following disclaimer in the documentation
14
+ * and/or other materials provided with the distribution.
15
+ *
16
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26
+ * POSSIBILITY OF SUCH DAMAGE.
27
+ */
28
+ #ifndef picojson_h
29
+ #define picojson_h
30
+
31
+ #include <algorithm>
32
+ #include <cstdio>
33
+ #include <cstdlib>
34
+ #include <cstring>
35
+ #include <iostream>
36
+ #include <iterator>
37
+ #include <limits>
38
+ #include <map>
39
+ #include <stdexcept>
40
+ #include <string>
41
+ #include <vector>
42
+
43
+ // for isnan/isinf
44
+ #if __cplusplus>=201103L
45
+ # include <cmath>
46
+ #else
47
+ extern "C" {
48
+ # ifdef _MSC_VER
49
+ # include <float.h>
50
+ # elif defined(__INTEL_COMPILER)
51
+ # include <mathimf.h>
52
+ # else
53
+ # include <math.h>
54
+ # endif
55
+ }
56
+ #endif
57
+
58
+ // experimental support for int64_t (see README.mkdn for detail)
59
+ #ifdef PICOJSON_USE_INT64
60
+ # define __STDC_FORMAT_MACROS
61
+ # include <errno.h>
62
+ # include <inttypes.h>
63
+ #endif
64
+
65
+ // to disable the use of localeconv(3), set PICOJSON_USE_LOCALE to 0
66
+ #ifndef PICOJSON_USE_LOCALE
67
+ # define PICOJSON_USE_LOCALE 1
68
+ #endif
69
+ #if PICOJSON_USE_LOCALE
70
+ extern "C" {
71
+ # include <locale.h>
72
+ }
73
+ #endif
74
+
75
+ #ifndef PICOJSON_ASSERT
76
+ # define PICOJSON_ASSERT(e) do { if (! (e)) throw std::runtime_error(#e); } while (0)
77
+ #endif
78
+
79
+ #ifdef _MSC_VER
80
+ #define SNPRINTF _wsnprintf_s
81
+ #pragma warning(push)
82
+ #pragma warning(disable : 4244) // conversion from int to wchar_t
83
+ #pragma warning(disable : 4127) // conditional expression is constant
84
+ #pragma warning(disable : 4702) // unreachable code
85
+ #else
86
+ #define SNPRINTF swprintf
87
+ #endif
88
+
89
+ namespace picojson {
90
+
91
+ enum {
92
+ null_type,
93
+ boolean_type,
94
+ number_type,
95
+ string_type,
96
+ array_type,
97
+ object_type
98
+ #ifdef PICOJSON_USE_INT64
99
+ , int64_type
100
+ #endif
101
+ };
102
+
103
+ enum {
104
+ INDENT_WIDTH = 2
105
+ };
106
+
107
+ struct null {};
108
+
109
+ class value {
110
+ public:
111
+ typedef std::vector<value> array;
112
+ typedef std::map<std::wstring, value> object;
113
+ union _storage {
114
+ bool boolean_;
115
+ double number_;
116
+ #ifdef PICOJSON_USE_INT64
117
+ int64_t int64_;
118
+ #endif
119
+ std::wstring* string_;
120
+ array* array_;
121
+ object* object_;
122
+ };
123
+ protected:
124
+ int type_;
125
+ _storage u_;
126
+ public:
127
+ value();
128
+ value(int type, bool);
129
+ explicit value(bool b);
130
+ #ifdef PICOJSON_USE_INT64
131
+ explicit value(int64_t i);
132
+ #endif
133
+ explicit value(double n);
134
+ explicit value(const std::wstring& s);
135
+ explicit value(const array& a);
136
+ explicit value(const object& o);
137
+ explicit value(const wchar_t* s);
138
+ value(const wchar_t* s, size_t len);
139
+ ~value();
140
+ value(const value& x);
141
+ value& operator=(const value& x);
142
+ void swap(value& x);
143
+ template <typename T> bool is() const;
144
+ template <typename T> const T& get() const;
145
+ template <typename T> T& get();
146
+ bool evaluate_as_boolean() const;
147
+ const value& get(size_t idx) const;
148
+ const value& get(const std::wstring& key) const;
149
+ value& get(size_t idx);
150
+ value& get(const std::wstring& key);
151
+
152
+ bool contains(size_t idx) const;
153
+ bool contains(const std::wstring& key) const;
154
+ std::wstring to_str() const;
155
+ template <typename Iter> void serialize(Iter os, bool prettify = false) const;
156
+ std::wstring serialize(bool prettify = false) const;
157
+ private:
158
+ template <typename T> value(const T*); // intentionally defined to block implicit conversion of pointer to bool
159
+ template <typename Iter> static void _indent(Iter os, int indent);
160
+ template <typename Iter> void _serialize(Iter os, int indent) const;
161
+ std::wstring _serialize(int indent) const;
162
+ };
163
+
164
+ typedef value::array array;
165
+ typedef value::object object;
166
+
167
+ inline value::value() : type_(null_type) {}
168
+
169
+ inline value::value(int type, bool) : type_(type) {
170
+ switch (type) {
171
+ #define INIT(p, v) case p##type: u_.p = v; break
172
+ INIT(boolean_, false);
173
+ INIT(number_, 0.0);
174
+ #ifdef PICOJSON_USE_INT64
175
+ INIT(int64_, 0);
176
+ #endif
177
+ INIT(string_, new std::wstring());
178
+ INIT(array_, new array());
179
+ INIT(object_, new object());
180
+ #undef INIT
181
+ default: break;
182
+ }
183
+ }
184
+
185
+ inline value::value(bool b) : type_(boolean_type) {
186
+ u_.boolean_ = b;
187
+ }
188
+
189
+ #ifdef PICOJSON_USE_INT64
190
+ inline value::value(int64_t i) : type_(int64_type) {
191
+ u_.int64_ = i;
192
+ }
193
+ #endif
194
+
195
+ inline value::value(double n) : type_(number_type) {
196
+ if (
197
+ #ifdef _MSC_VER
198
+ ! _finite(n)
199
+ #elif __cplusplus>=201103L || !(defined(isnan) && defined(isinf))
200
+ std::isnan(n) || std::isinf(n)
201
+ #else
202
+ isnan(n) || isinf(n)
203
+ #endif
204
+ ) {
205
+ throw std::overflow_error("");
206
+ }
207
+ u_.number_ = n;
208
+ }
209
+
210
+ inline value::value(const std::wstring& s) : type_(string_type) {
211
+ u_.string_ = new std::wstring(s);
212
+ }
213
+
214
+ inline value::value(const array& a) : type_(array_type) {
215
+ u_.array_ = new array(a);
216
+ }
217
+
218
+ inline value::value(const object& o) : type_(object_type) {
219
+ u_.object_ = new object(o);
220
+ }
221
+
222
+ inline value::value(const wchar_t* s) : type_(string_type) {
223
+ u_.string_ = new std::wstring(s);
224
+ }
225
+
226
+ inline value::value(const wchar_t* s, size_t len) : type_(string_type) {
227
+ u_.string_ = new std::wstring(s, len);
228
+ }
229
+
230
+ inline value::~value() {
231
+ switch (type_) {
232
+ #define DEINIT(p) case p##type: delete u_.p; break
233
+ DEINIT(string_);
234
+ DEINIT(array_);
235
+ DEINIT(object_);
236
+ #undef DEINIT
237
+ default: break;
238
+ }
239
+ }
240
+
241
+ inline value::value(const value& x) : type_(x.type_) {
242
+ switch (type_) {
243
+ #define INIT(p, v) case p##type: u_.p = v; break
244
+ INIT(string_, new std::wstring(*x.u_.string_));
245
+ INIT(array_, new array(*x.u_.array_));
246
+ INIT(object_, new object(*x.u_.object_));
247
+ #undef INIT
248
+ default:
249
+ u_ = x.u_;
250
+ break;
251
+ }
252
+ }
253
+
254
+ inline value& value::operator=(const value& x) {
255
+ if (this != &x) {
256
+ this->~value();
257
+ new (this) value(x);
258
+ }
259
+ return *this;
260
+ }
261
+
262
+ inline void value::swap(value& x) {
263
+ std::swap(type_, x.type_);
264
+ std::swap(u_, x.u_);
265
+ }
266
+
267
+ #define IS(ctype, jtype) \
268
+ template <> inline bool value::is<ctype>() const { \
269
+ return type_ == jtype##_type; \
270
+ }
271
+ IS(null, null)
272
+ IS(bool, boolean)
273
+ #ifdef PICOJSON_USE_INT64
274
+ IS(int64_t, int64)
275
+ #endif
276
+ IS(std::wstring, string)
277
+ IS(array, array)
278
+ IS(object, object)
279
+ #undef IS
280
+ template <> inline bool value::is<double>() const {
281
+ return type_ == number_type
282
+ #ifdef PICOJSON_USE_INT64
283
+ || type_ == int64_type
284
+ #endif
285
+ ;
286
+ }
287
+
288
+ #define GET(ctype, var) \
289
+ template <> inline const ctype& value::get<ctype>() const { \
290
+ PICOJSON_ASSERT("type mismatch! call is<type>() before get<type>()" \
291
+ && is<ctype>()); \
292
+ return var; \
293
+ } \
294
+ template <> inline ctype& value::get<ctype>() { \
295
+ PICOJSON_ASSERT("type mismatch! call is<type>() before get<type>()" \
296
+ && is<ctype>()); \
297
+ return var; \
298
+ }
299
+ GET(bool, u_.boolean_)
300
+ GET(std::wstring, *u_.string_)
301
+ GET(array, *u_.array_)
302
+ GET(object, *u_.object_)
303
+ #ifdef PICOJSON_USE_INT64
304
+ GET(double, (type_ == int64_type && (const_cast<value*>(this)->type_ = number_type, const_cast<value*>(this)->u_.number_ = u_.int64_), u_.number_))
305
+ GET(int64_t, u_.int64_)
306
+ #else
307
+ GET(double, u_.number_)
308
+ #endif
309
+ #undef GET
310
+
311
+ inline bool value::evaluate_as_boolean() const {
312
+ switch (type_) {
313
+ case null_type:
314
+ return false;
315
+ case boolean_type:
316
+ return u_.boolean_;
317
+ case number_type:
318
+ return u_.number_ != 0;
319
+ case string_type:
320
+ return ! u_.string_->empty();
321
+ default:
322
+ return true;
323
+ }
324
+ }
325
+
326
+ inline const value& value::get(size_t idx) const {
327
+ static value s_null;
328
+ PICOJSON_ASSERT(is<array>());
329
+ return idx < u_.array_->size() ? (*u_.array_)[idx] : s_null;
330
+ }
331
+
332
+ inline value& value::get(size_t idx) {
333
+ static value s_null;
334
+ PICOJSON_ASSERT(is<array>());
335
+ return idx < u_.array_->size() ? (*u_.array_)[idx] : s_null;
336
+ }
337
+
338
+ inline const value& value::get(const std::wstring& key) const {
339
+ static value s_null;
340
+ PICOJSON_ASSERT(is<object>());
341
+ object::const_iterator i = u_.object_->find(key);
342
+ return i != u_.object_->end() ? i->second : s_null;
343
+ }
344
+
345
+ inline value& value::get(const std::wstring& key) {
346
+ static value s_null;
347
+ PICOJSON_ASSERT(is<object>());
348
+ object::iterator i = u_.object_->find(key);
349
+ return i != u_.object_->end() ? i->second : s_null;
350
+ }
351
+
352
+ inline bool value::contains(size_t idx) const {
353
+ PICOJSON_ASSERT(is<array>());
354
+ return idx < u_.array_->size();
355
+ }
356
+
357
+ inline bool value::contains(const std::wstring& key) const {
358
+ PICOJSON_ASSERT(is<object>());
359
+ object::const_iterator i = u_.object_->find(key);
360
+ return i != u_.object_->end();
361
+ }
362
+
363
+ inline std::wstring value::to_str() const {
364
+ switch (type_) {
365
+ case null_type: return L"null";
366
+ case boolean_type: return u_.boolean_ ? L"true" : L"false";
367
+ #ifdef PICOJSON_USE_INT64
368
+ case int64_type: {
369
+ wchar_t buf[sizeof("-9223372036854775808")];
370
+ SNPRINTF(buf, sizeof(buf), L"%" PRId64, u_.int64_);
371
+ return buf;
372
+ }
373
+ #endif
374
+ case number_type: {
375
+ wchar_t buf[256];
376
+ double tmp;
377
+ SNPRINTF(buf, sizeof(buf), fabs(u_.number_) < (1ULL << 53) && modf(u_.number_, &tmp) == 0 ? L"%.f" : L"%.17g", u_.number_);
378
+ #if PICOJSON_USE_LOCALE
379
+ char *decimal_point = localeconv()->decimal_point;
380
+ if (strcmp(decimal_point, ".") != 0) {
381
+ size_t decimal_point_len = strlen(decimal_point);
382
+ std::string decimal_point_mbstring(decimal_point);
383
+ std::wstring decimal_point_string(decimal_point_mbstring.begin(), decimal_point_mbstring.end());
384
+ for (wchar_t *p = buf; *p != '\0'; ++p) {
385
+ if (wcsncmp(p, decimal_point_string.c_str(), decimal_point_len) == 0) {
386
+ return std::wstring(buf, p) + L"." + (p + decimal_point_len);
387
+ }
388
+ }
389
+ }
390
+ #endif
391
+ return buf;
392
+ }
393
+ case string_type: return *u_.string_;
394
+ case array_type: return L"array";
395
+ case object_type: return L"object";
396
+ default: PICOJSON_ASSERT(0);
397
+ #ifdef _MSC_VER
398
+ __assume(0);
399
+ #endif
400
+ }
401
+ return std::wstring();
402
+ }
403
+
404
+ template <typename Iter> void copy(const std::wstring& s, Iter oi) {
405
+ std::copy(s.begin(), s.end(), oi);
406
+ }
407
+
408
+ template <typename Iter> void serialize_str(const std::wstring& s, Iter oi) {
409
+ *oi++ = '"';
410
+ for (std::wstring::const_iterator i = s.begin(); i != s.end(); ++i) {
411
+ switch (*i) {
412
+ #define MAP(val, sym) case val: copy(sym, oi); break
413
+ MAP(L'"', L"\\\"");
414
+ MAP(L'\\', L"\\\\");
415
+ MAP(L'/', L"\\/");
416
+ MAP(L'\b', L"\\b");
417
+ MAP(L'\f', L"\\f");
418
+ MAP(L'\n', L"\\n");
419
+ MAP(L'\r', L"\\r");
420
+ MAP(L'\t', L"\\t");
421
+ #undef MAP
422
+ default:
423
+ if (static_cast<unsigned wchar_t>(*i) < 0x20 || *i == 0x7f) {
424
+ wchar_t buf[7];
425
+ SNPRINTF(buf, sizeof(buf), L"\\u%04x", *i & 0xff);
426
+ copy(buf, buf + 6, oi);
427
+ } else {
428
+ *oi++ = *i;
429
+ }
430
+ break;
431
+ }
432
+ }
433
+ *oi++ = '"';
434
+ }
435
+
436
+ template <typename Iter> void value::serialize(Iter oi, bool prettify) const {
437
+ return _serialize(oi, prettify ? 0 : -1);
438
+ }
439
+
440
+ inline std::wstring value::serialize(bool prettify) const {
441
+ return _serialize(prettify ? 0 : -1);
442
+ }
443
+
444
+ template <typename Iter> void value::_indent(Iter oi, int indent) {
445
+ *oi++ = '\n';
446
+ for (int i = 0; i < indent * INDENT_WIDTH; ++i) {
447
+ *oi++ = ' ';
448
+ }
449
+ }
450
+
451
+ template <typename Iter> void value::_serialize(Iter oi, int indent) const {
452
+ switch (type_) {
453
+ case string_type:
454
+ serialize_str(*u_.string_, oi);
455
+ break;
456
+ case array_type: {
457
+ *oi++ = '[';
458
+ if (indent != -1) {
459
+ ++indent;
460
+ }
461
+ for (array::const_iterator i = u_.array_->begin();
462
+ i != u_.array_->end();
463
+ ++i) {
464
+ if (i != u_.array_->begin()) {
465
+ *oi++ = ',';
466
+ }
467
+ if (indent != -1) {
468
+ _indent(oi, indent);
469
+ }
470
+ i->_serialize(oi, indent);
471
+ }
472
+ if (indent != -1) {
473
+ --indent;
474
+ if (! u_.array_->empty()) {
475
+ _indent(oi, indent);
476
+ }
477
+ }
478
+ *oi++ = ']';
479
+ break;
480
+ }
481
+ case object_type: {
482
+ *oi++ = '{';
483
+ if (indent != -1) {
484
+ ++indent;
485
+ }
486
+ for (object::const_iterator i = u_.object_->begin();
487
+ i != u_.object_->end();
488
+ ++i) {
489
+ if (i != u_.object_->begin()) {
490
+ *oi++ = ',';
491
+ }
492
+ if (indent != -1) {
493
+ _indent(oi, indent);
494
+ }
495
+ serialize_str(i->first, oi);
496
+ *oi++ = ':';
497
+ if (indent != -1) {
498
+ *oi++ = ' ';
499
+ }
500
+ i->second._serialize(oi, indent);
501
+ }
502
+ if (indent != -1) {
503
+ --indent;
504
+ if (! u_.object_->empty()) {
505
+ _indent(oi, indent);
506
+ }
507
+ }
508
+ *oi++ = '}';
509
+ break;
510
+ }
511
+ default:
512
+ copy(to_str(), oi);
513
+ break;
514
+ }
515
+ if (indent == 0) {
516
+ *oi++ = '\n';
517
+ }
518
+ }
519
+
520
+ inline std::wstring value::_serialize(int indent) const {
521
+ std::wstring s;
522
+ _serialize(std::back_inserter(s), indent);
523
+ return s;
524
+ }
525
+
526
+ template <typename Iter> class input {
527
+ protected:
528
+ Iter cur_, end_;
529
+ int last_ch_;
530
+ bool ungot_;
531
+ int line_;
532
+ public:
533
+ input(const Iter& first, const Iter& last) : cur_(first), end_(last), last_ch_(-1), ungot_(false), line_(1) {}
534
+ int getc() {
535
+ if (ungot_) {
536
+ ungot_ = false;
537
+ return last_ch_;
538
+ }
539
+ if (cur_ == end_) {
540
+ last_ch_ = -1;
541
+ return -1;
542
+ }
543
+ if (last_ch_ == '\n') {
544
+ line_++;
545
+ }
546
+ last_ch_ = *cur_ & 0xff;
547
+ ++cur_;
548
+ return last_ch_;
549
+ }
550
+ void ungetc() {
551
+ if (last_ch_ != -1) {
552
+ PICOJSON_ASSERT(! ungot_);
553
+ ungot_ = true;
554
+ }
555
+ }
556
+ Iter cur() const { return cur_; }
557
+ int line() const { return line_; }
558
+ void skip_ws() {
559
+ while (1) {
560
+ int ch = getc();
561
+ if (! (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r')) {
562
+ ungetc();
563
+ break;
564
+ }
565
+ }
566
+ }
567
+ bool expect(int expect) {
568
+ skip_ws();
569
+ if (getc() != expect) {
570
+ ungetc();
571
+ return false;
572
+ }
573
+ return true;
574
+ }
575
+ bool match(const std::wstring& pattern) {
576
+ for (std::wstring::const_iterator pi(pattern.begin());
577
+ pi != pattern.end();
578
+ ++pi) {
579
+ if (getc() != *pi) {
580
+ ungetc();
581
+ return false;
582
+ }
583
+ }
584
+ return true;
585
+ }
586
+ };
587
+
588
+ template<typename Iter> inline int _parse_quadhex(input<Iter> &in) {
589
+ int uni_ch = 0, hex;
590
+ for (int i = 0; i < 4; i++) {
591
+ if ((hex = in.getc()) == -1) {
592
+ return -1;
593
+ }
594
+ if ('0' <= hex && hex <= '9') {
595
+ hex -= '0';
596
+ } else if ('A' <= hex && hex <= 'F') {
597
+ hex -= 'A' - 0xa;
598
+ } else if ('a' <= hex && hex <= 'f') {
599
+ hex -= 'a' - 0xa;
600
+ } else {
601
+ in.ungetc();
602
+ return -1;
603
+ }
604
+ uni_ch = uni_ch * 16 + hex;
605
+ }
606
+ return uni_ch;
607
+ }
608
+
609
+ template<typename String, typename Iter> inline bool _parse_codepoint(String& out, input<Iter>& in) {
610
+ int uni_ch;
611
+ if ((uni_ch = _parse_quadhex(in)) == -1) {
612
+ return false;
613
+ }
614
+ if (0xd800 <= uni_ch && uni_ch <= 0xdfff) {
615
+ if (0xdc00 <= uni_ch) {
616
+ // a second 16-bit of a surrogate pair appeared
617
+ return false;
618
+ }
619
+ // first 16-bit of surrogate pair, get the next one
620
+ if (in.getc() != '\\' || in.getc() != 'u') {
621
+ in.ungetc();
622
+ return false;
623
+ }
624
+ int second = _parse_quadhex(in);
625
+ if (! (0xdc00 <= second && second <= 0xdfff)) {
626
+ return false;
627
+ }
628
+ uni_ch = ((uni_ch - 0xd800) << 10) | ((second - 0xdc00) & 0x3ff);
629
+ uni_ch += 0x10000;
630
+ }
631
+ if (uni_ch < 0x80) {
632
+ out.push_back(uni_ch);
633
+ } else {
634
+ if (uni_ch < 0x800) {
635
+ out.push_back(0xc0 | (uni_ch >> 6));
636
+ } else {
637
+ if (uni_ch < 0x10000) {
638
+ out.push_back(0xe0 | (uni_ch >> 12));
639
+ } else {
640
+ out.push_back(0xf0 | (uni_ch >> 18));
641
+ out.push_back(0x80 | ((uni_ch >> 12) & 0x3f));
642
+ }
643
+ out.push_back(0x80 | ((uni_ch >> 6) & 0x3f));
644
+ }
645
+ out.push_back(0x80 | (uni_ch & 0x3f));
646
+ }
647
+ return true;
648
+ }
649
+
650
+ template<typename String, typename Iter> inline bool _parse_string(String& out, input<Iter>& in) {
651
+ while (1) {
652
+ int ch = in.getc();
653
+ if (ch < ' ') {
654
+ in.ungetc();
655
+ return false;
656
+ } else if (ch == '"') {
657
+ return true;
658
+ } else if (ch == '\\') {
659
+ if ((ch = in.getc()) == -1) {
660
+ return false;
661
+ }
662
+ switch (ch) {
663
+ #define MAP(sym, val) case sym: out.push_back(val); break
664
+ MAP('"', '\"');
665
+ MAP('\\', '\\');
666
+ MAP('/', '/');
667
+ MAP('b', '\b');
668
+ MAP('f', '\f');
669
+ MAP('n', '\n');
670
+ MAP('r', '\r');
671
+ MAP('t', '\t');
672
+ #undef MAP
673
+ case 'u':
674
+ if (! _parse_codepoint(out, in)) {
675
+ return false;
676
+ }
677
+ break;
678
+ default:
679
+ return false;
680
+ }
681
+ } else {
682
+ out.push_back(ch);
683
+ }
684
+ }
685
+ return false;
686
+ }
687
+
688
+ template <typename Context, typename Iter> inline bool _parse_array(Context& ctx, input<Iter>& in) {
689
+ if (! ctx.parse_array_start()) {
690
+ return false;
691
+ }
692
+ size_t idx = 0;
693
+ if (in.expect(']')) {
694
+ return ctx.parse_array_stop(idx);
695
+ }
696
+ do {
697
+ if (! ctx.parse_array_item(in, idx)) {
698
+ return false;
699
+ }
700
+ idx++;
701
+ } while (in.expect(','));
702
+ return in.expect(']') && ctx.parse_array_stop(idx);
703
+ }
704
+
705
+ template <typename Context, typename Iter> inline bool _parse_object(Context& ctx, input<Iter>& in) {
706
+ if (! ctx.parse_object_start()) {
707
+ return false;
708
+ }
709
+ if (in.expect('}')) {
710
+ return true;
711
+ }
712
+ do {
713
+ std::wstring key;
714
+ if (! in.expect('"')
715
+ || ! _parse_string(key, in)
716
+ || ! in.expect(':')) {
717
+ return false;
718
+ }
719
+ if (! ctx.parse_object_item(in, key)) {
720
+ return false;
721
+ }
722
+ } while (in.expect(','));
723
+ return in.expect('}');
724
+ }
725
+
726
+ template <typename Iter> inline std::wstring _parse_number(input<Iter>& in) {
727
+ std::wstring num_str;
728
+ while (1) {
729
+ int ch = in.getc();
730
+ if (('0' <= ch && ch <= '9') || ch == '+' || ch == '-'
731
+ || ch == 'e' || ch == 'E') {
732
+ num_str.push_back(ch);
733
+ } else if (ch == '.') {
734
+ num_str.push_back(L'.');
735
+ } else {
736
+ in.ungetc();
737
+ break;
738
+ }
739
+ }
740
+ return num_str;
741
+ }
742
+
743
+ template <typename Context, typename Iter> inline bool _parse(Context& ctx, input<Iter>& in) {
744
+ in.skip_ws();
745
+ int ch = in.getc();
746
+ switch (ch) {
747
+ #define IS(ch, text, op) case ch: \
748
+ if (in.match(text) && op) { \
749
+ return true; \
750
+ } else { \
751
+ return false; \
752
+ }
753
+ IS('n', L"ull", ctx.set_null());
754
+ IS('f', L"alse", ctx.set_bool(false));
755
+ IS('t', L"rue", ctx.set_bool(true));
756
+ #undef IS
757
+ case '"':
758
+ return ctx.parse_string(in);
759
+ case '[':
760
+ return _parse_array(ctx, in);
761
+ case '{':
762
+ return _parse_object(ctx, in);
763
+ default:
764
+ if (('0' <= ch && ch <= '9') || ch == '-') {
765
+ double f;
766
+ wchar_t *endp;
767
+ in.ungetc();
768
+ std::wstring num_str = _parse_number(in);
769
+ if (num_str.empty()) {
770
+ return false;
771
+ }
772
+ #ifdef PICOJSON_USE_INT64
773
+ {
774
+ errno = 0;
775
+ intmax_t ival = strtoimax(num_str.c_str(), &endp, 10);
776
+ if (errno == 0
777
+ && std::numeric_limits<int64_t>::min() <= ival
778
+ && ival <= std::numeric_limits<int64_t>::max()
779
+ && endp == num_str.c_str() + num_str.size()) {
780
+ ctx.set_int64(ival);
781
+ return true;
782
+ }
783
+ }
784
+ #endif
785
+ f = wcstod(num_str.c_str(), &endp);
786
+ if (endp == num_str.c_str() + num_str.size()) {
787
+ ctx.set_number(f);
788
+ return true;
789
+ }
790
+ return false;
791
+ }
792
+ break;
793
+ }
794
+ in.ungetc();
795
+ return false;
796
+ }
797
+
798
+ class deny_parse_context {
799
+ public:
800
+ bool set_null() { return false; }
801
+ bool set_bool(bool) { return false; }
802
+ #ifdef PICOJSON_USE_INT64
803
+ bool set_int64(int64_t) { return false; }
804
+ #endif
805
+ bool set_number(double) { return false; }
806
+ template <typename Iter> bool parse_string(input<Iter>&) { return false; }
807
+ bool parse_array_start() { return false; }
808
+ template <typename Iter> bool parse_array_item(input<Iter>&, size_t) {
809
+ return false;
810
+ }
811
+ bool parse_array_stop(size_t) { return false; }
812
+ bool parse_object_start() { return false; }
813
+ template <typename Iter> bool parse_object_item(input<Iter>&, const std::wstring&) {
814
+ return false;
815
+ }
816
+ };
817
+
818
+ class default_parse_context {
819
+ protected:
820
+ value* out_;
821
+ public:
822
+ default_parse_context(value* out) : out_(out) {}
823
+ bool set_null() {
824
+ *out_ = value();
825
+ return true;
826
+ }
827
+ bool set_bool(bool b) {
828
+ *out_ = value(b);
829
+ return true;
830
+ }
831
+ #ifdef PICOJSON_USE_INT64
832
+ bool set_int64(int64_t i) {
833
+ *out_ = value(i);
834
+ return true;
835
+ }
836
+ #endif
837
+ bool set_number(double f) {
838
+ *out_ = value(f);
839
+ return true;
840
+ }
841
+ template<typename Iter> bool parse_string(input<Iter>& in) {
842
+ *out_ = value(string_type, false);
843
+ return _parse_string(out_->get<std::wstring>(), in);
844
+ }
845
+ bool parse_array_start() {
846
+ *out_ = value(array_type, false);
847
+ return true;
848
+ }
849
+ template <typename Iter> bool parse_array_item(input<Iter>& in, size_t) {
850
+ array& a = out_->get<array>();
851
+ a.push_back(value());
852
+ default_parse_context ctx(&a.back());
853
+ return _parse(ctx, in);
854
+ }
855
+ bool parse_array_stop(size_t) { return true; }
856
+ bool parse_object_start() {
857
+ *out_ = value(object_type, false);
858
+ return true;
859
+ }
860
+ template <typename Iter> bool parse_object_item(input<Iter>& in, const std::wstring& key) {
861
+ object& o = out_->get<object>();
862
+ default_parse_context ctx(&o[key]);
863
+ return _parse(ctx, in);
864
+ }
865
+ private:
866
+ default_parse_context(const default_parse_context&);
867
+ default_parse_context& operator=(const default_parse_context&);
868
+ };
869
+
870
+ class null_parse_context {
871
+ public:
872
+ struct dummy_str {
873
+ void push_back(int) {}
874
+ };
875
+ public:
876
+ null_parse_context() {}
877
+ bool set_null() { return true; }
878
+ bool set_bool(bool) { return true; }
879
+ #ifdef PICOJSON_USE_INT64
880
+ bool set_int64(int64_t) { return true; }
881
+ #endif
882
+ bool set_number(double) { return true; }
883
+ template <typename Iter> bool parse_string(input<Iter>& in) {
884
+ dummy_str s;
885
+ return _parse_string(s, in);
886
+ }
887
+ bool parse_array_start() { return true; }
888
+ template <typename Iter> bool parse_array_item(input<Iter>& in, size_t) {
889
+ return _parse(*this, in);
890
+ }
891
+ bool parse_array_stop(size_t) { return true; }
892
+ bool parse_object_start() { return true; }
893
+ template <typename Iter> bool parse_object_item(input<Iter>& in, const std::wstring&) {
894
+ return _parse(*this, in);
895
+ }
896
+ private:
897
+ null_parse_context(const null_parse_context&);
898
+ null_parse_context& operator=(const null_parse_context&);
899
+ };
900
+
901
+ // obsolete, use the version below
902
+ template <typename Iter> inline std::wstring parse(value& out, Iter& pos, const Iter& last) {
903
+ std::wstring err;
904
+ pos = parse(out, pos, last, &err);
905
+ return err;
906
+ }
907
+
908
+ template <typename Context, typename Iter> inline Iter _parse(Context& ctx, const Iter& first, const Iter& last, std::wstring* err) {
909
+ input<Iter> in(first, last);
910
+ if (! _parse(ctx, in) && err != NULL) {
911
+ wchar_t buf[64];
912
+ SNPRINTF(buf, sizeof(buf), L"syntax error at line %d near: ", in.line());
913
+ *err = buf;
914
+ while (1) {
915
+ int ch = in.getc();
916
+ if (ch == -1 || ch == '\n') {
917
+ break;
918
+ } else if (ch >= ' ') {
919
+ err->push_back(ch);
920
+ }
921
+ }
922
+ }
923
+ return in.cur();
924
+ }
925
+
926
+ template <typename Iter> inline Iter parse(value& out, const Iter& first, const Iter& last, std::wstring* err) {
927
+ default_parse_context ctx(&out);
928
+ return _parse(ctx, first, last, err);
929
+ }
930
+
931
+ inline std::wstring parse(value& out, std::wistream& is) {
932
+ std::wstring err;
933
+ parse(out, std::istreambuf_iterator<wchar_t>(is.rdbuf()),
934
+ std::istreambuf_iterator<wchar_t>(), &err);
935
+ return err;
936
+ }
937
+
938
+ template <typename T> struct last_error_t {
939
+ static std::wstring s;
940
+ };
941
+ template <typename T> std::wstring last_error_t<T>::s;
942
+
943
+ inline void set_last_error(const std::wstring& s) {
944
+ last_error_t<bool>::s = s;
945
+ }
946
+
947
+ inline const std::wstring& get_last_error() {
948
+ return last_error_t<bool>::s;
949
+ }
950
+
951
+ inline bool operator==(const value& x, const value& y) {
952
+ if (x.is<null>())
953
+ return y.is<null>();
954
+ #define PICOJSON_CMP(type) \
955
+ if (x.is<type>()) \
956
+ return y.is<type>() && x.get<type>() == y.get<type>()
957
+ PICOJSON_CMP(bool);
958
+ PICOJSON_CMP(double);
959
+ PICOJSON_CMP(std::wstring);
960
+ PICOJSON_CMP(array);
961
+ PICOJSON_CMP(object);
962
+ #undef PICOJSON_CMP
963
+ PICOJSON_ASSERT(0);
964
+ #ifdef _MSC_VER
965
+ __assume(0);
966
+ #endif
967
+ return false;
968
+ }
969
+
970
+ inline bool operator!=(const value& x, const value& y) {
971
+ return ! (x == y);
972
+ }
973
+ }
974
+
975
+ namespace std {
976
+ template<> inline void swap(picojson::value& x, picojson::value& y)
977
+ {
978
+ x.swap(y);
979
+ }
980
+ }
981
+
982
+ inline std::wistream& operator>>(std::wistream& is, picojson::value& x)
983
+ {
984
+ picojson::set_last_error(std::wstring());
985
+ std::wstring err = picojson::parse(x, is);
986
+ if (! err.empty()) {
987
+ picojson::set_last_error(err);
988
+ is.setstate(std::ios::failbit);
989
+ }
990
+ return is;
991
+ }
992
+
993
+ inline std::wostream& operator<<(std::wostream& os, const picojson::value& x)
994
+ {
995
+ x.serialize(std::ostream_iterator<char, wchar_t>(os));
996
+ return os;
997
+ }
998
+ #ifdef _MSC_VER
999
+ #pragma warning(pop)
1000
+ #endif
1001
+
1002
+ #endif
1003
+ #ifdef TEST_PICOJSON
1004
+ #ifdef _MSC_VER
1005
+ #pragma warning(disable : 4127) // conditional expression is constant
1006
+ #endif
1007
+
1008
+ using namespace std;
1009
+
1010
+ static bool success = true;
1011
+ static int test_num = 0;
1012
+
1013
+ static void ok(bool b, const wchar_t* name = L"")
1014
+ {
1015
+ if (! b)
1016
+ success = false;
1017
+ printf("%s %d - %s\n", b ? L"ok" : L"ng", ++test_num, name);
1018
+ }
1019
+
1020
+ static void done_testing()
1021
+ {
1022
+ printf("1..%d\n", test_num);
1023
+ }
1024
+
1025
+ template <typename T> void is(const T& x, const T& y, const wchar_t* name = L"")
1026
+ {
1027
+ if (x == y) {
1028
+ ok(true, name);
1029
+ } else {
1030
+ ok(false, name);
1031
+ }
1032
+ }
1033
+
1034
+ #include <algorithm>
1035
+ #include <sstream>
1036
+ #include <float.h>
1037
+ #include <limits.h>
1038
+
1039
+ int main(void)
1040
+ {
1041
+ #if PICOJSON_USE_LOCALE
1042
+ setlocale(LC_ALL, "");
1043
+ #endif
1044
+
1045
+ // constructors
1046
+ #define TEST(expr, expected) \
1047
+ is(picojson::value expr .serialize(), string(expected), "picojson::value" #expr)
1048
+
1049
+ TEST( (true), "true");
1050
+ TEST( (false), "false");
1051
+ TEST( (42.0), "42");
1052
+ TEST( (string("hello")), "\"hello\"");
1053
+ TEST( ("hello"), "\"hello\"");
1054
+ TEST( ("hello", 4), "\"hell\"");
1055
+
1056
+ {
1057
+ double a = 1;
1058
+ for (int i = 0; i < 1024; i++) {
1059
+ picojson::value vi(a);
1060
+ std::wstringstream ss;
1061
+ ss << vi;
1062
+ picojson::value vo;
1063
+ ss >> vo;
1064
+ double b = vo.get<double>();
1065
+ if ((i < 53 && a != b) || fabs(a - b) / b > 1e-8) {
1066
+ printf("ng i=%d a=%.18e b=%.18e\n", i, a, b);
1067
+ }
1068
+ a *= 2;
1069
+ }
1070
+ }
1071
+
1072
+ #undef TEST
1073
+
1074
+ #define TEST(in, type, cmp, serialize_test) { \
1075
+ picojson::value v; \
1076
+ const wchar_t* s = in; \
1077
+ string err = picojson::parse(v, s, s + strlen(s)); \
1078
+ ok(err.empty(), in " no error"); \
1079
+ ok(v.is<type>(), in " check type"); \
1080
+ is<type>(v.get<type>(), cmp, in " correct output"); \
1081
+ is(*s, '\0', in " read to eof"); \
1082
+ if (serialize_test) { \
1083
+ is(v.serialize(), string(in), in " serialize"); \
1084
+ } \
1085
+ }
1086
+ TEST("false", bool, false, true);
1087
+ TEST("true", bool, true, true);
1088
+ TEST("90.5", double, 90.5, false);
1089
+ TEST("1.7976931348623157e+308", double, DBL_MAX, false);
1090
+ TEST("\"hello\"", string, string("hello"), true);
1091
+ TEST("\"\\\"\\\\\\/\\b\\f\\n\\r\\t\"", string, string("\"\\/\b\f\n\r\t"),
1092
+ true);
1093
+ TEST("\"\\u0061\\u30af\\u30ea\\u30b9\"", string,
1094
+ string("a\xe3\x82\xaf\xe3\x83\xaa\xe3\x82\xb9"), false);
1095
+ TEST("\"\\ud840\\udc0b\"", string, string("\xf0\xa0\x80\x8b"), false);
1096
+ #ifdef PICOJSON_USE_INT64
1097
+ TEST("0", int64_t, 0, true);
1098
+ TEST("-9223372036854775808", int64_t, std::numeric_limits<int64_t>::min(), true);
1099
+ TEST("9223372036854775807", int64_t, std::numeric_limits<int64_t>::max(), true);
1100
+ #endif
1101
+ #undef TEST
1102
+
1103
+ #define TEST(type, expr) { \
1104
+ picojson::value v; \
1105
+ const wchar_t *s = expr; \
1106
+ string err = picojson::parse(v, s, s + strlen(s)); \
1107
+ ok(err.empty(), "empty " #type " no error"); \
1108
+ ok(v.is<picojson::type>(), "empty " #type " check type"); \
1109
+ ok(v.get<picojson::type>().empty(), "check " #type " array size"); \
1110
+ }
1111
+ TEST(array, "[]");
1112
+ TEST(object, "{}");
1113
+ #undef TEST
1114
+
1115
+ {
1116
+ picojson::value v;
1117
+ const wchar_t *s = "[1,true,\"hello\"]";
1118
+ string err = picojson::parse(v, s, s + strlen(s));
1119
+ ok(err.empty(), "array no error");
1120
+ ok(v.is<picojson::array>(), "array check type");
1121
+ is(v.get<picojson::array>().size(), size_t(3), "check array size");
1122
+ ok(v.contains(0), "check contains array[0]");
1123
+ ok(v.get(0).is<double>(), "check array[0] type");
1124
+ is(v.get(0).get<double>(), 1.0, "check array[0] value");
1125
+ ok(v.contains(1), "check contains array[1]");
1126
+ ok(v.get(1).is<bool>(), "check array[1] type");
1127
+ ok(v.get(1).get<bool>(), "check array[1] value");
1128
+ ok(v.contains(2), "check contains array[2]");
1129
+ ok(v.get(2).is<string>(), "check array[2] type");
1130
+ is(v.get(2).get<string>(), string("hello"), "check array[2] value");
1131
+ ok(!v.contains(3), "check not contains array[3]");
1132
+ }
1133
+
1134
+ {
1135
+ picojson::value v;
1136
+ const wchar_t *s = "{ \"a\": true }";
1137
+ string err = picojson::parse(v, s, s + strlen(s));
1138
+ ok(err.empty(), "object no error");
1139
+ ok(v.is<picojson::object>(), "object check type");
1140
+ is(v.get<picojson::object>().size(), size_t(1), "check object size");
1141
+ ok(v.contains("a"), "check contains property");
1142
+ ok(v.get("a").is<bool>(), "check bool property exists");
1143
+ is(v.get("a").get<bool>(), true, "check bool property value");
1144
+ is(v.serialize(), string("{\"a\":true}"), "serialize object");
1145
+ ok(!v.contains("z"), "check not contains property");
1146
+ }
1147
+
1148
+ #define TEST(json, msg) do { \
1149
+ picojson::value v; \
1150
+ const wchar_t *s = json; \
1151
+ string err = picojson::parse(v, s, s + strlen(s)); \
1152
+ is(err, string("syntax error at line " msg), msg); \
1153
+ } while (0)
1154
+ TEST("falsoa", "1 near: oa");
1155
+ TEST("{]", "1 near: ]");
1156
+ TEST("\n\bbell", "2 near: bell");
1157
+ TEST("\"abc\nd\"", "1 near: ");
1158
+ #undef TEST
1159
+
1160
+ {
1161
+ picojson::value v1, v2;
1162
+ const wchar_t *s;
1163
+ string err;
1164
+ s = "{ \"b\": true, \"a\": [1,2,\"three\"], \"d\": 2 }";
1165
+ err = picojson::parse(v1, s, s + strlen(s));
1166
+ s = "{ \"d\": 2.0, \"b\": true, \"a\": [1,2,\"three\"] }";
1167
+ err = picojson::parse(v2, s, s + strlen(s));
1168
+ ok((v1 == v2), "check == operator in deep comparison");
1169
+ }
1170
+
1171
+ {
1172
+ picojson::value v1, v2;
1173
+ const wchar_t *s;
1174
+ string err;
1175
+ s = "{ \"b\": true, \"a\": [1,2,\"three\"], \"d\": 2 }";
1176
+ err = picojson::parse(v1, s, s + strlen(s));
1177
+ s = "{ \"d\": 2.0, \"a\": [1,\"three\"], \"b\": true }";
1178
+ err = picojson::parse(v2, s, s + strlen(s));
1179
+ ok((v1 != v2), "check != operator for array in deep comparison");
1180
+ }
1181
+
1182
+ {
1183
+ picojson::value v1, v2;
1184
+ const wchar_t *s;
1185
+ string err;
1186
+ s = "{ \"b\": true, \"a\": [1,2,\"three\"], \"d\": 2 }";
1187
+ err = picojson::parse(v1, s, s + strlen(s));
1188
+ s = "{ \"d\": 2.0, \"a\": [1,2,\"three\"], \"b\": false }";
1189
+ err = picojson::parse(v2, s, s + strlen(s));
1190
+ ok((v1 != v2), "check != operator for object in deep comparison");
1191
+ }
1192
+
1193
+ {
1194
+ picojson::value v1, v2;
1195
+ const wchar_t *s;
1196
+ string err;
1197
+ s = "{ \"b\": true, \"a\": [1,2,\"three\"], \"d\": 2 }";
1198
+ err = picojson::parse(v1, s, s + strlen(s));
1199
+ picojson::object& o = v1.get<picojson::object>();
1200
+ o.erase("b");
1201
+ picojson::array& a = o["a"].get<picojson::array>();
1202
+ picojson::array::iterator i;
1203
+ i = std::remove(a.begin(), a.end(), picojson::value(std::wstring("three")));
1204
+ a.erase(i, a.end());
1205
+ s = "{ \"a\": [1,2], \"d\": 2 }";
1206
+ err = picojson::parse(v2, s, s + strlen(s));
1207
+ ok((v1 == v2), "check erase()");
1208
+ }
1209
+
1210
+ ok(picojson::value(3.0).serialize() == "3",
1211
+ "integral number should be serialized as a integer");
1212
+
1213
+ {
1214
+ const wchar_t* s = "{ \"a\": [1,2], \"d\": 2 }";
1215
+ picojson::null_parse_context ctx;
1216
+ string err;
1217
+ picojson::_parse(ctx, s, s + strlen(s), &err);
1218
+ ok(err.empty(), "null_parse_context");
1219
+ }
1220
+
1221
+ {
1222
+ picojson::value v1, v2;
1223
+ v1 = picojson::value(true);
1224
+ swap(v1, v2);
1225
+ ok(v1.is<picojson::null>(), "swap (null)");
1226
+ ok(v2.get<bool>() == true, "swap (bool)");
1227
+
1228
+ v1 = picojson::value("a");
1229
+ v2 = picojson::value(1.0);
1230
+ swap(v1, v2);
1231
+ ok(v1.get<double>() == 1.0, "swap (dobule)");
1232
+ ok(v2.get<string>() == "a", "swap (string)");
1233
+
1234
+ v1 = picojson::value(picojson::object());
1235
+ v2 = picojson::value(picojson::array());
1236
+ swap(v1, v2);
1237
+ ok(v1.is<picojson::array>(), "swap (array)");
1238
+ ok(v2.is<picojson::object>(), "swap (object)");
1239
+ }
1240
+
1241
+ {
1242
+ picojson::value v;
1243
+ const wchar_t *s = "{ \"a\": 1, \"b\": [ 2, { \"b1\": \"abc\" } ], \"c\": {}, \"d\": [] }";
1244
+ string err;
1245
+ err = picojson::parse(v, s, s + strlen(s));
1246
+ ok(err.empty(), "parse test data for prettifying output");
1247
+ ok(v.serialize() == "{\"a\":1,\"b\":[2,{\"b1\":\"abc\"}],\"c\":{},\"d\":[]}", "non-prettifying output");
1248
+ ok(v.serialize(true) == "{\n \"a\": 1,\n \"b\": [\n 2,\n {\n \"b1\": \"abc\"\n }\n ],\n \"c\": {},\n \"d\": []\n}\n", "prettifying output");
1249
+ }
1250
+
1251
+ try {
1252
+ picojson::value v(std::numeric_limits<double>::quiet_NaN());
1253
+ ok(false, "should not accept NaN");
1254
+ } catch (std::overflow_error e) {
1255
+ ok(true, "should not accept NaN");
1256
+ }
1257
+
1258
+ try {
1259
+ picojson::value v(std::numeric_limits<double>::infinity());
1260
+ ok(false, "should not accept infinity");
1261
+ } catch (std::overflow_error e) {
1262
+ ok(true, "should not accept infinity");
1263
+ }
1264
+
1265
+ try {
1266
+ picojson::value v(123.);
1267
+ ok(! v.is<bool>(), "is<wrong_type>() should return false");
1268
+ v.get<bool>();
1269
+ ok(false, "get<wrong_type>() should raise an error");
1270
+ } catch (std::runtime_error e) {
1271
+ ok(true, "get<wrong_type>() should raise an error");
1272
+ }
1273
+
1274
+ #ifdef PICOJSON_USE_INT64
1275
+ {
1276
+ picojson::value v1((int64_t)123);
1277
+ ok(v1.is<int64_t>(), "is int64_t");
1278
+ ok(v1.is<double>(), "is double as well");
1279
+ ok(v1.serialize() == "123", "serialize the value");
1280
+ ok(v1.get<int64_t>() == 123, "value is correct as int64_t");
1281
+ ok(v1.get<double>(), "value is correct as double");
1282
+
1283
+ ok(! v1.is<int64_t>(), "is no more int64_type once get<double>() is called");
1284
+ ok(v1.is<double>(), "and is still a double");
1285
+
1286
+ const wchar_t *s = "-9223372036854775809";
1287
+ ok(picojson::parse(v1, s, s + strlen(s)).empty(), "parse underflowing int64_t");
1288
+ ok(! v1.is<int64_t>(), "underflowing int is not int64_t");
1289
+ ok(v1.is<double>(), "underflowing int is double");
1290
+ ok(v1.get<double>() + 9.22337203685478e+18 < 65536, "double value is somewhat correct");
1291
+ }
1292
+ #endif
1293
+
1294
+ done_testing();
1295
+
1296
+ return success ? 0 : 1;
1297
+ }
1298
+
1299
+ #endif