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