Crow  1.1
A C++ microframework for the web
 
Loading...
Searching...
No Matches
json.h
1#pragma once
2
3//#define CROW_JSON_NO_ERROR_CHECK
4//#define CROW_JSON_USE_MAP
5//#define CROW_JSON_USE_INSERTION_ORDER
6
7#include <string>
8#include <map>
9#include <unordered_map>
10#include <iostream>
11#include <algorithm>
12#include <memory>
13#include <vector>
14#include <cmath>
15#include <cfloat>
16#include <utility>
17
18#include "crow/utility.h"
19#include "crow/settings.h"
20#include "crow/returnable.h"
21#include "crow/logging.h"
22
23using std::isinf;
24using std::isnan;
25
26#ifdef __CHAR_UNSIGNED__
27#define IS_CONTROL_ASCII(c) (c < 0x20)
28#else
29#define IS_CONTROL_ASCII(c) ((c >= 0) && (c < 0x20))
30#endif
31
32namespace crow // NOTE: Already documented in "crow/app.h"
33{
34 namespace mustache
35 {
36 class template_t;
37 }
38
39 namespace json
40 {
41 static inline char to_hex(char c)
42 {
43 c = c & 0xf;
44 if (c < 10)
45 return '0' + c;
46 return 'a' + c - 10;
47 }
48
49 inline void escape(const std::string& str, std::string& ret)
50 {
51 ret.reserve(ret.size() + str.size() + str.size() / 4);
52 for (auto c : str)
53 {
54 switch (c)
55 {
56 case '"': ret += "\\\""; break;
57 case '\\': ret += "\\\\"; break;
58 case '\n': ret += "\\n"; break;
59 case '\b': ret += "\\b"; break;
60 case '\f': ret += "\\f"; break;
61 case '\r': ret += "\\r"; break;
62 case '\t': ret += "\\t"; break;
63 default:
64 if (IS_CONTROL_ASCII(c))
65 {
66 ret += "\\u00";
67 ret += to_hex(c / 16);
68 ret += to_hex(c % 16);
69 }
70 else
71 ret += c;
72 break;
73 }
74 }
75 }
76 inline std::string escape(const std::string& str)
77 {
78 std::string ret;
79 escape(str, ret);
80 return ret;
81 }
82
83 enum class type : char
84 {
85 Null,
86 False,
87 True,
88 Number,
89 String,
90 List,
91 Object,
92 Function
93 };
94
95 inline const char* get_type_str(type t)
96 {
97 switch (t)
98 {
99 case type::Number: return "Number";
100 case type::False: return "False";
101 case type::True: return "True";
102 case type::List: return "List";
103 case type::String: return "String";
104 case type::Object: return "Object";
105 case type::Function: return "Function";
106 default: return "Unknown";
107 }
108 }
109
110 enum class num_type : char
111 {
112 Signed_integer,
113 Unsigned_integer,
114 Floating_point,
115 Null,
116 Double_precision_floating_point
117 };
118
119 class rvalue;
120 rvalue load(const char* data, size_t size);
121
122 namespace detail
123 {
124 /// A read string implementation with comparison functionality.
125 struct r_string
126 {
127 r_string(){}
128 r_string(char* s, char* e):
129 s_(s), e_(e){}
130 ~r_string()
131 {
132 if (owned_)
133 delete[] s_;
134 }
135
136 r_string(const r_string& r)
137 {
138 *this = r;
139 }
140
141 r_string(r_string&& r)
142 {
143 *this = std::move(r);
144 }
145
146 r_string& operator=(r_string&& r)
147 {
148 if (this == &r)
149 return *this;
150
151 if (owned_)
152 delete[] s_;
153
154 s_ = r.s_;
155 e_ = r.e_;
156 owned_ = r.owned_;
157 if (r.owned_)
158 r.owned_ = 0;
159 return *this;
160 }
161
162 r_string& operator=(const r_string& r)
163 {
164 if (this == &r)
165 return *this;
166
167 s_ = r.s_;
168 e_ = r.e_;
169 owned_ = 0;
170 return *this;
171 }
172
173 operator std::string() const
174 {
175 return std::string(s_, e_);
176 }
177
178
179 const char* begin() const { return s_; }
180 const char* end() const { return e_; }
181 size_t size() const { return end() - begin(); }
182
183 using iterator = const char*;
184 using const_iterator = const char*;
185
186 char* s_; ///< Start.
187 mutable char* e_; ///< End.
188 uint8_t owned_{0};
189 friend std::ostream& operator<<(std::ostream& os, const r_string& s)
190 {
191 os << static_cast<std::string>(s);
192 return os;
193 }
194
195 private:
196 void force(char* s, size_t length)
197 {
198 s_ = s;
199 e_ = s_ + length;
200 owned_ = 1;
201 }
202 friend rvalue crow::json::load(const char* data, size_t size);
203
204 friend bool operator==(const r_string& l, const r_string& r);
205 friend bool operator==(const std::string& l, const r_string& r);
206 friend bool operator==(const r_string& l, const std::string& r);
207
208 template<typename T, typename U>
209 inline static bool equals(const T& l, const U& r)
210 {
211 if (l.size() != r.size())
212 return false;
213
214 for (size_t i = 0; i < l.size(); i++)
215 {
216 if (*(l.begin() + i) != *(r.begin() + i))
217 return false;
218 }
219
220 return true;
221 }
222 };
223
224 inline bool operator<(const r_string& l, const r_string& r)
225 {
226 return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end());
227 }
228
229 inline bool operator<(const r_string& l, const std::string& r)
230 {
231 return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end());
232 }
233
234 inline bool operator<(const std::string& l, const r_string& r)
235 {
236 return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end());
237 }
238
239 inline bool operator>(const r_string& l, const r_string& r)
240 {
241 return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end());
242 }
243
244 inline bool operator>(const r_string& l, const std::string& r)
245 {
246 return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end());
247 }
248
249 inline bool operator>(const std::string& l, const r_string& r)
250 {
251 return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end());
252 }
253
254 inline bool operator==(const r_string& l, const r_string& r)
255 {
256 return r_string::equals(l, r);
257 }
258
259 inline bool operator==(const r_string& l, const std::string& r)
260 {
261 return r_string::equals(l, r);
262 }
263
264 inline bool operator==(const std::string& l, const r_string& r)
265 {
266 return r_string::equals(l, r);
267 }
268
269 inline bool operator!=(const r_string& l, const r_string& r)
270 {
271 return !(l == r);
272 }
273
274 inline bool operator!=(const r_string& l, const std::string& r)
275 {
276 return !(l == r);
277 }
278
279 inline bool operator!=(const std::string& l, const r_string& r)
280 {
281 return !(l == r);
282 }
283
285 {
286 template<typename Value>
287 using object_type =
288 std::unordered_map<std::string, Value>;
289 };
290
292 {
293 template<typename Value>
294 using object_type =
295 std::map<std::string, Value>;
296 };
297
299 {
300 template<typename Value>
301 using object_type = utility::ordered_object<std::string, Value>;
302 };
303
304#if defined(CROW_JSON_USE_INSERTION_ORDER) && defined(CROW_JSON_USE_MAP)
305#error "Only one JSON object ordering policy may be selected"
306#elif defined(CROW_JSON_USE_INSERTION_ORDER)
308#elif defined(CROW_JSON_USE_MAP)
310#else
312#endif
313
314 } // namespace detail
315
316 /// JSON read value.
317
318 ///
319 /// Value can mean any json value, including a JSON object.
320 /// Read means this class is used to primarily read strings into a JSON value.
321 class rvalue
322 {
323 static const int cached_bit = 2;
324 static const int error_bit = 4;
325
326 public:
327 rvalue() noexcept:
328 option_{error_bit}
329 {
330 }
331 rvalue(type t) noexcept:
332 lsize_{}, lremain_{}, t_{t}
333 {
334 }
335 rvalue(type t, char* s, char* e) noexcept:
336 start_{s}, end_{e}, t_{t}
337 {
338 determine_num_type();
339 }
340
341 rvalue(const rvalue& r):
342 start_(r.start_), end_(r.end_), key_(r.key_), t_(r.t_), nt_(r.nt_), option_(r.option_)
343 {
344 copy_l(r);
345 }
346
347 rvalue(rvalue&& r) noexcept
348 {
349 *this = std::move(r);
350 }
351
352 rvalue& operator=(const rvalue& r)
353 {
354 start_ = r.start_;
355 end_ = r.end_;
356 key_ = r.key_;
357 t_ = r.t_;
358 nt_ = r.nt_;
359 option_ = r.option_;
360 copy_l(r);
361 return *this;
362 }
363 rvalue& operator=(rvalue&& r) noexcept
364 {
365 start_ = r.start_;
366 end_ = r.end_;
367 key_ = std::move(r.key_);
368 l_ = std::move(r.l_);
369 lsize_ = r.lsize_;
370 lremain_ = r.lremain_;
371 t_ = r.t_;
372 nt_ = r.nt_;
373 option_ = r.option_;
374 return *this;
375 }
376
377 explicit operator bool() const noexcept
378 {
379 return (option_ & error_bit) == 0;
380 }
381
382 explicit operator int64_t() const
383 {
384 return i();
385 }
386
387 explicit operator uint64_t() const
388 {
389 return u();
390 }
391
392 explicit operator int() const
393 {
394 return static_cast<int>(i());
395 }
396
397 /// Return any json value (not object or list) as a string.
398 explicit operator std::string() const
399 {
400#ifndef CROW_JSON_NO_ERROR_CHECK
401 if (t() == type::Object || t() == type::List)
402 throw std::runtime_error("json type container");
403#endif
404 switch (t())
405 {
406 case type::String:
407 return std::string(s());
408 case type::Null:
409 return std::string("null");
410 case type::True:
411 return std::string("true");
412 case type::False:
413 return std::string("false");
414 default:
415 return std::string(start_, end_ - start_);
416 }
417 }
418
419 /// The type of the JSON value.
420 type t() const
421 {
422#ifndef CROW_JSON_NO_ERROR_CHECK
423 if (option_ & error_bit)
424 {
425 throw std::runtime_error("invalid json object");
426 }
427#endif
428 return t_;
429 }
430
431 /// The number type of the JSON value.
432 num_type nt() const
433 {
434#ifndef CROW_JSON_NO_ERROR_CHECK
435 if (option_ & error_bit)
436 {
437 throw std::runtime_error("invalid json object");
438 }
439#endif
440 return nt_;
441 }
442
443 /// The integer value.
444 int64_t i() const
445 {
446#ifndef CROW_JSON_NO_ERROR_CHECK
447 switch (t())
448 {
449 case type::Number:
450 case type::String:
451 return utility::lexical_cast<int64_t>(start_, end_ - start_);
452 default:
453 const std::string msg = "expected number, got: " + std::string(get_type_str(t()));
454 throw std::runtime_error(msg);
455 }
456#else
457 return utility::lexical_cast<int64_t>(start_, end_ - start_);
458#endif
459 }
460
461 /// The unsigned integer value.
462 uint64_t u() const
463 {
464#ifndef CROW_JSON_NO_ERROR_CHECK
465 switch (t())
466 {
467 case type::Number:
468 case type::String:
469 return utility::lexical_cast<uint64_t>(start_, end_ - start_);
470 default:
471 throw std::runtime_error(std::string("expected number, got: ") + get_type_str(t()));
472 }
473#endif
474 return utility::lexical_cast<uint64_t>(start_, end_ - start_);
475 }
476
477 /// The double precision floating-point number value.
478 double d() const
479 {
480#ifndef CROW_JSON_NO_ERROR_CHECK
481 if (t() != type::Number)
482 throw std::runtime_error("value is not number");
483#endif
484 return utility::lexical_cast<double>(start_, end_ - start_);
485 }
486
487 /// The boolean value.
488 bool b() const
489 {
490#ifndef CROW_JSON_NO_ERROR_CHECK
491 if (t() != type::True && t() != type::False)
492 throw std::runtime_error("value is not boolean");
493#endif
494 return t() == type::True;
495 }
496
497 /// The string value.
499 {
500#ifndef CROW_JSON_NO_ERROR_CHECK
501 if (t() != type::String)
502 throw std::runtime_error("value is not string");
503#endif
504 unescape();
505 return detail::r_string{start_, end_};
506 }
507
508 /// The list or object value
509 std::vector<rvalue> lo() const
510 {
511#ifndef CROW_JSON_NO_ERROR_CHECK
512 if (t() != type::Object && t() != type::List)
513 throw std::runtime_error("value is not a container");
514#endif
515 std::vector<rvalue> ret;
516 ret.reserve(lsize_);
517 for (uint32_t i = 0; i < lsize_; i++)
518 {
519 ret.emplace_back(l_[i]);
520 }
521 return ret;
522 }
523
524 /// Convert escaped string character to their original form ("\\n" -> '\n').
525 void unescape() const
526 {
527 if (*(start_ - 1))
528 {
529 char* head = start_;
530 char* tail = start_;
531 while (head != end_)
532 {
533 if (*head == '\\')
534 {
535 switch (*++head)
536 {
537 case '"': *tail++ = '"'; break;
538 case '\\': *tail++ = '\\'; break;
539 case '/': *tail++ = '/'; break;
540 case 'b': *tail++ = '\b'; break;
541 case 'f': *tail++ = '\f'; break;
542 case 'n': *tail++ = '\n'; break;
543 case 'r': *tail++ = '\r'; break;
544 case 't': *tail++ = '\t'; break;
545 case 'u':
546 {
547 auto from_hex = [](char c) {
548 if (c >= 'a')
549 return c - 'a' + 10;
550 if (c >= 'A')
551 return c - 'A' + 10;
552 return c - '0';
553 };
554 unsigned int code =
555 (from_hex(head[1]) << 12) +
556 (from_hex(head[2]) << 8) +
557 (from_hex(head[3]) << 4) +
558 from_hex(head[4]);
559 head += 4;
560 if (code >= 0xD800 && code <= 0xDFFF)
561 {
562 // UTF-16 surrogate: a high half followed by an escaped low half
563 // encodes one code point; an unpaired half is not a valid code
564 // point, so it is replaced with U+FFFD to keep the output valid UTF-8.
565 unsigned int low = 0;
566 if (code <= 0xDBFF && head[1] == '\\' && head[2] == 'u')
567 {
568 low = (from_hex(head[3]) << 12) +
569 (from_hex(head[4]) << 8) +
570 (from_hex(head[5]) << 4) +
571 from_hex(head[6]);
572 }
573 if (low >= 0xDC00 && low <= 0xDFFF)
574 {
575 code = 0x10000 + ((code - 0xD800) << 10) + (low - 0xDC00);
576 *tail++ = 0xF0 | (code >> 18);
577 *tail++ = 0x80 | ((code >> 12) & 0x3F);
578 *tail++ = 0x80 | ((code >> 6) & 0x3F);
579 *tail++ = 0x80 | (code & 0x3F);
580 head += 6;
581 }
582 else
583 {
584 *tail++ = 0xEF;
585 *tail++ = 0xBF;
586 *tail++ = 0xBD;
587 }
588 }
589 else if (code >= 0x800)
590 {
591 *tail++ = 0xE0 | (code >> 12);
592 *tail++ = 0x80 | ((code >> 6) & 0x3F);
593 *tail++ = 0x80 | (code & 0x3F);
594 }
595 else if (code >= 0x80)
596 {
597 *tail++ = 0xC0 | (code >> 6);
598 *tail++ = 0x80 | (code & 0x3F);
599 }
600 else
601 {
602 *tail++ = code;
603 }
604 }
605 break;
606 }
607 }
608 else
609 *tail++ = *head;
610 head++;
611 }
612 end_ = tail;
613 *end_ = 0;
614 *(start_ - 1) = 0;
615 }
616 }
617
618 /// Check if the json object has the passed string as a key.
619 bool has(const char* str) const
620 {
621 return has(std::string(str));
622 }
623
624 bool has(const std::string& str) const
625 {
626 struct Pred
627 {
628 bool operator()(const rvalue& l, const rvalue& r) const
629 {
630 return l.key_ < r.key_;
631 }
632 bool operator()(const rvalue& l, const std::string& r) const
633 {
634 return l.key_ < r;
635 }
636 bool operator()(const std::string& l, const rvalue& r) const
637 {
638 return l < r.key_;
639 }
640 };
641 if (!is_cached())
642 {
643 std::sort(begin(), end(), Pred());
644 set_cached();
645 }
646 auto it = lower_bound(begin(), end(), str, Pred());
647 return it != end() && it->key_ == str;
648 }
649
650 int count(const std::string& str) const
651 {
652 return has(str) ? 1 : 0;
653 }
654
655 rvalue* begin() const
656 {
657#ifndef CROW_JSON_NO_ERROR_CHECK
658 if (t() != type::Object && t() != type::List)
659 throw std::runtime_error("value is not a container");
660#endif
661 return l_.get();
662 }
663 rvalue* end() const
664 {
665#ifndef CROW_JSON_NO_ERROR_CHECK
666 if (t() != type::Object && t() != type::List)
667 throw std::runtime_error("value is not a container");
668#endif
669 return l_.get() + lsize_;
670 }
671
672 const detail::r_string& key() const
673 {
674 return key_;
675 }
676
677 size_t size() const
678 {
679 if (t() == type::String)
680 return s().size();
681#ifndef CROW_JSON_NO_ERROR_CHECK
682 if (t() != type::Object && t() != type::List)
683 throw std::runtime_error("value is not a container");
684#endif
685 return lsize_;
686 }
687
688 const rvalue& operator[](int index) const
689 {
690#ifndef CROW_JSON_NO_ERROR_CHECK
691 if (t() != type::List)
692 throw std::runtime_error("value is not a list");
693 if (index >= static_cast<int>(lsize_) || index < 0)
694 throw std::runtime_error("list out of bound");
695#endif
696 return l_[index];
697 }
698
699 const rvalue& operator[](size_t index) const
700 {
701#ifndef CROW_JSON_NO_ERROR_CHECK
702 if (t() != type::List)
703 throw std::runtime_error("value is not a list");
704 if (index >= lsize_)
705 throw std::runtime_error("list out of bound");
706#endif
707 return l_[index];
708 }
709
710 const rvalue& operator[](const char* str) const
711 {
712 return this->operator[](std::string(str));
713 }
714
715 const rvalue& operator[](const std::string& str) const
716 {
717#ifndef CROW_JSON_NO_ERROR_CHECK
718 if (t() != type::Object)
719 throw std::runtime_error("value is not an object");
720#endif
721 struct Pred
722 {
723 bool operator()(const rvalue& l, const rvalue& r) const
724 {
725 return l.key_ < r.key_;
726 }
727 bool operator()(const rvalue& l, const std::string& r) const
728 {
729 return l.key_ < r;
730 }
731 bool operator()(const std::string& l, const rvalue& r) const
732 {
733 return l < r.key_;
734 }
735 };
736 if (!is_cached())
737 {
738 std::sort(begin(), end(), Pred());
739 set_cached();
740 }
741 auto it = lower_bound(begin(), end(), str, Pred());
742 if (it != end() && it->key_ == str)
743 return *it;
744#ifndef CROW_JSON_NO_ERROR_CHECK
745 throw std::runtime_error("cannot find key: " + str);
746#else
747 static rvalue nullValue;
748 return nullValue;
749#endif
750 }
751
752 void set_error()
753 {
754 option_ |= error_bit;
755 }
756
757 bool error() const
758 {
759 return (option_ & error_bit) != 0;
760 }
761
762 std::vector<std::string> keys() const
763 {
764#ifndef CROW_JSON_NO_ERROR_CHECK
765 if (t() != type::Object)
766 throw std::runtime_error("value is not an object");
767#endif
768 std::vector<std::string> ret;
769 ret.reserve(lsize_);
770 for (uint32_t i = 0; i < lsize_; i++)
771 {
772 ret.emplace_back(std::string(l_[i].key()));
773 }
774 return ret;
775 }
776
777 private:
778 bool is_cached() const
779 {
780 return (option_ & cached_bit) != 0;
781 }
782 void set_cached() const
783 {
784 option_ |= cached_bit;
785 }
786 void copy_l(const rvalue& r)
787 {
788 if (r.t() != type::Object && r.t() != type::List)
789 return;
790 lsize_ = r.lsize_;
791 lremain_ = 0;
792 l_.reset(new rvalue[lsize_]);
793 std::copy(r.begin(), r.end(), begin());
794 }
795
796 void emplace_back(rvalue&& v)
797 {
798 if (!lremain_)
799 {
800 int new_size = lsize_ + lsize_;
801 if (new_size - lsize_ > 60000)
802 new_size = lsize_ + 60000;
803 if (new_size < 4)
804 new_size = 4;
805 rvalue* p = new rvalue[new_size];
806 rvalue* p2 = p;
807 for (auto& x : *this)
808 *p2++ = std::move(x);
809 l_.reset(p);
810 lremain_ = new_size - lsize_;
811 }
812 l_[lsize_++] = std::move(v);
813 lremain_--;
814 }
815
816 /// Determines num_type from the string.
817 void determine_num_type()
818 {
819 if (t_ != type::Number)
820 {
821 nt_ = num_type::Null;
822 return;
823 }
824
825 const std::size_t len = end_ - start_;
826 const bool has_minus = std::memchr(start_, '-', len) != nullptr;
827 const bool has_e = std::memchr(start_, 'e', len) != nullptr || std::memchr(start_, 'E', len) != nullptr;
828 const bool has_dec_sep = std::memchr(start_, '.', len) != nullptr;
829 if (has_dec_sep || has_e)
830 nt_ = num_type::Floating_point;
831 else if (has_minus)
832 nt_ = num_type::Signed_integer;
833 else
834 nt_ = num_type::Unsigned_integer;
835 }
836
837 mutable char* start_;
838 mutable char* end_;
839 detail::r_string key_;
840 std::unique_ptr<rvalue[]> l_;
841 uint32_t lsize_;
842 uint16_t lremain_;
843 type t_;
844 num_type nt_{num_type::Null};
845 mutable uint8_t option_{0};
846
847 friend rvalue load_nocopy_internal(char* data, size_t size);
848 friend rvalue load(const char* data, size_t size);
849 friend std::ostream& operator<<(std::ostream& os, const rvalue& r)
850 {
851 switch (r.t_)
852 {
853
854 case type::Null: os << "null"; break;
855 case type::False: os << "false"; break;
856 case type::True: os << "true"; break;
857 case type::Number:
858 {
859 switch (r.nt())
860 {
861 case num_type::Floating_point: os << r.d(); break;
862 case num_type::Double_precision_floating_point: os << r.d(); break;
863 case num_type::Signed_integer: os << r.i(); break;
864 case num_type::Unsigned_integer: os << r.u(); break;
865 case num_type::Null: throw std::runtime_error("Number with num_type Null");
866 }
867 }
868 break;
869 case type::String: os << '"' << r.s() << '"'; break;
870 case type::List:
871 {
872 os << '[';
873 bool first = true;
874 for (auto& x : r)
875 {
876 if (!first)
877 os << ',';
878 first = false;
879 os << x;
880 }
881 os << ']';
882 }
883 break;
884 case type::Object:
885 {
886 os << '{';
887 bool first = true;
888 for (auto& x : r)
889 {
890 if (!first)
891 os << ',';
892 os << '"' << escape(x.key_) << "\":";
893 first = false;
894 os << x;
895 }
896 os << '}';
897 }
898 break;
899 case type::Function: os << "custom function"; break;
900 }
901 return os;
902 }
903 };
904 namespace detail
905 {
906 }
907
908 inline bool operator==(const rvalue& l, const std::string& r)
909 {
910 return l.s() == r;
911 }
912
913 inline bool operator==(const std::string& l, const rvalue& r)
914 {
915 return l == r.s();
916 }
917
918 inline bool operator!=(const rvalue& l, const std::string& r)
919 {
920 return l.s() != r;
921 }
922
923 inline bool operator!=(const std::string& l, const rvalue& r)
924 {
925 return l != r.s();
926 }
927
928 inline bool operator==(const rvalue& l, const int& r)
929 {
930 return l.i() == r;
931 }
932
933 inline bool operator==(const int& l, const rvalue& r)
934 {
935 return l == r.i();
936 }
937
938 inline bool operator!=(const rvalue& l, const int& r)
939 {
940 return l.i() != r;
941 }
942
943 inline bool operator!=(const int& l, const rvalue& r)
944 {
945 return l != r.i();
946 }
947
948
949 inline rvalue load_nocopy_internal(char* data, size_t size)
950 {
951 // Defend against excessive recursion
952 static constexpr unsigned max_depth = 1024;
953
954 //static const char* escaped = "\"\\/\b\f\n\r\t";
955 struct Parser
956 {
957 Parser(char* data_, size_t /*size*/):
958 data(data_)
959 {
960 }
961
962 bool consume(char c)
963 {
964 if (CROW_UNLIKELY(*data != c))
965 return false;
966 data++;
967 return true;
968 }
969
970 void ws_skip()
971 {
972 while (*data == ' ' || *data == '\t' || *data == '\r' || *data == '\n')
973 ++data;
974 }
975
976 rvalue decode_string()
977 {
978 if (CROW_UNLIKELY(!consume('"')))
979 return {};
980 char* start = data;
981 uint8_t has_escaping = 0;
982 while (1)
983 {
984 if (CROW_LIKELY(*data != '"' && *data != '\\' && *data != '\0'))
985 {
986 data++;
987 }
988 else if (*data == '"')
989 {
990 *data = 0;
991 *(start - 1) = has_escaping;
992 data++;
993 return {type::String, start, data - 1};
994 }
995 else if (*data == '\\')
996 {
997 has_escaping = 1;
998 data++;
999 switch (*data)
1000 {
1001 case 'u':
1002 {
1003 auto check = [](char c) {
1004 return ('0' <= c && c <= '9') ||
1005 ('a' <= c && c <= 'f') ||
1006 ('A' <= c && c <= 'F');
1007 };
1008 if (!(check(*(data + 1)) &&
1009 check(*(data + 2)) &&
1010 check(*(data + 3)) &&
1011 check(*(data + 4))))
1012 return {};
1013 }
1014 data += 5;
1015 break;
1016 case '"':
1017 case '\\':
1018 case '/':
1019 case 'b':
1020 case 'f':
1021 case 'n':
1022 case 'r':
1023 case 't':
1024 data++;
1025 break;
1026 default:
1027 return {};
1028 }
1029 }
1030 else
1031 return {};
1032 }
1033 return {};
1034 }
1035
1036 rvalue decode_list(unsigned depth)
1037 {
1038 rvalue ret(type::List);
1039 if (CROW_UNLIKELY(!consume('[')) || CROW_UNLIKELY(depth > max_depth))
1040 {
1041 ret.set_error();
1042 return ret;
1043 }
1044 ws_skip();
1045 if (CROW_UNLIKELY(*data == ']'))
1046 {
1047 data++;
1048 return ret;
1049 }
1050
1051 while (1)
1052 {
1053 auto v = decode_value(depth + 1);
1054 if (CROW_UNLIKELY(!v))
1055 {
1056 ret.set_error();
1057 break;
1058 }
1059 ws_skip();
1060 ret.emplace_back(std::move(v));
1061 if (*data == ']')
1062 {
1063 data++;
1064 break;
1065 }
1066 if (CROW_UNLIKELY(!consume(',')))
1067 {
1068 ret.set_error();
1069 break;
1070 }
1071 ws_skip();
1072 }
1073 return ret;
1074 }
1075
1076 rvalue decode_number()
1077 {
1078 char* start = data;
1079
1080 enum NumberParsingState
1081 {
1082 Minus,
1083 AfterMinus,
1084 ZeroFirst,
1085 Digits,
1086 DigitsAfterPoints,
1087 E,
1088 DigitsAfterE,
1089 Invalid,
1090 } state{Minus};
1091 while (CROW_LIKELY(state != Invalid))
1092 {
1093 switch (*data)
1094 {
1095 case '0':
1096 state = static_cast<NumberParsingState>("\2\2\7\3\4\6\6"[state]);
1097 /*if (state == NumberParsingState::Minus || state == NumberParsingState::AfterMinus)
1098 {
1099 state = NumberParsingState::ZeroFirst;
1100 }
1101 else if (state == NumberParsingState::Digits ||
1102 state == NumberParsingState::DigitsAfterE ||
1103 state == NumberParsingState::DigitsAfterPoints)
1104 {
1105 // ok; pass
1106 }
1107 else if (state == NumberParsingState::E)
1108 {
1109 state = NumberParsingState::DigitsAfterE;
1110 }
1111 else
1112 return {};*/
1113 break;
1114 case '1':
1115 case '2':
1116 case '3':
1117 case '4':
1118 case '5':
1119 case '6':
1120 case '7':
1121 case '8':
1122 case '9':
1123 state = static_cast<NumberParsingState>("\3\3\7\3\4\6\6"[state]);
1124 while (*(data + 1) >= '0' && *(data + 1) <= '9')
1125 data++;
1126 /*if (state == NumberParsingState::Minus || state == NumberParsingState::AfterMinus)
1127 {
1128 state = NumberParsingState::Digits;
1129 }
1130 else if (state == NumberParsingState::Digits ||
1131 state == NumberParsingState::DigitsAfterE ||
1132 state == NumberParsingState::DigitsAfterPoints)
1133 {
1134 // ok; pass
1135 }
1136 else if (state == NumberParsingState::E)
1137 {
1138 state = NumberParsingState::DigitsAfterE;
1139 }
1140 else
1141 return {};*/
1142 break;
1143 case '.':
1144 state = static_cast<NumberParsingState>("\7\7\4\4\7\7\7"[state]);
1145 /*
1146 if (state == NumberParsingState::Digits || state == NumberParsingState::ZeroFirst)
1147 {
1148 state = NumberParsingState::DigitsAfterPoints;
1149 }
1150 else
1151 return {};
1152 */
1153 break;
1154 case '-':
1155 state = static_cast<NumberParsingState>("\1\7\7\7\7\6\7"[state]);
1156 /*if (state == NumberParsingState::Minus)
1157 {
1158 state = NumberParsingState::AfterMinus;
1159 }
1160 else if (state == NumberParsingState::E)
1161 {
1162 state = NumberParsingState::DigitsAfterE;
1163 }
1164 else
1165 return {};*/
1166 break;
1167 case '+':
1168 state = static_cast<NumberParsingState>("\7\7\7\7\7\6\7"[state]);
1169 /*if (state == NumberParsingState::E)
1170 {
1171 state = NumberParsingState::DigitsAfterE;
1172 }
1173 else
1174 return {};*/
1175 break;
1176 case 'e':
1177 case 'E':
1178 state = static_cast<NumberParsingState>("\7\7\7\5\5\7\7"[state]);
1179 /*if (state == NumberParsingState::Digits ||
1180 state == NumberParsingState::DigitsAfterPoints)
1181 {
1182 state = NumberParsingState::E;
1183 }
1184 else
1185 return {};*/
1186 break;
1187 default:
1188 if (CROW_LIKELY(state == NumberParsingState::ZeroFirst ||
1189 state == NumberParsingState::Digits ||
1190 state == NumberParsingState::DigitsAfterPoints ||
1191 state == NumberParsingState::DigitsAfterE))
1192 return {type::Number, start, data};
1193 else
1194 return {};
1195 }
1196 data++;
1197 }
1198
1199 return {};
1200 }
1201
1202
1203 rvalue decode_value(unsigned depth)
1204 {
1205 if (CROW_UNLIKELY(depth > max_depth))
1206 {
1207 rvalue ret;
1208 ret.set_error();
1209 return ret;
1210 }
1211
1212 switch (*data)
1213 {
1214 case '[':
1215 return decode_list(depth + 1);
1216 case '{':
1217 return decode_object(depth + 1);
1218 case '"':
1219 return decode_string();
1220 case 't':
1221 if ( //e-data >= 4 &&
1222 data[1] == 'r' &&
1223 data[2] == 'u' &&
1224 data[3] == 'e')
1225 {
1226 data += 4;
1227 return {type::True};
1228 }
1229 else
1230 return {};
1231 case 'f':
1232 if ( //e-data >= 5 &&
1233 data[1] == 'a' &&
1234 data[2] == 'l' &&
1235 data[3] == 's' &&
1236 data[4] == 'e')
1237 {
1238 data += 5;
1239 return {type::False};
1240 }
1241 else
1242 return {};
1243 case 'n':
1244 if ( //e-data >= 4 &&
1245 data[1] == 'u' &&
1246 data[2] == 'l' &&
1247 data[3] == 'l')
1248 {
1249 data += 4;
1250 return {type::Null};
1251 }
1252 else
1253 return {};
1254 //case '1': case '2': case '3':
1255 //case '4': case '5': case '6':
1256 //case '7': case '8': case '9':
1257 //case '0': case '-':
1258 default:
1259 return decode_number();
1260 }
1261 return {};
1262 }
1263
1264 rvalue decode_object(unsigned depth)
1265 {
1266 rvalue ret(type::Object);
1267 if (CROW_UNLIKELY(!consume('{')) || CROW_UNLIKELY(depth > max_depth))
1268 {
1269 ret.set_error();
1270 return ret;
1271 }
1272
1273 ws_skip();
1274
1275 if (CROW_UNLIKELY(*data == '}'))
1276 {
1277 data++;
1278 return ret;
1279 }
1280
1281 while (1)
1282 {
1283 auto t = decode_string();
1284 if (CROW_UNLIKELY(!t))
1285 {
1286 ret.set_error();
1287 break;
1288 }
1289
1290 ws_skip();
1291 if (CROW_UNLIKELY(!consume(':')))
1292 {
1293 ret.set_error();
1294 break;
1295 }
1296
1297 // TODO(ipkn) caching key to speed up (flyweight?)
1298 // I have no idea how flyweight could apply here, but maybe some speedup can happen if we stopped checking type since decode_string returns a string anyway
1299 auto key = t.s();
1300
1301 ws_skip();
1302 auto v = decode_value(depth + 1);
1303 if (CROW_UNLIKELY(!v))
1304 {
1305 ret.set_error();
1306 break;
1307 }
1308 ws_skip();
1309
1310 v.key_ = std::move(key);
1311 ret.emplace_back(std::move(v));
1312 if (CROW_UNLIKELY(*data == '}'))
1313 {
1314 data++;
1315 break;
1316 }
1317 if (CROW_UNLIKELY(!consume(',')))
1318 {
1319 ret.set_error();
1320 break;
1321 }
1322 ws_skip();
1323 }
1324 return ret;
1325 }
1326
1327 rvalue parse()
1328 {
1329 ws_skip();
1330 auto ret = decode_value(0); // or decode object?
1331 ws_skip();
1332 if (ret && *data != '\0')
1333 ret.set_error();
1334 return ret;
1335 }
1336
1337 char* data;
1338 };
1339 return Parser(data, size).parse();
1340 }
1341 inline rvalue load(const char* data, size_t size)
1342 {
1343 char* s = new char[size + 1];
1344 memcpy(s, data, size);
1345 s[size] = 0;
1346 auto ret = load_nocopy_internal(s, size);
1347 if (ret)
1348 ret.key_.force(s, size);
1349 else
1350 delete[] s;
1351 return ret;
1352 }
1353
1354 inline rvalue load(const char* data)
1355 {
1356 return load(data, strlen(data));
1357 }
1358
1359 inline rvalue load(const std::string& str)
1360 {
1361 return load(str.data(), str.size());
1362 }
1363
1364 struct wvalue_reader;
1365
1366 /**
1367 * @brief JSON write value.
1368 *
1369 * Value can mean any json value, including a JSON object.<br>
1370 * Write means this class is used to primarily assemble JSON objects using keys and values and export those into a string.
1371 * The object container is selected at compile time. By default, object keys use an
1372 * `std::unordered_map`; `CROW_JSON_USE_MAP` selects lexicographically sorted keys,
1373 * while `CROW_JSON_USE_INSERTION_ORDER` preserves the order of newly inserted keys.
1374 * Updating an existing key does not change its position. These options affect the
1375 * order of serialized JSON object keys and cannot be used together.
1376 */
1377 class wvalue : public returnable
1378 {
1379 friend class crow::mustache::template_t;
1380 friend struct wvalue_reader;
1381
1382 public:
1383 using object = detail::object_policy::object_type<wvalue>;
1384
1385 using list = std::vector<wvalue>;
1386
1387 type t() const { return t_; }
1388
1389 /// Create an empty json value (outputs "{}" instead of a "null" string)
1390 static crow::json::wvalue empty_object() { return crow::json::wvalue::object(); }
1391
1392 private:
1393 type t_{type::Null}; ///< The type of the value.
1394 num_type nt{num_type::Null}; ///< The specific type of the number if \ref t_ is a number.
1395 union number
1396 {
1397 double d;
1398 int64_t si;
1399 uint64_t ui;
1400
1401 public:
1402 constexpr number() noexcept:
1403 ui() {} /* default constructor initializes unsigned integer. */
1404 constexpr number(std::uint64_t value) noexcept:
1405 ui(value) {}
1406 constexpr number(std::int64_t value) noexcept:
1407 si(value) {}
1408 explicit constexpr number(double value) noexcept:
1409 d(value) {}
1410 explicit constexpr number(float value) noexcept:
1411 d(value) {}
1412 } num; ///< Value if type is a number.
1413 std::string s; ///< Value if type is a string.
1414 std::unique_ptr<list> l; ///< Value if type is a list.
1415 std::unique_ptr<object> o; ///< Value if type is a JSON object.
1416 std::function<std::string(std::string&)> f; ///< Value if type is a function (C++ lambda)
1417
1418 public:
1419 wvalue():
1420 returnable("application/json") {}
1421
1422 wvalue(std::nullptr_t):
1423 returnable("application/json"), t_(type::Null) {}
1424
1425 wvalue(bool value):
1426 returnable("application/json"), t_(value ? type::True : type::False) {}
1427
1428 wvalue(std::uint8_t value):
1429 returnable("application/json"), t_(type::Number), nt(num_type::Unsigned_integer), num(static_cast<std::uint64_t>(value)) {}
1430 wvalue(std::uint16_t value):
1431 returnable("application/json"), t_(type::Number), nt(num_type::Unsigned_integer), num(static_cast<std::uint64_t>(value)) {}
1432 wvalue(std::uint32_t value):
1433 returnable("application/json"), t_(type::Number), nt(num_type::Unsigned_integer), num(static_cast<std::uint64_t>(value)) {}
1434 wvalue(std::uint64_t value):
1435 returnable("application/json"), t_(type::Number), nt(num_type::Unsigned_integer), num(static_cast<std::uint64_t>(value)) {}
1436
1437 wvalue(std::int8_t value):
1438 returnable("application/json"), t_(type::Number), nt(num_type::Signed_integer), num(static_cast<std::int64_t>(value)) {}
1439 wvalue(std::int16_t value):
1440 returnable("application/json"), t_(type::Number), nt(num_type::Signed_integer), num(static_cast<std::int64_t>(value)) {}
1441 wvalue(std::int32_t value):
1442 returnable("application/json"), t_(type::Number), nt(num_type::Signed_integer), num(static_cast<std::int64_t>(value)) {}
1443 wvalue(std::int64_t value):
1444 returnable("application/json"), t_(type::Number), nt(num_type::Signed_integer), num(static_cast<std::int64_t>(value)) {}
1445
1446 wvalue(float value):
1447 returnable("application/json"), t_(type::Number), nt(num_type::Floating_point), num(static_cast<double>(value)) {}
1448 wvalue(double value):
1449 returnable("application/json"), t_(type::Number), nt(num_type::Double_precision_floating_point), num(static_cast<double>(value)) {}
1450
1451 wvalue(char const* value):
1452 returnable("application/json"), t_(type::String), s(value) {}
1453
1454 wvalue(std::string const& value):
1455 returnable("application/json"), t_(type::String), s(value) {}
1456 wvalue(std::string&& value):
1457 returnable("application/json"), t_(type::String), s(std::move(value)) {}
1458
1459 wvalue(std::initializer_list<std::pair<std::string const, wvalue>> initializer_list):
1460 returnable("application/json"), t_(type::Object), o(new object(initializer_list)) {}
1461
1462 wvalue(object const& value):
1463 returnable("application/json"), t_(type::Object), o(new object(value)) {}
1464 wvalue(object&& value):
1465 returnable("application/json"), t_(type::Object), o(new object(std::move(value))) {}
1466
1467 wvalue(const list& r):
1468 returnable("application/json")
1469 {
1470 t_ = type::List;
1471 l = std::make_unique<list>();
1472 l->reserve(r.size());
1473 for (auto it = r.begin(); it != r.end(); ++it)
1474 l->emplace_back(*it);
1475 }
1476 wvalue(list& r):
1477 returnable("application/json")
1478 {
1479 t_ = type::List;
1480 l = std::make_unique<list>();
1481 l->reserve(r.size());
1482 for (auto it = r.begin(); it != r.end(); ++it)
1483 l->emplace_back(*it);
1484 }
1485
1486 /// Create a write value from a read value (useful for editing JSON strings).
1487 wvalue(const rvalue& r):
1488 returnable("application/json")
1489 {
1490 t_ = r.t();
1491 switch (r.t())
1492 {
1493 case type::Null:
1494 case type::False:
1495 case type::True:
1496 case type::Function:
1497 return;
1498 case type::Number:
1499 nt = r.nt();
1500 if (nt == num_type::Floating_point || nt == num_type::Double_precision_floating_point)
1501 num.d = r.d();
1502 else if (nt == num_type::Signed_integer)
1503 num.si = r.i();
1504 else
1505 num.ui = r.u();
1506 return;
1507 case type::String:
1508 s = r.s();
1509 return;
1510 case type::List:
1511 l = std::make_unique<list>();
1512 l->reserve(r.size());
1513 for (auto it = r.begin(); it != r.end(); ++it)
1514 l->emplace_back(*it);
1515 return;
1516 case type::Object:
1517 o = std::make_unique<object>();
1518 for (auto it = r.begin(); it != r.end(); ++it)
1519 o->emplace(it->key(), *it);
1520 return;
1521 }
1522 }
1523
1524 wvalue(const wvalue& r):
1525 returnable("application/json")
1526 {
1527 t_ = r.t();
1528 switch (r.t())
1529 {
1530 case type::Null:
1531 case type::False:
1532 case type::True:
1533 return;
1534 case type::Number:
1535 nt = r.nt;
1536 if (nt == num_type::Floating_point || nt == num_type::Double_precision_floating_point)
1537 num.d = r.num.d;
1538 else if (nt == num_type::Signed_integer)
1539 num.si = r.num.si;
1540 else
1541 num.ui = r.num.ui;
1542 return;
1543 case type::String:
1544 s = r.s;
1545 return;
1546 case type::List:
1547 l = std::make_unique<list>();
1548 l->reserve(r.size());
1549 for (auto it = r.l->begin(); it != r.l->end(); ++it)
1550 l->emplace_back(*it);
1551 return;
1552 case type::Object:
1553 o = std::make_unique<object>();
1554 o->insert(r.o->begin(), r.o->end());
1555 return;
1556 case type::Function:
1557 f = r.f;
1558 }
1559 }
1560
1561 wvalue(wvalue&& r):
1562 returnable("application/json")
1563 {
1564 *this = std::move(r);
1565 }
1566
1567 wvalue& operator=(wvalue&& r)
1568 {
1569 t_ = r.t_;
1570 nt = r.nt;
1571 num = r.num;
1572 s = std::move(r.s);
1573 l = std::move(r.l);
1574 o = std::move(r.o);
1575 return *this;
1576 }
1577
1578 /// Used for compatibility, same as \ref reset()
1579 void clear()
1580 {
1581 reset();
1582 }
1583
1584 void reset()
1585 {
1586 t_ = type::Null;
1587 l.reset();
1588 o.reset();
1589 }
1590
1591 wvalue& operator=(std::nullptr_t)
1592 {
1593 reset();
1594 return *this;
1595 }
1596 wvalue& operator=(bool value)
1597 {
1598 reset();
1599 if (value)
1600 t_ = type::True;
1601 else
1602 t_ = type::False;
1603 return *this;
1604 }
1605
1606 wvalue& operator=(float value)
1607 {
1608 reset();
1609 t_ = type::Number;
1610 num.d = value;
1611 nt = num_type::Floating_point;
1612 return *this;
1613 }
1614
1615 wvalue& operator=(double value)
1616 {
1617 reset();
1618 t_ = type::Number;
1619 num.d = value;
1620 nt = num_type::Double_precision_floating_point;
1621 return *this;
1622 }
1623
1624 wvalue& operator=(unsigned short value)
1625 {
1626 reset();
1627 t_ = type::Number;
1628 num.ui = value;
1629 nt = num_type::Unsigned_integer;
1630 return *this;
1631 }
1632
1633 wvalue& operator=(short value)
1634 {
1635 reset();
1636 t_ = type::Number;
1637 num.si = value;
1638 nt = num_type::Signed_integer;
1639 return *this;
1640 }
1641
1642 wvalue& operator=(long long value)
1643 {
1644 reset();
1645 t_ = type::Number;
1646 num.si = value;
1647 nt = num_type::Signed_integer;
1648 return *this;
1649 }
1650
1651 wvalue& operator=(long value)
1652 {
1653 reset();
1654 t_ = type::Number;
1655 num.si = value;
1656 nt = num_type::Signed_integer;
1657 return *this;
1658 }
1659
1660 wvalue& operator=(int value)
1661 {
1662 reset();
1663 t_ = type::Number;
1664 num.si = value;
1665 nt = num_type::Signed_integer;
1666 return *this;
1667 }
1668
1669 wvalue& operator=(unsigned long long value)
1670 {
1671 reset();
1672 t_ = type::Number;
1673 num.ui = value;
1674 nt = num_type::Unsigned_integer;
1675 return *this;
1676 }
1677
1678 wvalue& operator=(unsigned long value)
1679 {
1680 reset();
1681 t_ = type::Number;
1682 num.ui = value;
1683 nt = num_type::Unsigned_integer;
1684 return *this;
1685 }
1686
1687 wvalue& operator=(unsigned int value)
1688 {
1689 reset();
1690 t_ = type::Number;
1691 num.ui = value;
1692 nt = num_type::Unsigned_integer;
1693 return *this;
1694 }
1695
1696 wvalue& operator=(const char* str)
1697 {
1698 reset();
1699 t_ = type::String;
1700 s = str;
1701 return *this;
1702 }
1703
1704 wvalue& operator=(const std::string& str)
1705 {
1706 reset();
1707 t_ = type::String;
1708 s = str;
1709 return *this;
1710 }
1711
1712 wvalue& operator=(list&& v)
1713 {
1714 if (t_ != type::List)
1715 reset();
1716 t_ = type::List;
1717 if (!l)
1718 l = std::make_unique<list>();
1719 l->clear();
1720 l->resize(v.size());
1721 size_t idx = 0;
1722 for (auto& x : v)
1723 {
1724 (*l)[idx++] = std::move(x);
1725 }
1726 return *this;
1727 }
1728
1729 template<typename T>
1730 wvalue& operator=(const std::vector<T>& v)
1731 {
1732 if (t_ != type::List)
1733 reset();
1734 t_ = type::List;
1735 if (!l)
1736 l = std::make_unique<list>();
1737 l->clear();
1738 l->resize(v.size());
1739 size_t idx = 0;
1740 for (auto& x : v)
1741 {
1742 (*l)[idx++] = x;
1743 }
1744 return *this;
1745 }
1746
1747 wvalue& operator=(std::initializer_list<std::pair<std::string const, wvalue>> initializer_list)
1748 {
1749 if (t_ != type::Object)
1750 {
1751 reset();
1752 t_ = type::Object;
1753 o = std::make_unique<object>(initializer_list);
1754 }
1755 else
1756 {
1757#if defined(__APPLE__) || defined(__MACH__) || defined(__FreeBSD__) || defined(__ANDROID__) || defined(_LIBCPP_VERSION)
1758 o = std::make_unique<object>(initializer_list);
1759#else
1760 (*o) = initializer_list;
1761#endif
1762 }
1763 return *this;
1764 }
1765
1766 wvalue& operator=(object const& value)
1767 {
1768 if (t_ != type::Object)
1769 {
1770 reset();
1771 t_ = type::Object;
1772 o = std::make_unique<object>(value);
1773 }
1774 else
1775 {
1776#if defined(__APPLE__) || defined(__MACH__) || defined(__FreeBSD__) || defined(__ANDROID__) || defined(_LIBCPP_VERSION)
1777 o = std::make_unique<object>(value);
1778#else
1779 (*o) = value;
1780#endif
1781 }
1782 return *this;
1783 }
1784
1785 wvalue& operator=(object&& value)
1786 {
1787 if (t_ != type::Object)
1788 {
1789 reset();
1790 t_ = type::Object;
1791 o = std::make_unique<object>(std::move(value));
1792 }
1793 else
1794 {
1795 (*o) = std::move(value);
1796 }
1797 return *this;
1798 }
1799
1800 wvalue& operator=(std::function<std::string(std::string&)>&& func)
1801 {
1802 reset();
1803 t_ = type::Function;
1804 f = std::move(func);
1805 return *this;
1806 }
1807
1808 wvalue& operator[](unsigned index)
1809 {
1810 if (t_ != type::List)
1811 reset();
1812 t_ = type::List;
1813 if (!l)
1814 l = std::make_unique<list>();
1815 if (l->size() < index + 1)
1816 l->resize(index + 1);
1817 return (*l)[index];
1818 }
1819
1820 const wvalue& operator[](unsigned index) const
1821 {
1822 return const_cast<wvalue*>(this)->operator[](index);
1823 }
1824
1825 /// Check if the object contains the given key.
1826 bool has(const char* key) const
1827 {
1828 return has(std::string(key));
1829 }
1830
1831 /// Check if the object contains the given key.
1832 bool has(const std::string& key) const
1833 {
1834 if (t_ != type::Object)
1835 return false;
1836 if (!o)
1837 return false;
1838#if (__cplusplus>=202002L)
1839 return o->contains(key);
1840#else
1841 return o->count(key)>0;
1842#endif
1843 }
1844
1845 size_t count(const std::string& str) const
1846 {
1847 if (t_ != type::Object)
1848 return 0;
1849 if (!o)
1850 return 0;
1851 return o->count(str);
1852 }
1853
1854 wvalue& operator[](const std::string& str)
1855 {
1856 if (t_ != type::Object)
1857 reset();
1858 t_ = type::Object;
1859 if (!o)
1860 o = std::make_unique<object>();
1861 return (*o)[str];
1862 }
1863
1864 const wvalue& operator[](const std::string& str) const
1865 {
1866 return const_cast<wvalue*>(this)->operator[](str);
1867 }
1868
1869 std::vector<std::string> keys() const
1870 {
1871 if (t_ != type::Object)
1872 return {};
1873 std::vector<std::string> result;
1874 for (auto& kv : *o)
1875 {
1876 result.push_back(kv.first);
1877 }
1878 return result;
1879 }
1880
1881 std::string execute(std::string txt = "") const //Not using reference because it cannot be used with a default rvalue
1882 {
1883 if (t_ != type::Function)
1884 return "";
1885 return f(txt);
1886 }
1887
1888 /// If the wvalue is a list, it returns the length of the list, otherwise it returns 1.
1889 std::size_t size() const
1890 {
1891 if (t_ != type::List)
1892 return 1;
1893 return l->size();
1894 }
1895
1896 /// Returns an estimated size of the value in bytes.
1897 size_t estimate_length() const
1898 {
1899 switch (t_)
1900 {
1901 case type::Null: return 4;
1902 case type::False: return 5;
1903 case type::True: return 4;
1904 case type::Number: return 30;
1905 case type::String: return 2 + s.size() + s.size() / 2;
1906 case type::List:
1907 {
1908 size_t sum{};
1909 if (l)
1910 {
1911 for (auto& x : *l)
1912 {
1913 sum += 1;
1914 sum += x.estimate_length();
1915 }
1916 }
1917 return sum + 2;
1918 }
1919 case type::Object:
1920 {
1921 size_t sum{};
1922 if (o)
1923 {
1924 for (auto& kv : *o)
1925 {
1926 sum += 2;
1927 sum += 2 + kv.first.size() + kv.first.size() / 2;
1928 sum += kv.second.estimate_length();
1929 }
1930 }
1931 return sum + 2;
1932 }
1933 case type::Function:
1934 return 0;
1935 }
1936 return 1;
1937 }
1938
1939 private:
1940 inline void dump_string(const std::string& str, std::string& out) const
1941 {
1942 out.push_back('"');
1943 escape(str, out);
1944 out.push_back('"');
1945 }
1946
1947 inline void dump_indentation_part(std::string& out, const size_t indent, const char separator, const int indent_level) const
1948 {
1949 out.push_back('\n');
1950 out.append(indent_level * indent, separator);
1951 }
1952
1953
1954 inline void dump_internal(const wvalue& v, std::string& out, const size_t indent, const char separator, const int indent_level = 0) const
1955 {
1956 switch (v.t_)
1957 {
1958 case type::Null: out += "null"; break;
1959 case type::False: out += "false"; break;
1960 case type::True: out += "true"; break;
1961 case type::Number:
1962 {
1963 if (v.nt == num_type::Floating_point || v.nt == num_type::Double_precision_floating_point)
1964 {
1965 if (isnan(v.num.d) || isinf(v.num.d))
1966 {
1967 out += "null";
1968 CROW_LOG_WARNING << "Invalid JSON value detected (" << v.num.d << "), value set to null";
1969 break;
1970 }
1971 enum
1972 {
1973 start,
1974 decp, // Decimal point
1975 zero,
1976 exp // in the exponent
1977 } f_state;
1978 char outbuf[128];
1979 if (v.nt == num_type::Double_precision_floating_point)
1980 {
1981#ifdef _MSC_VER
1982 sprintf_s(outbuf, sizeof(outbuf), "%.*g", std::numeric_limits<double>::max_digits10, v.num.d);
1983#else
1984 snprintf(outbuf, sizeof(outbuf), "%.*g", std::numeric_limits<double>::max_digits10, v.num.d);
1985#endif
1986 }
1987 else
1988 {
1989#ifdef _MSC_VER
1990 sprintf_s(outbuf, sizeof(outbuf), "%f", v.num.d);
1991#else
1992 snprintf(outbuf, sizeof(outbuf), "%f", v.num.d);
1993#endif
1994 }
1995 char* p = &outbuf[0];
1996 char* pos_first_trailing_0 = nullptr;
1997 char* pos_exponent = nullptr;
1998 f_state = start;
1999 while (*p != '\0')
2000 {
2001 //std::cout << *p << std::endl;
2002 char ch = *p;
2003 switch (f_state)
2004 {
2005 case start: // Loop and lookahead until a decimal point is found
2006 if (ch == '.')
2007 {
2008 char fch = *(p + 1);
2009 // if the first character is 0, leave it be (this is so that "1.00000" becomes "1.0" and not "1.")
2010 if (fch != '\0' && fch == '0') p++;
2011 f_state = decp;
2012 }
2013 p++;
2014 break;
2015 case decp: // Loop until a 0 is found, if found, record its position
2016 if (ch == '0')
2017 {
2018 f_state = zero;
2019 pos_first_trailing_0 = p;
2020 }
2021 else if (ch == 'e')
2022 {
2023 pos_exponent = p;
2024 f_state = exp;
2025 }
2026 p++;
2027 break;
2028 case zero: // if a non 0 is found (e.g. 1.00004) remove the earlier recorded 0 position and look for more trailing 0s
2029 if (ch == 'e')
2030 {
2031 pos_exponent = p;
2032 f_state = exp;
2033 }
2034 else if (ch != '0')
2035 {
2036 pos_first_trailing_0 = nullptr;
2037 f_state = decp;
2038 }
2039 p++;
2040 break;
2041 case exp: // if an 'e' has been found, one is in the exponent; no more looking for trailing zeroes
2042 p++;
2043 break;
2044 }
2045 }
2046 if (pos_first_trailing_0 != nullptr) // if any trailing 0s are found, terminate the string where they begin
2047 {
2048 *pos_first_trailing_0 = '\0';
2049 if (pos_exponent != nullptr) // if there is an exponent, include it
2050 {
2051 strcpy(pos_first_trailing_0, pos_exponent);
2052 }
2053 }
2054 out += outbuf;
2055 }
2056 else if (v.nt == num_type::Signed_integer)
2057 {
2058 out += std::to_string(v.num.si);
2059 }
2060 else
2061 {
2062 out += std::to_string(v.num.ui);
2063 }
2064 }
2065 break;
2066 case type::String: dump_string(v.s, out); break;
2067 case type::List:
2068 {
2069 out.push_back('[');
2070
2071 if (indent !=std::string::npos)
2072 {
2073 dump_indentation_part(out, indent, separator, indent_level + 1);
2074 }
2075
2076 if (v.l)
2077 {
2078 bool first = true;
2079 for (auto& x : *v.l)
2080 {
2081 if (!first)
2082 {
2083 out.push_back(',');
2084
2085 if (indent != std::string::npos)
2086 {
2087 dump_indentation_part(out, indent, separator, indent_level + 1);
2088 }
2089 }
2090 first = false;
2091 dump_internal(x, out, indent, separator, indent_level + 1);
2092 }
2093 }
2094
2095 if (indent !=std::string::npos)
2096 {
2097 dump_indentation_part(out, indent, separator, indent_level);
2098 }
2099
2100 out.push_back(']');
2101 }
2102 break;
2103 case type::Object:
2104 {
2105 out.push_back('{');
2106
2107 if (indent != std::string::npos)
2108 {
2109 dump_indentation_part(out, indent, separator, indent_level + 1);
2110 }
2111
2112 if (v.o)
2113 {
2114 bool first = true;
2115 for (auto& kv : *v.o)
2116 {
2117 if (!first)
2118 {
2119 out.push_back(',');
2120 if (indent != std::string::npos)
2121 {
2122 dump_indentation_part(out, indent, separator, indent_level + 1);
2123 }
2124 }
2125 first = false;
2126 dump_string(kv.first, out);
2127 out.push_back(':');
2128
2129 if (indent != std::string::npos)
2130 {
2131 out.push_back(' ');
2132 }
2133
2134 dump_internal(kv.second, out, indent, separator, indent_level + 1);
2135 }
2136 }
2137
2138 if (indent != std::string::npos)
2139 {
2140 dump_indentation_part(out, indent, separator, indent_level);
2141 }
2142
2143 out.push_back('}');
2144 }
2145 break;
2146
2147 case type::Function:
2148 out += "custom function";
2149 break;
2150 }
2151 }
2152
2153 public:
2154 std::string dump(const size_t indent, const char separator = ' ') const
2155 {
2156 std::string ret;
2157 ret.reserve(estimate_length());
2158 dump_internal(*this, ret, indent, separator);
2159 return ret;
2160 }
2161
2162 std::string dump() const override
2163 {
2164 static constexpr size_t DontIndent = std::string::npos;
2165
2166 return dump(DontIndent);
2167 }
2168
2169 /// Return json string.
2170 explicit operator std::string() const
2171 {
2172 return dump();
2173 }
2174 };
2175
2176 // Used for accessing the internals of a wvalue
2178 {
2179 int64_t get(int64_t fallback)
2180 {
2181 if (ref.t() != type::Number || ref.nt == num_type::Floating_point ||
2182 ref.nt == num_type::Double_precision_floating_point)
2183 return fallback;
2184 return ref.num.si;
2185 }
2186
2187 double get(double fallback)
2188 {
2189 if (ref.t() != type::Number || ref.nt != num_type::Floating_point ||
2190 ref.nt == num_type::Double_precision_floating_point)
2191 return fallback;
2192 return ref.num.d;
2193 }
2194
2195 bool get(bool fallback)
2196 {
2197 if (ref.t() == type::True) return true;
2198 if (ref.t() == type::False) return false;
2199 return fallback;
2200 }
2201
2202 std::string get(const std::string& fallback)
2203 {
2204 if (ref.t() != type::String) return fallback;
2205 return ref.s;
2206 }
2207
2208 const wvalue& ref;
2209 };
2210
2211 //std::vector<asio::const_buffer> dump_ref(wvalue& v)
2212 //{
2213 //}
2214 } // namespace json
2215} // namespace crow
JSON read value.
Definition json.h:322
int64_t i() const
The integer value.
Definition json.h:444
bool has(const char *str) const
Check if the json object has the passed string as a key.
Definition json.h:619
double d() const
The double precision floating-point number value.
Definition json.h:478
bool b() const
The boolean value.
Definition json.h:488
std::vector< rvalue > lo() const
The list or object value.
Definition json.h:509
uint64_t u() const
The unsigned integer value.
Definition json.h:462
void unescape() const
Convert escaped string character to their original form ("\\n" -> ' ').
Definition json.h:525
num_type nt() const
The number type of the JSON value.
Definition json.h:432
type t() const
The type of the JSON value.
Definition json.h:420
detail::r_string s() const
The string value.
Definition json.h:498
JSON write value.
Definition json.h:1378
wvalue(const rvalue &r)
Create a write value from a read value (useful for editing JSON strings).
Definition json.h:1487
std::size_t size() const
If the wvalue is a list, it returns the length of the list, otherwise it returns 1.
Definition json.h:1889
bool has(const std::string &key) const
Check if the object contains the given key.
Definition json.h:1832
size_t estimate_length() const
Returns an estimated size of the value in bytes.
Definition json.h:1897
static crow::json::wvalue empty_object()
Create an empty json value (outputs "{}" instead of a "null" string)
Definition json.h:1390
bool has(const char *key) const
Check if the object contains the given key.
Definition json.h:1826
void clear()
Used for compatibility, same as reset()
Definition json.h:1579
Compiled mustache template object.
Definition mustache.h:157
The main namespace of the library. In this namespace is defined the most important classes and functi...
Definition json.h:292
A read string implementation with comparison functionality.
Definition json.h:126
char * s_
Start.
Definition json.h:186
char * e_
End.
Definition json.h:187
Definition json.h:2178
An abstract class that allows any other class to be returned by a handler.
Definition returnable.h:9