Coverage Report

Created: 2026-04-12 06:18

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