KiCad PCB EDA Suite
json11.cpp
Go to the documentation of this file.
1 /* Copyright (c) 2013 Dropbox, Inc.
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining a copy
4  * of this software and associated documentation files (the "Software"), to deal
5  * in the Software without restriction, including without limitation the rights
6  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7  * copies of the Software, and to permit persons to whom the Software is
8  * furnished to do so, subject to the following conditions:
9  *
10  * The above copyright notice and this permission notice shall be included in
11  * all copies or substantial portions of the Software.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19  * THE SOFTWARE.
20  */
21 
22 #include "json11.hpp"
23 #include <cassert>
24 #include <cmath>
25 #include <cstdlib>
26 #include <cstdio>
27 #include <limits>
28 
29 namespace json11 {
30 static const int max_depth = 200;
31 
32 using std::string;
33 using std::vector;
34 using std::map;
35 using std::make_shared;
36 using std::initializer_list;
37 using std::move;
38 
39 /* Helper for representing null - just a do-nothing struct, plus comparison
40  * operators so the helpers in JsonValue work. We can't use nullptr_t because
41  * it may not be orderable.
42  */
43 struct NullStruct
44 {
45  bool operator==( NullStruct ) const { return true; }
46  bool operator<( NullStruct ) const { return false; }
47 };
48 
49 /* * * * * * * * * * * * * * * * * * * *
50  * Serialization
51  */
52 
53 static void dump( NullStruct, string& out )
54 {
55  out += "null";
56 }
57 
58 
59 static void dump( double value, string& out )
60 {
61  if( std::isfinite( value ) )
62  {
63  char buf[32];
64  snprintf( buf, sizeof buf, "%.17g", value );
65  out += buf;
66  }
67  else
68  {
69  out += "null";
70  }
71 }
72 
73 
74 static void dump( int value, string& out )
75 {
76  char buf[32];
77 
78  snprintf( buf, sizeof buf, "%d", value );
79  out += buf;
80 }
81 
82 
83 static void dump( bool value, string& out )
84 {
85  out += value ? "true" : "false";
86 }
87 
88 
89 static void dump( const string& value, string& out )
90 {
91  out += '"';
92 
93  for( size_t i = 0; i < value.length(); i++ )
94  {
95  const char ch = value[i];
96 
97  if( ch == '\\' )
98  {
99  out += "\\\\";
100  }
101  else if( ch == '"' )
102  {
103  out += "\\\"";
104  }
105  else if( ch == '\b' )
106  {
107  out += "\\b";
108  }
109  else if( ch == '\f' )
110  {
111  out += "\\f";
112  }
113  else if( ch == '\n' )
114  {
115  out += "\\n";
116  }
117  else if( ch == '\r' )
118  {
119  out += "\\r";
120  }
121  else if( ch == '\t' )
122  {
123  out += "\\t";
124  }
125  else if( static_cast<uint8_t>(ch) <= 0x1f )
126  {
127  char buf[8];
128  snprintf( buf, sizeof buf, "\\u%04x", ch );
129  out += buf;
130  }
131  else if( static_cast<uint8_t>(ch) == 0xe2 && static_cast<uint8_t>(value[i + 1]) == 0x80
132  && static_cast<uint8_t>(value[i + 2]) == 0xa8 )
133  {
134  out += "\\u2028";
135  i += 2;
136  }
137  else if( static_cast<uint8_t>(ch) == 0xe2 && static_cast<uint8_t>(value[i + 1]) == 0x80
138  && static_cast<uint8_t>(value[i + 2]) == 0xa9 )
139  {
140  out += "\\u2029";
141  i += 2;
142  }
143  else
144  {
145  out += ch;
146  }
147  }
148 
149  out += '"';
150 }
151 
152 
153 static void dump( const Json::array& values, string& out )
154 {
155  bool first = true;
156 
157  out += "[";
158 
159  for( const auto& value : values )
160  {
161  if( !first )
162  out += ", ";
163 
164  value.dump( out );
165  first = false;
166  }
167 
168  out += "]";
169 }
170 
171 
172 static void dump( const Json::object& values, string& out )
173 {
174  bool first = true;
175 
176  out += "{";
177 
178  for( const auto& kv : values )
179  {
180  if( !first )
181  out += ", ";
182 
183  dump( kv.first, out );
184  out += ": ";
185  kv.second.dump( out );
186  first = false;
187  }
188 
189  out += "}";
190 }
191 
192 
193 void Json::dump( string& out ) const
194 {
195  m_ptr->dump( out );
196 }
197 
198 
199 /* * * * * * * * * * * * * * * * * * * *
200  * Value wrappers
201  */
202 
203 template <Json::Type tag, typename T>
204 class Value : public JsonValue
205 {
206 protected:
207 
208  // Constructors
209  explicit Value( const T& value ) : m_value( value ) {}
210  explicit Value( T&& value ) : m_value( move( value ) ) {}
211 
212  // Get type tag
213  Json::Type type() const override
214  {
215  return tag;
216  }
217 
218  // Comparisons
219  bool equals( const JsonValue* other ) const override
220  {
221  return m_value == static_cast<const Value<tag, T>*>(other)->m_value;
222  }
223 
224  bool less( const JsonValue* other ) const override
225  {
226  return m_value < static_cast<const Value<tag, T>*>(other)->m_value;
227  }
228 
229  const T m_value;
230  void dump( string& out ) const override { json11::dump( m_value, out ); }
231 };
232 
233 class JsonDouble final : public Value<Json::NUMBER, double>
234 {
235  double number_value() const override { return m_value; }
236  int int_value() const override { return static_cast<int>(m_value); }
237  bool equals( const JsonValue* other ) const override
238  {
239  return m_value == other->number_value();
240  }
241  bool less( const JsonValue* other ) const override
242  {
243  return m_value < other->number_value();
244  }
245 
246 public:
247  explicit JsonDouble( double value ) : Value( value ) {}
248 };
249 
250 class JsonInt final : public Value<Json::NUMBER, int>
251 {
252  double number_value() const override { return m_value; }
253  int int_value() const override { return m_value; }
254  bool equals( const JsonValue* other ) const override
255  {
256  return m_value == other->number_value();
257  }
258  bool less( const JsonValue* other ) const override
259  {
260  return m_value < other->number_value();
261  }
262 
263 public:
264  explicit JsonInt( int value ) : Value( value ) {}
265 };
266 
267 class JsonBoolean final : public Value<Json::BOOL, bool>
268 {
269  bool bool_value() const override { return m_value; }
270 
271 public:
272  explicit JsonBoolean( bool value ) : Value( value ) {}
273 };
274 
275 class JsonString final : public Value<Json::STRING, string>
276 {
277  const string& string_value() const override { return m_value; }
278 
279 public:
280  explicit JsonString( const string& value ) : Value( value ) {}
281  explicit JsonString( string&& value ) : Value( move( value ) ) {}
282 };
283 
284 class JsonArray final : public Value<Json::ARRAY, Json::array>
285 {
286  const Json::array& array_items() const override { return m_value; }
287  const Json& operator[]( size_t i ) const override;
288 
289 public:
290  explicit JsonArray( const Json::array& value ) : Value( value ) {}
291  explicit JsonArray( Json::array&& value ) : Value( move( value ) ) {}
292 };
293 
294 class JsonObject final : public Value<Json::OBJECT, Json::object>
295 {
296  const Json::object& object_items() const override { return m_value; }
297  const Json& operator[]( const string& key ) const override;
298 
299 public:
300  explicit JsonObject( const Json::object& value ) : Value( value ) {}
301  explicit JsonObject( Json::object&& value ) : Value( move( value ) ) {}
302 };
303 
304 class JsonNull final : public Value<Json::NUL, NullStruct>
305 {
306 public:
307  JsonNull() : Value( {} ) {}
308 };
309 
310 /* * * * * * * * * * * * * * * * * * * *
311  * Static globals - static-init-safe
312  */
313 struct Statics
314 {
315  const std::shared_ptr<JsonValue> null = make_shared<JsonNull>();
316  const std::shared_ptr<JsonValue> t = make_shared<JsonBoolean>( true );
317  const std::shared_ptr<JsonValue> f = make_shared<JsonBoolean>( false );
318  const string empty_string;
319  const vector<Json> empty_vector;
320  const map<string, Json> empty_map;
321  Statics() {}
322 };
323 
324 static const Statics& statics()
325 {
326  static const Statics s {};
327 
328  return s;
329 }
330 
331 
332 static const Json& static_null()
333 {
334  // This has to be separate, not in Statics, because Json() accesses statics().null.
335  static const Json json_null;
336 
337  return json_null;
338 }
339 
340 
341 /* * * * * * * * * * * * * * * * * * * *
342  * Constructors
343  */
344 
345 Json::Json() noexcept : m_ptr( statics().null )
346 {
347 }
348 
349 
350 Json::Json( std::nullptr_t ) noexcept : m_ptr( statics().null )
351 {
352 }
353 
354 
355 Json::Json( double value ) : m_ptr( make_shared<JsonDouble>( value ) )
356 {
357 }
358 
359 
360 Json::Json( int value ) : m_ptr( make_shared<JsonInt>( value ) )
361 {
362 }
363 
364 
365 Json::Json( bool value ) : m_ptr( value ? statics().t : statics().f )
366 {
367 }
368 
369 
370 Json::Json( const string& value ) : m_ptr( make_shared<JsonString>( value ) )
371 {
372 }
373 
374 
375 Json::Json( string&& value ) : m_ptr( make_shared<JsonString>( move( value ) ) )
376 {
377 }
378 
379 
380 Json::Json( const char* value ) : m_ptr( make_shared<JsonString>( value ) )
381 {
382 }
383 
384 
385 Json::Json( const Json::array& values ) : m_ptr( make_shared<JsonArray>( values ) )
386 {
387 }
388 
389 
390 Json::Json( Json::array&& values ) : m_ptr( make_shared<JsonArray>( move( values ) ) )
391 {
392 }
393 
394 
395 Json::Json( const Json::object& values ) : m_ptr( make_shared<JsonObject>( values ) )
396 {
397 }
398 
399 
400 Json::Json( Json::object&& values ) : m_ptr( make_shared<JsonObject>( move( values ) ) )
401 {
402 }
403 
404 
405 /* * * * * * * * * * * * * * * * * * * *
406  * Accessors
407  */
408 
409 Json::Type Json::type() const
410 {
411  return m_ptr->type();
412 }
413 
414 
415 double Json::number_value() const
416 {
417  return m_ptr->number_value();
418 }
419 
420 
421 int Json::int_value() const
422 {
423  return m_ptr->int_value();
424 }
425 
426 
427 bool Json::bool_value() const
428 {
429  return m_ptr->bool_value();
430 }
431 
432 
433 const string& Json::string_value() const
434 {
435  return m_ptr->string_value();
436 }
437 
438 
439 const vector<Json>& Json::array_items() const
440 {
441  return m_ptr->array_items();
442 }
443 
444 
445 const map<string, Json>& Json::object_items() const
446 {
447  return m_ptr->object_items();
448 }
449 
450 
451 const Json& Json::operator[]( size_t i ) const
452 {
453  return (*m_ptr)[i];
454 }
455 
456 
457 const Json& Json::operator[]( const string& key ) const
458 {
459  return (*m_ptr)[key];
460 }
461 
462 
463 double JsonValue::number_value() const
464 {
465  return 0;
466 }
467 
468 
469 int JsonValue::int_value() const
470 {
471  return 0;
472 }
473 
474 
475 bool JsonValue::bool_value() const
476 {
477  return false;
478 }
479 
480 
481 const string& JsonValue::string_value() const
482 {
483  return statics().empty_string;
484 }
485 
486 
487 const vector<Json>& JsonValue::array_items() const
488 {
489  return statics().empty_vector;
490 }
491 
492 
493 const map<string, Json>& JsonValue::object_items() const
494 {
495  return statics().empty_map;
496 }
497 
498 
499 const Json& JsonValue::operator[]( size_t ) const
500 {
501  return static_null();
502 }
503 
504 
505 const Json& JsonValue::operator[]( const string& ) const
506 {
507  return static_null();
508 }
509 
510 
511 const Json& JsonObject::operator[]( const string& key ) const
512 {
513  auto iter = m_value.find( key );
514 
515  return ( iter == m_value.end() ) ? static_null() : iter->second;
516 }
517 
518 
519 const Json& JsonArray::operator[]( size_t i ) const
520 {
521  if( i >= m_value.size() )
522  return static_null();
523  else
524  return m_value[i];
525 }
526 
527 
528 /* * * * * * * * * * * * * * * * * * * *
529  * Comparison
530  */
531 
532 bool Json::operator==( const Json& other ) const
533 {
534  if( m_ptr == other.m_ptr )
535  return true;
536 
537  if( m_ptr->type() != other.m_ptr->type() )
538  return false;
539 
540  return m_ptr->equals( other.m_ptr.get() );
541 }
542 
543 
544 bool Json::operator<( const Json& other ) const
545 {
546  if( m_ptr == other.m_ptr )
547  return false;
548 
549  if( m_ptr->type() != other.m_ptr->type() )
550  return m_ptr->type() < other.m_ptr->type();
551 
552  return m_ptr->less( other.m_ptr.get() );
553 }
554 
555 
556 /* * * * * * * * * * * * * * * * * * * *
557  * Parsing
558  */
559 
560 /* esc(c)
561  *
562  * Format char c suitable for printing in an error message.
563  */
564 static inline string esc( char c )
565 {
566  char buf[12];
567 
568  if( static_cast<uint8_t>(c) >= 0x20 && static_cast<uint8_t>(c) <= 0x7f )
569  {
570  snprintf( buf, sizeof buf, "'%c' (%d)", c, c );
571  }
572  else
573  {
574  snprintf( buf, sizeof buf, "(%d)", c );
575  }
576 
577  return string( buf );
578 }
579 
580 
581 static inline bool in_range( long x, long lower, long upper )
582 {
583  return x >= lower && x <= upper;
584 }
585 
586 
587 namespace {
588 /* JsonParser
589  *
590  * Object that tracks all state of an in-progress parse.
591  */
592 struct JsonParser final
593 {
594  /* State
595  */
596  const string& str;
597  size_t i;
598  string& err;
599  bool failed;
600  const JsonParse strategy;
601 
602  /* fail(msg, err_ret = Json())
603  *
604  * Mark this parse as failed.
605  */
606  Json fail( string&& msg )
607  {
608  return fail( move( msg ), Json() );
609  }
610 
611  template <typename T>
612  T fail( string&& msg, const T err_ret )
613  {
614  if( !failed )
615  err = std::move( msg );
616 
617  failed = true;
618  return err_ret;
619  }
620 
621  /* consume_whitespace()
622  *
623  * Advance until the current character is non-whitespace.
624  */
625  void consume_whitespace()
626  {
627  while( str[i] == ' ' || str[i] == '\r' || str[i] == '\n' || str[i] == '\t' )
628  i++;
629  }
630 
631  /* consume_comment()
632  *
633  * Advance comments (c-style inline and multiline).
634  */
635  bool consume_comment()
636  {
637  bool comment_found = false;
638 
639  if( str[i] == '/' )
640  {
641  i++;
642 
643  if( i == str.size() )
644  return fail( "unexpected end of input after start of comment", false );
645 
646  if( str[i] == '/' ) // inline comment
647  {
648  i++;
649 
650  // advance until next line, or end of input
651  while( i < str.size() && str[i] != '\n' )
652  {
653  i++;
654  }
655 
656  comment_found = true;
657  }
658  else if( str[i] == '*' ) // multiline comment
659  {
660  i++;
661 
662  if( i > str.size() - 2 )
663  return fail( "unexpected end of input inside multi-line comment", false );
664 
665  // advance until closing tokens
666  while( !(str[i] == '*' && str[i + 1] == '/') )
667  {
668  i++;
669 
670  if( i > str.size() - 2 )
671  return fail(
672  "unexpected end of input inside multi-line comment", false );
673  }
674 
675  i += 2;
676  comment_found = true;
677  }
678  else
679  return fail( "malformed comment", false );
680  }
681 
682  return comment_found;
683  }
684 
685  /* consume_garbage()
686  *
687  * Advance until the current character is non-whitespace and non-comment.
688  */
689  void consume_garbage()
690  {
691  consume_whitespace();
692 
693  if( strategy == JsonParse::COMMENTS )
694  {
695  bool comment_found = false;
696 
697  do {
698  comment_found = consume_comment();
699 
700  if( failed ) return;
701 
702  consume_whitespace();
703  } while( comment_found );
704  }
705  }
706 
707  /* get_next_token()
708  *
709  * Return the next non-whitespace character. If the end of the input is reached,
710  * flag an error and return 0.
711  */
712  char get_next_token()
713  {
714  consume_garbage();
715 
716  if( failed ) return (char) 0;
717 
718  if( i == str.size() )
719  return fail( "unexpected end of input", (char) 0 );
720 
721  return str[i++];
722  }
723 
724  /* encode_utf8(pt, out)
725  *
726  * Encode pt as UTF-8 and add it to out.
727  */
728  void encode_utf8( long pt, string& out )
729  {
730  if( pt < 0 )
731  return;
732 
733  if( pt < 0x80 )
734  {
735  out += static_cast<char>(pt);
736  }
737  else if( pt < 0x800 )
738  {
739  out += static_cast<char>( (pt >> 6) | 0xC0 );
740  out += static_cast<char>( (pt & 0x3F) | 0x80 );
741  }
742  else if( pt < 0x10000 )
743  {
744  out += static_cast<char>( (pt >> 12) | 0xE0 );
745  out += static_cast<char>( ( (pt >> 6) & 0x3F ) | 0x80 );
746  out += static_cast<char>( (pt & 0x3F) | 0x80 );
747  }
748  else
749  {
750  out += static_cast<char>( (pt >> 18) | 0xF0 );
751  out += static_cast<char>( ( (pt >> 12) & 0x3F ) | 0x80 );
752  out += static_cast<char>( ( (pt >> 6) & 0x3F ) | 0x80 );
753  out += static_cast<char>( (pt & 0x3F) | 0x80 );
754  }
755  }
756 
757  /* parse_string()
758  *
759  * Parse a string, starting at the current position.
760  */
761  string parse_string()
762  {
763  string out;
764  long last_escaped_codepoint = -1;
765 
766  while( true )
767  {
768  if( i == str.size() )
769  return fail( "unexpected end of input in string", "" );
770 
771  char ch = str[i++];
772 
773  if( ch == '"' )
774  {
775  encode_utf8( last_escaped_codepoint, out );
776  return out;
777  }
778 
779  if( in_range( ch, 0, 0x1f ) )
780  return fail( "unescaped " + esc( ch ) + " in string", "" );
781 
782  // The usual case: non-escaped characters
783  if( ch != '\\' )
784  {
785  encode_utf8( last_escaped_codepoint, out );
786  last_escaped_codepoint = -1;
787  out += ch;
788  continue;
789  }
790 
791  // Handle escapes
792  if( i == str.size() )
793  return fail( "unexpected end of input in string", "" );
794 
795  ch = str[i++];
796 
797  if( ch == 'u' )
798  {
799  // Extract 4-byte escape sequence
800  string esc = str.substr( i, 4 );
801 
802  // Explicitly check length of the substring. The following loop
803  // relies on std::string returning the terminating NUL when
804  // accessing str[length]. Checking here reduces brittleness.
805  if( esc.length() < 4 )
806  {
807  return fail( "bad \\u escape: " + esc, "" );
808  }
809 
810  for( size_t j = 0; j < 4; j++ )
811  {
812  if( !in_range( esc[j], 'a', 'f' ) && !in_range( esc[j], 'A', 'F' )
813  && !in_range( esc[j], '0', '9' ) )
814  return fail( "bad \\u escape: " + esc, "" );
815  }
816 
817  long codepoint = strtol( esc.data(), nullptr, 16 );
818 
819  // JSON specifies that characters outside the BMP shall be encoded as a pair
820  // of 4-hex-digit \u escapes encoding their surrogate pair components. Check
821  // whether we're in the middle of such a beast: the previous codepoint was an
822  // escaped lead (high) surrogate, and this is a trail (low) surrogate.
823  if( in_range( last_escaped_codepoint, 0xD800, 0xDBFF )
824  && in_range( codepoint, 0xDC00, 0xDFFF ) )
825  {
826  // Reassemble the two surrogate pairs into one astral-plane character, per
827  // the UTF-16 algorithm.
828  encode_utf8( ( ( (last_escaped_codepoint - 0xD800) << 10 )
829  | (codepoint - 0xDC00) ) + 0x10000, out );
830  last_escaped_codepoint = -1;
831  }
832  else
833  {
834  encode_utf8( last_escaped_codepoint, out );
835  last_escaped_codepoint = codepoint;
836  }
837 
838  i += 4;
839  continue;
840  }
841 
842  encode_utf8( last_escaped_codepoint, out );
843  last_escaped_codepoint = -1;
844 
845  if( ch == 'b' )
846  {
847  out += '\b';
848  }
849  else if( ch == 'f' )
850  {
851  out += '\f';
852  }
853  else if( ch == 'n' )
854  {
855  out += '\n';
856  }
857  else if( ch == 'r' )
858  {
859  out += '\r';
860  }
861  else if( ch == 't' )
862  {
863  out += '\t';
864  }
865  else if( ch == '"' || ch == '\\' || ch == '/' )
866  {
867  out += ch;
868  }
869  else
870  {
871  return fail( "invalid escape character " + esc( ch ), "" );
872  }
873  }
874  }
875 
876  /* parse_number()
877  *
878  * Parse a double.
879  */
880  Json parse_number()
881  {
882  size_t start_pos = i;
883 
884  if( str[i] == '-' )
885  i++;
886 
887  // Integer part
888  if( str[i] == '0' )
889  {
890  i++;
891 
892  if( in_range( str[i], '0', '9' ) )
893  return fail( "leading 0s not permitted in numbers" );
894  }
895  else if( in_range( str[i], '1', '9' ) )
896  {
897  i++;
898 
899  while( in_range( str[i], '0', '9' ) )
900  i++;
901  }
902  else
903  {
904  return fail( "invalid " + esc( str[i] ) + " in number" );
905  }
906 
907  if( str[i] != '.' && str[i] != 'e' && str[i] != 'E'
908  && (i - start_pos) <= static_cast<size_t>(std::numeric_limits<int>::digits10) )
909  {
910  return std::atoi( str.c_str() + start_pos );
911  }
912 
913  // Decimal part
914  if( str[i] == '.' )
915  {
916  i++;
917 
918  if( !in_range( str[i], '0', '9' ) )
919  return fail( "at least one digit required in fractional part" );
920 
921  while( in_range( str[i], '0', '9' ) )
922  i++;
923  }
924 
925  // Exponent part
926  if( str[i] == 'e' || str[i] == 'E' )
927  {
928  i++;
929 
930  if( str[i] == '+' || str[i] == '-' )
931  i++;
932 
933  if( !in_range( str[i], '0', '9' ) )
934  return fail( "at least one digit required in exponent" );
935 
936  while( in_range( str[i], '0', '9' ) )
937  i++;
938  }
939 
940  return std::strtod( str.c_str() + start_pos, nullptr );
941  }
942 
943  /* expect(str, res)
944  *
945  * Expect that 'str' starts at the character that was just read. If it does, advance
946  * the input and return res. If not, flag an error.
947  */
948  Json expect( const string& expected, Json res )
949  {
950  assert( i != 0 );
951  i--;
952 
953  if( str.compare( i, expected.length(), expected ) == 0 )
954  {
955  i += expected.length();
956  return res;
957  }
958  else
959  {
960  return fail( "parse error: expected " + expected + ", got " +
961  str.substr( i, expected.length() ) );
962  }
963  }
964 
965  /* parse_json()
966  *
967  * Parse a JSON object.
968  */
969  Json parse_json( int depth )
970  {
971  if( depth > max_depth )
972  {
973  return fail( "exceeded maximum nesting depth" );
974  }
975 
976  char ch = get_next_token();
977 
978  if( failed )
979  return Json();
980 
981  if( ch == '-' || (ch >= '0' && ch <= '9') )
982  {
983  i--;
984  return parse_number();
985  }
986 
987  if( ch == 't' )
988  return expect( "true", true );
989 
990  if( ch == 'f' )
991  return expect( "false", false );
992 
993  if( ch == 'n' )
994  return expect( "null", Json() );
995 
996  if( ch == '"' )
997  return parse_string();
998 
999  if( ch == '{' )
1000  {
1001  map<string, Json> data;
1002  ch = get_next_token();
1003 
1004  if( ch == '}' )
1005  return data;
1006 
1007  while( 1 )
1008  {
1009  if( ch != '"' )
1010  return fail( "expected '\"' in object, got " + esc( ch ) );
1011 
1012  string key = parse_string();
1013 
1014  if( failed )
1015  return Json();
1016 
1017  ch = get_next_token();
1018 
1019  if( ch != ':' )
1020  return fail( "expected ':' in object, got " + esc( ch ) );
1021 
1022  data[std::move( key )] = parse_json( depth + 1 );
1023 
1024  if( failed )
1025  return Json();
1026 
1027  ch = get_next_token();
1028 
1029  if( ch == '}' )
1030  break;
1031 
1032  if( ch != ',' )
1033  return fail( "expected ',' in object, got " + esc( ch ) );
1034 
1035  ch = get_next_token();
1036  }
1037 
1038  return data;
1039  }
1040 
1041  if( ch == '[' )
1042  {
1043  vector<Json> data;
1044  ch = get_next_token();
1045 
1046  if( ch == ']' )
1047  return data;
1048 
1049  while( 1 )
1050  {
1051  i--;
1052  data.push_back( parse_json( depth + 1 ) );
1053 
1054  if( failed )
1055  return Json();
1056 
1057  ch = get_next_token();
1058 
1059  if( ch == ']' )
1060  break;
1061 
1062  if( ch != ',' )
1063  return fail( "expected ',' in list, got " + esc( ch ) );
1064 
1065  ch = get_next_token();
1066  (void) ch;
1067  }
1068 
1069  return data;
1070  }
1071 
1072  return fail( "expected value, got " + esc( ch ) );
1073  }
1074 };
1075 } // namespace {
1076 
1077 Json Json::parse( const string& in, string& err, JsonParse strategy )
1078 {
1079  JsonParser parser {
1080  in, 0, err, false, strategy
1081  };
1082  Json result = parser.parse_json( 0 );
1083 
1084  // Check for any trailing garbage
1085  parser.consume_garbage();
1086 
1087  if( parser.failed )
1088  return Json();
1089 
1090  if( parser.i != in.size() )
1091  return parser.fail( "unexpected trailing " + esc( in[parser.i] ) );
1092 
1093  return result;
1094 }
1095 
1096 
1097 // Documented in json11.hpp
1098 vector<Json> Json::parse_multi( const string& in,
1099  std::string::size_type& parser_stop_pos,
1100  string& err,
1101  JsonParse strategy )
1102 {
1103  JsonParser parser {
1104  in, 0, err, false, strategy
1105  };
1106 
1107  parser_stop_pos = 0;
1108  vector<Json> json_vec;
1109 
1110  while( parser.i != in.size() && !parser.failed )
1111  {
1112  json_vec.push_back( parser.parse_json( 0 ) );
1113 
1114  if( parser.failed )
1115  break;
1116 
1117  // Check for another object
1118  parser.consume_garbage();
1119 
1120  if( parser.failed )
1121  break;
1122 
1123  parser_stop_pos = parser.i;
1124  }
1125 
1126  return json_vec;
1127 }
1128 
1129 
1130 /* * * * * * * * * * * * * * * * * * * *
1131  * Shape-checking
1132  */
1133 
1134 bool Json::has_shape( const shape& types, string& err ) const
1135 {
1136  if( !is_object() )
1137  {
1138  err = "expected JSON object, got " + dump();
1139  return false;
1140  }
1141 
1142  for( auto& item : types )
1143  {
1144  if( (*this)[item.first].type() != item.second )
1145  {
1146  err = "bad type for " + item.first + " in " + dump();
1147  return false;
1148  }
1149  }
1150 
1151  return true;
1152 }
1153 } // namespace json11
bool operator<(NullStruct) const
Definition: json11.cpp:46
bool equals(const JsonValue *other) const override
Definition: json11.cpp:237
int int_value() const override
Definition: json11.cpp:236
void dump(string &out) const override
Definition: json11.cpp:230
const Json::object & object_items() const override
Definition: json11.cpp:296
bool less(const JsonValue *other) const override
Definition: json11.cpp:224
static const Json & static_null()
Definition: json11.cpp:332
double number_value() const override
Definition: json11.cpp:252
const Json & operator[](size_t i) const override
Definition: json11.cpp:519
const Json::array & array_items() const override
Definition: json11.cpp:286
const T m_value
Definition: json11.cpp:229
const string empty_string
Definition: json11.cpp:318
static bool in_range(long x, long lower, long upper)
Definition: json11.cpp:581
static void dump(const Json::object &values, string &out)
Definition: json11.cpp:172
JsonArray(const Json::array &value)
Definition: json11.cpp:290
bool operator<(const COMPONENT &item1, const COMPONENT &item2)
Operator < compares two COMPONENT objects by reference designator.
bool operator==(const PART_LIB &aLibrary, const wxString &aName)
Case insensitive library name comparison.
#define kv
Json::Type type() const override
Definition: json11.cpp:213
const string & str
Definition: json11.cpp:596
JsonArray(Json::array &&value)
Definition: json11.cpp:291
Value(const T &value)
Definition: json11.cpp:209
static void dump(NullStruct, string &out)
Definition: json11.cpp:53
JsonDouble(double value)
Definition: json11.cpp:247
int int_value() const override
Definition: json11.cpp:253
bool less(const JsonValue *other) const override
Definition: json11.cpp:241
bool equals(const JsonValue *other) const override
Definition: json11.cpp:254
JsonString(string &&value)
Definition: json11.cpp:281
static string esc(char c)
Definition: json11.cpp:564
string & err
Definition: json11.cpp:598
static const int max_depth
Definition: json11.cpp:30
double number_value() const override
Definition: json11.cpp:235
bool bool_value() const override
Definition: json11.cpp:269
const map< string, Json > empty_map
Definition: json11.cpp:320
const string & string_value() const override
Definition: json11.cpp:277
bool failed
Definition: json11.cpp:599
const Json & operator[](const string &key) const override
Definition: json11.cpp:511
Value(T &&value)
Definition: json11.cpp:210
const JsonParse strategy
Definition: json11.cpp:600
size_t i
Definition: json11.cpp:597
JsonBoolean(bool value)
Definition: json11.cpp:272
bool operator==(NullStruct) const
Definition: json11.cpp:45
JsonString(const string &value)
Definition: json11.cpp:280
JsonObject(const Json::object &value)
Definition: json11.cpp:300
static const Statics & statics()
Definition: json11.cpp:324
const vector< Json > empty_vector
Definition: json11.cpp:319
JsonInt(int value)
Definition: json11.cpp:264
bool less(const JsonValue *other) const override
Definition: json11.cpp:258
JsonObject(Json::object &&value)
Definition: json11.cpp:301
bool equals(const JsonValue *other) const override
Definition: json11.cpp:219