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