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 = 1024;
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 if (CROW_UNLIKELY(depth > max_depth))
1146 {
1147 rvalue ret;
1148 ret.set_error();
1149 return ret;
1150 }
1151
1152 switch (*data)
1153 {
1154 case '[':
1155 return decode_list(depth + 1);
1156 case '{':
1157 return decode_object(depth + 1);
1158 case '"':
1159 return decode_string();
1160 case 't':
1161 if ( //e-data >= 4 &&
1162 data[1] == 'r' &&
1163 data[2] == 'u' &&
1164 data[3] == 'e')
1165 {
1166 data += 4;
1167 return {type::True};
1168 }
1169 else
1170 return {};
1171 case 'f':
1172 if ( //e-data >= 5 &&
1173 data[1] == 'a' &&
1174 data[2] == 'l' &&
1175 data[3] == 's' &&
1176 data[4] == 'e')
1177 {
1178 data += 5;
1179 return {type::False};
1180 }
1181 else
1182 return {};
1183 case 'n':
1184 if ( //e-data >= 4 &&
1185 data[1] == 'u' &&
1186 data[2] == 'l' &&
1187 data[3] == 'l')
1188 {
1189 data += 4;
1190 return {type::Null};
1191 }
1192 else
1193 return {};
1194 //case '1': case '2': case '3':
1195 //case '4': case '5': case '6':
1196 //case '7': case '8': case '9':
1197 //case '0': case '-':
1198 default:
1199 return decode_number();
1200 }
1201 return {};
1202 }
1203
1204 rvalue decode_object(unsigned depth)
1205 {
1206 rvalue ret(type::Object);
1207 if (CROW_UNLIKELY(!consume('{')) || CROW_UNLIKELY(depth > max_depth))
1208 {
1209 ret.set_error();
1210 return ret;
1211 }
1212
1213 ws_skip();
1214
1215 if (CROW_UNLIKELY(*data == '}'))
1216 {
1217 data++;
1218 return ret;
1219 }
1220
1221 while (1)
1222 {
1223 auto t = decode_string();
1224 if (CROW_UNLIKELY(!t))
1225 {
1226 ret.set_error();
1227 break;
1228 }
1229
1230 ws_skip();
1231 if (CROW_UNLIKELY(!consume(':')))
1232 {
1233 ret.set_error();
1234 break;
1235 }
1236
1237 // TODO(ipkn) caching key to speed up (flyweight?)
1238 // 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
1239 auto key = t.s();
1240
1241 ws_skip();
1242 auto v = decode_value(depth + 1);
1243 if (CROW_UNLIKELY(!v))
1244 {
1245 ret.set_error();
1246 break;
1247 }
1248 ws_skip();
1249
1250 v.key_ = std::move(key);
1251 ret.emplace_back(std::move(v));
1252 if (CROW_UNLIKELY(*data == '}'))
1253 {
1254 data++;
1255 break;
1256 }
1257 if (CROW_UNLIKELY(!consume(',')))
1258 {
1259 ret.set_error();
1260 break;
1261 }
1262 ws_skip();
1263 }
1264 return ret;
1265 }
1266
1267 rvalue parse()
1268 {
1269 ws_skip();
1270 auto ret = decode_value(0); // or decode object?
1271 ws_skip();
1272 if (ret && *data != '\0')
1273 ret.set_error();
1274 return ret;
1275 }
1276
1277 char* data;
1278 };
1279 return Parser(data, size).parse();
1280 }
1281 inline rvalue load(const char* data, size_t size)
1282 {
1283 char* s = new char[size + 1];
1284 memcpy(s, data, size);
1285 s[size] = 0;
1286 auto ret = load_nocopy_internal(s, size);
1287 if (ret)
1288 ret.key_.force(s, size);
1289 else
1290 delete[] s;
1291 return ret;
1292 }
1293
1294 inline rvalue load(const char* data)
1295 {
1296 return load(data, strlen(data));
1297 }
1298
1299 inline rvalue load(const std::string& str)
1300 {
1301 return load(str.data(), str.size());
1302 }
1303
1304 struct wvalue_reader;
1305
1306 /// JSON write value.
1307
1308 ///
1309 /// Value can mean any json value, including a JSON object.<br>
1310 /// Write means this class is used to primarily assemble JSON objects using keys and values and export those into a string.
1311 class wvalue : public returnable
1312 {
1313 friend class crow::mustache::template_t;
1314 friend struct wvalue_reader;
1315
1316 public:
1317 using object =
1318#ifdef CROW_JSON_USE_MAP
1319 std::map<std::string, wvalue>;
1320#else
1321 std::unordered_map<std::string, wvalue>;
1322#endif
1323
1324 using list = std::vector<wvalue>;
1325
1326 type t() const { return t_; }
1327
1328 /// Create an empty json value (outputs "{}" instead of a "null" string)
1329 static crow::json::wvalue empty_object() { return crow::json::wvalue::object(); }
1330
1331 private:
1332 type t_{type::Null}; ///< The type of the value.
1333 num_type nt{num_type::Null}; ///< The specific type of the number if \ref t_ is a number.
1334 union number
1335 {
1336 double d;
1337 int64_t si;
1338 uint64_t ui;
1339
1340 public:
1341 constexpr number() noexcept:
1342 ui() {} /* default constructor initializes unsigned integer. */
1343 constexpr number(std::uint64_t value) noexcept:
1344 ui(value) {}
1345 constexpr number(std::int64_t value) noexcept:
1346 si(value) {}
1347 explicit constexpr number(double value) noexcept:
1348 d(value) {}
1349 explicit constexpr number(float value) noexcept:
1350 d(value) {}
1351 } num; ///< Value if type is a number.
1352 std::string s; ///< Value if type is a string.
1353 std::unique_ptr<list> l; ///< Value if type is a list.
1354 std::unique_ptr<object> o; ///< Value if type is a JSON object.
1355 std::function<std::string(std::string&)> f; ///< Value if type is a function (C++ lambda)
1356
1357 public:
1358 wvalue():
1359 returnable("application/json") {}
1360
1361 wvalue(std::nullptr_t):
1362 returnable("application/json"), t_(type::Null) {}
1363
1364 wvalue(bool value):
1365 returnable("application/json"), t_(value ? type::True : type::False) {}
1366
1367 wvalue(std::uint8_t value):
1368 returnable("application/json"), t_(type::Number), nt(num_type::Unsigned_integer), num(static_cast<std::uint64_t>(value)) {}
1369 wvalue(std::uint16_t value):
1370 returnable("application/json"), t_(type::Number), nt(num_type::Unsigned_integer), num(static_cast<std::uint64_t>(value)) {}
1371 wvalue(std::uint32_t value):
1372 returnable("application/json"), t_(type::Number), nt(num_type::Unsigned_integer), num(static_cast<std::uint64_t>(value)) {}
1373 wvalue(std::uint64_t value):
1374 returnable("application/json"), t_(type::Number), nt(num_type::Unsigned_integer), num(static_cast<std::uint64_t>(value)) {}
1375
1376 wvalue(std::int8_t value):
1377 returnable("application/json"), t_(type::Number), nt(num_type::Signed_integer), num(static_cast<std::int64_t>(value)) {}
1378 wvalue(std::int16_t value):
1379 returnable("application/json"), t_(type::Number), nt(num_type::Signed_integer), num(static_cast<std::int64_t>(value)) {}
1380 wvalue(std::int32_t value):
1381 returnable("application/json"), t_(type::Number), nt(num_type::Signed_integer), num(static_cast<std::int64_t>(value)) {}
1382 wvalue(std::int64_t value):
1383 returnable("application/json"), t_(type::Number), nt(num_type::Signed_integer), num(static_cast<std::int64_t>(value)) {}
1384
1385 wvalue(float value):
1386 returnable("application/json"), t_(type::Number), nt(num_type::Floating_point), num(static_cast<double>(value)) {}
1387 wvalue(double value):
1388 returnable("application/json"), t_(type::Number), nt(num_type::Double_precision_floating_point), num(static_cast<double>(value)) {}
1389
1390 wvalue(char const* value):
1391 returnable("application/json"), t_(type::String), s(value) {}
1392
1393 wvalue(std::string const& value):
1394 returnable("application/json"), t_(type::String), s(value) {}
1395 wvalue(std::string&& value):
1396 returnable("application/json"), t_(type::String), s(std::move(value)) {}
1397
1398 wvalue(std::initializer_list<std::pair<std::string const, wvalue>> initializer_list):
1399 returnable("application/json"), t_(type::Object), o(new object(initializer_list)) {}
1400
1401 wvalue(object const& value):
1402 returnable("application/json"), t_(type::Object), o(new object(value)) {}
1403 wvalue(object&& value):
1404 returnable("application/json"), t_(type::Object), o(new object(std::move(value))) {}
1405
1406 wvalue(const list& r):
1407 returnable("application/json")
1408 {
1409 t_ = type::List;
1410 l = std::unique_ptr<list>(new list{});
1411 l->reserve(r.size());
1412 for (auto it = r.begin(); it != r.end(); ++it)
1413 l->emplace_back(*it);
1414 }
1415 wvalue(list& r):
1416 returnable("application/json")
1417 {
1418 t_ = type::List;
1419 l = std::unique_ptr<list>(new list{});
1420 l->reserve(r.size());
1421 for (auto it = r.begin(); it != r.end(); ++it)
1422 l->emplace_back(*it);
1423 }
1424
1425 /// Create a write value from a read value (useful for editing JSON strings).
1426 wvalue(const rvalue& r):
1427 returnable("application/json")
1428 {
1429 t_ = r.t();
1430 switch (r.t())
1431 {
1432 case type::Null:
1433 case type::False:
1434 case type::True:
1435 case type::Function:
1436 return;
1437 case type::Number:
1438 nt = r.nt();
1439 if (nt == num_type::Floating_point || nt == num_type::Double_precision_floating_point)
1440 num.d = r.d();
1441 else if (nt == num_type::Signed_integer)
1442 num.si = r.i();
1443 else
1444 num.ui = r.u();
1445 return;
1446 case type::String:
1447 s = r.s();
1448 return;
1449 case type::List:
1450 l = std::unique_ptr<list>(new list{});
1451 l->reserve(r.size());
1452 for (auto it = r.begin(); it != r.end(); ++it)
1453 l->emplace_back(*it);
1454 return;
1455 case type::Object:
1456 o = std::unique_ptr<object>(new object{});
1457 for (auto it = r.begin(); it != r.end(); ++it)
1458 o->emplace(it->key(), *it);
1459 return;
1460 }
1461 }
1462
1463 wvalue(const wvalue& r):
1464 returnable("application/json")
1465 {
1466 t_ = r.t();
1467 switch (r.t())
1468 {
1469 case type::Null:
1470 case type::False:
1471 case type::True:
1472 return;
1473 case type::Number:
1474 nt = r.nt;
1475 if (nt == num_type::Floating_point || nt == num_type::Double_precision_floating_point)
1476 num.d = r.num.d;
1477 else if (nt == num_type::Signed_integer)
1478 num.si = r.num.si;
1479 else
1480 num.ui = r.num.ui;
1481 return;
1482 case type::String:
1483 s = r.s;
1484 return;
1485 case type::List:
1486 l = std::unique_ptr<list>(new list{});
1487 l->reserve(r.size());
1488 for (auto it = r.l->begin(); it != r.l->end(); ++it)
1489 l->emplace_back(*it);
1490 return;
1491 case type::Object:
1492 o = std::unique_ptr<object>(new object{});
1493 o->insert(r.o->begin(), r.o->end());
1494 return;
1495 case type::Function:
1496 f = r.f;
1497 }
1498 }
1499
1500 wvalue(wvalue&& r):
1501 returnable("application/json")
1502 {
1503 *this = std::move(r);
1504 }
1505
1506 wvalue& operator=(wvalue&& r)
1507 {
1508 t_ = r.t_;
1509 nt = r.nt;
1510 num = r.num;
1511 s = std::move(r.s);
1512 l = std::move(r.l);
1513 o = std::move(r.o);
1514 return *this;
1515 }
1516
1517 /// Used for compatibility, same as \ref reset()
1518 void clear()
1519 {
1520 reset();
1521 }
1522
1523 void reset()
1524 {
1525 t_ = type::Null;
1526 l.reset();
1527 o.reset();
1528 }
1529
1530 wvalue& operator=(std::nullptr_t)
1531 {
1532 reset();
1533 return *this;
1534 }
1535 wvalue& operator=(bool value)
1536 {
1537 reset();
1538 if (value)
1539 t_ = type::True;
1540 else
1541 t_ = type::False;
1542 return *this;
1543 }
1544
1545 wvalue& operator=(float value)
1546 {
1547 reset();
1548 t_ = type::Number;
1549 num.d = value;
1550 nt = num_type::Floating_point;
1551 return *this;
1552 }
1553
1554 wvalue& operator=(double value)
1555 {
1556 reset();
1557 t_ = type::Number;
1558 num.d = value;
1559 nt = num_type::Double_precision_floating_point;
1560 return *this;
1561 }
1562
1563 wvalue& operator=(unsigned short value)
1564 {
1565 reset();
1566 t_ = type::Number;
1567 num.ui = value;
1568 nt = num_type::Unsigned_integer;
1569 return *this;
1570 }
1571
1572 wvalue& operator=(short value)
1573 {
1574 reset();
1575 t_ = type::Number;
1576 num.si = value;
1577 nt = num_type::Signed_integer;
1578 return *this;
1579 }
1580
1581 wvalue& operator=(long long value)
1582 {
1583 reset();
1584 t_ = type::Number;
1585 num.si = value;
1586 nt = num_type::Signed_integer;
1587 return *this;
1588 }
1589
1590 wvalue& operator=(long value)
1591 {
1592 reset();
1593 t_ = type::Number;
1594 num.si = value;
1595 nt = num_type::Signed_integer;
1596 return *this;
1597 }
1598
1599 wvalue& operator=(int value)
1600 {
1601 reset();
1602 t_ = type::Number;
1603 num.si = value;
1604 nt = num_type::Signed_integer;
1605 return *this;
1606 }
1607
1608 wvalue& operator=(unsigned long long value)
1609 {
1610 reset();
1611 t_ = type::Number;
1612 num.ui = value;
1613 nt = num_type::Unsigned_integer;
1614 return *this;
1615 }
1616
1617 wvalue& operator=(unsigned long value)
1618 {
1619 reset();
1620 t_ = type::Number;
1621 num.ui = value;
1622 nt = num_type::Unsigned_integer;
1623 return *this;
1624 }
1625
1626 wvalue& operator=(unsigned int value)
1627 {
1628 reset();
1629 t_ = type::Number;
1630 num.ui = value;
1631 nt = num_type::Unsigned_integer;
1632 return *this;
1633 }
1634
1635 wvalue& operator=(const char* str)
1636 {
1637 reset();
1638 t_ = type::String;
1639 s = str;
1640 return *this;
1641 }
1642
1643 wvalue& operator=(const std::string& str)
1644 {
1645 reset();
1646 t_ = type::String;
1647 s = str;
1648 return *this;
1649 }
1650
1651 wvalue& operator=(list&& v)
1652 {
1653 if (t_ != type::List)
1654 reset();
1655 t_ = type::List;
1656 if (!l)
1657 l = std::unique_ptr<list>(new list{});
1658 l->clear();
1659 l->resize(v.size());
1660 size_t idx = 0;
1661 for (auto& x : v)
1662 {
1663 (*l)[idx++] = std::move(x);
1664 }
1665 return *this;
1666 }
1667
1668 template<typename T>
1669 wvalue& operator=(const std::vector<T>& v)
1670 {
1671 if (t_ != type::List)
1672 reset();
1673 t_ = type::List;
1674 if (!l)
1675 l = std::unique_ptr<list>(new list{});
1676 l->clear();
1677 l->resize(v.size());
1678 size_t idx = 0;
1679 for (auto& x : v)
1680 {
1681 (*l)[idx++] = x;
1682 }
1683 return *this;
1684 }
1685
1686 wvalue& operator=(std::initializer_list<std::pair<std::string const, wvalue>> initializer_list)
1687 {
1688 if (t_ != type::Object)
1689 {
1690 reset();
1691 t_ = type::Object;
1692 o = std::unique_ptr<object>(new object(initializer_list));
1693 }
1694 else
1695 {
1696#if defined(__APPLE__) || defined(__MACH__) || defined(__FreeBSD__) || defined(__ANDROID__) || defined(_LIBCPP_VERSION)
1697 o = std::unique_ptr<object>(new object(initializer_list));
1698#else
1699 (*o) = initializer_list;
1700#endif
1701 }
1702 return *this;
1703 }
1704
1705 wvalue& operator=(object const& value)
1706 {
1707 if (t_ != type::Object)
1708 {
1709 reset();
1710 t_ = type::Object;
1711 o = std::unique_ptr<object>(new object(value));
1712 }
1713 else
1714 {
1715#if defined(__APPLE__) || defined(__MACH__) || defined(__FreeBSD__) || defined(__ANDROID__) || defined(_LIBCPP_VERSION)
1716 o = std::unique_ptr<object>(new object(value));
1717#else
1718 (*o) = value;
1719#endif
1720 }
1721 return *this;
1722 }
1723
1724 wvalue& operator=(object&& value)
1725 {
1726 if (t_ != type::Object)
1727 {
1728 reset();
1729 t_ = type::Object;
1730 o = std::unique_ptr<object>(new object(std::move(value)));
1731 }
1732 else
1733 {
1734 (*o) = std::move(value);
1735 }
1736 return *this;
1737 }
1738
1739 wvalue& operator=(std::function<std::string(std::string&)>&& func)
1740 {
1741 reset();
1742 t_ = type::Function;
1743 f = std::move(func);
1744 return *this;
1745 }
1746
1747 wvalue& operator[](unsigned index)
1748 {
1749 if (t_ != type::List)
1750 reset();
1751 t_ = type::List;
1752 if (!l)
1753 l = std::unique_ptr<list>(new list{});
1754 if (l->size() < index + 1)
1755 l->resize(index + 1);
1756 return (*l)[index];
1757 }
1758
1759 const wvalue& operator[](unsigned index) const
1760 {
1761 return const_cast<wvalue*>(this)->operator[](index);
1762 }
1763
1764 /// Check if the object contains the given key.
1765 bool has(const char* key) const
1766 {
1767 return has(std::string(key));
1768 }
1769
1770 /// Check if the object contains the given key.
1771 bool has(const std::string& key) const
1772 {
1773 if (t_ != type::Object)
1774 return false;
1775 if (!o)
1776 return false;
1777#if (__cplusplus>=202002L)
1778 return o->contains(key);
1779#else
1780 return o->count(key)>0;
1781#endif
1782 }
1783
1784 int count(const std::string& str) const
1785 {
1786 if (t_ != type::Object)
1787 return 0;
1788 if (!o)
1789 return 0;
1790 return o->count(str);
1791 }
1792
1793 wvalue& operator[](const std::string& str)
1794 {
1795 if (t_ != type::Object)
1796 reset();
1797 t_ = type::Object;
1798 if (!o)
1799 o = std::unique_ptr<object>(new object{});
1800 return (*o)[str];
1801 }
1802
1803 const wvalue& operator[](const std::string& str) const
1804 {
1805 return const_cast<wvalue*>(this)->operator[](str);
1806 }
1807
1808 std::vector<std::string> keys() const
1809 {
1810 if (t_ != type::Object)
1811 return {};
1812 std::vector<std::string> result;
1813 for (auto& kv : *o)
1814 {
1815 result.push_back(kv.first);
1816 }
1817 return result;
1818 }
1819
1820 std::string execute(std::string txt = "") const //Not using reference because it cannot be used with a default rvalue
1821 {
1822 if (t_ != type::Function)
1823 return "";
1824 return f(txt);
1825 }
1826
1827 /// If the wvalue is a list, it returns the length of the list, otherwise it returns 1.
1828 std::size_t size() const
1829 {
1830 if (t_ != type::List)
1831 return 1;
1832 return l->size();
1833 }
1834
1835 /// Returns an estimated size of the value in bytes.
1836 size_t estimate_length() const
1837 {
1838 switch (t_)
1839 {
1840 case type::Null: return 4;
1841 case type::False: return 5;
1842 case type::True: return 4;
1843 case type::Number: return 30;
1844 case type::String: return 2 + s.size() + s.size() / 2;
1845 case type::List:
1846 {
1847 size_t sum{};
1848 if (l)
1849 {
1850 for (auto& x : *l)
1851 {
1852 sum += 1;
1853 sum += x.estimate_length();
1854 }
1855 }
1856 return sum + 2;
1857 }
1858 case type::Object:
1859 {
1860 size_t sum{};
1861 if (o)
1862 {
1863 for (auto& kv : *o)
1864 {
1865 sum += 2;
1866 sum += 2 + kv.first.size() + kv.first.size() / 2;
1867 sum += kv.second.estimate_length();
1868 }
1869 }
1870 return sum + 2;
1871 }
1872 case type::Function:
1873 return 0;
1874 }
1875 return 1;
1876 }
1877
1878 private:
1879 inline void dump_string(const std::string& str, std::string& out) const
1880 {
1881 out.push_back('"');
1882 escape(str, out);
1883 out.push_back('"');
1884 }
1885
1886 inline void dump_indentation_part(std::string& out, const size_t indent, const char separator, const int indent_level) const
1887 {
1888 out.push_back('\n');
1889 out.append(indent_level * indent, separator);
1890 }
1891
1892
1893 inline void dump_internal(const wvalue& v, std::string& out, const size_t indent, const char separator, const int indent_level = 0) const
1894 {
1895 switch (v.t_)
1896 {
1897 case type::Null: out += "null"; break;
1898 case type::False: out += "false"; break;
1899 case type::True: out += "true"; break;
1900 case type::Number:
1901 {
1902 if (v.nt == num_type::Floating_point || v.nt == num_type::Double_precision_floating_point)
1903 {
1904 if (isnan(v.num.d) || isinf(v.num.d))
1905 {
1906 out += "null";
1907 CROW_LOG_WARNING << "Invalid JSON value detected (" << v.num.d << "), value set to null";
1908 break;
1909 }
1910 enum
1911 {
1912 start,
1913 decp, // Decimal point
1914 zero,
1915 exp // in the exponent
1916 } f_state;
1917 char outbuf[128];
1918 if (v.nt == num_type::Double_precision_floating_point)
1919 {
1920#ifdef _MSC_VER
1921 sprintf_s(outbuf, sizeof(outbuf), "%.*g", std::numeric_limits<double>::max_digits10, v.num.d);
1922#else
1923 snprintf(outbuf, sizeof(outbuf), "%.*g", std::numeric_limits<double>::max_digits10, v.num.d);
1924#endif
1925 }
1926 else
1927 {
1928#ifdef _MSC_VER
1929 sprintf_s(outbuf, sizeof(outbuf), "%f", v.num.d);
1930#else
1931 snprintf(outbuf, sizeof(outbuf), "%f", v.num.d);
1932#endif
1933 }
1934 char* p = &outbuf[0];
1935 char* pos_first_trailing_0 = nullptr;
1936 char* pos_exponent = nullptr;
1937 f_state = start;
1938 while (*p != '\0')
1939 {
1940 //std::cout << *p << std::endl;
1941 char ch = *p;
1942 switch (f_state)
1943 {
1944 case start: // Loop and lookahead until a decimal point is found
1945 if (ch == '.')
1946 {
1947 char fch = *(p + 1);
1948 // if the first character is 0, leave it be (this is so that "1.00000" becomes "1.0" and not "1.")
1949 if (fch != '\0' && fch == '0') p++;
1950 f_state = decp;
1951 }
1952 p++;
1953 break;
1954 case decp: // Loop until a 0 is found, if found, record its position
1955 if (ch == '0')
1956 {
1957 f_state = zero;
1958 pos_first_trailing_0 = p;
1959 }
1960 else if (ch == 'e')
1961 {
1962 pos_exponent = p;
1963 f_state = exp;
1964 }
1965 p++;
1966 break;
1967 case zero: // if a non 0 is found (e.g. 1.00004) remove the earlier recorded 0 position and look for more trailing 0s
1968 if (ch == 'e')
1969 {
1970 pos_exponent = p;
1971 f_state = exp;
1972 }
1973 else if (ch != '0')
1974 {
1975 pos_first_trailing_0 = nullptr;
1976 f_state = decp;
1977 }
1978 p++;
1979 break;
1980 case exp: // if an 'e' has been found, one is in the exponent; no more looking for trailing zeroes
1981 p++;
1982 break;
1983 }
1984 }
1985 if (pos_first_trailing_0 != nullptr) // if any trailing 0s are found, terminate the string where they begin
1986 {
1987 *pos_first_trailing_0 = '\0';
1988 if (pos_exponent != nullptr) // if there is an exponent, include it
1989 {
1990 strcpy(pos_first_trailing_0, pos_exponent);
1991 }
1992 }
1993 out += outbuf;
1994 }
1995 else if (v.nt == num_type::Signed_integer)
1996 {
1997 out += std::to_string(v.num.si);
1998 }
1999 else
2000 {
2001 out += std::to_string(v.num.ui);
2002 }
2003 }
2004 break;
2005 case type::String: dump_string(v.s, out); break;
2006 case type::List:
2007 {
2008 out.push_back('[');
2009
2010 if (indent !=std::string::npos)
2011 {
2012 dump_indentation_part(out, indent, separator, indent_level + 1);
2013 }
2014
2015 if (v.l)
2016 {
2017 bool first = true;
2018 for (auto& x : *v.l)
2019 {
2020 if (!first)
2021 {
2022 out.push_back(',');
2023
2024 if (indent != std::string::npos)
2025 {
2026 dump_indentation_part(out, indent, separator, indent_level + 1);
2027 }
2028 }
2029 first = false;
2030 dump_internal(x, out, indent, separator, indent_level + 1);
2031 }
2032 }
2033
2034 if (indent !=std::string::npos)
2035 {
2036 dump_indentation_part(out, indent, separator, indent_level);
2037 }
2038
2039 out.push_back(']');
2040 }
2041 break;
2042 case type::Object:
2043 {
2044 out.push_back('{');
2045
2046 if (indent != std::string::npos)
2047 {
2048 dump_indentation_part(out, indent, separator, indent_level + 1);
2049 }
2050
2051 if (v.o)
2052 {
2053 bool first = true;
2054 for (auto& kv : *v.o)
2055 {
2056 if (!first)
2057 {
2058 out.push_back(',');
2059 if (indent != std::string::npos)
2060 {
2061 dump_indentation_part(out, indent, separator, indent_level + 1);
2062 }
2063 }
2064 first = false;
2065 dump_string(kv.first, out);
2066 out.push_back(':');
2067
2068 if (indent != std::string::npos)
2069 {
2070 out.push_back(' ');
2071 }
2072
2073 dump_internal(kv.second, out, indent, separator, indent_level + 1);
2074 }
2075 }
2076
2077 if (indent != std::string::npos)
2078 {
2079 dump_indentation_part(out, indent, separator, indent_level);
2080 }
2081
2082 out.push_back('}');
2083 }
2084 break;
2085
2086 case type::Function:
2087 out += "custom function";
2088 break;
2089 }
2090 }
2091
2092 public:
2093 std::string dump(const size_t indent, const char separator = ' ') const
2094 {
2095 std::string ret;
2096 ret.reserve(estimate_length());
2097 dump_internal(*this, ret, indent, separator);
2098 return ret;
2099 }
2100
2101 std::string dump() const override
2102 {
2103 static constexpr size_t DontIndent = std::string::npos;
2104
2105 return dump(DontIndent);
2106 }
2107
2108 /// Return json string.
2109 explicit operator std::string() const
2110 {
2111 return dump();
2112 }
2113 };
2114
2115 // Used for accessing the internals of a wvalue
2117 {
2118 int64_t get(int64_t fallback)
2119 {
2120 if (ref.t() != type::Number || ref.nt == num_type::Floating_point ||
2121 ref.nt == num_type::Double_precision_floating_point)
2122 return fallback;
2123 return ref.num.si;
2124 }
2125
2126 double get(double fallback)
2127 {
2128 if (ref.t() != type::Number || ref.nt != num_type::Floating_point ||
2129 ref.nt == num_type::Double_precision_floating_point)
2130 return fallback;
2131 return ref.num.d;
2132 }
2133
2134 bool get(bool fallback)
2135 {
2136 if (ref.t() == type::True) return true;
2137 if (ref.t() == type::False) return false;
2138 return fallback;
2139 }
2140
2141 std::string get(const std::string& fallback)
2142 {
2143 if (ref.t() != type::String) return fallback;
2144 return ref.s;
2145 }
2146
2147 const wvalue& ref;
2148 };
2149
2150 //std::vector<asio::const_buffer> dump_ref(wvalue& v)
2151 //{
2152 //}
2153 } // namespace json
2154} // 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:1312
wvalue(const rvalue &r)
Create a write value from a read value (useful for editing JSON strings).
Definition json.h:1426
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:1828
bool has(const std::string &key) const
Check if the object contains the given key.
Definition json.h:1771
size_t estimate_length() const
Returns an estimated size of the value in bytes.
Definition json.h:1836
static crow::json::wvalue empty_object()
Create an empty json value (outputs "{}" instead of a "null" string)
Definition json.h:1329
bool has(const char *key) const
Check if the object contains the given key.
Definition json.h:1765
void clear()
Used for compatibility, same as reset()
Definition json.h:1518
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:2117
An abstract class that allows any other class to be returned by a handler.
Definition returnable.h:9