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