Coverage Report

Created: 2025-07-09 06:27

/src/glaze/include/glaze/json/read.hpp
Line
Count
Source (jump to first uncovered line)
1
// Glaze Library
2
// For the license information refer to glaze.hpp
3
4
#pragma once
5
6
#include <charconv>
7
#include <climits>
8
#include <cwchar>
9
#include <filesystem>
10
#include <iterator>
11
#include <ranges>
12
#include <type_traits>
13
14
#include "glaze/core/common.hpp"
15
#include "glaze/core/opts.hpp"
16
#include "glaze/core/read.hpp"
17
#include "glaze/core/reflect.hpp"
18
#include "glaze/file/file_ops.hpp"
19
#include "glaze/json/json_concepts.hpp"
20
#include "glaze/json/skip.hpp"
21
#include "glaze/util/for_each.hpp"
22
#include "glaze/util/glaze_fast_float.hpp"
23
#include "glaze/util/type_traits.hpp"
24
#include "glaze/util/variant.hpp"
25
26
#ifdef _MSC_VER
27
// Turn off MSVC warning for unreachable code due to constexpr branching
28
#pragma warning(push)
29
#pragma warning(disable : 4702)
30
#endif
31
32
namespace glz
33
{
34
   // forward declare from json/wrappers.hpp to avoid circular include
35
   template <class T>
36
   struct quoted_t;
37
38
   template <>
39
   struct parse<JSON>
40
   {
41
      template <auto Opts, class T, is_context Ctx, class It0, class It1>
42
      GLZ_ALWAYS_INLINE static void op(T&& value, Ctx&& ctx, It0&& it, It1&& end)
43
10.7M
      {
44
         if constexpr (const_value_v<T>) {
45
            if constexpr (Opts.error_on_const_read) {
46
               ctx.error = error_code::attempt_const_read;
47
            }
48
            else {
49
               // do not read anything into the const value
50
               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), std::forward<It1>(end));
51
            }
52
         }
53
10.7M
         else {
54
10.7M
            using V = std::remove_cvref_t<T>;
55
10.7M
            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
56
10.7M
                                             std::forward<It1>(end));
57
10.7M
         }
58
10.7M
      }
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1EEER9my_structTkNS_10is_contextERNS_7contextERPKcSA_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
43
4.59k
      {
44
         if constexpr (const_value_v<T>) {
45
            if constexpr (Opts.error_on_const_read) {
46
               ctx.error = error_code::attempt_const_read;
47
            }
48
            else {
49
               // do not read anything into the const value
50
               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), std::forward<It1>(end));
51
            }
52
         }
53
4.59k
         else {
54
4.59k
            using V = std::remove_cvref_t<T>;
55
4.59k
            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
56
4.59k
                                             std::forward<It1>(end));
57
4.59k
         }
58
4.59k
      }
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj4EEERmTkNS_10is_contextERNS_7contextERPKcS9_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
43
16.7k
      {
44
         if constexpr (const_value_v<T>) {
45
            if constexpr (Opts.error_on_const_read) {
46
               ctx.error = error_code::attempt_const_read;
47
            }
48
            else {
49
               // do not read anything into the const value
50
               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), std::forward<It1>(end));
51
            }
52
         }
53
16.7k
         else {
54
16.7k
            using V = std::remove_cvref_t<T>;
55
16.7k
            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
56
16.7k
                                             std::forward<It1>(end));
57
16.7k
         }
58
16.7k
      }
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1EEER9my_structTkNS_10is_contextERNS_7contextERPKcSA_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
43
4.59k
      {
44
         if constexpr (const_value_v<T>) {
45
            if constexpr (Opts.error_on_const_read) {
46
               ctx.error = error_code::attempt_const_read;
47
            }
48
            else {
49
               // do not read anything into the const value
50
               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), std::forward<It1>(end));
51
            }
52
         }
53
4.59k
         else {
54
4.59k
            using V = std::remove_cvref_t<T>;
55
4.59k
            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
56
4.59k
                                             std::forward<It1>(end));
57
4.59k
         }
58
4.59k
      }
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj4EEERmTkNS_10is_contextERNS_7contextERPKcS9_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
43
16.7k
      {
44
         if constexpr (const_value_v<T>) {
45
            if constexpr (Opts.error_on_const_read) {
46
               ctx.error = error_code::attempt_const_read;
47
            }
48
            else {
49
               // do not read anything into the const value
50
               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), std::forward<It1>(end));
51
            }
52
         }
53
16.7k
         else {
54
16.7k
            using V = std::remove_cvref_t<T>;
55
16.7k
            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
56
16.7k
                                             std::forward<It1>(end));
57
16.7k
         }
58
16.7k
      }
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb1ELb1ELb1ELb1ELb0ELb0ELc32ELh3ELb1EEER9my_structTkNS_10is_contextERNS_7contextERPKcSA_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
43
6.10k
      {
44
         if constexpr (const_value_v<T>) {
45
            if constexpr (Opts.error_on_const_read) {
46
               ctx.error = error_code::attempt_const_read;
47
            }
48
            else {
49
               // do not read anything into the const value
50
               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), std::forward<It1>(end));
51
            }
52
         }
53
6.10k
         else {
54
6.10k
            using V = std::remove_cvref_t<T>;
55
6.10k
            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
56
6.10k
                                             std::forward<It1>(end));
57
6.10k
         }
58
6.10k
      }
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb1ELb1ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj4EEERmTkNS_10is_contextERNS_7contextERPKcS9_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
43
17.6k
      {
44
         if constexpr (const_value_v<T>) {
45
            if constexpr (Opts.error_on_const_read) {
46
               ctx.error = error_code::attempt_const_read;
47
            }
48
            else {
49
               // do not read anything into the const value
50
               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), std::forward<It1>(end));
51
            }
52
         }
53
17.6k
         else {
54
17.6k
            using V = std::remove_cvref_t<T>;
55
17.6k
            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
56
17.6k
                                             std::forward<It1>(end));
57
17.6k
         }
58
17.6k
      }
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEER1STkNS_10is_contextERNS_7contextERPKcSA_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
43
415
      {
44
         if constexpr (const_value_v<T>) {
45
            if constexpr (Opts.error_on_const_read) {
46
               ctx.error = error_code::attempt_const_read;
47
            }
48
            else {
49
               // do not read anything into the const value
50
               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), std::forward<It1>(end));
51
            }
52
         }
53
415
         else {
54
415
            using V = std::remove_cvref_t<T>;
55
415
            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
56
415
                                             std::forward<It1>(end));
57
415
         }
58
415
      }
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEER5ValueIfETkNS_10is_contextERNS_7contextERPKcSB_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
43
488
      {
44
         if constexpr (const_value_v<T>) {
45
            if constexpr (Opts.error_on_const_read) {
46
               ctx.error = error_code::attempt_const_read;
47
            }
48
            else {
49
               // do not read anything into the const value
50
               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), std::forward<It1>(end));
51
            }
52
         }
53
488
         else {
54
488
            using V = std::remove_cvref_t<T>;
55
488
            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
56
488
                                             std::forward<It1>(end));
57
488
         }
58
488
      }
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEER5ValueIdETkNS_10is_contextERNS_7contextERPKcSB_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
43
1.05k
      {
44
         if constexpr (const_value_v<T>) {
45
            if constexpr (Opts.error_on_const_read) {
46
               ctx.error = error_code::attempt_const_read;
47
            }
48
            else {
49
               // do not read anything into the const value
50
               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), std::forward<It1>(end));
51
            }
52
         }
53
1.05k
         else {
54
1.05k
            using V = std::remove_cvref_t<T>;
55
1.05k
            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
56
1.05k
                                             std::forward<It1>(end));
57
1.05k
         }
58
1.05k
      }
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEER5ValueIsETkNS_10is_contextERNS_7contextERPKcSB_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
43
106
      {
44
         if constexpr (const_value_v<T>) {
45
            if constexpr (Opts.error_on_const_read) {
46
               ctx.error = error_code::attempt_const_read;
47
            }
48
            else {
49
               // do not read anything into the const value
50
               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), std::forward<It1>(end));
51
            }
52
         }
53
106
         else {
54
106
            using V = std::remove_cvref_t<T>;
55
106
            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
56
106
                                             std::forward<It1>(end));
57
106
         }
58
106
      }
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEER5ValueItETkNS_10is_contextERNS_7contextERPKcSB_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
43
106
      {
44
         if constexpr (const_value_v<T>) {
45
            if constexpr (Opts.error_on_const_read) {
46
               ctx.error = error_code::attempt_const_read;
47
            }
48
            else {
49
               // do not read anything into the const value
50
               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), std::forward<It1>(end));
51
            }
52
         }
53
106
         else {
54
106
            using V = std::remove_cvref_t<T>;
55
106
            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
56
106
                                             std::forward<It1>(end));
57
106
         }
58
106
      }
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEER5ValueIiETkNS_10is_contextERNS_7contextERPKcSB_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
43
169
      {
44
         if constexpr (const_value_v<T>) {
45
            if constexpr (Opts.error_on_const_read) {
46
               ctx.error = error_code::attempt_const_read;
47
            }
48
            else {
49
               // do not read anything into the const value
50
               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), std::forward<It1>(end));
51
            }
52
         }
53
169
         else {
54
169
            using V = std::remove_cvref_t<T>;
55
169
            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
56
169
                                             std::forward<It1>(end));
57
169
         }
58
169
      }
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEER5ValueIjETkNS_10is_contextERNS_7contextERPKcSB_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
43
169
      {
44
         if constexpr (const_value_v<T>) {
45
            if constexpr (Opts.error_on_const_read) {
46
               ctx.error = error_code::attempt_const_read;
47
            }
48
            else {
49
               // do not read anything into the const value
50
               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), std::forward<It1>(end));
51
            }
52
         }
53
169
         else {
54
169
            using V = std::remove_cvref_t<T>;
55
169
            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
56
169
                                             std::forward<It1>(end));
57
169
         }
58
169
      }
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEER5ValueIlETkNS_10is_contextERNS_7contextERPKcSB_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
43
296
      {
44
         if constexpr (const_value_v<T>) {
45
            if constexpr (Opts.error_on_const_read) {
46
               ctx.error = error_code::attempt_const_read;
47
            }
48
            else {
49
               // do not read anything into the const value
50
               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), std::forward<It1>(end));
51
            }
52
         }
53
296
         else {
54
296
            using V = std::remove_cvref_t<T>;
55
296
            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
56
296
                                             std::forward<It1>(end));
57
296
         }
58
296
      }
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEER5ValueImETkNS_10is_contextERNS_7contextERPKcSB_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
43
296
      {
44
         if constexpr (const_value_v<T>) {
45
            if constexpr (Opts.error_on_const_read) {
46
               ctx.error = error_code::attempt_const_read;
47
            }
48
            else {
49
               // do not read anything into the const value
50
               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), std::forward<It1>(end));
51
            }
52
         }
53
296
         else {
54
296
            using V = std::remove_cvref_t<T>;
55
296
            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
56
296
                                             std::forward<It1>(end));
57
296
         }
58
296
      }
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEER5ValueIxETkNS_10is_contextERNS_7contextERPKcSB_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
43
290
      {
44
         if constexpr (const_value_v<T>) {
45
            if constexpr (Opts.error_on_const_read) {
46
               ctx.error = error_code::attempt_const_read;
47
            }
48
            else {
49
               // do not read anything into the const value
50
               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), std::forward<It1>(end));
51
            }
52
         }
53
290
         else {
54
290
            using V = std::remove_cvref_t<T>;
55
290
            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
56
290
                                             std::forward<It1>(end));
57
290
         }
58
290
      }
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEER5ValueIyETkNS_10is_contextERNS_7contextERPKcSB_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
43
290
      {
44
         if constexpr (const_value_v<T>) {
45
            if constexpr (Opts.error_on_const_read) {
46
               ctx.error = error_code::attempt_const_read;
47
            }
48
            else {
49
               // do not read anything into the const value
50
               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), std::forward<It1>(end));
51
            }
52
         }
53
290
         else {
54
290
            using V = std::remove_cvref_t<T>;
55
290
            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
56
290
                                             std::forward<It1>(end));
57
290
         }
58
290
      }
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1EEERNS_6json_tETkNS_10is_contextERNS_7contextERPKcSA_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
43
6.19k
      {
44
         if constexpr (const_value_v<T>) {
45
            if constexpr (Opts.error_on_const_read) {
46
               ctx.error = error_code::attempt_const_read;
47
            }
48
            else {
49
               // do not read anything into the const value
50
               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), std::forward<It1>(end));
51
            }
52
         }
53
6.19k
         else {
54
6.19k
            using V = std::remove_cvref_t<T>;
55
6.19k
            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
56
6.19k
                                             std::forward<It1>(end));
57
6.19k
         }
58
6.19k
      }
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj1EEERNSt3__13mapINS4_12basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEENS_6json_tENS4_4lessIvEENS9_INS4_4pairIKSB_SC_EEEEEETkNS_10is_contextERNS_7contextERPKcSP_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
43
7.82k
      {
44
         if constexpr (const_value_v<T>) {
45
            if constexpr (Opts.error_on_const_read) {
46
               ctx.error = error_code::attempt_const_read;
47
            }
48
            else {
49
               // do not read anything into the const value
50
               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), std::forward<It1>(end));
51
            }
52
         }
53
7.82k
         else {
54
7.82k
            using V = std::remove_cvref_t<T>;
55
7.82k
            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
56
7.82k
                                             std::forward<It1>(end));
57
7.82k
         }
58
7.82k
      }
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1EEERNSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEETkNS_10is_contextERNS_7contextERPKcSG_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
43
40.6k
      {
44
         if constexpr (const_value_v<T>) {
45
            if constexpr (Opts.error_on_const_read) {
46
               ctx.error = error_code::attempt_const_read;
47
            }
48
            else {
49
               // do not read anything into the const value
50
               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), std::forward<It1>(end));
51
            }
52
         }
53
40.6k
         else {
54
40.6k
            using V = std::remove_cvref_t<T>;
55
40.6k
            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
56
40.6k
                                             std::forward<It1>(end));
57
40.6k
         }
58
40.6k
      }
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj4EEERNS_6json_tETkNS_10is_contextERNS_7contextERPKcSA_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
43
1.75M
      {
44
         if constexpr (const_value_v<T>) {
45
            if constexpr (Opts.error_on_const_read) {
46
               ctx.error = error_code::attempt_const_read;
47
            }
48
            else {
49
               // do not read anything into the const value
50
               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), std::forward<It1>(end));
51
            }
52
         }
53
1.75M
         else {
54
1.75M
            using V = std::remove_cvref_t<T>;
55
1.75M
            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
56
1.75M
                                             std::forward<It1>(end));
57
1.75M
         }
58
1.75M
      }
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj4EEERNSt3__16vectorINS_6json_tENS4_9allocatorIS6_EEEETkNS_10is_contextERNS_7contextERPKcSF_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
43
17.0k
      {
44
         if constexpr (const_value_v<T>) {
45
            if constexpr (Opts.error_on_const_read) {
46
               ctx.error = error_code::attempt_const_read;
47
            }
48
            else {
49
               // do not read anything into the const value
50
               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), std::forward<It1>(end));
51
            }
52
         }
53
17.0k
         else {
54
17.0k
            using V = std::remove_cvref_t<T>;
55
17.0k
            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
56
17.0k
                                             std::forward<It1>(end));
57
17.0k
         }
58
17.0k
      }
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj4EEERNSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEETkNS_10is_contextERNS_7contextERPKcSG_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
43
4.47k
      {
44
         if constexpr (const_value_v<T>) {
45
            if constexpr (Opts.error_on_const_read) {
46
               ctx.error = error_code::attempt_const_read;
47
            }
48
            else {
49
               // do not read anything into the const value
50
               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), std::forward<It1>(end));
51
            }
52
         }
53
4.47k
         else {
54
4.47k
            using V = std::remove_cvref_t<T>;
55
4.47k
            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
56
4.47k
                                             std::forward<It1>(end));
57
4.47k
         }
58
4.47k
      }
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj4EEERbTkNS_10is_contextERNS_7contextERPKcS9_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
43
1.31k
      {
44
         if constexpr (const_value_v<T>) {
45
            if constexpr (Opts.error_on_const_read) {
46
               ctx.error = error_code::attempt_const_read;
47
            }
48
            else {
49
               // do not read anything into the const value
50
               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), std::forward<It1>(end));
51
            }
52
         }
53
1.31k
         else {
54
1.31k
            using V = std::remove_cvref_t<T>;
55
1.31k
            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
56
1.31k
                                             std::forward<It1>(end));
57
1.31k
         }
58
1.31k
      }
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj4EEERdTkNS_10is_contextERNS_7contextERPKcS9_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
43
1.73M
      {
44
         if constexpr (const_value_v<T>) {
45
            if constexpr (Opts.error_on_const_read) {
46
               ctx.error = error_code::attempt_const_read;
47
            }
48
            else {
49
               // do not read anything into the const value
50
               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), std::forward<It1>(end));
51
            }
52
         }
53
1.73M
         else {
54
1.73M
            using V = std::remove_cvref_t<T>;
55
1.73M
            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
56
1.73M
                                             std::forward<It1>(end));
57
1.73M
         }
58
1.73M
      }
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1EEERNS_6json_tETkNS_10is_contextERNS_7contextERPKcSA_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
43
6.19k
      {
44
         if constexpr (const_value_v<T>) {
45
            if constexpr (Opts.error_on_const_read) {
46
               ctx.error = error_code::attempt_const_read;
47
            }
48
            else {
49
               // do not read anything into the const value
50
               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), std::forward<It1>(end));
51
            }
52
         }
53
6.19k
         else {
54
6.19k
            using V = std::remove_cvref_t<T>;
55
6.19k
            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
56
6.19k
                                             std::forward<It1>(end));
57
6.19k
         }
58
6.19k
      }
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj1EEERNSt3__13mapINS4_12basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEENS_6json_tENS4_4lessIvEENS9_INS4_4pairIKSB_SC_EEEEEETkNS_10is_contextERNS_7contextERPKcSP_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
43
7.86k
      {
44
         if constexpr (const_value_v<T>) {
45
            if constexpr (Opts.error_on_const_read) {
46
               ctx.error = error_code::attempt_const_read;
47
            }
48
            else {
49
               // do not read anything into the const value
50
               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), std::forward<It1>(end));
51
            }
52
         }
53
7.86k
         else {
54
7.86k
            using V = std::remove_cvref_t<T>;
55
7.86k
            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
56
7.86k
                                             std::forward<It1>(end));
57
7.86k
         }
58
7.86k
      }
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1EEERNSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEETkNS_10is_contextERNS_7contextERPKcSG_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
43
40.7k
      {
44
         if constexpr (const_value_v<T>) {
45
            if constexpr (Opts.error_on_const_read) {
46
               ctx.error = error_code::attempt_const_read;
47
            }
48
            else {
49
               // do not read anything into the const value
50
               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), std::forward<It1>(end));
51
            }
52
         }
53
40.7k
         else {
54
40.7k
            using V = std::remove_cvref_t<T>;
55
40.7k
            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
56
40.7k
                                             std::forward<It1>(end));
57
40.7k
         }
58
40.7k
      }
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj4EEERNS_6json_tETkNS_10is_contextERNS_7contextERPKcSA_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
43
1.75M
      {
44
         if constexpr (const_value_v<T>) {
45
            if constexpr (Opts.error_on_const_read) {
46
               ctx.error = error_code::attempt_const_read;
47
            }
48
            else {
49
               // do not read anything into the const value
50
               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), std::forward<It1>(end));
51
            }
52
         }
53
1.75M
         else {
54
1.75M
            using V = std::remove_cvref_t<T>;
55
1.75M
            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
56
1.75M
                                             std::forward<It1>(end));
57
1.75M
         }
58
1.75M
      }
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj4EEERNSt3__16vectorINS_6json_tENS4_9allocatorIS6_EEEETkNS_10is_contextERNS_7contextERPKcSF_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
43
17.0k
      {
44
         if constexpr (const_value_v<T>) {
45
            if constexpr (Opts.error_on_const_read) {
46
               ctx.error = error_code::attempt_const_read;
47
            }
48
            else {
49
               // do not read anything into the const value
50
               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), std::forward<It1>(end));
51
            }
52
         }
53
17.0k
         else {
54
17.0k
            using V = std::remove_cvref_t<T>;
55
17.0k
            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
56
17.0k
                                             std::forward<It1>(end));
57
17.0k
         }
58
17.0k
      }
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj4EEERNSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEETkNS_10is_contextERNS_7contextERPKcSG_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
43
4.47k
      {
44
         if constexpr (const_value_v<T>) {
45
            if constexpr (Opts.error_on_const_read) {
46
               ctx.error = error_code::attempt_const_read;
47
            }
48
            else {
49
               // do not read anything into the const value
50
               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), std::forward<It1>(end));
51
            }
52
         }
53
4.47k
         else {
54
4.47k
            using V = std::remove_cvref_t<T>;
55
4.47k
            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
56
4.47k
                                             std::forward<It1>(end));
57
4.47k
         }
58
4.47k
      }
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj4EEERbTkNS_10is_contextERNS_7contextERPKcS9_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
43
1.31k
      {
44
         if constexpr (const_value_v<T>) {
45
            if constexpr (Opts.error_on_const_read) {
46
               ctx.error = error_code::attempt_const_read;
47
            }
48
            else {
49
               // do not read anything into the const value
50
               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), std::forward<It1>(end));
51
            }
52
         }
53
1.31k
         else {
54
1.31k
            using V = std::remove_cvref_t<T>;
55
1.31k
            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
56
1.31k
                                             std::forward<It1>(end));
57
1.31k
         }
58
1.31k
      }
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj4EEERdTkNS_10is_contextERNS_7contextERPKcS9_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
43
1.73M
      {
44
         if constexpr (const_value_v<T>) {
45
            if constexpr (Opts.error_on_const_read) {
46
               ctx.error = error_code::attempt_const_read;
47
            }
48
            else {
49
               // do not read anything into the const value
50
               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), std::forward<It1>(end));
51
            }
52
         }
53
1.73M
         else {
54
1.73M
            using V = std::remove_cvref_t<T>;
55
1.73M
            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
56
1.73M
                                             std::forward<It1>(end));
57
1.73M
         }
58
1.73M
      }
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEERNS_6json_tETkNS_10is_contextERNS_7contextERPKcSA_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
43
6.19k
      {
44
         if constexpr (const_value_v<T>) {
45
            if constexpr (Opts.error_on_const_read) {
46
               ctx.error = error_code::attempt_const_read;
47
            }
48
            else {
49
               // do not read anything into the const value
50
               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), std::forward<It1>(end));
51
            }
52
         }
53
6.19k
         else {
54
6.19k
            using V = std::remove_cvref_t<T>;
55
6.19k
            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
56
6.19k
                                             std::forward<It1>(end));
57
6.19k
         }
58
6.19k
      }
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj33EEERNSt3__13mapINS4_12basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEENS_6json_tENS4_4lessIvEENS9_INS4_4pairIKSB_SC_EEEEEETkNS_10is_contextERNS_7contextERPKcSP_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
43
7.86k
      {
44
         if constexpr (const_value_v<T>) {
45
            if constexpr (Opts.error_on_const_read) {
46
               ctx.error = error_code::attempt_const_read;
47
            }
48
            else {
49
               // do not read anything into the const value
50
               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), std::forward<It1>(end));
51
            }
52
         }
53
7.86k
         else {
54
7.86k
            using V = std::remove_cvref_t<T>;
55
7.86k
            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
56
7.86k
                                             std::forward<It1>(end));
57
7.86k
         }
58
7.86k
      }
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEERNSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEETkNS_10is_contextERNS_7contextERPKcSG_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
43
40.7k
      {
44
         if constexpr (const_value_v<T>) {
45
            if constexpr (Opts.error_on_const_read) {
46
               ctx.error = error_code::attempt_const_read;
47
            }
48
            else {
49
               // do not read anything into the const value
50
               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), std::forward<It1>(end));
51
            }
52
         }
53
40.7k
         else {
54
40.7k
            using V = std::remove_cvref_t<T>;
55
40.7k
            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
56
40.7k
                                             std::forward<It1>(end));
57
40.7k
         }
58
40.7k
      }
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj36EEERNS_6json_tETkNS_10is_contextERNS_7contextERPKcSA_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
43
1.75M
      {
44
         if constexpr (const_value_v<T>) {
45
            if constexpr (Opts.error_on_const_read) {
46
               ctx.error = error_code::attempt_const_read;
47
            }
48
            else {
49
               // do not read anything into the const value
50
               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), std::forward<It1>(end));
51
            }
52
         }
53
1.75M
         else {
54
1.75M
            using V = std::remove_cvref_t<T>;
55
1.75M
            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
56
1.75M
                                             std::forward<It1>(end));
57
1.75M
         }
58
1.75M
      }
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj36EEERNSt3__16vectorINS_6json_tENS4_9allocatorIS6_EEEETkNS_10is_contextERNS_7contextERPKcSF_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
43
17.0k
      {
44
         if constexpr (const_value_v<T>) {
45
            if constexpr (Opts.error_on_const_read) {
46
               ctx.error = error_code::attempt_const_read;
47
            }
48
            else {
49
               // do not read anything into the const value
50
               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), std::forward<It1>(end));
51
            }
52
         }
53
17.0k
         else {
54
17.0k
            using V = std::remove_cvref_t<T>;
55
17.0k
            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
56
17.0k
                                             std::forward<It1>(end));
57
17.0k
         }
58
17.0k
      }
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj36EEERNSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEETkNS_10is_contextERNS_7contextERPKcSG_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
43
4.46k
      {
44
         if constexpr (const_value_v<T>) {
45
            if constexpr (Opts.error_on_const_read) {
46
               ctx.error = error_code::attempt_const_read;
47
            }
48
            else {
49
               // do not read anything into the const value
50
               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), std::forward<It1>(end));
51
            }
52
         }
53
4.46k
         else {
54
4.46k
            using V = std::remove_cvref_t<T>;
55
4.46k
            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
56
4.46k
                                             std::forward<It1>(end));
57
4.46k
         }
58
4.46k
      }
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj36EEERbTkNS_10is_contextERNS_7contextERPKcS9_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
43
1.31k
      {
44
         if constexpr (const_value_v<T>) {
45
            if constexpr (Opts.error_on_const_read) {
46
               ctx.error = error_code::attempt_const_read;
47
            }
48
            else {
49
               // do not read anything into the const value
50
               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), std::forward<It1>(end));
51
            }
52
         }
53
1.31k
         else {
54
1.31k
            using V = std::remove_cvref_t<T>;
55
1.31k
            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
56
1.31k
                                             std::forward<It1>(end));
57
1.31k
         }
58
1.31k
      }
_ZN3glz5parseILj10EE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj36EEERdTkNS_10is_contextERNS_7contextERPKcS9_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
43
1.73M
      {
44
         if constexpr (const_value_v<T>) {
45
            if constexpr (Opts.error_on_const_read) {
46
               ctx.error = error_code::attempt_const_read;
47
            }
48
            else {
49
               // do not read anything into the const value
50
               skip_value<JSON>::op<Opts>(std::forward<Ctx>(ctx), std::forward<It0>(it), std::forward<It1>(end));
51
            }
52
         }
53
1.73M
         else {
54
1.73M
            using V = std::remove_cvref_t<T>;
55
1.73M
            from<JSON, V>::template op<Opts>(std::forward<T>(value), std::forward<Ctx>(ctx), std::forward<It0>(it),
56
1.73M
                                             std::forward<It1>(end));
57
1.73M
         }
58
1.73M
      }
59
60
      // This unknown key handler should not be given unescaped keys, that is for the user to handle.
61
      template <auto Opts, class T, is_context Ctx, class It0, class It1>
62
      static void handle_unknown(const sv& key, T&& value, Ctx&& ctx, It0&& it, It1&& end)
63
      {
64
         using ValueType = std::decay_t<decltype(value)>;
65
         if constexpr (has_unknown_reader<ValueType>) {
66
            constexpr auto& reader = meta_unknown_read_v<ValueType>;
67
            using ReaderType = meta_unknown_read_t<ValueType>;
68
            if constexpr (std::is_member_object_pointer_v<ReaderType>) {
69
               using MemberType = typename member_value<ReaderType>::type;
70
               if constexpr (map_subscriptable<MemberType>) {
71
                  parse<JSON>::op<Opts>((value.*reader)[key], ctx, it, end);
72
               }
73
               else {
74
                  static_assert(false_v<T>, "target must have subscript operator");
75
               }
76
            }
77
            else if constexpr (std::is_member_function_pointer_v<ReaderType>) {
78
               using ReturnType = typename return_type<ReaderType>::type;
79
               if constexpr (std::is_void_v<ReturnType>) {
80
                  using TupleType = typename inputs_as_tuple<ReaderType>::type;
81
                  if constexpr (glz::tuple_size_v<TupleType> == 2) {
82
                     std::decay_t<glz::tuple_element_t<1, TupleType>> input{};
83
                     parse<JSON>::op<Opts>(input, ctx, it, end);
84
                     if (bool(ctx.error)) [[unlikely]]
85
                        return;
86
                     (value.*reader)(key, input);
87
                  }
88
                  else {
89
                     static_assert(false_v<T>, "method must have 2 args");
90
                  }
91
               }
92
               else {
93
                  static_assert(false_v<T>, "method must have void return");
94
               }
95
            }
96
            else {
97
               static_assert(false_v<T>, "unknown_read type not handled");
98
            }
99
         }
100
         else {
101
            skip_value<JSON>::op<Opts>(ctx, it, end);
102
         }
103
      }
104
   };
105
106
   // Unless we can mutate the input buffer we need somewhere to store escaped strings for key lookup, etc.
107
   // We don't put this in the context because we don't want to continually reallocate.
108
   // IMPORTANT: Do not call use this when nested calls may be made that need additional buffers on the same thread.
109
   inline std::string& string_buffer() noexcept
110
0
   {
111
0
      static thread_local std::string buffer(256, '\0');
112
0
      return buffer;
113
0
   }
114
115
   // We use an error buffer to avoid multiple allocations in the case that errors occur multiple times.
116
   inline std::string& error_buffer() noexcept
117
0
   {
118
0
      static thread_local std::string buffer(256, '\0');
119
0
      return buffer;
120
0
   }
121
122
   template <class T>
123
      requires(glaze_value_t<T> && !custom_read<T>)
124
   struct from<JSON, T>
125
   {
126
      template <auto Opts, class Value, is_context Ctx, class It0, class It1>
127
      GLZ_ALWAYS_INLINE static void op(Value&& value, Ctx&& ctx, It0&& it, It1&& end)
128
5.28M
      {
129
5.28M
         using V = std::decay_t<decltype(get_member(std::declval<Value>(), meta_wrapper_v<T>))>;
130
5.28M
         from<JSON, V>::template op<Opts>(get_member(std::forward<Value>(value), meta_wrapper_v<T>),
131
5.28M
                                          std::forward<Ctx>(ctx), std::forward<It0>(it), std::forward<It1>(end));
132
5.28M
      }
_ZN3glz4fromILj10ENS_6json_tEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1EEERS1_TkNS_10is_contextERNS_7contextERPKcSA_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
128
6.19k
      {
129
6.19k
         using V = std::decay_t<decltype(get_member(std::declval<Value>(), meta_wrapper_v<T>))>;
130
6.19k
         from<JSON, V>::template op<Opts>(get_member(std::forward<Value>(value), meta_wrapper_v<T>),
131
6.19k
                                          std::forward<Ctx>(ctx), std::forward<It0>(it), std::forward<It1>(end));
132
6.19k
      }
_ZN3glz4fromILj10ENS_6json_tEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj4EEERS1_TkNS_10is_contextERNS_7contextERPKcSA_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
128
1.75M
      {
129
1.75M
         using V = std::decay_t<decltype(get_member(std::declval<Value>(), meta_wrapper_v<T>))>;
130
1.75M
         from<JSON, V>::template op<Opts>(get_member(std::forward<Value>(value), meta_wrapper_v<T>),
131
1.75M
                                          std::forward<Ctx>(ctx), std::forward<It0>(it), std::forward<It1>(end));
132
1.75M
      }
_ZN3glz4fromILj10ENS_6json_tEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1EEERS1_TkNS_10is_contextERNS_7contextERPKcSA_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
128
6.19k
      {
129
6.19k
         using V = std::decay_t<decltype(get_member(std::declval<Value>(), meta_wrapper_v<T>))>;
130
6.19k
         from<JSON, V>::template op<Opts>(get_member(std::forward<Value>(value), meta_wrapper_v<T>),
131
6.19k
                                          std::forward<Ctx>(ctx), std::forward<It0>(it), std::forward<It1>(end));
132
6.19k
      }
_ZN3glz4fromILj10ENS_6json_tEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj4EEERS1_TkNS_10is_contextERNS_7contextERPKcSA_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
128
1.75M
      {
129
1.75M
         using V = std::decay_t<decltype(get_member(std::declval<Value>(), meta_wrapper_v<T>))>;
130
1.75M
         from<JSON, V>::template op<Opts>(get_member(std::forward<Value>(value), meta_wrapper_v<T>),
131
1.75M
                                          std::forward<Ctx>(ctx), std::forward<It0>(it), std::forward<It1>(end));
132
1.75M
      }
_ZN3glz4fromILj10ENS_6json_tEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEERS1_TkNS_10is_contextERNS_7contextERPKcSA_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
128
6.19k
      {
129
6.19k
         using V = std::decay_t<decltype(get_member(std::declval<Value>(), meta_wrapper_v<T>))>;
130
6.19k
         from<JSON, V>::template op<Opts>(get_member(std::forward<Value>(value), meta_wrapper_v<T>),
131
6.19k
                                          std::forward<Ctx>(ctx), std::forward<It0>(it), std::forward<It1>(end));
132
6.19k
      }
_ZN3glz4fromILj10ENS_6json_tEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj36EEERS1_TkNS_10is_contextERNS_7contextERPKcSA_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
128
1.75M
      {
129
1.75M
         using V = std::decay_t<decltype(get_member(std::declval<Value>(), meta_wrapper_v<T>))>;
130
1.75M
         from<JSON, V>::template op<Opts>(get_member(std::forward<Value>(value), meta_wrapper_v<T>),
131
1.75M
                                          std::forward<Ctx>(ctx), std::forward<It0>(it), std::forward<It1>(end));
132
1.75M
      }
133
   };
134
135
   template <auto Opts>
136
   GLZ_ALWAYS_INLINE bool parse_ws_colon(is_context auto& ctx, auto&& it, auto&& end) noexcept
137
121k
   {
138
121k
      if (skip_ws<Opts>(ctx, it, end)) {
139
51
         return true;
140
51
      }
141
121k
      if (match_invalid_end<':', Opts>(ctx, it, end)) {
142
826
         return true;
143
826
      }
144
120k
      if (skip_ws<Opts>(ctx, it, end)) {
145
17
         return true;
146
17
      }
147
120k
      return false;
148
120k
   }
_ZN3glz14parse_ws_colonITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1EEETkNS_10is_contextENS_7contextERPKcS5_EEbRT0_OT1_OT2_
Line
Count
Source
137
40.4k
   {
138
40.4k
      if (skip_ws<Opts>(ctx, it, end)) {
139
51
         return true;
140
51
      }
141
40.3k
      if (match_invalid_end<':', Opts>(ctx, it, end)) {
142
442
         return true;
143
442
      }
144
39.9k
      if (skip_ws<Opts>(ctx, it, end)) {
145
17
         return true;
146
17
      }
147
39.9k
      return false;
148
39.9k
   }
_ZN3glz14parse_ws_colonITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1EEETkNS_10is_contextENS_7contextERPKcS5_EEbRT0_OT1_OT2_
Line
Count
Source
137
40.4k
   {
138
40.4k
      if (skip_ws<Opts>(ctx, it, end)) {
139
0
         return true;
140
0
      }
141
40.4k
      if (match_invalid_end<':', Opts>(ctx, it, end)) {
142
201
         return true;
143
201
      }
144
40.2k
      if (skip_ws<Opts>(ctx, it, end)) {
145
0
         return true;
146
0
      }
147
40.2k
      return false;
148
40.2k
   }
_ZN3glz14parse_ws_colonITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEETkNS_10is_contextENS_7contextERPKcS5_EEbRT0_OT1_OT2_
Line
Count
Source
137
40.2k
   {
138
40.2k
      if (skip_ws<Opts>(ctx, it, end)) {
139
0
         return true;
140
0
      }
141
40.2k
      if (match_invalid_end<':', Opts>(ctx, it, end)) {
142
183
         return true;
143
183
      }
144
40.1k
      if (skip_ws<Opts>(ctx, it, end)) {
145
0
         return true;
146
0
      }
147
40.1k
      return false;
148
40.1k
   }
149
150
   template <auto Opts, class T, size_t I, class Value, class... SelectedIndex>
151
      requires(glaze_object_t<T> || reflectable<T>)
152
   void decode_index(Value&& value, is_context auto&& ctx, auto&& it, auto&& end, SelectedIndex&&... selected_index)
153
111k
   {
154
111k
      static constexpr auto Key = get<I>(reflect<T>::keys);
155
111k
      static constexpr auto KeyWithEndQuote = join_v<Key, chars<"\"">>;
156
111k
      static constexpr auto Length = KeyWithEndQuote.size();
157
158
111k
      if (((it + Length) < end) && comparitor<KeyWithEndQuote>(it)) [[likely]] {
159
111k
         it += Length;
160
111k
         if constexpr (not Opts.null_terminated) {
161
32.3k
            if (it == end) [[unlikely]] {
162
0
               ctx.error = error_code::unexpected_end;
163
0
               return;
164
0
            }
165
32.3k
         }
166
167
111k
         if (skip_ws<Opts>(ctx, it, end)) {
168
53
            return;
169
53
         }
170
111k
         if (match_invalid_end<':', Opts>(ctx, it, end)) {
171
307
            return;
172
307
         }
173
111k
         if (skip_ws<Opts>(ctx, it, end)) {
174
61
            return;
175
61
         }
176
177
111k
         using V = refl_t<T, I>;
178
179
         if constexpr (const_value_v<V>) {
180
            if constexpr (Opts.error_on_const_read) {
181
               ctx.error = error_code::attempt_const_read;
182
            }
183
            else {
184
               // do not read anything into the const value
185
               skip_value<JSON>::op<Opts>(ctx, it, end);
186
            }
187
         }
188
111k
         else {
189
            if constexpr (glaze_object_t<T>) {
190
               from<JSON, std::remove_cvref_t<V>>::template op<ws_handled<Opts>()>(
191
                  get_member(value, get<I>(reflect<T>::values)), ctx, it, end);
192
            }
193
111k
            else {
194
111k
               from<JSON, std::remove_cvref_t<V>>::template op<ws_handled<Opts>()>(
195
111k
                  get_member(value, get<I>(to_tie(value))), ctx, it, end);
196
111k
            }
197
111k
         }
198
199
         if constexpr (Opts.error_on_missing_keys || Opts.partial_read) {
200
            ((selected_index = I), ...);
201
         }
202
111k
      }
203
272
      else [[unlikely]] {
204
272
         if constexpr (Opts.error_on_unknown_keys) {
205
272
            ctx.error = error_code::unknown_key;
206
         }
207
         else {
208
            auto* start = it;
209
            skip_string_view<Opts>(ctx, it, end);
210
            if (bool(ctx.error)) [[unlikely]]
211
               return;
212
            const sv key = {start, size_t(it - start)};
213
            ++it;
214
            if constexpr (not Opts.null_terminated) {
215
               if (it == end) [[unlikely]] {
216
                  ctx.error = error_code::unexpected_end;
217
                  return;
218
               }
219
            }
220
221
            if (parse_ws_colon<Opts>(ctx, it, end)) {
222
               return;
223
            }
224
225
            parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
226
         }
227
272
      }
228
111k
   }
_ZN3glz12decode_indexITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1EEE9my_structLm0ERS2_JETkNS_10is_contextERNS_7contextERPKcS8_Qoo14glaze_object_tIT0_E11reflectableIS9_EEEvOT2_OT4_OT5_OT6_DpOT3_
Line
Count
Source
153
8.54k
   {
154
8.54k
      static constexpr auto Key = get<I>(reflect<T>::keys);
155
8.54k
      static constexpr auto KeyWithEndQuote = join_v<Key, chars<"\"">>;
156
8.54k
      static constexpr auto Length = KeyWithEndQuote.size();
157
158
8.54k
      if (((it + Length) < end) && comparitor<KeyWithEndQuote>(it)) [[likely]] {
159
8.52k
         it += Length;
160
8.52k
         if constexpr (not Opts.null_terminated) {
161
8.52k
            if (it == end) [[unlikely]] {
162
0
               ctx.error = error_code::unexpected_end;
163
0
               return;
164
0
            }
165
8.52k
         }
166
167
8.52k
         if (skip_ws<Opts>(ctx, it, end)) {
168
16
            return;
169
16
         }
170
8.50k
         if (match_invalid_end<':', Opts>(ctx, it, end)) {
171
29
            return;
172
29
         }
173
8.47k
         if (skip_ws<Opts>(ctx, it, end)) {
174
18
            return;
175
18
         }
176
177
8.46k
         using V = refl_t<T, I>;
178
179
         if constexpr (const_value_v<V>) {
180
            if constexpr (Opts.error_on_const_read) {
181
               ctx.error = error_code::attempt_const_read;
182
            }
183
            else {
184
               // do not read anything into the const value
185
               skip_value<JSON>::op<Opts>(ctx, it, end);
186
            }
187
         }
188
8.46k
         else {
189
            if constexpr (glaze_object_t<T>) {
190
               from<JSON, std::remove_cvref_t<V>>::template op<ws_handled<Opts>()>(
191
                  get_member(value, get<I>(reflect<T>::values)), ctx, it, end);
192
            }
193
8.46k
            else {
194
8.46k
               from<JSON, std::remove_cvref_t<V>>::template op<ws_handled<Opts>()>(
195
8.46k
                  get_member(value, get<I>(to_tie(value))), ctx, it, end);
196
8.46k
            }
197
8.46k
         }
198
199
         if constexpr (Opts.error_on_missing_keys || Opts.partial_read) {
200
            ((selected_index = I), ...);
201
         }
202
8.46k
      }
203
21
      else [[unlikely]] {
204
21
         if constexpr (Opts.error_on_unknown_keys) {
205
21
            ctx.error = error_code::unknown_key;
206
         }
207
         else {
208
            auto* start = it;
209
            skip_string_view<Opts>(ctx, it, end);
210
            if (bool(ctx.error)) [[unlikely]]
211
               return;
212
            const sv key = {start, size_t(it - start)};
213
            ++it;
214
            if constexpr (not Opts.null_terminated) {
215
               if (it == end) [[unlikely]] {
216
                  ctx.error = error_code::unexpected_end;
217
                  return;
218
               }
219
            }
220
221
            if (parse_ws_colon<Opts>(ctx, it, end)) {
222
               return;
223
            }
224
225
            parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
226
         }
227
21
      }
228
8.54k
   }
_ZN3glz12decode_indexITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1EEE9my_structLm1ERS2_JETkNS_10is_contextERNS_7contextERPKcS8_Qoo14glaze_object_tIT0_E11reflectableIS9_EEEvOT2_OT4_OT5_OT6_DpOT3_
Line
Count
Source
153
14.8k
   {
154
14.8k
      static constexpr auto Key = get<I>(reflect<T>::keys);
155
14.8k
      static constexpr auto KeyWithEndQuote = join_v<Key, chars<"\"">>;
156
14.8k
      static constexpr auto Length = KeyWithEndQuote.size();
157
158
14.8k
      if (((it + Length) < end) && comparitor<KeyWithEndQuote>(it)) [[likely]] {
159
14.8k
         it += Length;
160
14.8k
         if constexpr (not Opts.null_terminated) {
161
14.8k
            if (it == end) [[unlikely]] {
162
0
               ctx.error = error_code::unexpected_end;
163
0
               return;
164
0
            }
165
14.8k
         }
166
167
14.8k
         if (skip_ws<Opts>(ctx, it, end)) {
168
16
            return;
169
16
         }
170
14.7k
         if (match_invalid_end<':', Opts>(ctx, it, end)) {
171
23
            return;
172
23
         }
173
14.7k
         if (skip_ws<Opts>(ctx, it, end)) {
174
17
            return;
175
17
         }
176
177
14.7k
         using V = refl_t<T, I>;
178
179
         if constexpr (const_value_v<V>) {
180
            if constexpr (Opts.error_on_const_read) {
181
               ctx.error = error_code::attempt_const_read;
182
            }
183
            else {
184
               // do not read anything into the const value
185
               skip_value<JSON>::op<Opts>(ctx, it, end);
186
            }
187
         }
188
14.7k
         else {
189
            if constexpr (glaze_object_t<T>) {
190
               from<JSON, std::remove_cvref_t<V>>::template op<ws_handled<Opts>()>(
191
                  get_member(value, get<I>(reflect<T>::values)), ctx, it, end);
192
            }
193
14.7k
            else {
194
14.7k
               from<JSON, std::remove_cvref_t<V>>::template op<ws_handled<Opts>()>(
195
14.7k
                  get_member(value, get<I>(to_tie(value))), ctx, it, end);
196
14.7k
            }
197
14.7k
         }
198
199
         if constexpr (Opts.error_on_missing_keys || Opts.partial_read) {
200
            ((selected_index = I), ...);
201
         }
202
14.7k
      }
203
29
      else [[unlikely]] {
204
29
         if constexpr (Opts.error_on_unknown_keys) {
205
29
            ctx.error = error_code::unknown_key;
206
         }
207
         else {
208
            auto* start = it;
209
            skip_string_view<Opts>(ctx, it, end);
210
            if (bool(ctx.error)) [[unlikely]]
211
               return;
212
            const sv key = {start, size_t(it - start)};
213
            ++it;
214
            if constexpr (not Opts.null_terminated) {
215
               if (it == end) [[unlikely]] {
216
                  ctx.error = error_code::unexpected_end;
217
                  return;
218
               }
219
            }
220
221
            if (parse_ws_colon<Opts>(ctx, it, end)) {
222
               return;
223
            }
224
225
            parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
226
         }
227
29
      }
228
14.8k
   }
_ZN3glz12decode_indexITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1EEE9my_structLm2ERS2_JETkNS_10is_contextERNS_7contextERPKcS8_Qoo14glaze_object_tIT0_E11reflectableIS9_EEEvOT2_OT4_OT5_OT6_DpOT3_
Line
Count
Source
153
3
   {
154
3
      static constexpr auto Key = get<I>(reflect<T>::keys);
155
3
      static constexpr auto KeyWithEndQuote = join_v<Key, chars<"\"">>;
156
3
      static constexpr auto Length = KeyWithEndQuote.size();
157
158
3
      if (((it + Length) < end) && comparitor<KeyWithEndQuote>(it)) [[likely]] {
159
0
         it += Length;
160
0
         if constexpr (not Opts.null_terminated) {
161
0
            if (it == end) [[unlikely]] {
162
0
               ctx.error = error_code::unexpected_end;
163
0
               return;
164
0
            }
165
0
         }
166
167
0
         if (skip_ws<Opts>(ctx, it, end)) {
168
0
            return;
169
0
         }
170
0
         if (match_invalid_end<':', Opts>(ctx, it, end)) {
171
0
            return;
172
0
         }
173
0
         if (skip_ws<Opts>(ctx, it, end)) {
174
0
            return;
175
0
         }
176
177
0
         using V = refl_t<T, I>;
178
179
         if constexpr (const_value_v<V>) {
180
            if constexpr (Opts.error_on_const_read) {
181
               ctx.error = error_code::attempt_const_read;
182
            }
183
            else {
184
               // do not read anything into the const value
185
               skip_value<JSON>::op<Opts>(ctx, it, end);
186
            }
187
         }
188
0
         else {
189
            if constexpr (glaze_object_t<T>) {
190
               from<JSON, std::remove_cvref_t<V>>::template op<ws_handled<Opts>()>(
191
                  get_member(value, get<I>(reflect<T>::values)), ctx, it, end);
192
            }
193
0
            else {
194
0
               from<JSON, std::remove_cvref_t<V>>::template op<ws_handled<Opts>()>(
195
0
                  get_member(value, get<I>(to_tie(value))), ctx, it, end);
196
0
            }
197
0
         }
198
199
         if constexpr (Opts.error_on_missing_keys || Opts.partial_read) {
200
            ((selected_index = I), ...);
201
         }
202
0
      }
203
3
      else [[unlikely]] {
204
3
         if constexpr (Opts.error_on_unknown_keys) {
205
3
            ctx.error = error_code::unknown_key;
206
         }
207
         else {
208
            auto* start = it;
209
            skip_string_view<Opts>(ctx, it, end);
210
            if (bool(ctx.error)) [[unlikely]]
211
               return;
212
            const sv key = {start, size_t(it - start)};
213
            ++it;
214
            if constexpr (not Opts.null_terminated) {
215
               if (it == end) [[unlikely]] {
216
                  ctx.error = error_code::unexpected_end;
217
                  return;
218
               }
219
            }
220
221
            if (parse_ws_colon<Opts>(ctx, it, end)) {
222
               return;
223
            }
224
225
            parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
226
         }
227
3
      }
228
3
   }
_ZN3glz12decode_indexITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1EEE9my_structLm3ERS2_JETkNS_10is_contextERNS_7contextERPKcS8_Qoo14glaze_object_tIT0_E11reflectableIS9_EEEvOT2_OT4_OT5_OT6_DpOT3_
Line
Count
Source
153
9.06k
   {
154
9.06k
      static constexpr auto Key = get<I>(reflect<T>::keys);
155
9.06k
      static constexpr auto KeyWithEndQuote = join_v<Key, chars<"\"">>;
156
9.06k
      static constexpr auto Length = KeyWithEndQuote.size();
157
158
9.06k
      if (((it + Length) < end) && comparitor<KeyWithEndQuote>(it)) [[likely]] {
159
9.03k
         it += Length;
160
9.03k
         if constexpr (not Opts.null_terminated) {
161
9.03k
            if (it == end) [[unlikely]] {
162
0
               ctx.error = error_code::unexpected_end;
163
0
               return;
164
0
            }
165
9.03k
         }
166
167
9.03k
         if (skip_ws<Opts>(ctx, it, end)) {
168
15
            return;
169
15
         }
170
9.01k
         if (match_invalid_end<':', Opts>(ctx, it, end)) {
171
20
            return;
172
20
         }
173
8.99k
         if (skip_ws<Opts>(ctx, it, end)) {
174
18
            return;
175
18
         }
176
177
8.97k
         using V = refl_t<T, I>;
178
179
         if constexpr (const_value_v<V>) {
180
            if constexpr (Opts.error_on_const_read) {
181
               ctx.error = error_code::attempt_const_read;
182
            }
183
            else {
184
               // do not read anything into the const value
185
               skip_value<JSON>::op<Opts>(ctx, it, end);
186
            }
187
         }
188
8.97k
         else {
189
            if constexpr (glaze_object_t<T>) {
190
               from<JSON, std::remove_cvref_t<V>>::template op<ws_handled<Opts>()>(
191
                  get_member(value, get<I>(reflect<T>::values)), ctx, it, end);
192
            }
193
8.97k
            else {
194
8.97k
               from<JSON, std::remove_cvref_t<V>>::template op<ws_handled<Opts>()>(
195
8.97k
                  get_member(value, get<I>(to_tie(value))), ctx, it, end);
196
8.97k
            }
197
8.97k
         }
198
199
         if constexpr (Opts.error_on_missing_keys || Opts.partial_read) {
200
            ((selected_index = I), ...);
201
         }
202
8.97k
      }
203
29
      else [[unlikely]] {
204
29
         if constexpr (Opts.error_on_unknown_keys) {
205
29
            ctx.error = error_code::unknown_key;
206
         }
207
         else {
208
            auto* start = it;
209
            skip_string_view<Opts>(ctx, it, end);
210
            if (bool(ctx.error)) [[unlikely]]
211
               return;
212
            const sv key = {start, size_t(it - start)};
213
            ++it;
214
            if constexpr (not Opts.null_terminated) {
215
               if (it == end) [[unlikely]] {
216
                  ctx.error = error_code::unexpected_end;
217
                  return;
218
               }
219
            }
220
221
            if (parse_ws_colon<Opts>(ctx, it, end)) {
222
               return;
223
            }
224
225
            parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
226
         }
227
29
      }
228
9.06k
   }
_ZN3glz12decode_indexITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1EEE9my_structLm0ERS2_JETkNS_10is_contextERNS_7contextERPKcS8_Qoo14glaze_object_tIT0_E11reflectableIS9_EEEvOT2_OT4_OT5_OT6_DpOT3_
Line
Count
Source
153
8.54k
   {
154
8.54k
      static constexpr auto Key = get<I>(reflect<T>::keys);
155
8.54k
      static constexpr auto KeyWithEndQuote = join_v<Key, chars<"\"">>;
156
8.54k
      static constexpr auto Length = KeyWithEndQuote.size();
157
158
8.54k
      if (((it + Length) < end) && comparitor<KeyWithEndQuote>(it)) [[likely]] {
159
8.52k
         it += Length;
160
         if constexpr (not Opts.null_terminated) {
161
            if (it == end) [[unlikely]] {
162
               ctx.error = error_code::unexpected_end;
163
               return;
164
            }
165
         }
166
167
8.52k
         if (skip_ws<Opts>(ctx, it, end)) {
168
0
            return;
169
0
         }
170
8.52k
         if (match_invalid_end<':', Opts>(ctx, it, end)) {
171
37
            return;
172
37
         }
173
8.48k
         if (skip_ws<Opts>(ctx, it, end)) {
174
0
            return;
175
0
         }
176
177
8.48k
         using V = refl_t<T, I>;
178
179
         if constexpr (const_value_v<V>) {
180
            if constexpr (Opts.error_on_const_read) {
181
               ctx.error = error_code::attempt_const_read;
182
            }
183
            else {
184
               // do not read anything into the const value
185
               skip_value<JSON>::op<Opts>(ctx, it, end);
186
            }
187
         }
188
8.48k
         else {
189
            if constexpr (glaze_object_t<T>) {
190
               from<JSON, std::remove_cvref_t<V>>::template op<ws_handled<Opts>()>(
191
                  get_member(value, get<I>(reflect<T>::values)), ctx, it, end);
192
            }
193
8.48k
            else {
194
8.48k
               from<JSON, std::remove_cvref_t<V>>::template op<ws_handled<Opts>()>(
195
8.48k
                  get_member(value, get<I>(to_tie(value))), ctx, it, end);
196
8.48k
            }
197
8.48k
         }
198
199
         if constexpr (Opts.error_on_missing_keys || Opts.partial_read) {
200
            ((selected_index = I), ...);
201
         }
202
8.48k
      }
203
21
      else [[unlikely]] {
204
21
         if constexpr (Opts.error_on_unknown_keys) {
205
21
            ctx.error = error_code::unknown_key;
206
         }
207
         else {
208
            auto* start = it;
209
            skip_string_view<Opts>(ctx, it, end);
210
            if (bool(ctx.error)) [[unlikely]]
211
               return;
212
            const sv key = {start, size_t(it - start)};
213
            ++it;
214
            if constexpr (not Opts.null_terminated) {
215
               if (it == end) [[unlikely]] {
216
                  ctx.error = error_code::unexpected_end;
217
                  return;
218
               }
219
            }
220
221
            if (parse_ws_colon<Opts>(ctx, it, end)) {
222
               return;
223
            }
224
225
            parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
226
         }
227
21
      }
228
8.54k
   }
_ZN3glz12decode_indexITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1EEE9my_structLm1ERS2_JETkNS_10is_contextERNS_7contextERPKcS8_Qoo14glaze_object_tIT0_E11reflectableIS9_EEEvOT2_OT4_OT5_OT6_DpOT3_
Line
Count
Source
153
14.8k
   {
154
14.8k
      static constexpr auto Key = get<I>(reflect<T>::keys);
155
14.8k
      static constexpr auto KeyWithEndQuote = join_v<Key, chars<"\"">>;
156
14.8k
      static constexpr auto Length = KeyWithEndQuote.size();
157
158
14.8k
      if (((it + Length) < end) && comparitor<KeyWithEndQuote>(it)) [[likely]] {
159
14.8k
         it += Length;
160
         if constexpr (not Opts.null_terminated) {
161
            if (it == end) [[unlikely]] {
162
               ctx.error = error_code::unexpected_end;
163
               return;
164
            }
165
         }
166
167
14.8k
         if (skip_ws<Opts>(ctx, it, end)) {
168
0
            return;
169
0
         }
170
14.8k
         if (match_invalid_end<':', Opts>(ctx, it, end)) {
171
34
            return;
172
34
         }
173
14.7k
         if (skip_ws<Opts>(ctx, it, end)) {
174
0
            return;
175
0
         }
176
177
14.7k
         using V = refl_t<T, I>;
178
179
         if constexpr (const_value_v<V>) {
180
            if constexpr (Opts.error_on_const_read) {
181
               ctx.error = error_code::attempt_const_read;
182
            }
183
            else {
184
               // do not read anything into the const value
185
               skip_value<JSON>::op<Opts>(ctx, it, end);
186
            }
187
         }
188
14.7k
         else {
189
            if constexpr (glaze_object_t<T>) {
190
               from<JSON, std::remove_cvref_t<V>>::template op<ws_handled<Opts>()>(
191
                  get_member(value, get<I>(reflect<T>::values)), ctx, it, end);
192
            }
193
14.7k
            else {
194
14.7k
               from<JSON, std::remove_cvref_t<V>>::template op<ws_handled<Opts>()>(
195
14.7k
                  get_member(value, get<I>(to_tie(value))), ctx, it, end);
196
14.7k
            }
197
14.7k
         }
198
199
         if constexpr (Opts.error_on_missing_keys || Opts.partial_read) {
200
            ((selected_index = I), ...);
201
         }
202
14.7k
      }
203
29
      else [[unlikely]] {
204
29
         if constexpr (Opts.error_on_unknown_keys) {
205
29
            ctx.error = error_code::unknown_key;
206
         }
207
         else {
208
            auto* start = it;
209
            skip_string_view<Opts>(ctx, it, end);
210
            if (bool(ctx.error)) [[unlikely]]
211
               return;
212
            const sv key = {start, size_t(it - start)};
213
            ++it;
214
            if constexpr (not Opts.null_terminated) {
215
               if (it == end) [[unlikely]] {
216
                  ctx.error = error_code::unexpected_end;
217
                  return;
218
               }
219
            }
220
221
            if (parse_ws_colon<Opts>(ctx, it, end)) {
222
               return;
223
            }
224
225
            parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
226
         }
227
29
      }
228
14.8k
   }
_ZN3glz12decode_indexITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1EEE9my_structLm2ERS2_JETkNS_10is_contextERNS_7contextERPKcS8_Qoo14glaze_object_tIT0_E11reflectableIS9_EEEvOT2_OT4_OT5_OT6_DpOT3_
Line
Count
Source
153
3
   {
154
3
      static constexpr auto Key = get<I>(reflect<T>::keys);
155
3
      static constexpr auto KeyWithEndQuote = join_v<Key, chars<"\"">>;
156
3
      static constexpr auto Length = KeyWithEndQuote.size();
157
158
3
      if (((it + Length) < end) && comparitor<KeyWithEndQuote>(it)) [[likely]] {
159
0
         it += Length;
160
         if constexpr (not Opts.null_terminated) {
161
            if (it == end) [[unlikely]] {
162
               ctx.error = error_code::unexpected_end;
163
               return;
164
            }
165
         }
166
167
0
         if (skip_ws<Opts>(ctx, it, end)) {
168
0
            return;
169
0
         }
170
0
         if (match_invalid_end<':', Opts>(ctx, it, end)) {
171
0
            return;
172
0
         }
173
0
         if (skip_ws<Opts>(ctx, it, end)) {
174
0
            return;
175
0
         }
176
177
0
         using V = refl_t<T, I>;
178
179
         if constexpr (const_value_v<V>) {
180
            if constexpr (Opts.error_on_const_read) {
181
               ctx.error = error_code::attempt_const_read;
182
            }
183
            else {
184
               // do not read anything into the const value
185
               skip_value<JSON>::op<Opts>(ctx, it, end);
186
            }
187
         }
188
0
         else {
189
            if constexpr (glaze_object_t<T>) {
190
               from<JSON, std::remove_cvref_t<V>>::template op<ws_handled<Opts>()>(
191
                  get_member(value, get<I>(reflect<T>::values)), ctx, it, end);
192
            }
193
0
            else {
194
0
               from<JSON, std::remove_cvref_t<V>>::template op<ws_handled<Opts>()>(
195
0
                  get_member(value, get<I>(to_tie(value))), ctx, it, end);
196
0
            }
197
0
         }
198
199
         if constexpr (Opts.error_on_missing_keys || Opts.partial_read) {
200
            ((selected_index = I), ...);
201
         }
202
0
      }
203
3
      else [[unlikely]] {
204
3
         if constexpr (Opts.error_on_unknown_keys) {
205
3
            ctx.error = error_code::unknown_key;
206
         }
207
         else {
208
            auto* start = it;
209
            skip_string_view<Opts>(ctx, it, end);
210
            if (bool(ctx.error)) [[unlikely]]
211
               return;
212
            const sv key = {start, size_t(it - start)};
213
            ++it;
214
            if constexpr (not Opts.null_terminated) {
215
               if (it == end) [[unlikely]] {
216
                  ctx.error = error_code::unexpected_end;
217
                  return;
218
               }
219
            }
220
221
            if (parse_ws_colon<Opts>(ctx, it, end)) {
222
               return;
223
            }
224
225
            parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
226
         }
227
3
      }
228
3
   }
_ZN3glz12decode_indexITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1EEE9my_structLm3ERS2_JETkNS_10is_contextERNS_7contextERPKcS8_Qoo14glaze_object_tIT0_E11reflectableIS9_EEEvOT2_OT4_OT5_OT6_DpOT3_
Line
Count
Source
153
9.06k
   {
154
9.06k
      static constexpr auto Key = get<I>(reflect<T>::keys);
155
9.06k
      static constexpr auto KeyWithEndQuote = join_v<Key, chars<"\"">>;
156
9.06k
      static constexpr auto Length = KeyWithEndQuote.size();
157
158
9.06k
      if (((it + Length) < end) && comparitor<KeyWithEndQuote>(it)) [[likely]] {
159
9.03k
         it += Length;
160
         if constexpr (not Opts.null_terminated) {
161
            if (it == end) [[unlikely]] {
162
               ctx.error = error_code::unexpected_end;
163
               return;
164
            }
165
         }
166
167
9.03k
         if (skip_ws<Opts>(ctx, it, end)) {
168
0
            return;
169
0
         }
170
9.03k
         if (match_invalid_end<':', Opts>(ctx, it, end)) {
171
30
            return;
172
30
         }
173
9.00k
         if (skip_ws<Opts>(ctx, it, end)) {
174
0
            return;
175
0
         }
176
177
9.00k
         using V = refl_t<T, I>;
178
179
         if constexpr (const_value_v<V>) {
180
            if constexpr (Opts.error_on_const_read) {
181
               ctx.error = error_code::attempt_const_read;
182
            }
183
            else {
184
               // do not read anything into the const value
185
               skip_value<JSON>::op<Opts>(ctx, it, end);
186
            }
187
         }
188
9.00k
         else {
189
            if constexpr (glaze_object_t<T>) {
190
               from<JSON, std::remove_cvref_t<V>>::template op<ws_handled<Opts>()>(
191
                  get_member(value, get<I>(reflect<T>::values)), ctx, it, end);
192
            }
193
9.00k
            else {
194
9.00k
               from<JSON, std::remove_cvref_t<V>>::template op<ws_handled<Opts>()>(
195
9.00k
                  get_member(value, get<I>(to_tie(value))), ctx, it, end);
196
9.00k
            }
197
9.00k
         }
198
199
         if constexpr (Opts.error_on_missing_keys || Opts.partial_read) {
200
            ((selected_index = I), ...);
201
         }
202
9.00k
      }
203
29
      else [[unlikely]] {
204
29
         if constexpr (Opts.error_on_unknown_keys) {
205
29
            ctx.error = error_code::unknown_key;
206
         }
207
         else {
208
            auto* start = it;
209
            skip_string_view<Opts>(ctx, it, end);
210
            if (bool(ctx.error)) [[unlikely]]
211
               return;
212
            const sv key = {start, size_t(it - start)};
213
            ++it;
214
            if constexpr (not Opts.null_terminated) {
215
               if (it == end) [[unlikely]] {
216
                  ctx.error = error_code::unexpected_end;
217
                  return;
218
               }
219
            }
220
221
            if (parse_ws_colon<Opts>(ctx, it, end)) {
222
               return;
223
            }
224
225
            parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
226
         }
227
29
      }
228
9.06k
   }
_ZN3glz12decode_indexITnDaXtlNS_4optsELj10ELb1ELb1ELb1ELb1ELb0ELb0ELc32ELh3ELb1EEE9my_structLm0ERS2_JETkNS_10is_contextERNS_7contextERPKcS8_Qoo14glaze_object_tIT0_E11reflectableIS9_EEEvOT2_OT4_OT5_OT6_DpOT3_
Line
Count
Source
153
9.75k
   {
154
9.75k
      static constexpr auto Key = get<I>(reflect<T>::keys);
155
9.75k
      static constexpr auto KeyWithEndQuote = join_v<Key, chars<"\"">>;
156
9.75k
      static constexpr auto Length = KeyWithEndQuote.size();
157
158
9.75k
      if (((it + Length) < end) && comparitor<KeyWithEndQuote>(it)) [[likely]] {
159
9.72k
         it += Length;
160
         if constexpr (not Opts.null_terminated) {
161
            if (it == end) [[unlikely]] {
162
               ctx.error = error_code::unexpected_end;
163
               return;
164
            }
165
         }
166
167
9.72k
         if (skip_ws<Opts>(ctx, it, end)) {
168
2
            return;
169
2
         }
170
9.72k
         if (match_invalid_end<':', Opts>(ctx, it, end)) {
171
45
            return;
172
45
         }
173
9.67k
         if (skip_ws<Opts>(ctx, it, end)) {
174
2
            return;
175
2
         }
176
177
9.67k
         using V = refl_t<T, I>;
178
179
         if constexpr (const_value_v<V>) {
180
            if constexpr (Opts.error_on_const_read) {
181
               ctx.error = error_code::attempt_const_read;
182
            }
183
            else {
184
               // do not read anything into the const value
185
               skip_value<JSON>::op<Opts>(ctx, it, end);
186
            }
187
         }
188
9.67k
         else {
189
            if constexpr (glaze_object_t<T>) {
190
               from<JSON, std::remove_cvref_t<V>>::template op<ws_handled<Opts>()>(
191
                  get_member(value, get<I>(reflect<T>::values)), ctx, it, end);
192
            }
193
9.67k
            else {
194
9.67k
               from<JSON, std::remove_cvref_t<V>>::template op<ws_handled<Opts>()>(
195
9.67k
                  get_member(value, get<I>(to_tie(value))), ctx, it, end);
196
9.67k
            }
197
9.67k
         }
198
199
         if constexpr (Opts.error_on_missing_keys || Opts.partial_read) {
200
            ((selected_index = I), ...);
201
         }
202
9.67k
      }
203
25
      else [[unlikely]] {
204
25
         if constexpr (Opts.error_on_unknown_keys) {
205
25
            ctx.error = error_code::unknown_key;
206
         }
207
         else {
208
            auto* start = it;
209
            skip_string_view<Opts>(ctx, it, end);
210
            if (bool(ctx.error)) [[unlikely]]
211
               return;
212
            const sv key = {start, size_t(it - start)};
213
            ++it;
214
            if constexpr (not Opts.null_terminated) {
215
               if (it == end) [[unlikely]] {
216
                  ctx.error = error_code::unexpected_end;
217
                  return;
218
               }
219
            }
220
221
            if (parse_ws_colon<Opts>(ctx, it, end)) {
222
               return;
223
            }
224
225
            parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
226
         }
227
25
      }
228
9.75k
   }
_ZN3glz12decode_indexITnDaXtlNS_4optsELj10ELb1ELb1ELb1ELb1ELb0ELb0ELc32ELh3ELb1EEE9my_structLm1ERS2_JETkNS_10is_contextERNS_7contextERPKcS8_Qoo14glaze_object_tIT0_E11reflectableIS9_EEEvOT2_OT4_OT5_OT6_DpOT3_
Line
Count
Source
153
24.1k
   {
154
24.1k
      static constexpr auto Key = get<I>(reflect<T>::keys);
155
24.1k
      static constexpr auto KeyWithEndQuote = join_v<Key, chars<"\"">>;
156
24.1k
      static constexpr auto Length = KeyWithEndQuote.size();
157
158
24.1k
      if (((it + Length) < end) && comparitor<KeyWithEndQuote>(it)) [[likely]] {
159
24.1k
         it += Length;
160
         if constexpr (not Opts.null_terminated) {
161
            if (it == end) [[unlikely]] {
162
               ctx.error = error_code::unexpected_end;
163
               return;
164
            }
165
         }
166
167
24.1k
         if (skip_ws<Opts>(ctx, it, end)) {
168
2
            return;
169
2
         }
170
24.1k
         if (match_invalid_end<':', Opts>(ctx, it, end)) {
171
49
            return;
172
49
         }
173
24.0k
         if (skip_ws<Opts>(ctx, it, end)) {
174
4
            return;
175
4
         }
176
177
24.0k
         using V = refl_t<T, I>;
178
179
         if constexpr (const_value_v<V>) {
180
            if constexpr (Opts.error_on_const_read) {
181
               ctx.error = error_code::attempt_const_read;
182
            }
183
            else {
184
               // do not read anything into the const value
185
               skip_value<JSON>::op<Opts>(ctx, it, end);
186
            }
187
         }
188
24.0k
         else {
189
            if constexpr (glaze_object_t<T>) {
190
               from<JSON, std::remove_cvref_t<V>>::template op<ws_handled<Opts>()>(
191
                  get_member(value, get<I>(reflect<T>::values)), ctx, it, end);
192
            }
193
24.0k
            else {
194
24.0k
               from<JSON, std::remove_cvref_t<V>>::template op<ws_handled<Opts>()>(
195
24.0k
                  get_member(value, get<I>(to_tie(value))), ctx, it, end);
196
24.0k
            }
197
24.0k
         }
198
199
         if constexpr (Opts.error_on_missing_keys || Opts.partial_read) {
200
            ((selected_index = I), ...);
201
         }
202
24.0k
      }
203
32
      else [[unlikely]] {
204
32
         if constexpr (Opts.error_on_unknown_keys) {
205
32
            ctx.error = error_code::unknown_key;
206
         }
207
         else {
208
            auto* start = it;
209
            skip_string_view<Opts>(ctx, it, end);
210
            if (bool(ctx.error)) [[unlikely]]
211
               return;
212
            const sv key = {start, size_t(it - start)};
213
            ++it;
214
            if constexpr (not Opts.null_terminated) {
215
               if (it == end) [[unlikely]] {
216
                  ctx.error = error_code::unexpected_end;
217
                  return;
218
               }
219
            }
220
221
            if (parse_ws_colon<Opts>(ctx, it, end)) {
222
               return;
223
            }
224
225
            parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
226
         }
227
32
      }
228
24.1k
   }
_ZN3glz12decode_indexITnDaXtlNS_4optsELj10ELb1ELb1ELb1ELb1ELb0ELb0ELc32ELh3ELb1EEE9my_structLm2ERS2_JETkNS_10is_contextERNS_7contextERPKcS8_Qoo14glaze_object_tIT0_E11reflectableIS9_EEEvOT2_OT4_OT5_OT6_DpOT3_
Line
Count
Source
153
2
   {
154
2
      static constexpr auto Key = get<I>(reflect<T>::keys);
155
2
      static constexpr auto KeyWithEndQuote = join_v<Key, chars<"\"">>;
156
2
      static constexpr auto Length = KeyWithEndQuote.size();
157
158
2
      if (((it + Length) < end) && comparitor<KeyWithEndQuote>(it)) [[likely]] {
159
0
         it += Length;
160
         if constexpr (not Opts.null_terminated) {
161
            if (it == end) [[unlikely]] {
162
               ctx.error = error_code::unexpected_end;
163
               return;
164
            }
165
         }
166
167
0
         if (skip_ws<Opts>(ctx, it, end)) {
168
0
            return;
169
0
         }
170
0
         if (match_invalid_end<':', Opts>(ctx, it, end)) {
171
0
            return;
172
0
         }
173
0
         if (skip_ws<Opts>(ctx, it, end)) {
174
0
            return;
175
0
         }
176
177
0
         using V = refl_t<T, I>;
178
179
         if constexpr (const_value_v<V>) {
180
            if constexpr (Opts.error_on_const_read) {
181
               ctx.error = error_code::attempt_const_read;
182
            }
183
            else {
184
               // do not read anything into the const value
185
               skip_value<JSON>::op<Opts>(ctx, it, end);
186
            }
187
         }
188
0
         else {
189
            if constexpr (glaze_object_t<T>) {
190
               from<JSON, std::remove_cvref_t<V>>::template op<ws_handled<Opts>()>(
191
                  get_member(value, get<I>(reflect<T>::values)), ctx, it, end);
192
            }
193
0
            else {
194
0
               from<JSON, std::remove_cvref_t<V>>::template op<ws_handled<Opts>()>(
195
0
                  get_member(value, get<I>(to_tie(value))), ctx, it, end);
196
0
            }
197
0
         }
198
199
         if constexpr (Opts.error_on_missing_keys || Opts.partial_read) {
200
            ((selected_index = I), ...);
201
         }
202
0
      }
203
2
      else [[unlikely]] {
204
2
         if constexpr (Opts.error_on_unknown_keys) {
205
2
            ctx.error = error_code::unknown_key;
206
         }
207
         else {
208
            auto* start = it;
209
            skip_string_view<Opts>(ctx, it, end);
210
            if (bool(ctx.error)) [[unlikely]]
211
               return;
212
            const sv key = {start, size_t(it - start)};
213
            ++it;
214
            if constexpr (not Opts.null_terminated) {
215
               if (it == end) [[unlikely]] {
216
                  ctx.error = error_code::unexpected_end;
217
                  return;
218
               }
219
            }
220
221
            if (parse_ws_colon<Opts>(ctx, it, end)) {
222
               return;
223
            }
224
225
            parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
226
         }
227
2
      }
228
2
   }
_ZN3glz12decode_indexITnDaXtlNS_4optsELj10ELb1ELb1ELb1ELb1ELb0ELb0ELc32ELh3ELb1EEE9my_structLm3ERS2_JETkNS_10is_contextERNS_7contextERPKcS8_Qoo14glaze_object_tIT0_E11reflectableIS9_EEEvOT2_OT4_OT5_OT6_DpOT3_
Line
Count
Source
153
9.39k
   {
154
9.39k
      static constexpr auto Key = get<I>(reflect<T>::keys);
155
9.39k
      static constexpr auto KeyWithEndQuote = join_v<Key, chars<"\"">>;
156
9.39k
      static constexpr auto Length = KeyWithEndQuote.size();
157
158
9.39k
      if (((it + Length) < end) && comparitor<KeyWithEndQuote>(it)) [[likely]] {
159
9.34k
         it += Length;
160
         if constexpr (not Opts.null_terminated) {
161
            if (it == end) [[unlikely]] {
162
               ctx.error = error_code::unexpected_end;
163
               return;
164
            }
165
         }
166
167
9.34k
         if (skip_ws<Opts>(ctx, it, end)) {
168
2
            return;
169
2
         }
170
9.34k
         if (match_invalid_end<':', Opts>(ctx, it, end)) {
171
40
            return;
172
40
         }
173
9.30k
         if (skip_ws<Opts>(ctx, it, end)) {
174
2
            return;
175
2
         }
176
177
9.30k
         using V = refl_t<T, I>;
178
179
         if constexpr (const_value_v<V>) {
180
            if constexpr (Opts.error_on_const_read) {
181
               ctx.error = error_code::attempt_const_read;
182
            }
183
            else {
184
               // do not read anything into the const value
185
               skip_value<JSON>::op<Opts>(ctx, it, end);
186
            }
187
         }
188
9.30k
         else {
189
            if constexpr (glaze_object_t<T>) {
190
               from<JSON, std::remove_cvref_t<V>>::template op<ws_handled<Opts>()>(
191
                  get_member(value, get<I>(reflect<T>::values)), ctx, it, end);
192
            }
193
9.30k
            else {
194
9.30k
               from<JSON, std::remove_cvref_t<V>>::template op<ws_handled<Opts>()>(
195
9.30k
                  get_member(value, get<I>(to_tie(value))), ctx, it, end);
196
9.30k
            }
197
9.30k
         }
198
199
         if constexpr (Opts.error_on_missing_keys || Opts.partial_read) {
200
            ((selected_index = I), ...);
201
         }
202
9.30k
      }
203
49
      else [[unlikely]] {
204
49
         if constexpr (Opts.error_on_unknown_keys) {
205
49
            ctx.error = error_code::unknown_key;
206
         }
207
         else {
208
            auto* start = it;
209
            skip_string_view<Opts>(ctx, it, end);
210
            if (bool(ctx.error)) [[unlikely]]
211
               return;
212
            const sv key = {start, size_t(it - start)};
213
            ++it;
214
            if constexpr (not Opts.null_terminated) {
215
               if (it == end) [[unlikely]] {
216
                  ctx.error = error_code::unexpected_end;
217
                  return;
218
               }
219
            }
220
221
            if (parse_ws_colon<Opts>(ctx, it, end)) {
222
               return;
223
            }
224
225
            parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
226
         }
227
49
      }
228
9.39k
   }
_ZN3glz12decode_indexITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEE1SLm0ERS2_JETkNS_10is_contextERNS_7contextERPKcS8_Qoo14glaze_object_tIT0_E11reflectableIS9_EEEvOT2_OT4_OT5_OT6_DpOT3_
Line
Count
Source
153
415
   {
154
415
      static constexpr auto Key = get<I>(reflect<T>::keys);
155
415
      static constexpr auto KeyWithEndQuote = join_v<Key, chars<"\"">>;
156
415
      static constexpr auto Length = KeyWithEndQuote.size();
157
158
415
      if (((it + Length) < end) && comparitor<KeyWithEndQuote>(it)) [[likely]] {
159
415
         it += Length;
160
         if constexpr (not Opts.null_terminated) {
161
            if (it == end) [[unlikely]] {
162
               ctx.error = error_code::unexpected_end;
163
               return;
164
            }
165
         }
166
167
415
         if (skip_ws<Opts>(ctx, it, end)) {
168
0
            return;
169
0
         }
170
415
         if (match_invalid_end<':', Opts>(ctx, it, end)) {
171
0
            return;
172
0
         }
173
415
         if (skip_ws<Opts>(ctx, it, end)) {
174
0
            return;
175
0
         }
176
177
415
         using V = refl_t<T, I>;
178
179
         if constexpr (const_value_v<V>) {
180
            if constexpr (Opts.error_on_const_read) {
181
               ctx.error = error_code::attempt_const_read;
182
            }
183
            else {
184
               // do not read anything into the const value
185
               skip_value<JSON>::op<Opts>(ctx, it, end);
186
            }
187
         }
188
415
         else {
189
            if constexpr (glaze_object_t<T>) {
190
               from<JSON, std::remove_cvref_t<V>>::template op<ws_handled<Opts>()>(
191
                  get_member(value, get<I>(reflect<T>::values)), ctx, it, end);
192
            }
193
415
            else {
194
415
               from<JSON, std::remove_cvref_t<V>>::template op<ws_handled<Opts>()>(
195
415
                  get_member(value, get<I>(to_tie(value))), ctx, it, end);
196
415
            }
197
415
         }
198
199
         if constexpr (Opts.error_on_missing_keys || Opts.partial_read) {
200
            ((selected_index = I), ...);
201
         }
202
415
      }
203
0
      else [[unlikely]] {
204
0
         if constexpr (Opts.error_on_unknown_keys) {
205
0
            ctx.error = error_code::unknown_key;
206
         }
207
         else {
208
            auto* start = it;
209
            skip_string_view<Opts>(ctx, it, end);
210
            if (bool(ctx.error)) [[unlikely]]
211
               return;
212
            const sv key = {start, size_t(it - start)};
213
            ++it;
214
            if constexpr (not Opts.null_terminated) {
215
               if (it == end) [[unlikely]] {
216
                  ctx.error = error_code::unexpected_end;
217
                  return;
218
               }
219
            }
220
221
            if (parse_ws_colon<Opts>(ctx, it, end)) {
222
               return;
223
            }
224
225
            parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
226
         }
227
0
      }
228
415
   }
_ZN3glz12decode_indexITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEE5ValueIfELm0ERS3_JETkNS_10is_contextERNS_7contextERPKcS9_Qoo14glaze_object_tIT0_E11reflectableISA_EEEvOT2_OT4_OT5_OT6_DpOT3_
Line
Count
Source
153
488
   {
154
488
      static constexpr auto Key = get<I>(reflect<T>::keys);
155
488
      static constexpr auto KeyWithEndQuote = join_v<Key, chars<"\"">>;
156
488
      static constexpr auto Length = KeyWithEndQuote.size();
157
158
488
      if (((it + Length) < end) && comparitor<KeyWithEndQuote>(it)) [[likely]] {
159
488
         it += Length;
160
         if constexpr (not Opts.null_terminated) {
161
            if (it == end) [[unlikely]] {
162
               ctx.error = error_code::unexpected_end;
163
               return;
164
            }
165
         }
166
167
488
         if (skip_ws<Opts>(ctx, it, end)) {
168
0
            return;
169
0
         }
170
488
         if (match_invalid_end<':', Opts>(ctx, it, end)) {
171
0
            return;
172
0
         }
173
488
         if (skip_ws<Opts>(ctx, it, end)) {
174
0
            return;
175
0
         }
176
177
488
         using V = refl_t<T, I>;
178
179
         if constexpr (const_value_v<V>) {
180
            if constexpr (Opts.error_on_const_read) {
181
               ctx.error = error_code::attempt_const_read;
182
            }
183
            else {
184
               // do not read anything into the const value
185
               skip_value<JSON>::op<Opts>(ctx, it, end);
186
            }
187
         }
188
488
         else {
189
            if constexpr (glaze_object_t<T>) {
190
               from<JSON, std::remove_cvref_t<V>>::template op<ws_handled<Opts>()>(
191
                  get_member(value, get<I>(reflect<T>::values)), ctx, it, end);
192
            }
193
488
            else {
194
488
               from<JSON, std::remove_cvref_t<V>>::template op<ws_handled<Opts>()>(
195
488
                  get_member(value, get<I>(to_tie(value))), ctx, it, end);
196
488
            }
197
488
         }
198
199
         if constexpr (Opts.error_on_missing_keys || Opts.partial_read) {
200
            ((selected_index = I), ...);
201
         }
202
488
      }
203
0
      else [[unlikely]] {
204
0
         if constexpr (Opts.error_on_unknown_keys) {
205
0
            ctx.error = error_code::unknown_key;
206
         }
207
         else {
208
            auto* start = it;
209
            skip_string_view<Opts>(ctx, it, end);
210
            if (bool(ctx.error)) [[unlikely]]
211
               return;
212
            const sv key = {start, size_t(it - start)};
213
            ++it;
214
            if constexpr (not Opts.null_terminated) {
215
               if (it == end) [[unlikely]] {
216
                  ctx.error = error_code::unexpected_end;
217
                  return;
218
               }
219
            }
220
221
            if (parse_ws_colon<Opts>(ctx, it, end)) {
222
               return;
223
            }
224
225
            parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
226
         }
227
0
      }
228
488
   }
_ZN3glz12decode_indexITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEE5ValueIdELm0ERS3_JETkNS_10is_contextERNS_7contextERPKcS9_Qoo14glaze_object_tIT0_E11reflectableISA_EEEvOT2_OT4_OT5_OT6_DpOT3_
Line
Count
Source
153
1.05k
   {
154
1.05k
      static constexpr auto Key = get<I>(reflect<T>::keys);
155
1.05k
      static constexpr auto KeyWithEndQuote = join_v<Key, chars<"\"">>;
156
1.05k
      static constexpr auto Length = KeyWithEndQuote.size();
157
158
1.05k
      if (((it + Length) < end) && comparitor<KeyWithEndQuote>(it)) [[likely]] {
159
1.05k
         it += Length;
160
         if constexpr (not Opts.null_terminated) {
161
            if (it == end) [[unlikely]] {
162
               ctx.error = error_code::unexpected_end;
163
               return;
164
            }
165
         }
166
167
1.05k
         if (skip_ws<Opts>(ctx, it, end)) {
168
0
            return;
169
0
         }
170
1.05k
         if (match_invalid_end<':', Opts>(ctx, it, end)) {
171
0
            return;
172
0
         }
173
1.05k
         if (skip_ws<Opts>(ctx, it, end)) {
174
0
            return;
175
0
         }
176
177
1.05k
         using V = refl_t<T, I>;
178
179
         if constexpr (const_value_v<V>) {
180
            if constexpr (Opts.error_on_const_read) {
181
               ctx.error = error_code::attempt_const_read;
182
            }
183
            else {
184
               // do not read anything into the const value
185
               skip_value<JSON>::op<Opts>(ctx, it, end);
186
            }
187
         }
188
1.05k
         else {
189
            if constexpr (glaze_object_t<T>) {
190
               from<JSON, std::remove_cvref_t<V>>::template op<ws_handled<Opts>()>(
191
                  get_member(value, get<I>(reflect<T>::values)), ctx, it, end);
192
            }
193
1.05k
            else {
194
1.05k
               from<JSON, std::remove_cvref_t<V>>::template op<ws_handled<Opts>()>(
195
1.05k
                  get_member(value, get<I>(to_tie(value))), ctx, it, end);
196
1.05k
            }
197
1.05k
         }
198
199
         if constexpr (Opts.error_on_missing_keys || Opts.partial_read) {
200
            ((selected_index = I), ...);
201
         }
202
1.05k
      }
203
0
      else [[unlikely]] {
204
0
         if constexpr (Opts.error_on_unknown_keys) {
205
0
            ctx.error = error_code::unknown_key;
206
         }
207
         else {
208
            auto* start = it;
209
            skip_string_view<Opts>(ctx, it, end);
210
            if (bool(ctx.error)) [[unlikely]]
211
               return;
212
            const sv key = {start, size_t(it - start)};
213
            ++it;
214
            if constexpr (not Opts.null_terminated) {
215
               if (it == end) [[unlikely]] {
216
                  ctx.error = error_code::unexpected_end;
217
                  return;
218
               }
219
            }
220
221
            if (parse_ws_colon<Opts>(ctx, it, end)) {
222
               return;
223
            }
224
225
            parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
226
         }
227
0
      }
228
1.05k
   }
_ZN3glz12decode_indexITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEE5ValueIsELm0ERS3_JETkNS_10is_contextERNS_7contextERPKcS9_Qoo14glaze_object_tIT0_E11reflectableISA_EEEvOT2_OT4_OT5_OT6_DpOT3_
Line
Count
Source
153
106
   {
154
106
      static constexpr auto Key = get<I>(reflect<T>::keys);
155
106
      static constexpr auto KeyWithEndQuote = join_v<Key, chars<"\"">>;
156
106
      static constexpr auto Length = KeyWithEndQuote.size();
157
158
106
      if (((it + Length) < end) && comparitor<KeyWithEndQuote>(it)) [[likely]] {
159
106
         it += Length;
160
         if constexpr (not Opts.null_terminated) {
161
            if (it == end) [[unlikely]] {
162
               ctx.error = error_code::unexpected_end;
163
               return;
164
            }
165
         }
166
167
106
         if (skip_ws<Opts>(ctx, it, end)) {
168
0
            return;
169
0
         }
170
106
         if (match_invalid_end<':', Opts>(ctx, it, end)) {
171
0
            return;
172
0
         }
173
106
         if (skip_ws<Opts>(ctx, it, end)) {
174
0
            return;
175
0
         }
176
177
106
         using V = refl_t<T, I>;
178
179
         if constexpr (const_value_v<V>) {
180
            if constexpr (Opts.error_on_const_read) {
181
               ctx.error = error_code::attempt_const_read;
182
            }
183
            else {
184
               // do not read anything into the const value
185
               skip_value<JSON>::op<Opts>(ctx, it, end);
186
            }
187
         }
188
106
         else {
189
            if constexpr (glaze_object_t<T>) {
190
               from<JSON, std::remove_cvref_t<V>>::template op<ws_handled<Opts>()>(
191
                  get_member(value, get<I>(reflect<T>::values)), ctx, it, end);
192
            }
193
106
            else {
194
106
               from<JSON, std::remove_cvref_t<V>>::template op<ws_handled<Opts>()>(
195
106
                  get_member(value, get<I>(to_tie(value))), ctx, it, end);
196
106
            }
197
106
         }
198
199
         if constexpr (Opts.error_on_missing_keys || Opts.partial_read) {
200
            ((selected_index = I), ...);
201
         }
202
106
      }
203
0
      else [[unlikely]] {
204
0
         if constexpr (Opts.error_on_unknown_keys) {
205
0
            ctx.error = error_code::unknown_key;
206
         }
207
         else {
208
            auto* start = it;
209
            skip_string_view<Opts>(ctx, it, end);
210
            if (bool(ctx.error)) [[unlikely]]
211
               return;
212
            const sv key = {start, size_t(it - start)};
213
            ++it;
214
            if constexpr (not Opts.null_terminated) {
215
               if (it == end) [[unlikely]] {
216
                  ctx.error = error_code::unexpected_end;
217
                  return;
218
               }
219
            }
220
221
            if (parse_ws_colon<Opts>(ctx, it, end)) {
222
               return;
223
            }
224
225
            parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
226
         }
227
0
      }
228
106
   }
_ZN3glz12decode_indexITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEE5ValueItELm0ERS3_JETkNS_10is_contextERNS_7contextERPKcS9_Qoo14glaze_object_tIT0_E11reflectableISA_EEEvOT2_OT4_OT5_OT6_DpOT3_
Line
Count
Source
153
106
   {
154
106
      static constexpr auto Key = get<I>(reflect<T>::keys);
155
106
      static constexpr auto KeyWithEndQuote = join_v<Key, chars<"\"">>;
156
106
      static constexpr auto Length = KeyWithEndQuote.size();
157
158
106
      if (((it + Length) < end) && comparitor<KeyWithEndQuote>(it)) [[likely]] {
159
106
         it += Length;
160
         if constexpr (not Opts.null_terminated) {
161
            if (it == end) [[unlikely]] {
162
               ctx.error = error_code::unexpected_end;
163
               return;
164
            }
165
         }
166
167
106
         if (skip_ws<Opts>(ctx, it, end)) {
168
0
            return;
169
0
         }
170
106
         if (match_invalid_end<':', Opts>(ctx, it, end)) {
171
0
            return;
172
0
         }
173
106
         if (skip_ws<Opts>(ctx, it, end)) {
174
0
            return;
175
0
         }
176
177
106
         using V = refl_t<T, I>;
178
179
         if constexpr (const_value_v<V>) {
180
            if constexpr (Opts.error_on_const_read) {
181
               ctx.error = error_code::attempt_const_read;
182
            }
183
            else {
184
               // do not read anything into the const value
185
               skip_value<JSON>::op<Opts>(ctx, it, end);
186
            }
187
         }
188
106
         else {
189
            if constexpr (glaze_object_t<T>) {
190
               from<JSON, std::remove_cvref_t<V>>::template op<ws_handled<Opts>()>(
191
                  get_member(value, get<I>(reflect<T>::values)), ctx, it, end);
192
            }
193
106
            else {
194
106
               from<JSON, std::remove_cvref_t<V>>::template op<ws_handled<Opts>()>(
195
106
                  get_member(value, get<I>(to_tie(value))), ctx, it, end);
196
106
            }
197
106
         }
198
199
         if constexpr (Opts.error_on_missing_keys || Opts.partial_read) {
200
            ((selected_index = I), ...);
201
         }
202
106
      }
203
0
      else [[unlikely]] {
204
0
         if constexpr (Opts.error_on_unknown_keys) {
205
0
            ctx.error = error_code::unknown_key;
206
         }
207
         else {
208
            auto* start = it;
209
            skip_string_view<Opts>(ctx, it, end);
210
            if (bool(ctx.error)) [[unlikely]]
211
               return;
212
            const sv key = {start, size_t(it - start)};
213
            ++it;
214
            if constexpr (not Opts.null_terminated) {
215
               if (it == end) [[unlikely]] {
216
                  ctx.error = error_code::unexpected_end;
217
                  return;
218
               }
219
            }
220
221
            if (parse_ws_colon<Opts>(ctx, it, end)) {
222
               return;
223
            }
224
225
            parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
226
         }
227
0
      }
228
106
   }
_ZN3glz12decode_indexITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEE5ValueIiELm0ERS3_JETkNS_10is_contextERNS_7contextERPKcS9_Qoo14glaze_object_tIT0_E11reflectableISA_EEEvOT2_OT4_OT5_OT6_DpOT3_
Line
Count
Source
153
169
   {
154
169
      static constexpr auto Key = get<I>(reflect<T>::keys);
155
169
      static constexpr auto KeyWithEndQuote = join_v<Key, chars<"\"">>;
156
169
      static constexpr auto Length = KeyWithEndQuote.size();
157
158
169
      if (((it + Length) < end) && comparitor<KeyWithEndQuote>(it)) [[likely]] {
159
169
         it += Length;
160
         if constexpr (not Opts.null_terminated) {
161
            if (it == end) [[unlikely]] {
162
               ctx.error = error_code::unexpected_end;
163
               return;
164
            }
165
         }
166
167
169
         if (skip_ws<Opts>(ctx, it, end)) {
168
0
            return;
169
0
         }
170
169
         if (match_invalid_end<':', Opts>(ctx, it, end)) {
171
0
            return;
172
0
         }
173
169
         if (skip_ws<Opts>(ctx, it, end)) {
174
0
            return;
175
0
         }
176
177
169
         using V = refl_t<T, I>;
178
179
         if constexpr (const_value_v<V>) {
180
            if constexpr (Opts.error_on_const_read) {
181
               ctx.error = error_code::attempt_const_read;
182
            }
183
            else {
184
               // do not read anything into the const value
185
               skip_value<JSON>::op<Opts>(ctx, it, end);
186
            }
187
         }
188
169
         else {
189
            if constexpr (glaze_object_t<T>) {
190
               from<JSON, std::remove_cvref_t<V>>::template op<ws_handled<Opts>()>(
191
                  get_member(value, get<I>(reflect<T>::values)), ctx, it, end);
192
            }
193
169
            else {
194
169
               from<JSON, std::remove_cvref_t<V>>::template op<ws_handled<Opts>()>(
195
169
                  get_member(value, get<I>(to_tie(value))), ctx, it, end);
196
169
            }
197
169
         }
198
199
         if constexpr (Opts.error_on_missing_keys || Opts.partial_read) {
200
            ((selected_index = I), ...);
201
         }
202
169
      }
203
0
      else [[unlikely]] {
204
0
         if constexpr (Opts.error_on_unknown_keys) {
205
0
            ctx.error = error_code::unknown_key;
206
         }
207
         else {
208
            auto* start = it;
209
            skip_string_view<Opts>(ctx, it, end);
210
            if (bool(ctx.error)) [[unlikely]]
211
               return;
212
            const sv key = {start, size_t(it - start)};
213
            ++it;
214
            if constexpr (not Opts.null_terminated) {
215
               if (it == end) [[unlikely]] {
216
                  ctx.error = error_code::unexpected_end;
217
                  return;
218
               }
219
            }
220
221
            if (parse_ws_colon<Opts>(ctx, it, end)) {
222
               return;
223
            }
224
225
            parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
226
         }
227
0
      }
228
169
   }
_ZN3glz12decode_indexITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEE5ValueIjELm0ERS3_JETkNS_10is_contextERNS_7contextERPKcS9_Qoo14glaze_object_tIT0_E11reflectableISA_EEEvOT2_OT4_OT5_OT6_DpOT3_
Line
Count
Source
153
169
   {
154
169
      static constexpr auto Key = get<I>(reflect<T>::keys);
155
169
      static constexpr auto KeyWithEndQuote = join_v<Key, chars<"\"">>;
156
169
      static constexpr auto Length = KeyWithEndQuote.size();
157
158
169
      if (((it + Length) < end) && comparitor<KeyWithEndQuote>(it)) [[likely]] {
159
169
         it += Length;
160
         if constexpr (not Opts.null_terminated) {
161
            if (it == end) [[unlikely]] {
162
               ctx.error = error_code::unexpected_end;
163
               return;
164
            }
165
         }
166
167
169
         if (skip_ws<Opts>(ctx, it, end)) {
168
0
            return;
169
0
         }
170
169
         if (match_invalid_end<':', Opts>(ctx, it, end)) {
171
0
            return;
172
0
         }
173
169
         if (skip_ws<Opts>(ctx, it, end)) {
174
0
            return;
175
0
         }
176
177
169
         using V = refl_t<T, I>;
178
179
         if constexpr (const_value_v<V>) {
180
            if constexpr (Opts.error_on_const_read) {
181
               ctx.error = error_code::attempt_const_read;
182
            }
183
            else {
184
               // do not read anything into the const value
185
               skip_value<JSON>::op<Opts>(ctx, it, end);
186
            }
187
         }
188
169
         else {
189
            if constexpr (glaze_object_t<T>) {
190
               from<JSON, std::remove_cvref_t<V>>::template op<ws_handled<Opts>()>(
191
                  get_member(value, get<I>(reflect<T>::values)), ctx, it, end);
192
            }
193
169
            else {
194
169
               from<JSON, std::remove_cvref_t<V>>::template op<ws_handled<Opts>()>(
195
169
                  get_member(value, get<I>(to_tie(value))), ctx, it, end);
196
169
            }
197
169
         }
198
199
         if constexpr (Opts.error_on_missing_keys || Opts.partial_read) {
200
            ((selected_index = I), ...);
201
         }
202
169
      }
203
0
      else [[unlikely]] {
204
0
         if constexpr (Opts.error_on_unknown_keys) {
205
0
            ctx.error = error_code::unknown_key;
206
         }
207
         else {
208
            auto* start = it;
209
            skip_string_view<Opts>(ctx, it, end);
210
            if (bool(ctx.error)) [[unlikely]]
211
               return;
212
            const sv key = {start, size_t(it - start)};
213
            ++it;
214
            if constexpr (not Opts.null_terminated) {
215
               if (it == end) [[unlikely]] {
216
                  ctx.error = error_code::unexpected_end;
217
                  return;
218
               }
219
            }
220
221
            if (parse_ws_colon<Opts>(ctx, it, end)) {
222
               return;
223
            }
224
225
            parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
226
         }
227
0
      }
228
169
   }
_ZN3glz12decode_indexITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEE5ValueIlELm0ERS3_JETkNS_10is_contextERNS_7contextERPKcS9_Qoo14glaze_object_tIT0_E11reflectableISA_EEEvOT2_OT4_OT5_OT6_DpOT3_
Line
Count
Source
153
296
   {
154
296
      static constexpr auto Key = get<I>(reflect<T>::keys);
155
296
      static constexpr auto KeyWithEndQuote = join_v<Key, chars<"\"">>;
156
296
      static constexpr auto Length = KeyWithEndQuote.size();
157
158
296
      if (((it + Length) < end) && comparitor<KeyWithEndQuote>(it)) [[likely]] {
159
296
         it += Length;
160
         if constexpr (not Opts.null_terminated) {
161
            if (it == end) [[unlikely]] {
162
               ctx.error = error_code::unexpected_end;
163
               return;
164
            }
165
         }
166
167
296
         if (skip_ws<Opts>(ctx, it, end)) {
168
0
            return;
169
0
         }
170
296
         if (match_invalid_end<':', Opts>(ctx, it, end)) {
171
0
            return;
172
0
         }
173
296
         if (skip_ws<Opts>(ctx, it, end)) {
174
0
            return;
175
0
         }
176
177
296
         using V = refl_t<T, I>;
178
179
         if constexpr (const_value_v<V>) {
180
            if constexpr (Opts.error_on_const_read) {
181
               ctx.error = error_code::attempt_const_read;
182
            }
183
            else {
184
               // do not read anything into the const value
185
               skip_value<JSON>::op<Opts>(ctx, it, end);
186
            }
187
         }
188
296
         else {
189
            if constexpr (glaze_object_t<T>) {
190
               from<JSON, std::remove_cvref_t<V>>::template op<ws_handled<Opts>()>(
191
                  get_member(value, get<I>(reflect<T>::values)), ctx, it, end);
192
            }
193
296
            else {
194
296
               from<JSON, std::remove_cvref_t<V>>::template op<ws_handled<Opts>()>(
195
296
                  get_member(value, get<I>(to_tie(value))), ctx, it, end);
196
296
            }
197
296
         }
198
199
         if constexpr (Opts.error_on_missing_keys || Opts.partial_read) {
200
            ((selected_index = I), ...);
201
         }
202
296
      }
203
0
      else [[unlikely]] {
204
0
         if constexpr (Opts.error_on_unknown_keys) {
205
0
            ctx.error = error_code::unknown_key;
206
         }
207
         else {
208
            auto* start = it;
209
            skip_string_view<Opts>(ctx, it, end);
210
            if (bool(ctx.error)) [[unlikely]]
211
               return;
212
            const sv key = {start, size_t(it - start)};
213
            ++it;
214
            if constexpr (not Opts.null_terminated) {
215
               if (it == end) [[unlikely]] {
216
                  ctx.error = error_code::unexpected_end;
217
                  return;
218
               }
219
            }
220
221
            if (parse_ws_colon<Opts>(ctx, it, end)) {
222
               return;
223
            }
224
225
            parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
226
         }
227
0
      }
228
296
   }
_ZN3glz12decode_indexITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEE5ValueImELm0ERS3_JETkNS_10is_contextERNS_7contextERPKcS9_Qoo14glaze_object_tIT0_E11reflectableISA_EEEvOT2_OT4_OT5_OT6_DpOT3_
Line
Count
Source
153
296
   {
154
296
      static constexpr auto Key = get<I>(reflect<T>::keys);
155
296
      static constexpr auto KeyWithEndQuote = join_v<Key, chars<"\"">>;
156
296
      static constexpr auto Length = KeyWithEndQuote.size();
157
158
296
      if (((it + Length) < end) && comparitor<KeyWithEndQuote>(it)) [[likely]] {
159
296
         it += Length;
160
         if constexpr (not Opts.null_terminated) {
161
            if (it == end) [[unlikely]] {
162
               ctx.error = error_code::unexpected_end;
163
               return;
164
            }
165
         }
166
167
296
         if (skip_ws<Opts>(ctx, it, end)) {
168
0
            return;
169
0
         }
170
296
         if (match_invalid_end<':', Opts>(ctx, it, end)) {
171
0
            return;
172
0
         }
173
296
         if (skip_ws<Opts>(ctx, it, end)) {
174
0
            return;
175
0
         }
176
177
296
         using V = refl_t<T, I>;
178
179
         if constexpr (const_value_v<V>) {
180
            if constexpr (Opts.error_on_const_read) {
181
               ctx.error = error_code::attempt_const_read;
182
            }
183
            else {
184
               // do not read anything into the const value
185
               skip_value<JSON>::op<Opts>(ctx, it, end);
186
            }
187
         }
188
296
         else {
189
            if constexpr (glaze_object_t<T>) {
190
               from<JSON, std::remove_cvref_t<V>>::template op<ws_handled<Opts>()>(
191
                  get_member(value, get<I>(reflect<T>::values)), ctx, it, end);
192
            }
193
296
            else {
194
296
               from<JSON, std::remove_cvref_t<V>>::template op<ws_handled<Opts>()>(
195
296
                  get_member(value, get<I>(to_tie(value))), ctx, it, end);
196
296
            }
197
296
         }
198
199
         if constexpr (Opts.error_on_missing_keys || Opts.partial_read) {
200
            ((selected_index = I), ...);
201
         }
202
296
      }
203
0
      else [[unlikely]] {
204
0
         if constexpr (Opts.error_on_unknown_keys) {
205
0
            ctx.error = error_code::unknown_key;
206
         }
207
         else {
208
            auto* start = it;
209
            skip_string_view<Opts>(ctx, it, end);
210
            if (bool(ctx.error)) [[unlikely]]
211
               return;
212
            const sv key = {start, size_t(it - start)};
213
            ++it;
214
            if constexpr (not Opts.null_terminated) {
215
               if (it == end) [[unlikely]] {
216
                  ctx.error = error_code::unexpected_end;
217
                  return;
218
               }
219
            }
220
221
            if (parse_ws_colon<Opts>(ctx, it, end)) {
222
               return;
223
            }
224
225
            parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
226
         }
227
0
      }
228
296
   }
_ZN3glz12decode_indexITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEE5ValueIxELm0ERS3_JETkNS_10is_contextERNS_7contextERPKcS9_Qoo14glaze_object_tIT0_E11reflectableISA_EEEvOT2_OT4_OT5_OT6_DpOT3_
Line
Count
Source
153
290
   {
154
290
      static constexpr auto Key = get<I>(reflect<T>::keys);
155
290
      static constexpr auto KeyWithEndQuote = join_v<Key, chars<"\"">>;
156
290
      static constexpr auto Length = KeyWithEndQuote.size();
157
158
290
      if (((it + Length) < end) && comparitor<KeyWithEndQuote>(it)) [[likely]] {
159
290
         it += Length;
160
         if constexpr (not Opts.null_terminated) {
161
            if (it == end) [[unlikely]] {
162
               ctx.error = error_code::unexpected_end;
163
               return;
164
            }
165
         }
166
167
290
         if (skip_ws<Opts>(ctx, it, end)) {
168
0
            return;
169
0
         }
170
290
         if (match_invalid_end<':', Opts>(ctx, it, end)) {
171
0
            return;
172
0
         }
173
290
         if (skip_ws<Opts>(ctx, it, end)) {
174
0
            return;
175
0
         }
176
177
290
         using V = refl_t<T, I>;
178
179
         if constexpr (const_value_v<V>) {
180
            if constexpr (Opts.error_on_const_read) {
181
               ctx.error = error_code::attempt_const_read;
182
            }
183
            else {
184
               // do not read anything into the const value
185
               skip_value<JSON>::op<Opts>(ctx, it, end);
186
            }
187
         }
188
290
         else {
189
            if constexpr (glaze_object_t<T>) {
190
               from<JSON, std::remove_cvref_t<V>>::template op<ws_handled<Opts>()>(
191
                  get_member(value, get<I>(reflect<T>::values)), ctx, it, end);
192
            }
193
290
            else {
194
290
               from<JSON, std::remove_cvref_t<V>>::template op<ws_handled<Opts>()>(
195
290
                  get_member(value, get<I>(to_tie(value))), ctx, it, end);
196
290
            }
197
290
         }
198
199
         if constexpr (Opts.error_on_missing_keys || Opts.partial_read) {
200
            ((selected_index = I), ...);
201
         }
202
290
      }
203
0
      else [[unlikely]] {
204
0
         if constexpr (Opts.error_on_unknown_keys) {
205
0
            ctx.error = error_code::unknown_key;
206
         }
207
         else {
208
            auto* start = it;
209
            skip_string_view<Opts>(ctx, it, end);
210
            if (bool(ctx.error)) [[unlikely]]
211
               return;
212
            const sv key = {start, size_t(it - start)};
213
            ++it;
214
            if constexpr (not Opts.null_terminated) {
215
               if (it == end) [[unlikely]] {
216
                  ctx.error = error_code::unexpected_end;
217
                  return;
218
               }
219
            }
220
221
            if (parse_ws_colon<Opts>(ctx, it, end)) {
222
               return;
223
            }
224
225
            parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
226
         }
227
0
      }
228
290
   }
_ZN3glz12decode_indexITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEE5ValueIyELm0ERS3_JETkNS_10is_contextERNS_7contextERPKcS9_Qoo14glaze_object_tIT0_E11reflectableISA_EEEvOT2_OT4_OT5_OT6_DpOT3_
Line
Count
Source
153
290
   {
154
290
      static constexpr auto Key = get<I>(reflect<T>::keys);
155
290
      static constexpr auto KeyWithEndQuote = join_v<Key, chars<"\"">>;
156
290
      static constexpr auto Length = KeyWithEndQuote.size();
157
158
290
      if (((it + Length) < end) && comparitor<KeyWithEndQuote>(it)) [[likely]] {
159
290
         it += Length;
160
         if constexpr (not Opts.null_terminated) {
161
            if (it == end) [[unlikely]] {
162
               ctx.error = error_code::unexpected_end;
163
               return;
164
            }
165
         }
166
167
290
         if (skip_ws<Opts>(ctx, it, end)) {
168
0
            return;
169
0
         }
170
290
         if (match_invalid_end<':', Opts>(ctx, it, end)) {
171
0
            return;
172
0
         }
173
290
         if (skip_ws<Opts>(ctx, it, end)) {
174
0
            return;
175
0
         }
176
177
290
         using V = refl_t<T, I>;
178
179
         if constexpr (const_value_v<V>) {
180
            if constexpr (Opts.error_on_const_read) {
181
               ctx.error = error_code::attempt_const_read;
182
            }
183
            else {
184
               // do not read anything into the const value
185
               skip_value<JSON>::op<Opts>(ctx, it, end);
186
            }
187
         }
188
290
         else {
189
            if constexpr (glaze_object_t<T>) {
190
               from<JSON, std::remove_cvref_t<V>>::template op<ws_handled<Opts>()>(
191
                  get_member(value, get<I>(reflect<T>::values)), ctx, it, end);
192
            }
193
290
            else {
194
290
               from<JSON, std::remove_cvref_t<V>>::template op<ws_handled<Opts>()>(
195
290
                  get_member(value, get<I>(to_tie(value))), ctx, it, end);
196
290
            }
197
290
         }
198
199
         if constexpr (Opts.error_on_missing_keys || Opts.partial_read) {
200
            ((selected_index = I), ...);
201
         }
202
290
      }
203
0
      else [[unlikely]] {
204
0
         if constexpr (Opts.error_on_unknown_keys) {
205
0
            ctx.error = error_code::unknown_key;
206
         }
207
         else {
208
            auto* start = it;
209
            skip_string_view<Opts>(ctx, it, end);
210
            if (bool(ctx.error)) [[unlikely]]
211
               return;
212
            const sv key = {start, size_t(it - start)};
213
            ++it;
214
            if constexpr (not Opts.null_terminated) {
215
               if (it == end) [[unlikely]] {
216
                  ctx.error = error_code::unexpected_end;
217
                  return;
218
               }
219
            }
220
221
            if (parse_ws_colon<Opts>(ctx, it, end)) {
222
               return;
223
            }
224
225
            parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
226
         }
227
0
      }
228
290
   }
229
230
   template <auto Opts, class T, size_t I, class Value>
231
      requires(glaze_enum_t<T> || (meta_keys<T> && std::is_enum_v<T>))
232
   void decode_index(Value&& value, is_context auto&& ctx, auto&& it, auto&& end) noexcept
233
   {
234
      static constexpr auto TargetKey = glz::get<I>(reflect<T>::keys);
235
      static constexpr auto Length = TargetKey.size();
236
237
      if (((it + Length) < end) && comparitor<TargetKey>(it)) [[likely]] {
238
         it += Length;
239
         if (*it != '"') [[unlikely]] {
240
            ctx.error = error_code::unexpected_enum;
241
            return;
242
         }
243
         value = get<I>(reflect<T>::values);
244
245
         ++it;
246
         if constexpr (not Opts.null_terminated) {
247
            if (it == end) {
248
               ctx.error = error_code::end_reached;
249
               return;
250
            }
251
         }
252
      }
253
      else [[unlikely]] {
254
         ctx.error = error_code::unexpected_enum;
255
         return;
256
      }
257
   }
258
259
   template <auto Opts, class T, auto& HashInfo, class Value, class... SelectedIndex>
260
      requires(glaze_object_t<T> || reflectable<T>)
261
   GLZ_ALWAYS_INLINE constexpr void parse_and_invoke(Value&& value, is_context auto&& ctx, auto&& it, auto&& end,
262
                                                     SelectedIndex&&... selected_index)
263
112k
   {
264
112k
      constexpr auto type = HashInfo.type;
265
112k
      constexpr auto N = reflect<T>::size;
266
267
112k
      static_assert(bool(type), "invalid hash algorithm");
268
269
112k
      if constexpr (N == 1) {
270
3.67k
         decode_index<Opts, T, 0>(value, ctx, it, end, selected_index...);
271
      }
272
108k
      else {
273
108k
         const auto index = decode_hash<JSON, T, HashInfo, HashInfo.type>::op(it, end);
274
275
108k
         if (index >= N) [[unlikely]] {
276
173
            if constexpr (Opts.error_on_unknown_keys) {
277
173
               ctx.error = error_code::unknown_key;
278
173
               return;
279
            }
280
            else {
281
               // we need to search until we find the ending quote of the key
282
               auto start = it;
283
               skip_string_view<Opts>(ctx, it, end);
284
               if (bool(ctx.error)) [[unlikely]]
285
                  return;
286
               const sv key = {start, size_t(it - start)};
287
               ++it; // skip the quote
288
               if constexpr (not Opts.null_terminated) {
289
                  if (it == end) [[unlikely]] {
290
                     ctx.error = error_code::unexpected_end;
291
                     return;
292
                  }
293
               }
294
295
               if (parse_ws_colon<Opts>(ctx, it, end)) {
296
                  return;
297
               }
298
299
               parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
300
               return;
301
            }
302
173
         }
303
304
         if constexpr (N == 2) {
305
            if (index == 0) {
306
               decode_index<Opts, T, 0>(value, ctx, it, end, selected_index...);
307
            }
308
            else {
309
               decode_index<Opts, T, 1>(value, ctx, it, end, selected_index...);
310
            }
311
         }
312
108k
         else {
313
108k
            visit<N>([&]<size_t I>() { decode_index<Opts, T, I>(value, ctx, it, end, selected_index...); }, index);
_ZZN3glz16parse_and_invokeITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1EEE9my_structTnRDaL_ZNS_9hash_infoIS2_EEERS2_JETkNS_10is_contextERNS_7contextERPKcSA_Qoo14glaze_object_tIT0_E11reflectableISB_EEEvOT2_OT4_OT5_OT6_DpOT3_ENKUlTnmvE_clILm0EEEDav
Line
Count
Source
313
8.54k
            visit<N>([&]<size_t I>() { decode_index<Opts, T, I>(value, ctx, it, end, selected_index...); }, index);
_ZZN3glz16parse_and_invokeITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1EEE9my_structTnRDaL_ZNS_9hash_infoIS2_EEERS2_JETkNS_10is_contextERNS_7contextERPKcSA_Qoo14glaze_object_tIT0_E11reflectableISB_EEEvOT2_OT4_OT5_OT6_DpOT3_ENKUlTnmvE_clILm1EEEDav
Line
Count
Source
313
14.8k
            visit<N>([&]<size_t I>() { decode_index<Opts, T, I>(value, ctx, it, end, selected_index...); }, index);
_ZZN3glz16parse_and_invokeITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1EEE9my_structTnRDaL_ZNS_9hash_infoIS2_EEERS2_JETkNS_10is_contextERNS_7contextERPKcSA_Qoo14glaze_object_tIT0_E11reflectableISB_EEEvOT2_OT4_OT5_OT6_DpOT3_ENKUlTnmvE_clILm2EEEDav
Line
Count
Source
313
3
            visit<N>([&]<size_t I>() { decode_index<Opts, T, I>(value, ctx, it, end, selected_index...); }, index);
_ZZN3glz16parse_and_invokeITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1EEE9my_structTnRDaL_ZNS_9hash_infoIS2_EEERS2_JETkNS_10is_contextERNS_7contextERPKcSA_Qoo14glaze_object_tIT0_E11reflectableISB_EEEvOT2_OT4_OT5_OT6_DpOT3_ENKUlTnmvE_clILm3EEEDav
Line
Count
Source
313
9.06k
            visit<N>([&]<size_t I>() { decode_index<Opts, T, I>(value, ctx, it, end, selected_index...); }, index);
_ZZN3glz16parse_and_invokeITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1EEE9my_structTnRDaL_ZNS_9hash_infoIS2_EEERS2_JETkNS_10is_contextERNS_7contextERPKcSA_Qoo14glaze_object_tIT0_E11reflectableISB_EEEvOT2_OT4_OT5_OT6_DpOT3_ENKUlTnmvE_clILm0EEEDav
Line
Count
Source
313
8.54k
            visit<N>([&]<size_t I>() { decode_index<Opts, T, I>(value, ctx, it, end, selected_index...); }, index);
_ZZN3glz16parse_and_invokeITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1EEE9my_structTnRDaL_ZNS_9hash_infoIS2_EEERS2_JETkNS_10is_contextERNS_7contextERPKcSA_Qoo14glaze_object_tIT0_E11reflectableISB_EEEvOT2_OT4_OT5_OT6_DpOT3_ENKUlTnmvE_clILm1EEEDav
Line
Count
Source
313
14.8k
            visit<N>([&]<size_t I>() { decode_index<Opts, T, I>(value, ctx, it, end, selected_index...); }, index);
_ZZN3glz16parse_and_invokeITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1EEE9my_structTnRDaL_ZNS_9hash_infoIS2_EEERS2_JETkNS_10is_contextERNS_7contextERPKcSA_Qoo14glaze_object_tIT0_E11reflectableISB_EEEvOT2_OT4_OT5_OT6_DpOT3_ENKUlTnmvE_clILm2EEEDav
Line
Count
Source
313
3
            visit<N>([&]<size_t I>() { decode_index<Opts, T, I>(value, ctx, it, end, selected_index...); }, index);
_ZZN3glz16parse_and_invokeITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1EEE9my_structTnRDaL_ZNS_9hash_infoIS2_EEERS2_JETkNS_10is_contextERNS_7contextERPKcSA_Qoo14glaze_object_tIT0_E11reflectableISB_EEEvOT2_OT4_OT5_OT6_DpOT3_ENKUlTnmvE_clILm3EEEDav
Line
Count
Source
313
9.06k
            visit<N>([&]<size_t I>() { decode_index<Opts, T, I>(value, ctx, it, end, selected_index...); }, index);
_ZZN3glz16parse_and_invokeITnDaXtlNS_4optsELj10ELb1ELb1ELb1ELb1ELb0ELb0ELc32ELh3ELb1EEE9my_structTnRDaL_ZNS_9hash_infoIS2_EEERS2_JETkNS_10is_contextERNS_7contextERPKcSA_Qoo14glaze_object_tIT0_E11reflectableISB_EEEvOT2_OT4_OT5_OT6_DpOT3_ENKUlTnmvE_clILm0EEEDav
Line
Count
Source
313
9.75k
            visit<N>([&]<size_t I>() { decode_index<Opts, T, I>(value, ctx, it, end, selected_index...); }, index);
_ZZN3glz16parse_and_invokeITnDaXtlNS_4optsELj10ELb1ELb1ELb1ELb1ELb0ELb0ELc32ELh3ELb1EEE9my_structTnRDaL_ZNS_9hash_infoIS2_EEERS2_JETkNS_10is_contextERNS_7contextERPKcSA_Qoo14glaze_object_tIT0_E11reflectableISB_EEEvOT2_OT4_OT5_OT6_DpOT3_ENKUlTnmvE_clILm1EEEDav
Line
Count
Source
313
24.1k
            visit<N>([&]<size_t I>() { decode_index<Opts, T, I>(value, ctx, it, end, selected_index...); }, index);
_ZZN3glz16parse_and_invokeITnDaXtlNS_4optsELj10ELb1ELb1ELb1ELb1ELb0ELb0ELc32ELh3ELb1EEE9my_structTnRDaL_ZNS_9hash_infoIS2_EEERS2_JETkNS_10is_contextERNS_7contextERPKcSA_Qoo14glaze_object_tIT0_E11reflectableISB_EEEvOT2_OT4_OT5_OT6_DpOT3_ENKUlTnmvE_clILm2EEEDav
Line
Count
Source
313
2
            visit<N>([&]<size_t I>() { decode_index<Opts, T, I>(value, ctx, it, end, selected_index...); }, index);
_ZZN3glz16parse_and_invokeITnDaXtlNS_4optsELj10ELb1ELb1ELb1ELb1ELb0ELb0ELc32ELh3ELb1EEE9my_structTnRDaL_ZNS_9hash_infoIS2_EEERS2_JETkNS_10is_contextERNS_7contextERPKcSA_Qoo14glaze_object_tIT0_E11reflectableISB_EEEvOT2_OT4_OT5_OT6_DpOT3_ENKUlTnmvE_clILm3EEEDav
Line
Count
Source
313
9.39k
            visit<N>([&]<size_t I>() { decode_index<Opts, T, I>(value, ctx, it, end, selected_index...); }, index);
314
108k
         }
315
108k
      }
316
112k
   }
_ZN3glz16parse_and_invokeITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1EEE9my_structTnRDaL_ZNS_9hash_infoIS2_EEERS2_JETkNS_10is_contextERNS_7contextERPKcSA_Qoo14glaze_object_tIT0_E11reflectableISB_EEEvOT2_OT4_OT5_OT6_DpOT3_
Line
Count
Source
263
32.4k
   {
264
32.4k
      constexpr auto type = HashInfo.type;
265
32.4k
      constexpr auto N = reflect<T>::size;
266
267
32.4k
      static_assert(bool(type), "invalid hash algorithm");
268
269
      if constexpr (N == 1) {
270
         decode_index<Opts, T, 0>(value, ctx, it, end, selected_index...);
271
      }
272
32.4k
      else {
273
32.4k
         const auto index = decode_hash<JSON, T, HashInfo, HashInfo.type>::op(it, end);
274
275
32.4k
         if (index >= N) [[unlikely]] {
276
37
            if constexpr (Opts.error_on_unknown_keys) {
277
37
               ctx.error = error_code::unknown_key;
278
37
               return;
279
            }
280
            else {
281
               // we need to search until we find the ending quote of the key
282
               auto start = it;
283
               skip_string_view<Opts>(ctx, it, end);
284
               if (bool(ctx.error)) [[unlikely]]
285
                  return;
286
               const sv key = {start, size_t(it - start)};
287
               ++it; // skip the quote
288
               if constexpr (not Opts.null_terminated) {
289
                  if (it == end) [[unlikely]] {
290
                     ctx.error = error_code::unexpected_end;
291
                     return;
292
                  }
293
               }
294
295
               if (parse_ws_colon<Opts>(ctx, it, end)) {
296
                  return;
297
               }
298
299
               parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
300
               return;
301
            }
302
37
         }
303
304
         if constexpr (N == 2) {
305
            if (index == 0) {
306
               decode_index<Opts, T, 0>(value, ctx, it, end, selected_index...);
307
            }
308
            else {
309
               decode_index<Opts, T, 1>(value, ctx, it, end, selected_index...);
310
            }
311
         }
312
32.4k
         else {
313
32.4k
            visit<N>([&]<size_t I>() { decode_index<Opts, T, I>(value, ctx, it, end, selected_index...); }, index);
314
32.4k
         }
315
32.4k
      }
316
32.4k
   }
_ZN3glz16parse_and_invokeITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1EEE9my_structTnRDaL_ZNS_9hash_infoIS2_EEERS2_JETkNS_10is_contextERNS_7contextERPKcSA_Qoo14glaze_object_tIT0_E11reflectableISB_EEEvOT2_OT4_OT5_OT6_DpOT3_
Line
Count
Source
263
32.5k
   {
264
32.5k
      constexpr auto type = HashInfo.type;
265
32.5k
      constexpr auto N = reflect<T>::size;
266
267
32.5k
      static_assert(bool(type), "invalid hash algorithm");
268
269
      if constexpr (N == 1) {
270
         decode_index<Opts, T, 0>(value, ctx, it, end, selected_index...);
271
      }
272
32.5k
      else {
273
32.5k
         const auto index = decode_hash<JSON, T, HashInfo, HashInfo.type>::op(it, end);
274
275
32.5k
         if (index >= N) [[unlikely]] {
276
62
            if constexpr (Opts.error_on_unknown_keys) {
277
62
               ctx.error = error_code::unknown_key;
278
62
               return;
279
            }
280
            else {
281
               // we need to search until we find the ending quote of the key
282
               auto start = it;
283
               skip_string_view<Opts>(ctx, it, end);
284
               if (bool(ctx.error)) [[unlikely]]
285
                  return;
286
               const sv key = {start, size_t(it - start)};
287
               ++it; // skip the quote
288
               if constexpr (not Opts.null_terminated) {
289
                  if (it == end) [[unlikely]] {
290
                     ctx.error = error_code::unexpected_end;
291
                     return;
292
                  }
293
               }
294
295
               if (parse_ws_colon<Opts>(ctx, it, end)) {
296
                  return;
297
               }
298
299
               parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
300
               return;
301
            }
302
62
         }
303
304
         if constexpr (N == 2) {
305
            if (index == 0) {
306
               decode_index<Opts, T, 0>(value, ctx, it, end, selected_index...);
307
            }
308
            else {
309
               decode_index<Opts, T, 1>(value, ctx, it, end, selected_index...);
310
            }
311
         }
312
32.5k
         else {
313
32.5k
            visit<N>([&]<size_t I>() { decode_index<Opts, T, I>(value, ctx, it, end, selected_index...); }, index);
314
32.5k
         }
315
32.5k
      }
316
32.5k
   }
_ZN3glz16parse_and_invokeITnDaXtlNS_4optsELj10ELb1ELb1ELb1ELb1ELb0ELb0ELc32ELh3ELb1EEE9my_structTnRDaL_ZNS_9hash_infoIS2_EEERS2_JETkNS_10is_contextERNS_7contextERPKcSA_Qoo14glaze_object_tIT0_E11reflectableISB_EEEvOT2_OT4_OT5_OT6_DpOT3_
Line
Count
Source
263
43.4k
   {
264
43.4k
      constexpr auto type = HashInfo.type;
265
43.4k
      constexpr auto N = reflect<T>::size;
266
267
43.4k
      static_assert(bool(type), "invalid hash algorithm");
268
269
      if constexpr (N == 1) {
270
         decode_index<Opts, T, 0>(value, ctx, it, end, selected_index...);
271
      }
272
43.4k
      else {
273
43.4k
         const auto index = decode_hash<JSON, T, HashInfo, HashInfo.type>::op(it, end);
274
275
43.4k
         if (index >= N) [[unlikely]] {
276
74
            if constexpr (Opts.error_on_unknown_keys) {
277
74
               ctx.error = error_code::unknown_key;
278
74
               return;
279
            }
280
            else {
281
               // we need to search until we find the ending quote of the key
282
               auto start = it;
283
               skip_string_view<Opts>(ctx, it, end);
284
               if (bool(ctx.error)) [[unlikely]]
285
                  return;
286
               const sv key = {start, size_t(it - start)};
287
               ++it; // skip the quote
288
               if constexpr (not Opts.null_terminated) {
289
                  if (it == end) [[unlikely]] {
290
                     ctx.error = error_code::unexpected_end;
291
                     return;
292
                  }
293
               }
294
295
               if (parse_ws_colon<Opts>(ctx, it, end)) {
296
                  return;
297
               }
298
299
               parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
300
               return;
301
            }
302
74
         }
303
304
         if constexpr (N == 2) {
305
            if (index == 0) {
306
               decode_index<Opts, T, 0>(value, ctx, it, end, selected_index...);
307
            }
308
            else {
309
               decode_index<Opts, T, 1>(value, ctx, it, end, selected_index...);
310
            }
311
         }
312
43.4k
         else {
313
43.4k
            visit<N>([&]<size_t I>() { decode_index<Opts, T, I>(value, ctx, it, end, selected_index...); }, index);
314
43.4k
         }
315
43.4k
      }
316
43.4k
   }
_ZN3glz16parse_and_invokeITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEE1STnRDaL_ZNS_9hash_infoIS2_EEERS2_JETkNS_10is_contextERNS_7contextERPKcSA_Qoo14glaze_object_tIT0_E11reflectableISB_EEEvOT2_OT4_OT5_OT6_DpOT3_
Line
Count
Source
263
415
   {
264
415
      constexpr auto type = HashInfo.type;
265
415
      constexpr auto N = reflect<T>::size;
266
267
415
      static_assert(bool(type), "invalid hash algorithm");
268
269
415
      if constexpr (N == 1) {
270
415
         decode_index<Opts, T, 0>(value, ctx, it, end, selected_index...);
271
      }
272
      else {
273
         const auto index = decode_hash<JSON, T, HashInfo, HashInfo.type>::op(it, end);
274
275
         if (index >= N) [[unlikely]] {
276
            if constexpr (Opts.error_on_unknown_keys) {
277
               ctx.error = error_code::unknown_key;
278
               return;
279
            }
280
            else {
281
               // we need to search until we find the ending quote of the key
282
               auto start = it;
283
               skip_string_view<Opts>(ctx, it, end);
284
               if (bool(ctx.error)) [[unlikely]]
285
                  return;
286
               const sv key = {start, size_t(it - start)};
287
               ++it; // skip the quote
288
               if constexpr (not Opts.null_terminated) {
289
                  if (it == end) [[unlikely]] {
290
                     ctx.error = error_code::unexpected_end;
291
                     return;
292
                  }
293
               }
294
295
               if (parse_ws_colon<Opts>(ctx, it, end)) {
296
                  return;
297
               }
298
299
               parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
300
               return;
301
            }
302
         }
303
304
         if constexpr (N == 2) {
305
            if (index == 0) {
306
               decode_index<Opts, T, 0>(value, ctx, it, end, selected_index...);
307
            }
308
            else {
309
               decode_index<Opts, T, 1>(value, ctx, it, end, selected_index...);
310
            }
311
         }
312
         else {
313
            visit<N>([&]<size_t I>() { decode_index<Opts, T, I>(value, ctx, it, end, selected_index...); }, index);
314
         }
315
      }
316
415
   }
_ZN3glz16parse_and_invokeITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEE5ValueIfETnRDaL_ZNS_9hash_infoIS3_EEERS3_JETkNS_10is_contextERNS_7contextERPKcSB_Qoo14glaze_object_tIT0_E11reflectableISC_EEEvOT2_OT4_OT5_OT6_DpOT3_
Line
Count
Source
263
488
   {
264
488
      constexpr auto type = HashInfo.type;
265
488
      constexpr auto N = reflect<T>::size;
266
267
488
      static_assert(bool(type), "invalid hash algorithm");
268
269
488
      if constexpr (N == 1) {
270
488
         decode_index<Opts, T, 0>(value, ctx, it, end, selected_index...);
271
      }
272
      else {
273
         const auto index = decode_hash<JSON, T, HashInfo, HashInfo.type>::op(it, end);
274
275
         if (index >= N) [[unlikely]] {
276
            if constexpr (Opts.error_on_unknown_keys) {
277
               ctx.error = error_code::unknown_key;
278
               return;
279
            }
280
            else {
281
               // we need to search until we find the ending quote of the key
282
               auto start = it;
283
               skip_string_view<Opts>(ctx, it, end);
284
               if (bool(ctx.error)) [[unlikely]]
285
                  return;
286
               const sv key = {start, size_t(it - start)};
287
               ++it; // skip the quote
288
               if constexpr (not Opts.null_terminated) {
289
                  if (it == end) [[unlikely]] {
290
                     ctx.error = error_code::unexpected_end;
291
                     return;
292
                  }
293
               }
294
295
               if (parse_ws_colon<Opts>(ctx, it, end)) {
296
                  return;
297
               }
298
299
               parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
300
               return;
301
            }
302
         }
303
304
         if constexpr (N == 2) {
305
            if (index == 0) {
306
               decode_index<Opts, T, 0>(value, ctx, it, end, selected_index...);
307
            }
308
            else {
309
               decode_index<Opts, T, 1>(value, ctx, it, end, selected_index...);
310
            }
311
         }
312
         else {
313
            visit<N>([&]<size_t I>() { decode_index<Opts, T, I>(value, ctx, it, end, selected_index...); }, index);
314
         }
315
      }
316
488
   }
_ZN3glz16parse_and_invokeITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEE5ValueIdETnRDaL_ZNS_9hash_infoIS3_EEERS3_JETkNS_10is_contextERNS_7contextERPKcSB_Qoo14glaze_object_tIT0_E11reflectableISC_EEEvOT2_OT4_OT5_OT6_DpOT3_
Line
Count
Source
263
1.05k
   {
264
1.05k
      constexpr auto type = HashInfo.type;
265
1.05k
      constexpr auto N = reflect<T>::size;
266
267
1.05k
      static_assert(bool(type), "invalid hash algorithm");
268
269
1.05k
      if constexpr (N == 1) {
270
1.05k
         decode_index<Opts, T, 0>(value, ctx, it, end, selected_index...);
271
      }
272
      else {
273
         const auto index = decode_hash<JSON, T, HashInfo, HashInfo.type>::op(it, end);
274
275
         if (index >= N) [[unlikely]] {
276
            if constexpr (Opts.error_on_unknown_keys) {
277
               ctx.error = error_code::unknown_key;
278
               return;
279
            }
280
            else {
281
               // we need to search until we find the ending quote of the key
282
               auto start = it;
283
               skip_string_view<Opts>(ctx, it, end);
284
               if (bool(ctx.error)) [[unlikely]]
285
                  return;
286
               const sv key = {start, size_t(it - start)};
287
               ++it; // skip the quote
288
               if constexpr (not Opts.null_terminated) {
289
                  if (it == end) [[unlikely]] {
290
                     ctx.error = error_code::unexpected_end;
291
                     return;
292
                  }
293
               }
294
295
               if (parse_ws_colon<Opts>(ctx, it, end)) {
296
                  return;
297
               }
298
299
               parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
300
               return;
301
            }
302
         }
303
304
         if constexpr (N == 2) {
305
            if (index == 0) {
306
               decode_index<Opts, T, 0>(value, ctx, it, end, selected_index...);
307
            }
308
            else {
309
               decode_index<Opts, T, 1>(value, ctx, it, end, selected_index...);
310
            }
311
         }
312
         else {
313
            visit<N>([&]<size_t I>() { decode_index<Opts, T, I>(value, ctx, it, end, selected_index...); }, index);
314
         }
315
      }
316
1.05k
   }
_ZN3glz16parse_and_invokeITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEE5ValueIsETnRDaL_ZNS_9hash_infoIS3_EEERS3_JETkNS_10is_contextERNS_7contextERPKcSB_Qoo14glaze_object_tIT0_E11reflectableISC_EEEvOT2_OT4_OT5_OT6_DpOT3_
Line
Count
Source
263
106
   {
264
106
      constexpr auto type = HashInfo.type;
265
106
      constexpr auto N = reflect<T>::size;
266
267
106
      static_assert(bool(type), "invalid hash algorithm");
268
269
106
      if constexpr (N == 1) {
270
106
         decode_index<Opts, T, 0>(value, ctx, it, end, selected_index...);
271
      }
272
      else {
273
         const auto index = decode_hash<JSON, T, HashInfo, HashInfo.type>::op(it, end);
274
275
         if (index >= N) [[unlikely]] {
276
            if constexpr (Opts.error_on_unknown_keys) {
277
               ctx.error = error_code::unknown_key;
278
               return;
279
            }
280
            else {
281
               // we need to search until we find the ending quote of the key
282
               auto start = it;
283
               skip_string_view<Opts>(ctx, it, end);
284
               if (bool(ctx.error)) [[unlikely]]
285
                  return;
286
               const sv key = {start, size_t(it - start)};
287
               ++it; // skip the quote
288
               if constexpr (not Opts.null_terminated) {
289
                  if (it == end) [[unlikely]] {
290
                     ctx.error = error_code::unexpected_end;
291
                     return;
292
                  }
293
               }
294
295
               if (parse_ws_colon<Opts>(ctx, it, end)) {
296
                  return;
297
               }
298
299
               parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
300
               return;
301
            }
302
         }
303
304
         if constexpr (N == 2) {
305
            if (index == 0) {
306
               decode_index<Opts, T, 0>(value, ctx, it, end, selected_index...);
307
            }
308
            else {
309
               decode_index<Opts, T, 1>(value, ctx, it, end, selected_index...);
310
            }
311
         }
312
         else {
313
            visit<N>([&]<size_t I>() { decode_index<Opts, T, I>(value, ctx, it, end, selected_index...); }, index);
314
         }
315
      }
316
106
   }
_ZN3glz16parse_and_invokeITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEE5ValueItETnRDaL_ZNS_9hash_infoIS3_EEERS3_JETkNS_10is_contextERNS_7contextERPKcSB_Qoo14glaze_object_tIT0_E11reflectableISC_EEEvOT2_OT4_OT5_OT6_DpOT3_
Line
Count
Source
263
106
   {
264
106
      constexpr auto type = HashInfo.type;
265
106
      constexpr auto N = reflect<T>::size;
266
267
106
      static_assert(bool(type), "invalid hash algorithm");
268
269
106
      if constexpr (N == 1) {
270
106
         decode_index<Opts, T, 0>(value, ctx, it, end, selected_index...);
271
      }
272
      else {
273
         const auto index = decode_hash<JSON, T, HashInfo, HashInfo.type>::op(it, end);
274
275
         if (index >= N) [[unlikely]] {
276
            if constexpr (Opts.error_on_unknown_keys) {
277
               ctx.error = error_code::unknown_key;
278
               return;
279
            }
280
            else {
281
               // we need to search until we find the ending quote of the key
282
               auto start = it;
283
               skip_string_view<Opts>(ctx, it, end);
284
               if (bool(ctx.error)) [[unlikely]]
285
                  return;
286
               const sv key = {start, size_t(it - start)};
287
               ++it; // skip the quote
288
               if constexpr (not Opts.null_terminated) {
289
                  if (it == end) [[unlikely]] {
290
                     ctx.error = error_code::unexpected_end;
291
                     return;
292
                  }
293
               }
294
295
               if (parse_ws_colon<Opts>(ctx, it, end)) {
296
                  return;
297
               }
298
299
               parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
300
               return;
301
            }
302
         }
303
304
         if constexpr (N == 2) {
305
            if (index == 0) {
306
               decode_index<Opts, T, 0>(value, ctx, it, end, selected_index...);
307
            }
308
            else {
309
               decode_index<Opts, T, 1>(value, ctx, it, end, selected_index...);
310
            }
311
         }
312
         else {
313
            visit<N>([&]<size_t I>() { decode_index<Opts, T, I>(value, ctx, it, end, selected_index...); }, index);
314
         }
315
      }
316
106
   }
_ZN3glz16parse_and_invokeITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEE5ValueIiETnRDaL_ZNS_9hash_infoIS3_EEERS3_JETkNS_10is_contextERNS_7contextERPKcSB_Qoo14glaze_object_tIT0_E11reflectableISC_EEEvOT2_OT4_OT5_OT6_DpOT3_
Line
Count
Source
263
169
   {
264
169
      constexpr auto type = HashInfo.type;
265
169
      constexpr auto N = reflect<T>::size;
266
267
169
      static_assert(bool(type), "invalid hash algorithm");
268
269
169
      if constexpr (N == 1) {
270
169
         decode_index<Opts, T, 0>(value, ctx, it, end, selected_index...);
271
      }
272
      else {
273
         const auto index = decode_hash<JSON, T, HashInfo, HashInfo.type>::op(it, end);
274
275
         if (index >= N) [[unlikely]] {
276
            if constexpr (Opts.error_on_unknown_keys) {
277
               ctx.error = error_code::unknown_key;
278
               return;
279
            }
280
            else {
281
               // we need to search until we find the ending quote of the key
282
               auto start = it;
283
               skip_string_view<Opts>(ctx, it, end);
284
               if (bool(ctx.error)) [[unlikely]]
285
                  return;
286
               const sv key = {start, size_t(it - start)};
287
               ++it; // skip the quote
288
               if constexpr (not Opts.null_terminated) {
289
                  if (it == end) [[unlikely]] {
290
                     ctx.error = error_code::unexpected_end;
291
                     return;
292
                  }
293
               }
294
295
               if (parse_ws_colon<Opts>(ctx, it, end)) {
296
                  return;
297
               }
298
299
               parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
300
               return;
301
            }
302
         }
303
304
         if constexpr (N == 2) {
305
            if (index == 0) {
306
               decode_index<Opts, T, 0>(value, ctx, it, end, selected_index...);
307
            }
308
            else {
309
               decode_index<Opts, T, 1>(value, ctx, it, end, selected_index...);
310
            }
311
         }
312
         else {
313
            visit<N>([&]<size_t I>() { decode_index<Opts, T, I>(value, ctx, it, end, selected_index...); }, index);
314
         }
315
      }
316
169
   }
_ZN3glz16parse_and_invokeITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEE5ValueIjETnRDaL_ZNS_9hash_infoIS3_EEERS3_JETkNS_10is_contextERNS_7contextERPKcSB_Qoo14glaze_object_tIT0_E11reflectableISC_EEEvOT2_OT4_OT5_OT6_DpOT3_
Line
Count
Source
263
169
   {
264
169
      constexpr auto type = HashInfo.type;
265
169
      constexpr auto N = reflect<T>::size;
266
267
169
      static_assert(bool(type), "invalid hash algorithm");
268
269
169
      if constexpr (N == 1) {
270
169
         decode_index<Opts, T, 0>(value, ctx, it, end, selected_index...);
271
      }
272
      else {
273
         const auto index = decode_hash<JSON, T, HashInfo, HashInfo.type>::op(it, end);
274
275
         if (index >= N) [[unlikely]] {
276
            if constexpr (Opts.error_on_unknown_keys) {
277
               ctx.error = error_code::unknown_key;
278
               return;
279
            }
280
            else {
281
               // we need to search until we find the ending quote of the key
282
               auto start = it;
283
               skip_string_view<Opts>(ctx, it, end);
284
               if (bool(ctx.error)) [[unlikely]]
285
                  return;
286
               const sv key = {start, size_t(it - start)};
287
               ++it; // skip the quote
288
               if constexpr (not Opts.null_terminated) {
289
                  if (it == end) [[unlikely]] {
290
                     ctx.error = error_code::unexpected_end;
291
                     return;
292
                  }
293
               }
294
295
               if (parse_ws_colon<Opts>(ctx, it, end)) {
296
                  return;
297
               }
298
299
               parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
300
               return;
301
            }
302
         }
303
304
         if constexpr (N == 2) {
305
            if (index == 0) {
306
               decode_index<Opts, T, 0>(value, ctx, it, end, selected_index...);
307
            }
308
            else {
309
               decode_index<Opts, T, 1>(value, ctx, it, end, selected_index...);
310
            }
311
         }
312
         else {
313
            visit<N>([&]<size_t I>() { decode_index<Opts, T, I>(value, ctx, it, end, selected_index...); }, index);
314
         }
315
      }
316
169
   }
_ZN3glz16parse_and_invokeITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEE5ValueIlETnRDaL_ZNS_9hash_infoIS3_EEERS3_JETkNS_10is_contextERNS_7contextERPKcSB_Qoo14glaze_object_tIT0_E11reflectableISC_EEEvOT2_OT4_OT5_OT6_DpOT3_
Line
Count
Source
263
296
   {
264
296
      constexpr auto type = HashInfo.type;
265
296
      constexpr auto N = reflect<T>::size;
266
267
296
      static_assert(bool(type), "invalid hash algorithm");
268
269
296
      if constexpr (N == 1) {
270
296
         decode_index<Opts, T, 0>(value, ctx, it, end, selected_index...);
271
      }
272
      else {
273
         const auto index = decode_hash<JSON, T, HashInfo, HashInfo.type>::op(it, end);
274
275
         if (index >= N) [[unlikely]] {
276
            if constexpr (Opts.error_on_unknown_keys) {
277
               ctx.error = error_code::unknown_key;
278
               return;
279
            }
280
            else {
281
               // we need to search until we find the ending quote of the key
282
               auto start = it;
283
               skip_string_view<Opts>(ctx, it, end);
284
               if (bool(ctx.error)) [[unlikely]]
285
                  return;
286
               const sv key = {start, size_t(it - start)};
287
               ++it; // skip the quote
288
               if constexpr (not Opts.null_terminated) {
289
                  if (it == end) [[unlikely]] {
290
                     ctx.error = error_code::unexpected_end;
291
                     return;
292
                  }
293
               }
294
295
               if (parse_ws_colon<Opts>(ctx, it, end)) {
296
                  return;
297
               }
298
299
               parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
300
               return;
301
            }
302
         }
303
304
         if constexpr (N == 2) {
305
            if (index == 0) {
306
               decode_index<Opts, T, 0>(value, ctx, it, end, selected_index...);
307
            }
308
            else {
309
               decode_index<Opts, T, 1>(value, ctx, it, end, selected_index...);
310
            }
311
         }
312
         else {
313
            visit<N>([&]<size_t I>() { decode_index<Opts, T, I>(value, ctx, it, end, selected_index...); }, index);
314
         }
315
      }
316
296
   }
_ZN3glz16parse_and_invokeITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEE5ValueImETnRDaL_ZNS_9hash_infoIS3_EEERS3_JETkNS_10is_contextERNS_7contextERPKcSB_Qoo14glaze_object_tIT0_E11reflectableISC_EEEvOT2_OT4_OT5_OT6_DpOT3_
Line
Count
Source
263
296
   {
264
296
      constexpr auto type = HashInfo.type;
265
296
      constexpr auto N = reflect<T>::size;
266
267
296
      static_assert(bool(type), "invalid hash algorithm");
268
269
296
      if constexpr (N == 1) {
270
296
         decode_index<Opts, T, 0>(value, ctx, it, end, selected_index...);
271
      }
272
      else {
273
         const auto index = decode_hash<JSON, T, HashInfo, HashInfo.type>::op(it, end);
274
275
         if (index >= N) [[unlikely]] {
276
            if constexpr (Opts.error_on_unknown_keys) {
277
               ctx.error = error_code::unknown_key;
278
               return;
279
            }
280
            else {
281
               // we need to search until we find the ending quote of the key
282
               auto start = it;
283
               skip_string_view<Opts>(ctx, it, end);
284
               if (bool(ctx.error)) [[unlikely]]
285
                  return;
286
               const sv key = {start, size_t(it - start)};
287
               ++it; // skip the quote
288
               if constexpr (not Opts.null_terminated) {
289
                  if (it == end) [[unlikely]] {
290
                     ctx.error = error_code::unexpected_end;
291
                     return;
292
                  }
293
               }
294
295
               if (parse_ws_colon<Opts>(ctx, it, end)) {
296
                  return;
297
               }
298
299
               parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
300
               return;
301
            }
302
         }
303
304
         if constexpr (N == 2) {
305
            if (index == 0) {
306
               decode_index<Opts, T, 0>(value, ctx, it, end, selected_index...);
307
            }
308
            else {
309
               decode_index<Opts, T, 1>(value, ctx, it, end, selected_index...);
310
            }
311
         }
312
         else {
313
            visit<N>([&]<size_t I>() { decode_index<Opts, T, I>(value, ctx, it, end, selected_index...); }, index);
314
         }
315
      }
316
296
   }
_ZN3glz16parse_and_invokeITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEE5ValueIxETnRDaL_ZNS_9hash_infoIS3_EEERS3_JETkNS_10is_contextERNS_7contextERPKcSB_Qoo14glaze_object_tIT0_E11reflectableISC_EEEvOT2_OT4_OT5_OT6_DpOT3_
Line
Count
Source
263
290
   {
264
290
      constexpr auto type = HashInfo.type;
265
290
      constexpr auto N = reflect<T>::size;
266
267
290
      static_assert(bool(type), "invalid hash algorithm");
268
269
290
      if constexpr (N == 1) {
270
290
         decode_index<Opts, T, 0>(value, ctx, it, end, selected_index...);
271
      }
272
      else {
273
         const auto index = decode_hash<JSON, T, HashInfo, HashInfo.type>::op(it, end);
274
275
         if (index >= N) [[unlikely]] {
276
            if constexpr (Opts.error_on_unknown_keys) {
277
               ctx.error = error_code::unknown_key;
278
               return;
279
            }
280
            else {
281
               // we need to search until we find the ending quote of the key
282
               auto start = it;
283
               skip_string_view<Opts>(ctx, it, end);
284
               if (bool(ctx.error)) [[unlikely]]
285
                  return;
286
               const sv key = {start, size_t(it - start)};
287
               ++it; // skip the quote
288
               if constexpr (not Opts.null_terminated) {
289
                  if (it == end) [[unlikely]] {
290
                     ctx.error = error_code::unexpected_end;
291
                     return;
292
                  }
293
               }
294
295
               if (parse_ws_colon<Opts>(ctx, it, end)) {
296
                  return;
297
               }
298
299
               parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
300
               return;
301
            }
302
         }
303
304
         if constexpr (N == 2) {
305
            if (index == 0) {
306
               decode_index<Opts, T, 0>(value, ctx, it, end, selected_index...);
307
            }
308
            else {
309
               decode_index<Opts, T, 1>(value, ctx, it, end, selected_index...);
310
            }
311
         }
312
         else {
313
            visit<N>([&]<size_t I>() { decode_index<Opts, T, I>(value, ctx, it, end, selected_index...); }, index);
314
         }
315
      }
316
290
   }
_ZN3glz16parse_and_invokeITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEE5ValueIyETnRDaL_ZNS_9hash_infoIS3_EEERS3_JETkNS_10is_contextERNS_7contextERPKcSB_Qoo14glaze_object_tIT0_E11reflectableISC_EEEvOT2_OT4_OT5_OT6_DpOT3_
Line
Count
Source
263
290
   {
264
290
      constexpr auto type = HashInfo.type;
265
290
      constexpr auto N = reflect<T>::size;
266
267
290
      static_assert(bool(type), "invalid hash algorithm");
268
269
290
      if constexpr (N == 1) {
270
290
         decode_index<Opts, T, 0>(value, ctx, it, end, selected_index...);
271
      }
272
      else {
273
         const auto index = decode_hash<JSON, T, HashInfo, HashInfo.type>::op(it, end);
274
275
         if (index >= N) [[unlikely]] {
276
            if constexpr (Opts.error_on_unknown_keys) {
277
               ctx.error = error_code::unknown_key;
278
               return;
279
            }
280
            else {
281
               // we need to search until we find the ending quote of the key
282
               auto start = it;
283
               skip_string_view<Opts>(ctx, it, end);
284
               if (bool(ctx.error)) [[unlikely]]
285
                  return;
286
               const sv key = {start, size_t(it - start)};
287
               ++it; // skip the quote
288
               if constexpr (not Opts.null_terminated) {
289
                  if (it == end) [[unlikely]] {
290
                     ctx.error = error_code::unexpected_end;
291
                     return;
292
                  }
293
               }
294
295
               if (parse_ws_colon<Opts>(ctx, it, end)) {
296
                  return;
297
               }
298
299
               parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
300
               return;
301
            }
302
         }
303
304
         if constexpr (N == 2) {
305
            if (index == 0) {
306
               decode_index<Opts, T, 0>(value, ctx, it, end, selected_index...);
307
            }
308
            else {
309
               decode_index<Opts, T, 1>(value, ctx, it, end, selected_index...);
310
            }
311
         }
312
         else {
313
            visit<N>([&]<size_t I>() { decode_index<Opts, T, I>(value, ctx, it, end, selected_index...); }, index);
314
         }
315
      }
316
290
   }
317
318
   template <is_member_function_pointer T>
319
   struct from<JSON, T>
320
   {
321
      template <auto Opts>
322
      GLZ_ALWAYS_INLINE static void op(auto&&, is_context auto&& ctx, auto&&...) noexcept
323
      {
324
         ctx.error = error_code::attempt_member_func_read;
325
      }
326
   };
327
328
   template <is_includer T>
329
   struct from<JSON, T>
330
   {
331
      template <auto Opts, class... Args>
332
      static void op(auto&&, is_context auto&& ctx, auto&& it, auto&& end) noexcept
333
      {
334
         if constexpr (!check_ws_handled(Opts)) {
335
            if (skip_ws<Opts>(ctx, it, end)) {
336
               return;
337
            }
338
         }
339
340
         match<R"("")", Opts>(ctx, it, end);
341
      }
342
   };
343
344
   template <is_bitset T>
345
   struct from<JSON, T>
346
   {
347
      template <auto Opts>
348
      static void op(auto&& value, is_context auto&& ctx, auto&& it, auto&& end) noexcept
349
      {
350
         if (match_invalid_end<'"', Opts>(ctx, it, end)) {
351
            return;
352
         }
353
354
         const auto n = value.size();
355
         for (size_t i = 1; it < end; ++i, ++it) {
356
            if (*it == '"') {
357
               ++it;
358
               if constexpr (not Opts.null_terminated) {
359
                  if (it == end) {
360
                     ctx.error = error_code::end_reached;
361
                     return;
362
                  }
363
               }
364
               return;
365
            }
366
367
            if (i > n) {
368
               ctx.error = error_code::exceeded_static_array_size;
369
               return;
370
            }
371
372
            if (*it == '0') {
373
               value[n - i] = 0;
374
            }
375
            else if (*it == '1') {
376
               value[n - i] = 1;
377
            }
378
            else [[unlikely]] {
379
               ctx.error = error_code::syntax_error;
380
               return;
381
            }
382
         }
383
384
         ctx.error = error_code::expected_quote;
385
      }
386
   };
387
388
   template <>
389
   struct from<JSON, skip>
390
   {
391
      template <auto Opts>
392
      GLZ_ALWAYS_INLINE static void op(auto&&, is_context auto&& ctx, auto&&... args) noexcept
393
      {
394
         skip_value<JSON>::op<Opts>(ctx, args...);
395
      }
396
   };
397
398
   template <is_reference_wrapper T>
399
   struct from<JSON, T>
400
   {
401
      template <auto Opts, class... Args>
402
      GLZ_ALWAYS_INLINE static void op(auto&& value, Args&&... args)
403
      {
404
         using V = std::decay_t<decltype(value.get())>;
405
         from<JSON, V>::template op<Opts>(value.get(), std::forward<Args>(args)...);
406
      }
407
   };
408
409
   template <>
410
   struct from<JSON, hidden>
411
   {
412
      template <auto Opts>
413
      GLZ_ALWAYS_INLINE static void op(auto&&, is_context auto&& ctx, auto&&...) noexcept
414
      {
415
         ctx.error = error_code::attempt_read_hidden;
416
      }
417
   };
418
419
   template <complex_t T>
420
   struct from<JSON, T>
421
   {
422
      template <auto Options>
423
      static void op(auto&& v, is_context auto&& ctx, auto&& it, auto&& end) noexcept
424
      {
425
         constexpr auto Opts = ws_handled_off<Options>();
426
         if constexpr (!check_ws_handled(Options)) {
427
            if (skip_ws<Opts>(ctx, it, end)) {
428
               return;
429
            }
430
         }
431
         if (match_invalid_end<'[', Opts>(ctx, it, end)) {
432
            return;
433
         }
434
         if constexpr (not Opts.null_terminated) {
435
            ++ctx.indentation_level;
436
         }
437
438
         auto* ptr = reinterpret_cast<typename T::value_type*>(&v);
439
         static_assert(sizeof(T) == sizeof(typename T::value_type) * 2);
440
         parse<JSON>::op<Opts>(ptr[0], ctx, it, end);
441
         if (bool(ctx.error)) [[unlikely]]
442
            return;
443
444
         if (skip_ws<Opts>(ctx, it, end)) {
445
            return;
446
         }
447
448
         if (match_invalid_end<',', Opts>(ctx, it, end)) {
449
            return;
450
         }
451
452
         parse<JSON>::op<Opts>(ptr[1], ctx, it, end);
453
         if (bool(ctx.error)) [[unlikely]]
454
            return;
455
456
         if (skip_ws<Opts>(ctx, it, end)) {
457
            return;
458
         }
459
         match<']'>(ctx, it);
460
         if constexpr (not Opts.null_terminated) {
461
            --ctx.indentation_level;
462
         }
463
      }
464
   };
465
466
   template <always_null_t T>
467
   struct from<JSON, T>
468
   {
469
      template <auto Opts>
470
      GLZ_ALWAYS_INLINE static void op(auto&&, is_context auto&& ctx, auto&& it, auto&& end) noexcept
471
      {
472
         if constexpr (!check_ws_handled(Opts)) {
473
            if (skip_ws<Opts>(ctx, it, end)) {
474
               return;
475
            }
476
         }
477
         static constexpr sv null_string = "null";
478
         if constexpr (not check_is_padded(Opts)) {
479
            const auto n = size_t(end - it);
480
            if ((n < 4) || not comparitor<null_string>(it)) [[unlikely]] {
481
               ctx.error = error_code::syntax_error;
482
            }
483
         }
484
         else {
485
            if (not comparitor<null_string>(it)) [[unlikely]] {
486
               ctx.error = error_code::syntax_error;
487
            }
488
         }
489
         it += 4; // always advance for performance
490
      }
491
   };
492
493
   template <bool_t T>
494
   struct from<JSON, T>
495
   {
496
      template <auto Opts>
497
      static void op(bool_t auto&& value, is_context auto&& ctx, auto&& it, auto&& end) noexcept
498
3.93k
      {
499
         if constexpr (Opts.quoted_num) {
500
            if (skip_ws<Opts>(ctx, it, end)) {
501
               return;
502
            }
503
            if (match_invalid_end<'"', Opts>(ctx, it, end)) {
504
               return;
505
            }
506
         }
507
508
         if constexpr (!check_ws_handled(Opts)) {
509
            if (skip_ws<Opts>(ctx, it, end)) {
510
               return;
511
            }
512
         }
513
514
         if constexpr (Opts.bools_as_numbers) {
515
            if (*it == '1') {
516
               value = true;
517
               ++it;
518
            }
519
            else if (*it == '0') {
520
               value = false;
521
               ++it;
522
            }
523
            else {
524
               ctx.error = error_code::syntax_error;
525
               return;
526
            }
527
         }
528
3.93k
         else {
529
3.93k
            if constexpr (not check_is_padded(Opts)) {
530
2.62k
               if (size_t(end - it) < 4) [[unlikely]] {
531
102
                  ctx.error = error_code::expected_true_or_false;
532
102
                  return;
533
102
               }
534
2.62k
            }
535
536
2.52k
            uint32_t c;
537
3.93k
            static constexpr uint32_t u_true = 0b01100101'01110101'01110010'01110100;
538
3.93k
            static constexpr uint32_t u_fals = 0b01110011'01101100'01100001'01100110;
539
3.93k
            std::memcpy(&c, it, 4);
540
3.93k
            it += 4;
541
3.93k
            if (c == u_true) {
542
2.66k
               value = true;
543
2.66k
            }
544
1.26k
            else if (it == end) [[unlikely]] {
545
79
               ctx.error = error_code::unexpected_end;
546
79
               return;
547
79
            }
548
1.19k
            else {
549
1.19k
               if (c == u_fals && (*it == 'e')) [[likely]] {
550
813
                  value = false;
551
813
                  ++it;
552
813
               }
553
377
               else [[unlikely]] {
554
377
                  ctx.error = error_code::expected_true_or_false;
555
377
                  return;
556
377
               }
557
1.19k
            }
558
3.93k
         }
559
560
         if constexpr (Opts.quoted_num) {
561
            if constexpr (not Opts.null_terminated) {
562
               if (it == end) [[unlikely]] {
563
                  ctx.error = error_code::unexpected_end;
564
                  return;
565
               }
566
            }
567
            if (match<'"'>(ctx, it)) {
568
               return;
569
            }
570
            if constexpr (not Opts.null_terminated) {
571
               if (it == end) {
572
                  ctx.error = error_code::end_reached;
573
                  return;
574
               }
575
            }
576
         }
577
3.93k
         else {
578
3.93k
            if constexpr (not Opts.null_terminated) {
579
1.31k
               if (it == end) {
580
15
                  ctx.error = error_code::end_reached;
581
15
                  return;
582
15
               }
583
1.31k
            }
584
3.93k
         }
585
3.93k
      }
_ZN3glz4fromILj10EbE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj4EEETkNS_6bool_tERbTkNS_10is_contextERNS_7contextERPKcS9_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
498
1.31k
      {
499
         if constexpr (Opts.quoted_num) {
500
            if (skip_ws<Opts>(ctx, it, end)) {
501
               return;
502
            }
503
            if (match_invalid_end<'"', Opts>(ctx, it, end)) {
504
               return;
505
            }
506
         }
507
508
         if constexpr (!check_ws_handled(Opts)) {
509
            if (skip_ws<Opts>(ctx, it, end)) {
510
               return;
511
            }
512
         }
513
514
         if constexpr (Opts.bools_as_numbers) {
515
            if (*it == '1') {
516
               value = true;
517
               ++it;
518
            }
519
            else if (*it == '0') {
520
               value = false;
521
               ++it;
522
            }
523
            else {
524
               ctx.error = error_code::syntax_error;
525
               return;
526
            }
527
         }
528
1.31k
         else {
529
1.31k
            if constexpr (not check_is_padded(Opts)) {
530
1.31k
               if (size_t(end - it) < 4) [[unlikely]] {
531
60
                  ctx.error = error_code::expected_true_or_false;
532
60
                  return;
533
60
               }
534
1.31k
            }
535
536
1.25k
            uint32_t c;
537
1.31k
            static constexpr uint32_t u_true = 0b01100101'01110101'01110010'01110100;
538
1.31k
            static constexpr uint32_t u_fals = 0b01110011'01101100'01100001'01100110;
539
1.31k
            std::memcpy(&c, it, 4);
540
1.31k
            it += 4;
541
1.31k
            if (c == u_true) {
542
889
               value = true;
543
889
            }
544
424
            else if (it == end) [[unlikely]] {
545
43
               ctx.error = error_code::unexpected_end;
546
43
               return;
547
43
            }
548
381
            else {
549
381
               if (c == u_fals && (*it == 'e')) [[likely]] {
550
271
                  value = false;
551
271
                  ++it;
552
271
               }
553
110
               else [[unlikely]] {
554
110
                  ctx.error = error_code::expected_true_or_false;
555
110
                  return;
556
110
               }
557
381
            }
558
1.31k
         }
559
560
         if constexpr (Opts.quoted_num) {
561
            if constexpr (not Opts.null_terminated) {
562
               if (it == end) [[unlikely]] {
563
                  ctx.error = error_code::unexpected_end;
564
                  return;
565
               }
566
            }
567
            if (match<'"'>(ctx, it)) {
568
               return;
569
            }
570
            if constexpr (not Opts.null_terminated) {
571
               if (it == end) {
572
                  ctx.error = error_code::end_reached;
573
                  return;
574
               }
575
            }
576
         }
577
1.31k
         else {
578
1.31k
            if constexpr (not Opts.null_terminated) {
579
1.31k
               if (it == end) {
580
15
                  ctx.error = error_code::end_reached;
581
15
                  return;
582
15
               }
583
1.31k
            }
584
1.31k
         }
585
1.31k
      }
_ZN3glz4fromILj10EbE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj4EEETkNS_6bool_tERbTkNS_10is_contextERNS_7contextERPKcS9_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
498
1.31k
      {
499
         if constexpr (Opts.quoted_num) {
500
            if (skip_ws<Opts>(ctx, it, end)) {
501
               return;
502
            }
503
            if (match_invalid_end<'"', Opts>(ctx, it, end)) {
504
               return;
505
            }
506
         }
507
508
         if constexpr (!check_ws_handled(Opts)) {
509
            if (skip_ws<Opts>(ctx, it, end)) {
510
               return;
511
            }
512
         }
513
514
         if constexpr (Opts.bools_as_numbers) {
515
            if (*it == '1') {
516
               value = true;
517
               ++it;
518
            }
519
            else if (*it == '0') {
520
               value = false;
521
               ++it;
522
            }
523
            else {
524
               ctx.error = error_code::syntax_error;
525
               return;
526
            }
527
         }
528
1.31k
         else {
529
1.31k
            if constexpr (not check_is_padded(Opts)) {
530
1.31k
               if (size_t(end - it) < 4) [[unlikely]] {
531
42
                  ctx.error = error_code::expected_true_or_false;
532
42
                  return;
533
42
               }
534
1.31k
            }
535
536
1.27k
            uint32_t c;
537
1.31k
            static constexpr uint32_t u_true = 0b01100101'01110101'01110010'01110100;
538
1.31k
            static constexpr uint32_t u_fals = 0b01110011'01101100'01100001'01100110;
539
1.31k
            std::memcpy(&c, it, 4);
540
1.31k
            it += 4;
541
1.31k
            if (c == u_true) {
542
889
               value = true;
543
889
            }
544
423
            else if (it == end) [[unlikely]] {
545
18
               ctx.error = error_code::unexpected_end;
546
18
               return;
547
18
            }
548
405
            else {
549
405
               if (c == u_fals && (*it == 'e')) [[likely]] {
550
271
                  value = false;
551
271
                  ++it;
552
271
               }
553
134
               else [[unlikely]] {
554
134
                  ctx.error = error_code::expected_true_or_false;
555
134
                  return;
556
134
               }
557
405
            }
558
1.31k
         }
559
560
         if constexpr (Opts.quoted_num) {
561
            if constexpr (not Opts.null_terminated) {
562
               if (it == end) [[unlikely]] {
563
                  ctx.error = error_code::unexpected_end;
564
                  return;
565
               }
566
            }
567
            if (match<'"'>(ctx, it)) {
568
               return;
569
            }
570
            if constexpr (not Opts.null_terminated) {
571
               if (it == end) {
572
                  ctx.error = error_code::end_reached;
573
                  return;
574
               }
575
            }
576
         }
577
1.31k
         else {
578
            if constexpr (not Opts.null_terminated) {
579
               if (it == end) {
580
                  ctx.error = error_code::end_reached;
581
                  return;
582
               }
583
            }
584
1.31k
         }
585
1.31k
      }
_ZN3glz4fromILj10EbE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj36EEETkNS_6bool_tERbTkNS_10is_contextERNS_7contextERPKcS9_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
498
1.31k
      {
499
         if constexpr (Opts.quoted_num) {
500
            if (skip_ws<Opts>(ctx, it, end)) {
501
               return;
502
            }
503
            if (match_invalid_end<'"', Opts>(ctx, it, end)) {
504
               return;
505
            }
506
         }
507
508
         if constexpr (!check_ws_handled(Opts)) {
509
            if (skip_ws<Opts>(ctx, it, end)) {
510
               return;
511
            }
512
         }
513
514
         if constexpr (Opts.bools_as_numbers) {
515
            if (*it == '1') {
516
               value = true;
517
               ++it;
518
            }
519
            else if (*it == '0') {
520
               value = false;
521
               ++it;
522
            }
523
            else {
524
               ctx.error = error_code::syntax_error;
525
               return;
526
            }
527
         }
528
1.31k
         else {
529
            if constexpr (not check_is_padded(Opts)) {
530
               if (size_t(end - it) < 4) [[unlikely]] {
531
                  ctx.error = error_code::expected_true_or_false;
532
                  return;
533
               }
534
            }
535
536
1.31k
            uint32_t c;
537
1.31k
            static constexpr uint32_t u_true = 0b01100101'01110101'01110010'01110100;
538
1.31k
            static constexpr uint32_t u_fals = 0b01110011'01101100'01100001'01100110;
539
1.31k
            std::memcpy(&c, it, 4);
540
1.31k
            it += 4;
541
1.31k
            if (c == u_true) {
542
889
               value = true;
543
889
            }
544
422
            else if (it == end) [[unlikely]] {
545
18
               ctx.error = error_code::unexpected_end;
546
18
               return;
547
18
            }
548
404
            else {
549
404
               if (c == u_fals && (*it == 'e')) [[likely]] {
550
271
                  value = false;
551
271
                  ++it;
552
271
               }
553
133
               else [[unlikely]] {
554
133
                  ctx.error = error_code::expected_true_or_false;
555
133
                  return;
556
133
               }
557
404
            }
558
1.31k
         }
559
560
         if constexpr (Opts.quoted_num) {
561
            if constexpr (not Opts.null_terminated) {
562
               if (it == end) [[unlikely]] {
563
                  ctx.error = error_code::unexpected_end;
564
                  return;
565
               }
566
            }
567
            if (match<'"'>(ctx, it)) {
568
               return;
569
            }
570
            if constexpr (not Opts.null_terminated) {
571
               if (it == end) {
572
                  ctx.error = error_code::end_reached;
573
                  return;
574
               }
575
            }
576
         }
577
1.31k
         else {
578
            if constexpr (not Opts.null_terminated) {
579
               if (it == end) {
580
                  ctx.error = error_code::end_reached;
581
                  return;
582
               }
583
            }
584
1.31k
         }
585
1.31k
      }
586
   };
587
588
   template <num_t T>
589
   struct from<JSON, T>
590
   {
591
      template <auto Opts, class It>
592
      GLZ_ALWAYS_INLINE static void op(auto&& value, is_context auto&& ctx, It&& it, auto&& end) noexcept
593
5.32M
      {
594
         if constexpr (Opts.quoted_num) {
595
            if (skip_ws<Opts>(ctx, it, end)) {
596
               return;
597
            }
598
            if (match_invalid_end<'"', Opts>(ctx, it, end)) {
599
               return;
600
            }
601
         }
602
603
         if constexpr (!check_ws_handled(Opts)) {
604
            if (skip_ws<Opts>(ctx, it, end)) {
605
               return;
606
            }
607
         }
608
609
5.32M
         using V = std::decay_t<decltype(value)>;
610
5.32M
         if constexpr (int_t<V>) {
611
79.5k
            static_assert(sizeof(*it) == sizeof(char));
612
613
79.5k
            if constexpr (Opts.null_terminated) {
614
54.3k
               if (not glz::atoi(value, it)) [[unlikely]] {
615
1.33k
                  ctx.error = error_code::parse_number_failure;
616
1.33k
                  return;
617
1.33k
               }
618
            }
619
25.1k
            else {
620
25.1k
               if (not glz::atoi(value, it, end)) [[unlikely]] {
621
498
                  ctx.error = error_code::parse_number_failure;
622
498
                  return;
623
498
               }
624
25.1k
            }
625
         }
626
5.24M
         else {
627
            if constexpr (is_float128<V>) {
628
               auto [ptr, ec] = std::from_chars(it, end, value);
629
               if (ec != std::errc()) {
630
                  ctx.error = error_code::parse_number_failure;
631
                  return;
632
               }
633
               it = ptr;
634
            }
635
5.24M
            else {
636
               if constexpr (std::is_volatile_v<std::remove_reference_t<decltype(value)>>) {
637
                  // Hardware may interact with value changes, so we parse into a temporary and assign in one
638
                  // place
639
                  V temp;
640
                  auto [ptr, ec] = glz::from_chars<Opts.null_terminated>(it, end, temp);
641
                  if (ec != std::errc()) [[unlikely]] {
642
                     ctx.error = error_code::parse_number_failure;
643
                     return;
644
                  }
645
                  value = temp;
646
                  it = ptr;
647
               }
648
5.24M
               else {
649
5.24M
                  auto [ptr, ec] = glz::from_chars<Opts.null_terminated>(it, end, value);
650
5.24M
                  if (ec != std::errc()) [[unlikely]] {
651
3.55k
                     ctx.error = error_code::parse_number_failure;
652
3.55k
                     return;
653
3.55k
                  }
654
5.24M
                  it = ptr;
655
5.24M
               }
656
5.24M
            }
657
5.24M
         }
658
659
         if constexpr (Opts.quoted_num) {
660
            if constexpr (not Opts.null_terminated) {
661
               if (it == end) [[unlikely]] {
662
                  ctx.error = error_code::unexpected_end;
663
                  return;
664
               }
665
            }
666
            if (match<'"'>(ctx, it)) {
667
               return;
668
            }
669
            if constexpr (not Opts.null_terminated) {
670
               if (it == end) {
671
                  ctx.error = error_code::end_reached;
672
                  return;
673
               }
674
            }
675
         }
676
5.32M
         else {
677
5.32M
            if constexpr (not Opts.null_terminated) {
678
1.77M
               if (it == end) {
679
5.07k
                  ctx.error = error_code::end_reached;
680
5.07k
                  return;
681
5.07k
               }
682
1.77M
            }
683
5.32M
         }
684
5.32M
      }
_ZN3glz4fromILj10EiE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj4EEERPKcRiTkNS_10is_contextERNS_7contextES6_EEvOT1_OT2_OT0_OT3_
Line
Count
Source
593
8.46k
      {
594
         if constexpr (Opts.quoted_num) {
595
            if (skip_ws<Opts>(ctx, it, end)) {
596
               return;
597
            }
598
            if (match_invalid_end<'"', Opts>(ctx, it, end)) {
599
               return;
600
            }
601
         }
602
603
         if constexpr (!check_ws_handled(Opts)) {
604
            if (skip_ws<Opts>(ctx, it, end)) {
605
               return;
606
            }
607
         }
608
609
8.46k
         using V = std::decay_t<decltype(value)>;
610
8.46k
         if constexpr (int_t<V>) {
611
8.46k
            static_assert(sizeof(*it) == sizeof(char));
612
613
            if constexpr (Opts.null_terminated) {
614
               if (not glz::atoi(value, it)) [[unlikely]] {
615
                  ctx.error = error_code::parse_number_failure;
616
                  return;
617
               }
618
            }
619
8.46k
            else {
620
8.46k
               if (not glz::atoi(value, it, end)) [[unlikely]] {
621
200
                  ctx.error = error_code::parse_number_failure;
622
200
                  return;
623
200
               }
624
8.46k
            }
625
         }
626
         else {
627
            if constexpr (is_float128<V>) {
628
               auto [ptr, ec] = std::from_chars(it, end, value);
629
               if (ec != std::errc()) {
630
                  ctx.error = error_code::parse_number_failure;
631
                  return;
632
               }
633
               it = ptr;
634
            }
635
            else {
636
               if constexpr (std::is_volatile_v<std::remove_reference_t<decltype(value)>>) {
637
                  // Hardware may interact with value changes, so we parse into a temporary and assign in one
638
                  // place
639
                  V temp;
640
                  auto [ptr, ec] = glz::from_chars<Opts.null_terminated>(it, end, temp);
641
                  if (ec != std::errc()) [[unlikely]] {
642
                     ctx.error = error_code::parse_number_failure;
643
                     return;
644
                  }
645
                  value = temp;
646
                  it = ptr;
647
               }
648
               else {
649
                  auto [ptr, ec] = glz::from_chars<Opts.null_terminated>(it, end, value);
650
                  if (ec != std::errc()) [[unlikely]] {
651
                     ctx.error = error_code::parse_number_failure;
652
                     return;
653
                  }
654
                  it = ptr;
655
               }
656
            }
657
         }
658
659
         if constexpr (Opts.quoted_num) {
660
            if constexpr (not Opts.null_terminated) {
661
               if (it == end) [[unlikely]] {
662
                  ctx.error = error_code::unexpected_end;
663
                  return;
664
               }
665
            }
666
            if (match<'"'>(ctx, it)) {
667
               return;
668
            }
669
            if constexpr (not Opts.null_terminated) {
670
               if (it == end) {
671
                  ctx.error = error_code::end_reached;
672
                  return;
673
               }
674
            }
675
         }
676
8.46k
         else {
677
8.46k
            if constexpr (not Opts.null_terminated) {
678
8.46k
               if (it == end) {
679
148
                  ctx.error = error_code::end_reached;
680
148
                  return;
681
148
               }
682
8.46k
            }
683
8.46k
         }
684
8.46k
      }
_ZN3glz4fromILj10EdE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj4EEERPKcRdTkNS_10is_contextERNS_7contextES6_EEvOT1_OT2_OT0_OT3_
Line
Count
Source
593
1.74M
      {
594
         if constexpr (Opts.quoted_num) {
595
            if (skip_ws<Opts>(ctx, it, end)) {
596
               return;
597
            }
598
            if (match_invalid_end<'"', Opts>(ctx, it, end)) {
599
               return;
600
            }
601
         }
602
603
         if constexpr (!check_ws_handled(Opts)) {
604
            if (skip_ws<Opts>(ctx, it, end)) {
605
               return;
606
            }
607
         }
608
609
1.74M
         using V = std::decay_t<decltype(value)>;
610
         if constexpr (int_t<V>) {
611
            static_assert(sizeof(*it) == sizeof(char));
612
613
            if constexpr (Opts.null_terminated) {
614
               if (not glz::atoi(value, it)) [[unlikely]] {
615
                  ctx.error = error_code::parse_number_failure;
616
                  return;
617
               }
618
            }
619
            else {
620
               if (not glz::atoi(value, it, end)) [[unlikely]] {
621
                  ctx.error = error_code::parse_number_failure;
622
                  return;
623
               }
624
            }
625
         }
626
1.74M
         else {
627
            if constexpr (is_float128<V>) {
628
               auto [ptr, ec] = std::from_chars(it, end, value);
629
               if (ec != std::errc()) {
630
                  ctx.error = error_code::parse_number_failure;
631
                  return;
632
               }
633
               it = ptr;
634
            }
635
1.74M
            else {
636
               if constexpr (std::is_volatile_v<std::remove_reference_t<decltype(value)>>) {
637
                  // Hardware may interact with value changes, so we parse into a temporary and assign in one
638
                  // place
639
                  V temp;
640
                  auto [ptr, ec] = glz::from_chars<Opts.null_terminated>(it, end, temp);
641
                  if (ec != std::errc()) [[unlikely]] {
642
                     ctx.error = error_code::parse_number_failure;
643
                     return;
644
                  }
645
                  value = temp;
646
                  it = ptr;
647
               }
648
1.74M
               else {
649
1.74M
                  auto [ptr, ec] = glz::from_chars<Opts.null_terminated>(it, end, value);
650
1.74M
                  if (ec != std::errc()) [[unlikely]] {
651
1.15k
                     ctx.error = error_code::parse_number_failure;
652
1.15k
                     return;
653
1.15k
                  }
654
1.74M
                  it = ptr;
655
1.74M
               }
656
1.74M
            }
657
1.74M
         }
658
659
         if constexpr (Opts.quoted_num) {
660
            if constexpr (not Opts.null_terminated) {
661
               if (it == end) [[unlikely]] {
662
                  ctx.error = error_code::unexpected_end;
663
                  return;
664
               }
665
            }
666
            if (match<'"'>(ctx, it)) {
667
               return;
668
            }
669
            if constexpr (not Opts.null_terminated) {
670
               if (it == end) {
671
                  ctx.error = error_code::end_reached;
672
                  return;
673
               }
674
            }
675
         }
676
1.74M
         else {
677
1.74M
            if constexpr (not Opts.null_terminated) {
678
1.74M
               if (it == end) {
679
4.72k
                  ctx.error = error_code::end_reached;
680
4.72k
                  return;
681
4.72k
               }
682
1.74M
            }
683
1.74M
         }
684
1.74M
      }
_ZN3glz4fromILj10EmE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj4EEERPKcRmTkNS_10is_contextERNS_7contextES6_EEvOT1_OT2_OT0_OT3_
Line
Count
Source
593
16.7k
      {
594
         if constexpr (Opts.quoted_num) {
595
            if (skip_ws<Opts>(ctx, it, end)) {
596
               return;
597
            }
598
            if (match_invalid_end<'"', Opts>(ctx, it, end)) {
599
               return;
600
            }
601
         }
602
603
         if constexpr (!check_ws_handled(Opts)) {
604
            if (skip_ws<Opts>(ctx, it, end)) {
605
               return;
606
            }
607
         }
608
609
16.7k
         using V = std::decay_t<decltype(value)>;
610
16.7k
         if constexpr (int_t<V>) {
611
16.7k
            static_assert(sizeof(*it) == sizeof(char));
612
613
            if constexpr (Opts.null_terminated) {
614
               if (not glz::atoi(value, it)) [[unlikely]] {
615
                  ctx.error = error_code::parse_number_failure;
616
                  return;
617
               }
618
            }
619
16.7k
            else {
620
16.7k
               if (not glz::atoi(value, it, end)) [[unlikely]] {
621
298
                  ctx.error = error_code::parse_number_failure;
622
298
                  return;
623
298
               }
624
16.7k
            }
625
         }
626
         else {
627
            if constexpr (is_float128<V>) {
628
               auto [ptr, ec] = std::from_chars(it, end, value);
629
               if (ec != std::errc()) {
630
                  ctx.error = error_code::parse_number_failure;
631
                  return;
632
               }
633
               it = ptr;
634
            }
635
            else {
636
               if constexpr (std::is_volatile_v<std::remove_reference_t<decltype(value)>>) {
637
                  // Hardware may interact with value changes, so we parse into a temporary and assign in one
638
                  // place
639
                  V temp;
640
                  auto [ptr, ec] = glz::from_chars<Opts.null_terminated>(it, end, temp);
641
                  if (ec != std::errc()) [[unlikely]] {
642
                     ctx.error = error_code::parse_number_failure;
643
                     return;
644
                  }
645
                  value = temp;
646
                  it = ptr;
647
               }
648
               else {
649
                  auto [ptr, ec] = glz::from_chars<Opts.null_terminated>(it, end, value);
650
                  if (ec != std::errc()) [[unlikely]] {
651
                     ctx.error = error_code::parse_number_failure;
652
                     return;
653
                  }
654
                  it = ptr;
655
               }
656
            }
657
         }
658
659
         if constexpr (Opts.quoted_num) {
660
            if constexpr (not Opts.null_terminated) {
661
               if (it == end) [[unlikely]] {
662
                  ctx.error = error_code::unexpected_end;
663
                  return;
664
               }
665
            }
666
            if (match<'"'>(ctx, it)) {
667
               return;
668
            }
669
            if constexpr (not Opts.null_terminated) {
670
               if (it == end) {
671
                  ctx.error = error_code::end_reached;
672
                  return;
673
               }
674
            }
675
         }
676
16.7k
         else {
677
16.7k
            if constexpr (not Opts.null_terminated) {
678
16.7k
               if (it == end) {
679
201
                  ctx.error = error_code::end_reached;
680
201
                  return;
681
201
               }
682
16.7k
            }
683
16.7k
         }
684
16.7k
      }
_ZN3glz4fromILj10EiE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj4EEERPKcRiTkNS_10is_contextERNS_7contextES6_EEvOT1_OT2_OT0_OT3_
Line
Count
Source
593
8.48k
      {
594
         if constexpr (Opts.quoted_num) {
595
            if (skip_ws<Opts>(ctx, it, end)) {
596
               return;
597
            }
598
            if (match_invalid_end<'"', Opts>(ctx, it, end)) {
599
               return;
600
            }
601
         }
602
603
         if constexpr (!check_ws_handled(Opts)) {
604
            if (skip_ws<Opts>(ctx, it, end)) {
605
               return;
606
            }
607
         }
608
609
8.48k
         using V = std::decay_t<decltype(value)>;
610
8.48k
         if constexpr (int_t<V>) {
611
8.48k
            static_assert(sizeof(*it) == sizeof(char));
612
613
8.48k
            if constexpr (Opts.null_terminated) {
614
8.48k
               if (not glz::atoi(value, it)) [[unlikely]] {
615
226
                  ctx.error = error_code::parse_number_failure;
616
226
                  return;
617
226
               }
618
            }
619
            else {
620
               if (not glz::atoi(value, it, end)) [[unlikely]] {
621
                  ctx.error = error_code::parse_number_failure;
622
                  return;
623
               }
624
            }
625
         }
626
         else {
627
            if constexpr (is_float128<V>) {
628
               auto [ptr, ec] = std::from_chars(it, end, value);
629
               if (ec != std::errc()) {
630
                  ctx.error = error_code::parse_number_failure;
631
                  return;
632
               }
633
               it = ptr;
634
            }
635
            else {
636
               if constexpr (std::is_volatile_v<std::remove_reference_t<decltype(value)>>) {
637
                  // Hardware may interact with value changes, so we parse into a temporary and assign in one
638
                  // place
639
                  V temp;
640
                  auto [ptr, ec] = glz::from_chars<Opts.null_terminated>(it, end, temp);
641
                  if (ec != std::errc()) [[unlikely]] {
642
                     ctx.error = error_code::parse_number_failure;
643
                     return;
644
                  }
645
                  value = temp;
646
                  it = ptr;
647
               }
648
               else {
649
                  auto [ptr, ec] = glz::from_chars<Opts.null_terminated>(it, end, value);
650
                  if (ec != std::errc()) [[unlikely]] {
651
                     ctx.error = error_code::parse_number_failure;
652
                     return;
653
                  }
654
                  it = ptr;
655
               }
656
            }
657
         }
658
659
         if constexpr (Opts.quoted_num) {
660
            if constexpr (not Opts.null_terminated) {
661
               if (it == end) [[unlikely]] {
662
                  ctx.error = error_code::unexpected_end;
663
                  return;
664
               }
665
            }
666
            if (match<'"'>(ctx, it)) {
667
               return;
668
            }
669
            if constexpr (not Opts.null_terminated) {
670
               if (it == end) {
671
                  ctx.error = error_code::end_reached;
672
                  return;
673
               }
674
            }
675
         }
676
8.48k
         else {
677
            if constexpr (not Opts.null_terminated) {
678
               if (it == end) {
679
                  ctx.error = error_code::end_reached;
680
                  return;
681
               }
682
            }
683
8.48k
         }
684
8.48k
      }
_ZN3glz4fromILj10EdE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj4EEERPKcRdTkNS_10is_contextERNS_7contextES6_EEvOT1_OT2_OT0_OT3_
Line
Count
Source
593
1.74M
      {
594
         if constexpr (Opts.quoted_num) {
595
            if (skip_ws<Opts>(ctx, it, end)) {
596
               return;
597
            }
598
            if (match_invalid_end<'"', Opts>(ctx, it, end)) {
599
               return;
600
            }
601
         }
602
603
         if constexpr (!check_ws_handled(Opts)) {
604
            if (skip_ws<Opts>(ctx, it, end)) {
605
               return;
606
            }
607
         }
608
609
1.74M
         using V = std::decay_t<decltype(value)>;
610
         if constexpr (int_t<V>) {
611
            static_assert(sizeof(*it) == sizeof(char));
612
613
            if constexpr (Opts.null_terminated) {
614
               if (not glz::atoi(value, it)) [[unlikely]] {
615
                  ctx.error = error_code::parse_number_failure;
616
                  return;
617
               }
618
            }
619
            else {
620
               if (not glz::atoi(value, it, end)) [[unlikely]] {
621
                  ctx.error = error_code::parse_number_failure;
622
                  return;
623
               }
624
            }
625
         }
626
1.74M
         else {
627
            if constexpr (is_float128<V>) {
628
               auto [ptr, ec] = std::from_chars(it, end, value);
629
               if (ec != std::errc()) {
630
                  ctx.error = error_code::parse_number_failure;
631
                  return;
632
               }
633
               it = ptr;
634
            }
635
1.74M
            else {
636
               if constexpr (std::is_volatile_v<std::remove_reference_t<decltype(value)>>) {
637
                  // Hardware may interact with value changes, so we parse into a temporary and assign in one
638
                  // place
639
                  V temp;
640
                  auto [ptr, ec] = glz::from_chars<Opts.null_terminated>(it, end, temp);
641
                  if (ec != std::errc()) [[unlikely]] {
642
                     ctx.error = error_code::parse_number_failure;
643
                     return;
644
                  }
645
                  value = temp;
646
                  it = ptr;
647
               }
648
1.74M
               else {
649
1.74M
                  auto [ptr, ec] = glz::from_chars<Opts.null_terminated>(it, end, value);
650
1.74M
                  if (ec != std::errc()) [[unlikely]] {
651
1.17k
                     ctx.error = error_code::parse_number_failure;
652
1.17k
                     return;
653
1.17k
                  }
654
1.74M
                  it = ptr;
655
1.74M
               }
656
1.74M
            }
657
1.74M
         }
658
659
         if constexpr (Opts.quoted_num) {
660
            if constexpr (not Opts.null_terminated) {
661
               if (it == end) [[unlikely]] {
662
                  ctx.error = error_code::unexpected_end;
663
                  return;
664
               }
665
            }
666
            if (match<'"'>(ctx, it)) {
667
               return;
668
            }
669
            if constexpr (not Opts.null_terminated) {
670
               if (it == end) {
671
                  ctx.error = error_code::end_reached;
672
                  return;
673
               }
674
            }
675
         }
676
1.74M
         else {
677
            if constexpr (not Opts.null_terminated) {
678
               if (it == end) {
679
                  ctx.error = error_code::end_reached;
680
                  return;
681
               }
682
            }
683
1.74M
         }
684
1.74M
      }
_ZN3glz4fromILj10EmE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj4EEERPKcRmTkNS_10is_contextERNS_7contextES6_EEvOT1_OT2_OT0_OT3_
Line
Count
Source
593
16.7k
      {
594
         if constexpr (Opts.quoted_num) {
595
            if (skip_ws<Opts>(ctx, it, end)) {
596
               return;
597
            }
598
            if (match_invalid_end<'"', Opts>(ctx, it, end)) {
599
               return;
600
            }
601
         }
602
603
         if constexpr (!check_ws_handled(Opts)) {
604
            if (skip_ws<Opts>(ctx, it, end)) {
605
               return;
606
            }
607
         }
608
609
16.7k
         using V = std::decay_t<decltype(value)>;
610
16.7k
         if constexpr (int_t<V>) {
611
16.7k
            static_assert(sizeof(*it) == sizeof(char));
612
613
16.7k
            if constexpr (Opts.null_terminated) {
614
16.7k
               if (not glz::atoi(value, it)) [[unlikely]] {
615
386
                  ctx.error = error_code::parse_number_failure;
616
386
                  return;
617
386
               }
618
            }
619
            else {
620
               if (not glz::atoi(value, it, end)) [[unlikely]] {
621
                  ctx.error = error_code::parse_number_failure;
622
                  return;
623
               }
624
            }
625
         }
626
         else {
627
            if constexpr (is_float128<V>) {
628
               auto [ptr, ec] = std::from_chars(it, end, value);
629
               if (ec != std::errc()) {
630
                  ctx.error = error_code::parse_number_failure;
631
                  return;
632
               }
633
               it = ptr;
634
            }
635
            else {
636
               if constexpr (std::is_volatile_v<std::remove_reference_t<decltype(value)>>) {
637
                  // Hardware may interact with value changes, so we parse into a temporary and assign in one
638
                  // place
639
                  V temp;
640
                  auto [ptr, ec] = glz::from_chars<Opts.null_terminated>(it, end, temp);
641
                  if (ec != std::errc()) [[unlikely]] {
642
                     ctx.error = error_code::parse_number_failure;
643
                     return;
644
                  }
645
                  value = temp;
646
                  it = ptr;
647
               }
648
               else {
649
                  auto [ptr, ec] = glz::from_chars<Opts.null_terminated>(it, end, value);
650
                  if (ec != std::errc()) [[unlikely]] {
651
                     ctx.error = error_code::parse_number_failure;
652
                     return;
653
                  }
654
                  it = ptr;
655
               }
656
            }
657
         }
658
659
         if constexpr (Opts.quoted_num) {
660
            if constexpr (not Opts.null_terminated) {
661
               if (it == end) [[unlikely]] {
662
                  ctx.error = error_code::unexpected_end;
663
                  return;
664
               }
665
            }
666
            if (match<'"'>(ctx, it)) {
667
               return;
668
            }
669
            if constexpr (not Opts.null_terminated) {
670
               if (it == end) {
671
                  ctx.error = error_code::end_reached;
672
                  return;
673
               }
674
            }
675
         }
676
16.7k
         else {
677
            if constexpr (not Opts.null_terminated) {
678
               if (it == end) {
679
                  ctx.error = error_code::end_reached;
680
                  return;
681
               }
682
            }
683
16.7k
         }
684
16.7k
      }
_ZN3glz4fromILj10EiE2opITnDaXtlNS_4optsELj10ELb1ELb1ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj4EEERPKcRiTkNS_10is_contextERNS_7contextES6_EEvOT1_OT2_OT0_OT3_
Line
Count
Source
593
9.67k
      {
594
         if constexpr (Opts.quoted_num) {
595
            if (skip_ws<Opts>(ctx, it, end)) {
596
               return;
597
            }
598
            if (match_invalid_end<'"', Opts>(ctx, it, end)) {
599
               return;
600
            }
601
         }
602
603
         if constexpr (!check_ws_handled(Opts)) {
604
            if (skip_ws<Opts>(ctx, it, end)) {
605
               return;
606
            }
607
         }
608
609
9.67k
         using V = std::decay_t<decltype(value)>;
610
9.67k
         if constexpr (int_t<V>) {
611
9.67k
            static_assert(sizeof(*it) == sizeof(char));
612
613
9.67k
            if constexpr (Opts.null_terminated) {
614
9.67k
               if (not glz::atoi(value, it)) [[unlikely]] {
615
253
                  ctx.error = error_code::parse_number_failure;
616
253
                  return;
617
253
               }
618
            }
619
            else {
620
               if (not glz::atoi(value, it, end)) [[unlikely]] {
621
                  ctx.error = error_code::parse_number_failure;
622
                  return;
623
               }
624
            }
625
         }
626
         else {
627
            if constexpr (is_float128<V>) {
628
               auto [ptr, ec] = std::from_chars(it, end, value);
629
               if (ec != std::errc()) {
630
                  ctx.error = error_code::parse_number_failure;
631
                  return;
632
               }
633
               it = ptr;
634
            }
635
            else {
636
               if constexpr (std::is_volatile_v<std::remove_reference_t<decltype(value)>>) {
637
                  // Hardware may interact with value changes, so we parse into a temporary and assign in one
638
                  // place
639
                  V temp;
640
                  auto [ptr, ec] = glz::from_chars<Opts.null_terminated>(it, end, temp);
641
                  if (ec != std::errc()) [[unlikely]] {
642
                     ctx.error = error_code::parse_number_failure;
643
                     return;
644
                  }
645
                  value = temp;
646
                  it = ptr;
647
               }
648
               else {
649
                  auto [ptr, ec] = glz::from_chars<Opts.null_terminated>(it, end, value);
650
                  if (ec != std::errc()) [[unlikely]] {
651
                     ctx.error = error_code::parse_number_failure;
652
                     return;
653
                  }
654
                  it = ptr;
655
               }
656
            }
657
         }
658
659
         if constexpr (Opts.quoted_num) {
660
            if constexpr (not Opts.null_terminated) {
661
               if (it == end) [[unlikely]] {
662
                  ctx.error = error_code::unexpected_end;
663
                  return;
664
               }
665
            }
666
            if (match<'"'>(ctx, it)) {
667
               return;
668
            }
669
            if constexpr (not Opts.null_terminated) {
670
               if (it == end) {
671
                  ctx.error = error_code::end_reached;
672
                  return;
673
               }
674
            }
675
         }
676
9.67k
         else {
677
            if constexpr (not Opts.null_terminated) {
678
               if (it == end) {
679
                  ctx.error = error_code::end_reached;
680
                  return;
681
               }
682
            }
683
9.67k
         }
684
9.67k
      }
_ZN3glz4fromILj10EdE2opITnDaXtlNS_4optsELj10ELb1ELb1ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj4EEERPKcRdTkNS_10is_contextERNS_7contextES6_EEvOT1_OT2_OT0_OT3_
Line
Count
Source
593
24.0k
      {
594
         if constexpr (Opts.quoted_num) {
595
            if (skip_ws<Opts>(ctx, it, end)) {
596
               return;
597
            }
598
            if (match_invalid_end<'"', Opts>(ctx, it, end)) {
599
               return;
600
            }
601
         }
602
603
         if constexpr (!check_ws_handled(Opts)) {
604
            if (skip_ws<Opts>(ctx, it, end)) {
605
               return;
606
            }
607
         }
608
609
24.0k
         using V = std::decay_t<decltype(value)>;
610
         if constexpr (int_t<V>) {
611
            static_assert(sizeof(*it) == sizeof(char));
612
613
            if constexpr (Opts.null_terminated) {
614
               if (not glz::atoi(value, it)) [[unlikely]] {
615
                  ctx.error = error_code::parse_number_failure;
616
                  return;
617
               }
618
            }
619
            else {
620
               if (not glz::atoi(value, it, end)) [[unlikely]] {
621
                  ctx.error = error_code::parse_number_failure;
622
                  return;
623
               }
624
            }
625
         }
626
24.0k
         else {
627
            if constexpr (is_float128<V>) {
628
               auto [ptr, ec] = std::from_chars(it, end, value);
629
               if (ec != std::errc()) {
630
                  ctx.error = error_code::parse_number_failure;
631
                  return;
632
               }
633
               it = ptr;
634
            }
635
24.0k
            else {
636
               if constexpr (std::is_volatile_v<std::remove_reference_t<decltype(value)>>) {
637
                  // Hardware may interact with value changes, so we parse into a temporary and assign in one
638
                  // place
639
                  V temp;
640
                  auto [ptr, ec] = glz::from_chars<Opts.null_terminated>(it, end, temp);
641
                  if (ec != std::errc()) [[unlikely]] {
642
                     ctx.error = error_code::parse_number_failure;
643
                     return;
644
                  }
645
                  value = temp;
646
                  it = ptr;
647
               }
648
24.0k
               else {
649
24.0k
                  auto [ptr, ec] = glz::from_chars<Opts.null_terminated>(it, end, value);
650
24.0k
                  if (ec != std::errc()) [[unlikely]] {
651
376
                     ctx.error = error_code::parse_number_failure;
652
376
                     return;
653
376
                  }
654
23.7k
                  it = ptr;
655
23.7k
               }
656
24.0k
            }
657
24.0k
         }
658
659
         if constexpr (Opts.quoted_num) {
660
            if constexpr (not Opts.null_terminated) {
661
               if (it == end) [[unlikely]] {
662
                  ctx.error = error_code::unexpected_end;
663
                  return;
664
               }
665
            }
666
            if (match<'"'>(ctx, it)) {
667
               return;
668
            }
669
            if constexpr (not Opts.null_terminated) {
670
               if (it == end) {
671
                  ctx.error = error_code::end_reached;
672
                  return;
673
               }
674
            }
675
         }
676
24.0k
         else {
677
            if constexpr (not Opts.null_terminated) {
678
               if (it == end) {
679
                  ctx.error = error_code::end_reached;
680
                  return;
681
               }
682
            }
683
24.0k
         }
684
24.0k
      }
_ZN3glz4fromILj10EmE2opITnDaXtlNS_4optsELj10ELb1ELb1ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj4EEERPKcRmTkNS_10is_contextERNS_7contextES6_EEvOT1_OT2_OT0_OT3_
Line
Count
Source
593
17.6k
      {
594
         if constexpr (Opts.quoted_num) {
595
            if (skip_ws<Opts>(ctx, it, end)) {
596
               return;
597
            }
598
            if (match_invalid_end<'"', Opts>(ctx, it, end)) {
599
               return;
600
            }
601
         }
602
603
         if constexpr (!check_ws_handled(Opts)) {
604
            if (skip_ws<Opts>(ctx, it, end)) {
605
               return;
606
            }
607
         }
608
609
17.6k
         using V = std::decay_t<decltype(value)>;
610
17.6k
         if constexpr (int_t<V>) {
611
17.6k
            static_assert(sizeof(*it) == sizeof(char));
612
613
17.6k
            if constexpr (Opts.null_terminated) {
614
17.6k
               if (not glz::atoi(value, it)) [[unlikely]] {
615
468
                  ctx.error = error_code::parse_number_failure;
616
468
                  return;
617
468
               }
618
            }
619
            else {
620
               if (not glz::atoi(value, it, end)) [[unlikely]] {
621
                  ctx.error = error_code::parse_number_failure;
622
                  return;
623
               }
624
            }
625
         }
626
         else {
627
            if constexpr (is_float128<V>) {
628
               auto [ptr, ec] = std::from_chars(it, end, value);
629
               if (ec != std::errc()) {
630
                  ctx.error = error_code::parse_number_failure;
631
                  return;
632
               }
633
               it = ptr;
634
            }
635
            else {
636
               if constexpr (std::is_volatile_v<std::remove_reference_t<decltype(value)>>) {
637
                  // Hardware may interact with value changes, so we parse into a temporary and assign in one
638
                  // place
639
                  V temp;
640
                  auto [ptr, ec] = glz::from_chars<Opts.null_terminated>(it, end, temp);
641
                  if (ec != std::errc()) [[unlikely]] {
642
                     ctx.error = error_code::parse_number_failure;
643
                     return;
644
                  }
645
                  value = temp;
646
                  it = ptr;
647
               }
648
               else {
649
                  auto [ptr, ec] = glz::from_chars<Opts.null_terminated>(it, end, value);
650
                  if (ec != std::errc()) [[unlikely]] {
651
                     ctx.error = error_code::parse_number_failure;
652
                     return;
653
                  }
654
                  it = ptr;
655
               }
656
            }
657
         }
658
659
         if constexpr (Opts.quoted_num) {
660
            if constexpr (not Opts.null_terminated) {
661
               if (it == end) [[unlikely]] {
662
                  ctx.error = error_code::unexpected_end;
663
                  return;
664
               }
665
            }
666
            if (match<'"'>(ctx, it)) {
667
               return;
668
            }
669
            if constexpr (not Opts.null_terminated) {
670
               if (it == end) {
671
                  ctx.error = error_code::end_reached;
672
                  return;
673
               }
674
            }
675
         }
676
17.6k
         else {
677
            if constexpr (not Opts.null_terminated) {
678
               if (it == end) {
679
                  ctx.error = error_code::end_reached;
680
                  return;
681
               }
682
            }
683
17.6k
         }
684
17.6k
      }
_ZN3glz4fromILj10EfE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj36EEERPKcRfTkNS_10is_contextERNS_7contextES6_EEvOT1_OT2_OT0_OT3_
Line
Count
Source
593
488
      {
594
         if constexpr (Opts.quoted_num) {
595
            if (skip_ws<Opts>(ctx, it, end)) {
596
               return;
597
            }
598
            if (match_invalid_end<'"', Opts>(ctx, it, end)) {
599
               return;
600
            }
601
         }
602
603
         if constexpr (!check_ws_handled(Opts)) {
604
            if (skip_ws<Opts>(ctx, it, end)) {
605
               return;
606
            }
607
         }
608
609
488
         using V = std::decay_t<decltype(value)>;
610
         if constexpr (int_t<V>) {
611
            static_assert(sizeof(*it) == sizeof(char));
612
613
            if constexpr (Opts.null_terminated) {
614
               if (not glz::atoi(value, it)) [[unlikely]] {
615
                  ctx.error = error_code::parse_number_failure;
616
                  return;
617
               }
618
            }
619
            else {
620
               if (not glz::atoi(value, it, end)) [[unlikely]] {
621
                  ctx.error = error_code::parse_number_failure;
622
                  return;
623
               }
624
            }
625
         }
626
488
         else {
627
            if constexpr (is_float128<V>) {
628
               auto [ptr, ec] = std::from_chars(it, end, value);
629
               if (ec != std::errc()) {
630
                  ctx.error = error_code::parse_number_failure;
631
                  return;
632
               }
633
               it = ptr;
634
            }
635
488
            else {
636
               if constexpr (std::is_volatile_v<std::remove_reference_t<decltype(value)>>) {
637
                  // Hardware may interact with value changes, so we parse into a temporary and assign in one
638
                  // place
639
                  V temp;
640
                  auto [ptr, ec] = glz::from_chars<Opts.null_terminated>(it, end, temp);
641
                  if (ec != std::errc()) [[unlikely]] {
642
                     ctx.error = error_code::parse_number_failure;
643
                     return;
644
                  }
645
                  value = temp;
646
                  it = ptr;
647
               }
648
488
               else {
649
488
                  auto [ptr, ec] = glz::from_chars<Opts.null_terminated>(it, end, value);
650
488
                  if (ec != std::errc()) [[unlikely]] {
651
0
                     ctx.error = error_code::parse_number_failure;
652
0
                     return;
653
0
                  }
654
488
                  it = ptr;
655
488
               }
656
488
            }
657
488
         }
658
659
         if constexpr (Opts.quoted_num) {
660
            if constexpr (not Opts.null_terminated) {
661
               if (it == end) [[unlikely]] {
662
                  ctx.error = error_code::unexpected_end;
663
                  return;
664
               }
665
            }
666
            if (match<'"'>(ctx, it)) {
667
               return;
668
            }
669
            if constexpr (not Opts.null_terminated) {
670
               if (it == end) {
671
                  ctx.error = error_code::end_reached;
672
                  return;
673
               }
674
            }
675
         }
676
488
         else {
677
            if constexpr (not Opts.null_terminated) {
678
               if (it == end) {
679
                  ctx.error = error_code::end_reached;
680
                  return;
681
               }
682
            }
683
488
         }
684
488
      }
_ZN3glz4fromILj10EdE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj36EEERPKcRdTkNS_10is_contextERNS_7contextES6_EEvOT1_OT2_OT0_OT3_
Line
Count
Source
593
1.73M
      {
594
         if constexpr (Opts.quoted_num) {
595
            if (skip_ws<Opts>(ctx, it, end)) {
596
               return;
597
            }
598
            if (match_invalid_end<'"', Opts>(ctx, it, end)) {
599
               return;
600
            }
601
         }
602
603
         if constexpr (!check_ws_handled(Opts)) {
604
            if (skip_ws<Opts>(ctx, it, end)) {
605
               return;
606
            }
607
         }
608
609
1.73M
         using V = std::decay_t<decltype(value)>;
610
         if constexpr (int_t<V>) {
611
            static_assert(sizeof(*it) == sizeof(char));
612
613
            if constexpr (Opts.null_terminated) {
614
               if (not glz::atoi(value, it)) [[unlikely]] {
615
                  ctx.error = error_code::parse_number_failure;
616
                  return;
617
               }
618
            }
619
            else {
620
               if (not glz::atoi(value, it, end)) [[unlikely]] {
621
                  ctx.error = error_code::parse_number_failure;
622
                  return;
623
               }
624
            }
625
         }
626
1.73M
         else {
627
            if constexpr (is_float128<V>) {
628
               auto [ptr, ec] = std::from_chars(it, end, value);
629
               if (ec != std::errc()) {
630
                  ctx.error = error_code::parse_number_failure;
631
                  return;
632
               }
633
               it = ptr;
634
            }
635
1.73M
            else {
636
               if constexpr (std::is_volatile_v<std::remove_reference_t<decltype(value)>>) {
637
                  // Hardware may interact with value changes, so we parse into a temporary and assign in one
638
                  // place
639
                  V temp;
640
                  auto [ptr, ec] = glz::from_chars<Opts.null_terminated>(it, end, temp);
641
                  if (ec != std::errc()) [[unlikely]] {
642
                     ctx.error = error_code::parse_number_failure;
643
                     return;
644
                  }
645
                  value = temp;
646
                  it = ptr;
647
               }
648
1.73M
               else {
649
1.73M
                  auto [ptr, ec] = glz::from_chars<Opts.null_terminated>(it, end, value);
650
1.73M
                  if (ec != std::errc()) [[unlikely]] {
651
853
                     ctx.error = error_code::parse_number_failure;
652
853
                     return;
653
853
                  }
654
1.73M
                  it = ptr;
655
1.73M
               }
656
1.73M
            }
657
1.73M
         }
658
659
         if constexpr (Opts.quoted_num) {
660
            if constexpr (not Opts.null_terminated) {
661
               if (it == end) [[unlikely]] {
662
                  ctx.error = error_code::unexpected_end;
663
                  return;
664
               }
665
            }
666
            if (match<'"'>(ctx, it)) {
667
               return;
668
            }
669
            if constexpr (not Opts.null_terminated) {
670
               if (it == end) {
671
                  ctx.error = error_code::end_reached;
672
                  return;
673
               }
674
            }
675
         }
676
1.73M
         else {
677
            if constexpr (not Opts.null_terminated) {
678
               if (it == end) {
679
                  ctx.error = error_code::end_reached;
680
                  return;
681
               }
682
            }
683
1.73M
         }
684
1.73M
      }
_ZN3glz4fromILj10EsE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj36EEERPKcRsTkNS_10is_contextERNS_7contextES6_EEvOT1_OT2_OT0_OT3_
Line
Count
Source
593
106
      {
594
         if constexpr (Opts.quoted_num) {
595
            if (skip_ws<Opts>(ctx, it, end)) {
596
               return;
597
            }
598
            if (match_invalid_end<'"', Opts>(ctx, it, end)) {
599
               return;
600
            }
601
         }
602
603
         if constexpr (!check_ws_handled(Opts)) {
604
            if (skip_ws<Opts>(ctx, it, end)) {
605
               return;
606
            }
607
         }
608
609
106
         using V = std::decay_t<decltype(value)>;
610
106
         if constexpr (int_t<V>) {
611
106
            static_assert(sizeof(*it) == sizeof(char));
612
613
106
            if constexpr (Opts.null_terminated) {
614
106
               if (not glz::atoi(value, it)) [[unlikely]] {
615
0
                  ctx.error = error_code::parse_number_failure;
616
0
                  return;
617
0
               }
618
            }
619
            else {
620
               if (not glz::atoi(value, it, end)) [[unlikely]] {
621
                  ctx.error = error_code::parse_number_failure;
622
                  return;
623
               }
624
            }
625
         }
626
         else {
627
            if constexpr (is_float128<V>) {
628
               auto [ptr, ec] = std::from_chars(it, end, value);
629
               if (ec != std::errc()) {
630
                  ctx.error = error_code::parse_number_failure;
631
                  return;
632
               }
633
               it = ptr;
634
            }
635
            else {
636
               if constexpr (std::is_volatile_v<std::remove_reference_t<decltype(value)>>) {
637
                  // Hardware may interact with value changes, so we parse into a temporary and assign in one
638
                  // place
639
                  V temp;
640
                  auto [ptr, ec] = glz::from_chars<Opts.null_terminated>(it, end, temp);
641
                  if (ec != std::errc()) [[unlikely]] {
642
                     ctx.error = error_code::parse_number_failure;
643
                     return;
644
                  }
645
                  value = temp;
646
                  it = ptr;
647
               }
648
               else {
649
                  auto [ptr, ec] = glz::from_chars<Opts.null_terminated>(it, end, value);
650
                  if (ec != std::errc()) [[unlikely]] {
651
                     ctx.error = error_code::parse_number_failure;
652
                     return;
653
                  }
654
                  it = ptr;
655
               }
656
            }
657
         }
658
659
         if constexpr (Opts.quoted_num) {
660
            if constexpr (not Opts.null_terminated) {
661
               if (it == end) [[unlikely]] {
662
                  ctx.error = error_code::unexpected_end;
663
                  return;
664
               }
665
            }
666
            if (match<'"'>(ctx, it)) {
667
               return;
668
            }
669
            if constexpr (not Opts.null_terminated) {
670
               if (it == end) {
671
                  ctx.error = error_code::end_reached;
672
                  return;
673
               }
674
            }
675
         }
676
106
         else {
677
            if constexpr (not Opts.null_terminated) {
678
               if (it == end) {
679
                  ctx.error = error_code::end_reached;
680
                  return;
681
               }
682
            }
683
106
         }
684
106
      }
_ZN3glz4fromILj10EtE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj36EEERPKcRtTkNS_10is_contextERNS_7contextES6_EEvOT1_OT2_OT0_OT3_
Line
Count
Source
593
106
      {
594
         if constexpr (Opts.quoted_num) {
595
            if (skip_ws<Opts>(ctx, it, end)) {
596
               return;
597
            }
598
            if (match_invalid_end<'"', Opts>(ctx, it, end)) {
599
               return;
600
            }
601
         }
602
603
         if constexpr (!check_ws_handled(Opts)) {
604
            if (skip_ws<Opts>(ctx, it, end)) {
605
               return;
606
            }
607
         }
608
609
106
         using V = std::decay_t<decltype(value)>;
610
106
         if constexpr (int_t<V>) {
611
106
            static_assert(sizeof(*it) == sizeof(char));
612
613
106
            if constexpr (Opts.null_terminated) {
614
106
               if (not glz::atoi(value, it)) [[unlikely]] {
615
0
                  ctx.error = error_code::parse_number_failure;
616
0
                  return;
617
0
               }
618
            }
619
            else {
620
               if (not glz::atoi(value, it, end)) [[unlikely]] {
621
                  ctx.error = error_code::parse_number_failure;
622
                  return;
623
               }
624
            }
625
         }
626
         else {
627
            if constexpr (is_float128<V>) {
628
               auto [ptr, ec] = std::from_chars(it, end, value);
629
               if (ec != std::errc()) {
630
                  ctx.error = error_code::parse_number_failure;
631
                  return;
632
               }
633
               it = ptr;
634
            }
635
            else {
636
               if constexpr (std::is_volatile_v<std::remove_reference_t<decltype(value)>>) {
637
                  // Hardware may interact with value changes, so we parse into a temporary and assign in one
638
                  // place
639
                  V temp;
640
                  auto [ptr, ec] = glz::from_chars<Opts.null_terminated>(it, end, temp);
641
                  if (ec != std::errc()) [[unlikely]] {
642
                     ctx.error = error_code::parse_number_failure;
643
                     return;
644
                  }
645
                  value = temp;
646
                  it = ptr;
647
               }
648
               else {
649
                  auto [ptr, ec] = glz::from_chars<Opts.null_terminated>(it, end, value);
650
                  if (ec != std::errc()) [[unlikely]] {
651
                     ctx.error = error_code::parse_number_failure;
652
                     return;
653
                  }
654
                  it = ptr;
655
               }
656
            }
657
         }
658
659
         if constexpr (Opts.quoted_num) {
660
            if constexpr (not Opts.null_terminated) {
661
               if (it == end) [[unlikely]] {
662
                  ctx.error = error_code::unexpected_end;
663
                  return;
664
               }
665
            }
666
            if (match<'"'>(ctx, it)) {
667
               return;
668
            }
669
            if constexpr (not Opts.null_terminated) {
670
               if (it == end) {
671
                  ctx.error = error_code::end_reached;
672
                  return;
673
               }
674
            }
675
         }
676
106
         else {
677
            if constexpr (not Opts.null_terminated) {
678
               if (it == end) {
679
                  ctx.error = error_code::end_reached;
680
                  return;
681
               }
682
            }
683
106
         }
684
106
      }
_ZN3glz4fromILj10EiE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj36EEERPKcRiTkNS_10is_contextERNS_7contextES6_EEvOT1_OT2_OT0_OT3_
Line
Count
Source
593
169
      {
594
         if constexpr (Opts.quoted_num) {
595
            if (skip_ws<Opts>(ctx, it, end)) {
596
               return;
597
            }
598
            if (match_invalid_end<'"', Opts>(ctx, it, end)) {
599
               return;
600
            }
601
         }
602
603
         if constexpr (!check_ws_handled(Opts)) {
604
            if (skip_ws<Opts>(ctx, it, end)) {
605
               return;
606
            }
607
         }
608
609
169
         using V = std::decay_t<decltype(value)>;
610
169
         if constexpr (int_t<V>) {
611
169
            static_assert(sizeof(*it) == sizeof(char));
612
613
169
            if constexpr (Opts.null_terminated) {
614
169
               if (not glz::atoi(value, it)) [[unlikely]] {
615
0
                  ctx.error = error_code::parse_number_failure;
616
0
                  return;
617
0
               }
618
            }
619
            else {
620
               if (not glz::atoi(value, it, end)) [[unlikely]] {
621
                  ctx.error = error_code::parse_number_failure;
622
                  return;
623
               }
624
            }
625
         }
626
         else {
627
            if constexpr (is_float128<V>) {
628
               auto [ptr, ec] = std::from_chars(it, end, value);
629
               if (ec != std::errc()) {
630
                  ctx.error = error_code::parse_number_failure;
631
                  return;
632
               }
633
               it = ptr;
634
            }
635
            else {
636
               if constexpr (std::is_volatile_v<std::remove_reference_t<decltype(value)>>) {
637
                  // Hardware may interact with value changes, so we parse into a temporary and assign in one
638
                  // place
639
                  V temp;
640
                  auto [ptr, ec] = glz::from_chars<Opts.null_terminated>(it, end, temp);
641
                  if (ec != std::errc()) [[unlikely]] {
642
                     ctx.error = error_code::parse_number_failure;
643
                     return;
644
                  }
645
                  value = temp;
646
                  it = ptr;
647
               }
648
               else {
649
                  auto [ptr, ec] = glz::from_chars<Opts.null_terminated>(it, end, value);
650
                  if (ec != std::errc()) [[unlikely]] {
651
                     ctx.error = error_code::parse_number_failure;
652
                     return;
653
                  }
654
                  it = ptr;
655
               }
656
            }
657
         }
658
659
         if constexpr (Opts.quoted_num) {
660
            if constexpr (not Opts.null_terminated) {
661
               if (it == end) [[unlikely]] {
662
                  ctx.error = error_code::unexpected_end;
663
                  return;
664
               }
665
            }
666
            if (match<'"'>(ctx, it)) {
667
               return;
668
            }
669
            if constexpr (not Opts.null_terminated) {
670
               if (it == end) {
671
                  ctx.error = error_code::end_reached;
672
                  return;
673
               }
674
            }
675
         }
676
169
         else {
677
            if constexpr (not Opts.null_terminated) {
678
               if (it == end) {
679
                  ctx.error = error_code::end_reached;
680
                  return;
681
               }
682
            }
683
169
         }
684
169
      }
_ZN3glz4fromILj10EjE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj36EEERPKcRjTkNS_10is_contextERNS_7contextES6_EEvOT1_OT2_OT0_OT3_
Line
Count
Source
593
169
      {
594
         if constexpr (Opts.quoted_num) {
595
            if (skip_ws<Opts>(ctx, it, end)) {
596
               return;
597
            }
598
            if (match_invalid_end<'"', Opts>(ctx, it, end)) {
599
               return;
600
            }
601
         }
602
603
         if constexpr (!check_ws_handled(Opts)) {
604
            if (skip_ws<Opts>(ctx, it, end)) {
605
               return;
606
            }
607
         }
608
609
169
         using V = std::decay_t<decltype(value)>;
610
169
         if constexpr (int_t<V>) {
611
169
            static_assert(sizeof(*it) == sizeof(char));
612
613
169
            if constexpr (Opts.null_terminated) {
614
169
               if (not glz::atoi(value, it)) [[unlikely]] {
615
0
                  ctx.error = error_code::parse_number_failure;
616
0
                  return;
617
0
               }
618
            }
619
            else {
620
               if (not glz::atoi(value, it, end)) [[unlikely]] {
621
                  ctx.error = error_code::parse_number_failure;
622
                  return;
623
               }
624
            }
625
         }
626
         else {
627
            if constexpr (is_float128<V>) {
628
               auto [ptr, ec] = std::from_chars(it, end, value);
629
               if (ec != std::errc()) {
630
                  ctx.error = error_code::parse_number_failure;
631
                  return;
632
               }
633
               it = ptr;
634
            }
635
            else {
636
               if constexpr (std::is_volatile_v<std::remove_reference_t<decltype(value)>>) {
637
                  // Hardware may interact with value changes, so we parse into a temporary and assign in one
638
                  // place
639
                  V temp;
640
                  auto [ptr, ec] = glz::from_chars<Opts.null_terminated>(it, end, temp);
641
                  if (ec != std::errc()) [[unlikely]] {
642
                     ctx.error = error_code::parse_number_failure;
643
                     return;
644
                  }
645
                  value = temp;
646
                  it = ptr;
647
               }
648
               else {
649
                  auto [ptr, ec] = glz::from_chars<Opts.null_terminated>(it, end, value);
650
                  if (ec != std::errc()) [[unlikely]] {
651
                     ctx.error = error_code::parse_number_failure;
652
                     return;
653
                  }
654
                  it = ptr;
655
               }
656
            }
657
         }
658
659
         if constexpr (Opts.quoted_num) {
660
            if constexpr (not Opts.null_terminated) {
661
               if (it == end) [[unlikely]] {
662
                  ctx.error = error_code::unexpected_end;
663
                  return;
664
               }
665
            }
666
            if (match<'"'>(ctx, it)) {
667
               return;
668
            }
669
            if constexpr (not Opts.null_terminated) {
670
               if (it == end) {
671
                  ctx.error = error_code::end_reached;
672
                  return;
673
               }
674
            }
675
         }
676
169
         else {
677
            if constexpr (not Opts.null_terminated) {
678
               if (it == end) {
679
                  ctx.error = error_code::end_reached;
680
                  return;
681
               }
682
            }
683
169
         }
684
169
      }
_ZN3glz4fromILj10ElE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj36EEERPKcRlTkNS_10is_contextERNS_7contextES6_EEvOT1_OT2_OT0_OT3_
Line
Count
Source
593
296
      {
594
         if constexpr (Opts.quoted_num) {
595
            if (skip_ws<Opts>(ctx, it, end)) {
596
               return;
597
            }
598
            if (match_invalid_end<'"', Opts>(ctx, it, end)) {
599
               return;
600
            }
601
         }
602
603
         if constexpr (!check_ws_handled(Opts)) {
604
            if (skip_ws<Opts>(ctx, it, end)) {
605
               return;
606
            }
607
         }
608
609
296
         using V = std::decay_t<decltype(value)>;
610
296
         if constexpr (int_t<V>) {
611
296
            static_assert(sizeof(*it) == sizeof(char));
612
613
296
            if constexpr (Opts.null_terminated) {
614
296
               if (not glz::atoi(value, it)) [[unlikely]] {
615
0
                  ctx.error = error_code::parse_number_failure;
616
0
                  return;
617
0
               }
618
            }
619
            else {
620
               if (not glz::atoi(value, it, end)) [[unlikely]] {
621
                  ctx.error = error_code::parse_number_failure;
622
                  return;
623
               }
624
            }
625
         }
626
         else {
627
            if constexpr (is_float128<V>) {
628
               auto [ptr, ec] = std::from_chars(it, end, value);
629
               if (ec != std::errc()) {
630
                  ctx.error = error_code::parse_number_failure;
631
                  return;
632
               }
633
               it = ptr;
634
            }
635
            else {
636
               if constexpr (std::is_volatile_v<std::remove_reference_t<decltype(value)>>) {
637
                  // Hardware may interact with value changes, so we parse into a temporary and assign in one
638
                  // place
639
                  V temp;
640
                  auto [ptr, ec] = glz::from_chars<Opts.null_terminated>(it, end, temp);
641
                  if (ec != std::errc()) [[unlikely]] {
642
                     ctx.error = error_code::parse_number_failure;
643
                     return;
644
                  }
645
                  value = temp;
646
                  it = ptr;
647
               }
648
               else {
649
                  auto [ptr, ec] = glz::from_chars<Opts.null_terminated>(it, end, value);
650
                  if (ec != std::errc()) [[unlikely]] {
651
                     ctx.error = error_code::parse_number_failure;
652
                     return;
653
                  }
654
                  it = ptr;
655
               }
656
            }
657
         }
658
659
         if constexpr (Opts.quoted_num) {
660
            if constexpr (not Opts.null_terminated) {
661
               if (it == end) [[unlikely]] {
662
                  ctx.error = error_code::unexpected_end;
663
                  return;
664
               }
665
            }
666
            if (match<'"'>(ctx, it)) {
667
               return;
668
            }
669
            if constexpr (not Opts.null_terminated) {
670
               if (it == end) {
671
                  ctx.error = error_code::end_reached;
672
                  return;
673
               }
674
            }
675
         }
676
296
         else {
677
            if constexpr (not Opts.null_terminated) {
678
               if (it == end) {
679
                  ctx.error = error_code::end_reached;
680
                  return;
681
               }
682
            }
683
296
         }
684
296
      }
_ZN3glz4fromILj10EmE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj36EEERPKcRmTkNS_10is_contextERNS_7contextES6_EEvOT1_OT2_OT0_OT3_
Line
Count
Source
593
296
      {
594
         if constexpr (Opts.quoted_num) {
595
            if (skip_ws<Opts>(ctx, it, end)) {
596
               return;
597
            }
598
            if (match_invalid_end<'"', Opts>(ctx, it, end)) {
599
               return;
600
            }
601
         }
602
603
         if constexpr (!check_ws_handled(Opts)) {
604
            if (skip_ws<Opts>(ctx, it, end)) {
605
               return;
606
            }
607
         }
608
609
296
         using V = std::decay_t<decltype(value)>;
610
296
         if constexpr (int_t<V>) {
611
296
            static_assert(sizeof(*it) == sizeof(char));
612
613
296
            if constexpr (Opts.null_terminated) {
614
296
               if (not glz::atoi(value, it)) [[unlikely]] {
615
0
                  ctx.error = error_code::parse_number_failure;
616
0
                  return;
617
0
               }
618
            }
619
            else {
620
               if (not glz::atoi(value, it, end)) [[unlikely]] {
621
                  ctx.error = error_code::parse_number_failure;
622
                  return;
623
               }
624
            }
625
         }
626
         else {
627
            if constexpr (is_float128<V>) {
628
               auto [ptr, ec] = std::from_chars(it, end, value);
629
               if (ec != std::errc()) {
630
                  ctx.error = error_code::parse_number_failure;
631
                  return;
632
               }
633
               it = ptr;
634
            }
635
            else {
636
               if constexpr (std::is_volatile_v<std::remove_reference_t<decltype(value)>>) {
637
                  // Hardware may interact with value changes, so we parse into a temporary and assign in one
638
                  // place
639
                  V temp;
640
                  auto [ptr, ec] = glz::from_chars<Opts.null_terminated>(it, end, temp);
641
                  if (ec != std::errc()) [[unlikely]] {
642
                     ctx.error = error_code::parse_number_failure;
643
                     return;
644
                  }
645
                  value = temp;
646
                  it = ptr;
647
               }
648
               else {
649
                  auto [ptr, ec] = glz::from_chars<Opts.null_terminated>(it, end, value);
650
                  if (ec != std::errc()) [[unlikely]] {
651
                     ctx.error = error_code::parse_number_failure;
652
                     return;
653
                  }
654
                  it = ptr;
655
               }
656
            }
657
         }
658
659
         if constexpr (Opts.quoted_num) {
660
            if constexpr (not Opts.null_terminated) {
661
               if (it == end) [[unlikely]] {
662
                  ctx.error = error_code::unexpected_end;
663
                  return;
664
               }
665
            }
666
            if (match<'"'>(ctx, it)) {
667
               return;
668
            }
669
            if constexpr (not Opts.null_terminated) {
670
               if (it == end) {
671
                  ctx.error = error_code::end_reached;
672
                  return;
673
               }
674
            }
675
         }
676
296
         else {
677
            if constexpr (not Opts.null_terminated) {
678
               if (it == end) {
679
                  ctx.error = error_code::end_reached;
680
                  return;
681
               }
682
            }
683
296
         }
684
296
      }
_ZN3glz4fromILj10ExE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj36EEERPKcRxTkNS_10is_contextERNS_7contextES6_EEvOT1_OT2_OT0_OT3_
Line
Count
Source
593
290
      {
594
         if constexpr (Opts.quoted_num) {
595
            if (skip_ws<Opts>(ctx, it, end)) {
596
               return;
597
            }
598
            if (match_invalid_end<'"', Opts>(ctx, it, end)) {
599
               return;
600
            }
601
         }
602
603
         if constexpr (!check_ws_handled(Opts)) {
604
            if (skip_ws<Opts>(ctx, it, end)) {
605
               return;
606
            }
607
         }
608
609
290
         using V = std::decay_t<decltype(value)>;
610
290
         if constexpr (int_t<V>) {
611
290
            static_assert(sizeof(*it) == sizeof(char));
612
613
290
            if constexpr (Opts.null_terminated) {
614
290
               if (not glz::atoi(value, it)) [[unlikely]] {
615
0
                  ctx.error = error_code::parse_number_failure;
616
0
                  return;
617
0
               }
618
            }
619
            else {
620
               if (not glz::atoi(value, it, end)) [[unlikely]] {
621
                  ctx.error = error_code::parse_number_failure;
622
                  return;
623
               }
624
            }
625
         }
626
         else {
627
            if constexpr (is_float128<V>) {
628
               auto [ptr, ec] = std::from_chars(it, end, value);
629
               if (ec != std::errc()) {
630
                  ctx.error = error_code::parse_number_failure;
631
                  return;
632
               }
633
               it = ptr;
634
            }
635
            else {
636
               if constexpr (std::is_volatile_v<std::remove_reference_t<decltype(value)>>) {
637
                  // Hardware may interact with value changes, so we parse into a temporary and assign in one
638
                  // place
639
                  V temp;
640
                  auto [ptr, ec] = glz::from_chars<Opts.null_terminated>(it, end, temp);
641
                  if (ec != std::errc()) [[unlikely]] {
642
                     ctx.error = error_code::parse_number_failure;
643
                     return;
644
                  }
645
                  value = temp;
646
                  it = ptr;
647
               }
648
               else {
649
                  auto [ptr, ec] = glz::from_chars<Opts.null_terminated>(it, end, value);
650
                  if (ec != std::errc()) [[unlikely]] {
651
                     ctx.error = error_code::parse_number_failure;
652
                     return;
653
                  }
654
                  it = ptr;
655
               }
656
            }
657
         }
658
659
         if constexpr (Opts.quoted_num) {
660
            if constexpr (not Opts.null_terminated) {
661
               if (it == end) [[unlikely]] {
662
                  ctx.error = error_code::unexpected_end;
663
                  return;
664
               }
665
            }
666
            if (match<'"'>(ctx, it)) {
667
               return;
668
            }
669
            if constexpr (not Opts.null_terminated) {
670
               if (it == end) {
671
                  ctx.error = error_code::end_reached;
672
                  return;
673
               }
674
            }
675
         }
676
290
         else {
677
            if constexpr (not Opts.null_terminated) {
678
               if (it == end) {
679
                  ctx.error = error_code::end_reached;
680
                  return;
681
               }
682
            }
683
290
         }
684
290
      }
_ZN3glz4fromILj10EyE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj36EEERPKcRyTkNS_10is_contextERNS_7contextES6_EEvOT1_OT2_OT0_OT3_
Line
Count
Source
593
290
      {
594
         if constexpr (Opts.quoted_num) {
595
            if (skip_ws<Opts>(ctx, it, end)) {
596
               return;
597
            }
598
            if (match_invalid_end<'"', Opts>(ctx, it, end)) {
599
               return;
600
            }
601
         }
602
603
         if constexpr (!check_ws_handled(Opts)) {
604
            if (skip_ws<Opts>(ctx, it, end)) {
605
               return;
606
            }
607
         }
608
609
290
         using V = std::decay_t<decltype(value)>;
610
290
         if constexpr (int_t<V>) {
611
290
            static_assert(sizeof(*it) == sizeof(char));
612
613
290
            if constexpr (Opts.null_terminated) {
614
290
               if (not glz::atoi(value, it)) [[unlikely]] {
615
0
                  ctx.error = error_code::parse_number_failure;
616
0
                  return;
617
0
               }
618
            }
619
            else {
620
               if (not glz::atoi(value, it, end)) [[unlikely]] {
621
                  ctx.error = error_code::parse_number_failure;
622
                  return;
623
               }
624
            }
625
         }
626
         else {
627
            if constexpr (is_float128<V>) {
628
               auto [ptr, ec] = std::from_chars(it, end, value);
629
               if (ec != std::errc()) {
630
                  ctx.error = error_code::parse_number_failure;
631
                  return;
632
               }
633
               it = ptr;
634
            }
635
            else {
636
               if constexpr (std::is_volatile_v<std::remove_reference_t<decltype(value)>>) {
637
                  // Hardware may interact with value changes, so we parse into a temporary and assign in one
638
                  // place
639
                  V temp;
640
                  auto [ptr, ec] = glz::from_chars<Opts.null_terminated>(it, end, temp);
641
                  if (ec != std::errc()) [[unlikely]] {
642
                     ctx.error = error_code::parse_number_failure;
643
                     return;
644
                  }
645
                  value = temp;
646
                  it = ptr;
647
               }
648
               else {
649
                  auto [ptr, ec] = glz::from_chars<Opts.null_terminated>(it, end, value);
650
                  if (ec != std::errc()) [[unlikely]] {
651
                     ctx.error = error_code::parse_number_failure;
652
                     return;
653
                  }
654
                  it = ptr;
655
               }
656
            }
657
         }
658
659
         if constexpr (Opts.quoted_num) {
660
            if constexpr (not Opts.null_terminated) {
661
               if (it == end) [[unlikely]] {
662
                  ctx.error = error_code::unexpected_end;
663
                  return;
664
               }
665
            }
666
            if (match<'"'>(ctx, it)) {
667
               return;
668
            }
669
            if constexpr (not Opts.null_terminated) {
670
               if (it == end) {
671
                  ctx.error = error_code::end_reached;
672
                  return;
673
               }
674
            }
675
         }
676
290
         else {
677
            if constexpr (not Opts.null_terminated) {
678
               if (it == end) {
679
                  ctx.error = error_code::end_reached;
680
                  return;
681
               }
682
            }
683
290
         }
684
290
      }
685
   };
686
687
   template <string_t T>
688
   struct from<JSON, T>
689
   {
690
      template <auto Opts, class It, class End>
691
         requires(check_is_padded(Opts))
692
      static void op(auto& value, is_context auto&& ctx, It&& it, End&& end)
693
45.6k
      {
694
         if constexpr (Opts.number) {
695
            auto start = it;
696
            skip_number<Opts>(ctx, it, end);
697
            if (bool(ctx.error)) [[unlikely]] {
698
               return;
699
            }
700
            value.append(start, size_t(it - start));
701
         }
702
45.6k
         else {
703
45.6k
            if constexpr (!check_opening_handled(Opts)) {
704
45.6k
               if constexpr (!check_ws_handled(Opts)) {
705
40.7k
                  if (skip_ws<Opts>(ctx, it, end)) {
706
0
                     return;
707
0
                  }
708
40.7k
               }
709
710
45.6k
               if (match_invalid_end<'"', Opts>(ctx, it, end)) {
711
141
                  return;
712
141
               }
713
45.6k
            }
714
715
45.6k
            if constexpr (not Opts.raw_string) {
716
45.6k
               static constexpr auto string_padding_bytes = 8;
717
718
45.6k
               auto start = it;
719
14.8M
               while (true) {
720
14.8M
                  if (it >= end) [[unlikely]] {
721
269
                     ctx.error = error_code::unexpected_end;
722
269
                     return;
723
269
                  }
724
725
14.8M
                  uint64_t chunk;
726
14.8M
                  std::memcpy(&chunk, it, 8);
727
14.8M
                  const uint64_t test_chars = has_quote(chunk);
728
14.8M
                  if (test_chars) {
729
1.18M
                     it += (countr_zero(test_chars) >> 3);
730
731
1.18M
                     auto* prev = it - 1;
732
2.35M
                     while (*prev == '\\') {
733
1.17M
                        --prev;
734
1.17M
                     }
735
1.18M
                     if (size_t(it - prev) % 2) {
736
45.2k
                        break;
737
45.2k
                     }
738
1.13M
                     ++it; // skip the escaped quote
739
1.13M
                  }
740
13.7M
                  else {
741
13.7M
                     it += 8;
742
13.7M
                  }
743
14.8M
               }
744
745
45.3k
               auto n = size_t(it - start);
746
45.3k
               value.resize(n + string_padding_bytes);
747
748
45.3k
               auto* p = value.data();
749
750
35.1M
               while (true) {
751
35.1M
                  if (start >= it) {
752
43.1k
                     break;
753
43.1k
                  }
754
755
35.0M
                  std::memcpy(p, start, 8);
756
35.0M
                  uint64_t swar;
757
35.0M
                  std::memcpy(&swar, p, 8);
758
759
35.0M
                  constexpr uint64_t lo7_mask = repeat_byte8(0b01111111);
760
35.0M
                  const uint64_t lo7 = swar & lo7_mask;
761
35.0M
                  const uint64_t backslash = (lo7 ^ repeat_byte8('\\')) + lo7_mask;
762
35.0M
                  const uint64_t less_32 = (swar & repeat_byte8(0b01100000)) + lo7_mask;
763
35.0M
                  uint64_t next = ~((backslash & less_32) | swar);
764
765
35.0M
                  next &= repeat_byte8(0b10000000);
766
35.0M
                  if (next == 0) {
767
3.99M
                     start += 8;
768
3.99M
                     p += 8;
769
3.99M
                     continue;
770
3.99M
                  }
771
772
31.0M
                  next = countr_zero(next) >> 3;
773
31.0M
                  start += next;
774
31.0M
                  if (start >= it) {
775
1.73k
                     break;
776
1.73k
                  }
777
778
31.0M
                  if ((*start & 0b11100000) == 0) [[unlikely]] {
779
280
                     ctx.error = error_code::syntax_error;
780
280
                     return;
781
280
                  }
782
31.0M
                  ++start; // skip the escape
783
31.0M
                  if (*start == 'u') {
784
488k
                     ++start;
785
488k
                     p += next;
786
488k
                     const auto mark = start;
787
488k
                     const auto offset = handle_unicode_code_point(start, p, end);
788
488k
                     if (offset == 0) [[unlikely]] {
789
53
                        ctx.error = error_code::unicode_escape_conversion_failure;
790
53
                        return;
791
53
                     }
792
488k
                     n += offset;
793
                     // escape + u + unicode code points
794
488k
                     n -= 2 + uint32_t(start - mark);
795
488k
                  }
796
30.5M
                  else {
797
30.5M
                     p += next;
798
30.5M
                     *p = char_unescape_table[uint8_t(*start)];
799
30.5M
                     if (*p == 0) [[unlikely]] {
800
35
                        ctx.error = error_code::invalid_escape;
801
35
                        return;
802
35
                     }
803
30.5M
                     ++p;
804
30.5M
                     ++start;
805
30.5M
                     --n;
806
30.5M
                  }
807
31.0M
               }
808
809
44.9k
               value.resize(n);
810
44.9k
               ++it;
811
            }
812
            else {
813
               // raw_string
814
               auto start = it;
815
               skip_string_view<Opts>(ctx, it, end);
816
               if (bool(ctx.error)) [[unlikely]]
817
                  return;
818
819
               value.assign(start, size_t(it - start));
820
               ++it;
821
            }
822
45.6k
         }
823
45.6k
      }
_ZN3glz4fromILj10ENSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj36EEERPKcSD_S7_TkNS_10is_contextERNS_7contextEQcl15check_is_paddedTL0__EEEvRT2_OT3_OT0_OT1_
Line
Count
Source
693
4.88k
      {
694
         if constexpr (Opts.number) {
695
            auto start = it;
696
            skip_number<Opts>(ctx, it, end);
697
            if (bool(ctx.error)) [[unlikely]] {
698
               return;
699
            }
700
            value.append(start, size_t(it - start));
701
         }
702
4.88k
         else {
703
4.88k
            if constexpr (!check_opening_handled(Opts)) {
704
               if constexpr (!check_ws_handled(Opts)) {
705
                  if (skip_ws<Opts>(ctx, it, end)) {
706
                     return;
707
                  }
708
               }
709
710
4.88k
               if (match_invalid_end<'"', Opts>(ctx, it, end)) {
711
0
                  return;
712
0
               }
713
4.88k
            }
714
715
4.88k
            if constexpr (not Opts.raw_string) {
716
4.88k
               static constexpr auto string_padding_bytes = 8;
717
718
4.88k
               auto start = it;
719
12.3M
               while (true) {
720
12.3M
                  if (it >= end) [[unlikely]] {
721
167
                     ctx.error = error_code::unexpected_end;
722
167
                     return;
723
167
                  }
724
725
12.3M
                  uint64_t chunk;
726
12.3M
                  std::memcpy(&chunk, it, 8);
727
12.3M
                  const uint64_t test_chars = has_quote(chunk);
728
12.3M
                  if (test_chars) {
729
1.14M
                     it += (countr_zero(test_chars) >> 3);
730
731
1.14M
                     auto* prev = it - 1;
732
2.31M
                     while (*prev == '\\') {
733
1.16M
                        --prev;
734
1.16M
                     }
735
1.14M
                     if (size_t(it - prev) % 2) {
736
4.71k
                        break;
737
4.71k
                     }
738
1.13M
                     ++it; // skip the escaped quote
739
1.13M
                  }
740
11.2M
                  else {
741
11.2M
                     it += 8;
742
11.2M
                  }
743
12.3M
               }
744
745
4.71k
               auto n = size_t(it - start);
746
4.71k
               value.resize(n + string_padding_bytes);
747
748
4.71k
               auto* p = value.data();
749
750
33.8M
               while (true) {
751
33.8M
                  if (start >= it) {
752
4.00k
                     break;
753
4.00k
                  }
754
755
33.8M
                  std::memcpy(p, start, 8);
756
33.8M
                  uint64_t swar;
757
33.8M
                  std::memcpy(&swar, p, 8);
758
759
33.8M
                  constexpr uint64_t lo7_mask = repeat_byte8(0b01111111);
760
33.8M
                  const uint64_t lo7 = swar & lo7_mask;
761
33.8M
                  const uint64_t backslash = (lo7 ^ repeat_byte8('\\')) + lo7_mask;
762
33.8M
                  const uint64_t less_32 = (swar & repeat_byte8(0b01100000)) + lo7_mask;
763
33.8M
                  uint64_t next = ~((backslash & less_32) | swar);
764
765
33.8M
                  next &= repeat_byte8(0b10000000);
766
33.8M
                  if (next == 0) {
767
3.04M
                     start += 8;
768
3.04M
                     p += 8;
769
3.04M
                     continue;
770
3.04M
                  }
771
772
30.7M
                  next = countr_zero(next) >> 3;
773
30.7M
                  start += next;
774
30.7M
                  if (start >= it) {
775
529
                     break;
776
529
                  }
777
778
30.7M
                  if ((*start & 0b11100000) == 0) [[unlikely]] {
779
113
                     ctx.error = error_code::syntax_error;
780
113
                     return;
781
113
                  }
782
30.7M
                  ++start; // skip the escape
783
30.7M
                  if (*start == 'u') {
784
255k
                     ++start;
785
255k
                     p += next;
786
255k
                     const auto mark = start;
787
255k
                     const auto offset = handle_unicode_code_point(start, p, end);
788
255k
                     if (offset == 0) [[unlikely]] {
789
46
                        ctx.error = error_code::unicode_escape_conversion_failure;
790
46
                        return;
791
46
                     }
792
255k
                     n += offset;
793
                     // escape + u + unicode code points
794
255k
                     n -= 2 + uint32_t(start - mark);
795
255k
                  }
796
30.5M
                  else {
797
30.5M
                     p += next;
798
30.5M
                     *p = char_unescape_table[uint8_t(*start)];
799
30.5M
                     if (*p == 0) [[unlikely]] {
800
20
                        ctx.error = error_code::invalid_escape;
801
20
                        return;
802
20
                     }
803
30.5M
                     ++p;
804
30.5M
                     ++start;
805
30.5M
                     --n;
806
30.5M
                  }
807
30.7M
               }
808
809
4.53k
               value.resize(n);
810
4.53k
               ++it;
811
            }
812
            else {
813
               // raw_string
814
               auto start = it;
815
               skip_string_view<Opts>(ctx, it, end);
816
               if (bool(ctx.error)) [[unlikely]]
817
                  return;
818
819
               value.assign(start, size_t(it - start));
820
               ++it;
821
            }
822
4.88k
         }
823
4.88k
      }
_ZN3glz4fromILj10ENSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEERPKcSD_S7_TkNS_10is_contextERNS_7contextEQcl15check_is_paddedTL0__EEEvRT2_OT3_OT0_OT1_
Line
Count
Source
693
40.7k
      {
694
         if constexpr (Opts.number) {
695
            auto start = it;
696
            skip_number<Opts>(ctx, it, end);
697
            if (bool(ctx.error)) [[unlikely]] {
698
               return;
699
            }
700
            value.append(start, size_t(it - start));
701
         }
702
40.7k
         else {
703
40.7k
            if constexpr (!check_opening_handled(Opts)) {
704
40.7k
               if constexpr (!check_ws_handled(Opts)) {
705
40.7k
                  if (skip_ws<Opts>(ctx, it, end)) {
706
0
                     return;
707
0
                  }
708
40.7k
               }
709
710
40.7k
               if (match_invalid_end<'"', Opts>(ctx, it, end)) {
711
141
                  return;
712
141
               }
713
40.7k
            }
714
715
40.7k
            if constexpr (not Opts.raw_string) {
716
40.7k
               static constexpr auto string_padding_bytes = 8;
717
718
40.7k
               auto start = it;
719
2.53M
               while (true) {
720
2.53M
                  if (it >= end) [[unlikely]] {
721
102
                     ctx.error = error_code::unexpected_end;
722
102
                     return;
723
102
                  }
724
725
2.53M
                  uint64_t chunk;
726
2.53M
                  std::memcpy(&chunk, it, 8);
727
2.53M
                  const uint64_t test_chars = has_quote(chunk);
728
2.53M
                  if (test_chars) {
729
41.3k
                     it += (countr_zero(test_chars) >> 3);
730
731
41.3k
                     auto* prev = it - 1;
732
43.9k
                     while (*prev == '\\') {
733
2.65k
                        --prev;
734
2.65k
                     }
735
41.3k
                     if (size_t(it - prev) % 2) {
736
40.4k
                        break;
737
40.4k
                     }
738
845
                     ++it; // skip the escaped quote
739
845
                  }
740
2.49M
                  else {
741
2.49M
                     it += 8;
742
2.49M
                  }
743
2.53M
               }
744
745
40.6k
               auto n = size_t(it - start);
746
40.6k
               value.resize(n + string_padding_bytes);
747
748
40.6k
               auto* p = value.data();
749
750
1.29M
               while (true) {
751
1.29M
                  if (start >= it) {
752
39.0k
                     break;
753
39.0k
                  }
754
755
1.25M
                  std::memcpy(p, start, 8);
756
1.25M
                  uint64_t swar;
757
1.25M
                  std::memcpy(&swar, p, 8);
758
759
1.25M
                  constexpr uint64_t lo7_mask = repeat_byte8(0b01111111);
760
1.25M
                  const uint64_t lo7 = swar & lo7_mask;
761
1.25M
                  const uint64_t backslash = (lo7 ^ repeat_byte8('\\')) + lo7_mask;
762
1.25M
                  const uint64_t less_32 = (swar & repeat_byte8(0b01100000)) + lo7_mask;
763
1.25M
                  uint64_t next = ~((backslash & less_32) | swar);
764
765
1.25M
                  next &= repeat_byte8(0b10000000);
766
1.25M
                  if (next == 0) {
767
952k
                     start += 8;
768
952k
                     p += 8;
769
952k
                     continue;
770
952k
                  }
771
772
303k
                  next = countr_zero(next) >> 3;
773
303k
                  start += next;
774
303k
                  if (start >= it) {
775
1.20k
                     break;
776
1.20k
                  }
777
778
302k
                  if ((*start & 0b11100000) == 0) [[unlikely]] {
779
167
                     ctx.error = error_code::syntax_error;
780
167
                     return;
781
167
                  }
782
302k
                  ++start; // skip the escape
783
302k
                  if (*start == 'u') {
784
233k
                     ++start;
785
233k
                     p += next;
786
233k
                     const auto mark = start;
787
233k
                     const auto offset = handle_unicode_code_point(start, p, end);
788
233k
                     if (offset == 0) [[unlikely]] {
789
7
                        ctx.error = error_code::unicode_escape_conversion_failure;
790
7
                        return;
791
7
                     }
792
233k
                     n += offset;
793
                     // escape + u + unicode code points
794
233k
                     n -= 2 + uint32_t(start - mark);
795
233k
                  }
796
68.8k
                  else {
797
68.8k
                     p += next;
798
68.8k
                     *p = char_unescape_table[uint8_t(*start)];
799
68.8k
                     if (*p == 0) [[unlikely]] {
800
15
                        ctx.error = error_code::invalid_escape;
801
15
                        return;
802
15
                     }
803
68.8k
                     ++p;
804
68.8k
                     ++start;
805
68.8k
                     --n;
806
68.8k
                  }
807
302k
               }
808
809
40.4k
               value.resize(n);
810
40.4k
               ++it;
811
            }
812
            else {
813
               // raw_string
814
               auto start = it;
815
               skip_string_view<Opts>(ctx, it, end);
816
               if (bool(ctx.error)) [[unlikely]]
817
                  return;
818
819
               value.assign(start, size_t(it - start));
820
               ++it;
821
            }
822
40.7k
         }
823
40.7k
      }
824
825
      template <auto Opts, class It, class End>
826
         requires(not check_is_padded(Opts))
827
      static void op(auto& value, is_context auto&& ctx, It&& it, End&& end)
828
90.3k
      {
829
         if constexpr (Opts.number) {
830
            auto start = it;
831
            skip_number<Opts>(ctx, it, end);
832
            if (bool(ctx.error)) [[unlikely]] {
833
               return;
834
            }
835
            if (start == it) [[unlikely]] {
836
               ctx.error = error_code::parse_number_failure;
837
               return;
838
            }
839
            value.append(start, size_t(it - start));
840
         }
841
90.3k
         else {
842
90.3k
            if constexpr (!check_opening_handled(Opts)) {
843
90.3k
               if constexpr (!check_ws_handled(Opts)) {
844
81.3k
                  if (skip_ws<Opts>(ctx, it, end)) {
845
0
                     return;
846
0
                  }
847
81.3k
               }
848
849
90.3k
               if (match_invalid_end<'"', Opts>(ctx, it, end)) {
850
249
                  return;
851
249
               }
852
90.3k
            }
853
854
90.3k
            if constexpr (not Opts.raw_string) {
855
90.3k
               static constexpr auto string_padding_bytes = 8;
856
857
90.3k
               if (size_t(end - it) >= 8) {
858
88.1k
                  auto start = it;
859
88.1k
                  const auto end8 = end - 8;
860
7.54M
                  while (true) {
861
7.54M
                     if (it >= end8) [[unlikely]] {
862
1.10k
                        break;
863
1.10k
                     }
864
865
7.54M
                     uint64_t chunk;
866
7.54M
                     std::memcpy(&chunk, it, 8);
867
7.54M
                     const uint64_t test_chars = has_quote(chunk);
868
7.54M
                     if (test_chars) {
869
91.6k
                        it += (countr_zero(test_chars) >> 3);
870
871
91.6k
                        auto* prev = it - 1;
872
101k
                        while (*prev == '\\') {
873
9.49k
                           --prev;
874
9.49k
                        }
875
91.6k
                        if (size_t(it - prev) % 2) {
876
87.0k
                           goto continue_decode;
877
87.0k
                        }
878
4.59k
                        ++it; // skip the escaped quote
879
4.59k
                     }
880
7.45M
                     else {
881
7.45M
                        it += 8;
882
7.45M
                     }
883
7.54M
                  }
884
885
5.79k
                  while (it[-1] == '\\') [[unlikely]] {
886
                     // if we ended on an escape character then we need to rewind
887
                     // because we lost our context
888
4.69k
                     --it;
889
4.69k
                  }
890
891
8.59k
                  for (; it < end; ++it) {
892
8.40k
                     if (*it == '"') {
893
1.12k
                        auto* prev = it - 1;
894
3.64k
                        while (*prev == '\\') {
895
2.51k
                           --prev;
896
2.51k
                        }
897
1.12k
                        if (size_t(it - prev) % 2) {
898
913
                           goto continue_decode;
899
913
                        }
900
1.12k
                     }
901
8.40k
                  }
902
903
189
                  ctx.error = error_code::unexpected_end;
904
189
                  return;
905
906
87.9k
               continue_decode:
907
908
87.9k
                  const auto available_padding = size_t(end - it);
909
87.9k
                  auto n = size_t(it - start);
910
87.9k
                  if (available_padding >= 8) [[likely]] {
911
87.0k
                     value.resize(n + string_padding_bytes);
912
913
87.0k
                     auto* p = value.data();
914
915
3.50M
                     while (true) {
916
3.50M
                        if (start >= it) {
917
84.1k
                           break;
918
84.1k
                        }
919
920
3.42M
                        std::memcpy(p, start, 8);
921
3.42M
                        uint64_t swar;
922
3.42M
                        std::memcpy(&swar, p, 8);
923
924
3.42M
                        constexpr uint64_t lo7_mask = repeat_byte8(0b01111111);
925
3.42M
                        const uint64_t lo7 = swar & lo7_mask;
926
3.42M
                        const uint64_t backslash = (lo7 ^ repeat_byte8('\\')) + lo7_mask;
927
3.42M
                        const uint64_t less_32 = (swar & repeat_byte8(0b01100000)) + lo7_mask;
928
3.42M
                        uint64_t next = ~((backslash & less_32) | swar);
929
930
3.42M
                        next &= repeat_byte8(0b10000000);
931
3.42M
                        if (next == 0) {
932
2.28M
                           start += 8;
933
2.28M
                           p += 8;
934
2.28M
                           continue;
935
2.28M
                        }
936
937
1.13M
                        next = countr_zero(next) >> 3;
938
1.13M
                        start += next;
939
1.13M
                        if (start >= it) {
940
2.71k
                           break;
941
2.71k
                        }
942
943
1.13M
                        if ((*start & 0b11100000) == 0) [[unlikely]] {
944
107
                           ctx.error = error_code::syntax_error;
945
107
                           return;
946
107
                        }
947
1.13M
                        ++start; // skip the escape
948
1.13M
                        if (*start == 'u') {
949
914k
                           ++start;
950
914k
                           p += next;
951
914k
                           const auto mark = start;
952
914k
                           const auto offset = handle_unicode_code_point(start, p, end);
953
914k
                           if (offset == 0) [[unlikely]] {
954
16
                              ctx.error = error_code::unicode_escape_conversion_failure;
955
16
                              return;
956
16
                           }
957
914k
                           n += offset;
958
                           // escape + u + unicode code points
959
914k
                           n -= 2 + uint32_t(start - mark);
960
914k
                        }
961
220k
                        else {
962
220k
                           p += next;
963
220k
                           *p = char_unescape_table[uint8_t(*start)];
964
220k
                           if (*p == 0) [[unlikely]] {
965
25
                              ctx.error = error_code::invalid_escape;
966
25
                              return;
967
25
                           }
968
220k
                           ++p;
969
220k
                           ++start;
970
220k
                           --n;
971
220k
                        }
972
1.13M
                     }
973
974
86.8k
                     value.resize(n);
975
86.8k
                     ++it;
976
86.8k
                  }
977
936
                  else {
978
                     // For large inputs this case of running out of buffer is very rare
979
936
                     value.resize(n);
980
936
                     auto* p = value.data();
981
982
936
                     it = start;
983
28.0M
                     while (it < end) [[likely]] {
984
28.0M
                        if (*it == '"') {
985
811
                           value.resize(size_t(p - value.data()));
986
811
                           ++it;
987
811
                           return;
988
811
                        }
989
990
28.0M
                        *p = *it;
991
992
28.0M
                        if (*it == '\\') {
993
72.2k
                           ++it; // skip the escape
994
72.2k
                           if (*it == 'u') {
995
65.6k
                              ++it;
996
65.6k
                              if (!handle_unicode_code_point(it, p, end)) [[unlikely]] {
997
85
                                 ctx.error = error_code::unicode_escape_conversion_failure;
998
85
                                 return;
999
85
                              }
1000
65.6k
                           }
1001
6.53k
                           else {
1002
6.53k
                              *p = char_unescape_table[uint8_t(*it)];
1003
6.53k
                              if (*p == 0) [[unlikely]] {
1004
40
                                 ctx.error = error_code::invalid_escape;
1005
40
                                 return;
1006
40
                              }
1007
6.49k
                              ++p;
1008
6.49k
                              ++it;
1009
6.49k
                           }
1010
72.2k
                        }
1011
27.9M
                        else {
1012
27.9M
                           ++it;
1013
27.9M
                           ++p;
1014
27.9M
                        }
1015
28.0M
                     }
1016
1017
0
                     ctx.error = error_code::unexpected_end;
1018
0
                  }
1019
87.9k
               }
1020
2.20k
               else {
1021
                  // For short strings
1022
1023
2.20k
                  std::array<char, 8> buffer{};
1024
1025
2.20k
                  auto* p = buffer.data();
1026
1027
3.67k
                  while (it < end) [[likely]] {
1028
3.17k
                     *p = *it;
1029
3.17k
                     if (*it == '"') {
1030
1.62k
                        value.assign(buffer.data(), size_t(p - buffer.data()));
1031
1.62k
                        ++it;
1032
1.62k
                        if constexpr (not Opts.null_terminated) {
1033
883
                           if (it == end) {
1034
103
                              ctx.error = error_code::end_reached;
1035
103
                              return;
1036
103
                           }
1037
883
                        }
1038
780
                        return;
1039
1.62k
                     }
1040
1.54k
                     else if (*it == '\\') {
1041
251
                        ++it; // skip the escape
1042
251
                        if constexpr (not Opts.null_terminated) {
1043
145
                           if (it == end) [[unlikely]] {
1044
5
                              ctx.error = error_code::unexpected_end;
1045
5
                              return;
1046
5
                           }
1047
145
                        }
1048
251
                        if (*it == 'u') {
1049
79
                           ++it;
1050
79
                           if constexpr (not Opts.null_terminated) {
1051
46
                              if (it == end) [[unlikely]] {
1052
2
                                 ctx.error = error_code::unexpected_end;
1053
2
                                 return;
1054
2
                              }
1055
46
                           }
1056
79
                           if (!handle_unicode_code_point(it, p, end)) [[unlikely]] {
1057
42
                              ctx.error = error_code::unicode_escape_conversion_failure;
1058
42
                              return;
1059
42
                           }
1060
79
                        }
1061
172
                        else {
1062
172
                           *p = char_unescape_table[uint8_t(*it)];
1063
172
                           if (*p == 0) [[unlikely]] {
1064
34
                              ctx.error = error_code::invalid_escape;
1065
34
                              return;
1066
34
                           }
1067
138
                           ++p;
1068
138
                           ++it;
1069
138
                        }
1070
251
                     }
1071
1.29k
                     else {
1072
1.29k
                        ++it;
1073
1.29k
                        ++p;
1074
1.29k
                     }
1075
3.17k
                  }
1076
1077
499
                  ctx.error = error_code::unexpected_end;
1078
499
               }
1079
            }
1080
            else {
1081
               // raw_string
1082
               auto start = it;
1083
               skip_string_view<Opts>(ctx, it, end);
1084
               if (bool(ctx.error)) [[unlikely]]
1085
                  return;
1086
1087
               value.assign(start, size_t(it - start));
1088
               ++it;
1089
            }
1090
90.3k
         }
1091
90.3k
      }
_ZN3glz4fromILj10ENSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj4EEERPKcSD_S7_TkNS_10is_contextERNS_7contextEQntcl15check_is_paddedTL0__EEEvRT2_OT3_OT0_OT1_
Line
Count
Source
828
4.47k
      {
829
         if constexpr (Opts.number) {
830
            auto start = it;
831
            skip_number<Opts>(ctx, it, end);
832
            if (bool(ctx.error)) [[unlikely]] {
833
               return;
834
            }
835
            if (start == it) [[unlikely]] {
836
               ctx.error = error_code::parse_number_failure;
837
               return;
838
            }
839
            value.append(start, size_t(it - start));
840
         }
841
4.47k
         else {
842
4.47k
            if constexpr (!check_opening_handled(Opts)) {
843
               if constexpr (!check_ws_handled(Opts)) {
844
                  if (skip_ws<Opts>(ctx, it, end)) {
845
                     return;
846
                  }
847
               }
848
849
4.47k
               if (match_invalid_end<'"', Opts>(ctx, it, end)) {
850
41
                  return;
851
41
               }
852
4.47k
            }
853
854
4.47k
            if constexpr (not Opts.raw_string) {
855
4.47k
               static constexpr auto string_padding_bytes = 8;
856
857
4.47k
               if (size_t(end - it) >= 8) {
858
4.11k
                  auto start = it;
859
4.11k
                  const auto end8 = end - 8;
860
1.23M
                  while (true) {
861
1.23M
                     if (it >= end8) [[unlikely]] {
862
288
                        break;
863
288
                     }
864
865
1.23M
                     uint64_t chunk;
866
1.23M
                     std::memcpy(&chunk, it, 8);
867
1.23M
                     const uint64_t test_chars = has_quote(chunk);
868
1.23M
                     if (test_chars) {
869
5.33k
                        it += (countr_zero(test_chars) >> 3);
870
871
5.33k
                        auto* prev = it - 1;
872
7.84k
                        while (*prev == '\\') {
873
2.51k
                           --prev;
874
2.51k
                        }
875
5.33k
                        if (size_t(it - prev) % 2) {
876
3.82k
                           goto continue_decode;
877
3.82k
                        }
878
1.50k
                        ++it; // skip the escaped quote
879
1.50k
                     }
880
1.23M
                     else {
881
1.23M
                        it += 8;
882
1.23M
                     }
883
1.23M
                  }
884
885
1.72k
                  while (it[-1] == '\\') [[unlikely]] {
886
                     // if we ended on an escape character then we need to rewind
887
                     // because we lost our context
888
1.44k
                     --it;
889
1.44k
                  }
890
891
2.59k
                  for (; it < end; ++it) {
892
2.54k
                     if (*it == '"') {
893
304
                        auto* prev = it - 1;
894
1.17k
                        while (*prev == '\\') {
895
866
                           --prev;
896
866
                        }
897
304
                        if (size_t(it - prev) % 2) {
898
240
                           goto continue_decode;
899
240
                        }
900
304
                     }
901
2.54k
                  }
902
903
48
                  ctx.error = error_code::unexpected_end;
904
48
                  return;
905
906
4.06k
               continue_decode:
907
908
4.06k
                  const auto available_padding = size_t(end - it);
909
4.06k
                  auto n = size_t(it - start);
910
4.06k
                  if (available_padding >= 8) [[likely]] {
911
3.84k
                     value.resize(n + string_padding_bytes);
912
913
3.84k
                     auto* p = value.data();
914
915
554k
                     while (true) {
916
554k
                        if (start >= it) {
917
3.39k
                           break;
918
3.39k
                        }
919
920
551k
                        std::memcpy(p, start, 8);
921
551k
                        uint64_t swar;
922
551k
                        std::memcpy(&swar, p, 8);
923
924
551k
                        constexpr uint64_t lo7_mask = repeat_byte8(0b01111111);
925
551k
                        const uint64_t lo7 = swar & lo7_mask;
926
551k
                        const uint64_t backslash = (lo7 ^ repeat_byte8('\\')) + lo7_mask;
927
551k
                        const uint64_t less_32 = (swar & repeat_byte8(0b01100000)) + lo7_mask;
928
551k
                        uint64_t next = ~((backslash & less_32) | swar);
929
930
551k
                        next &= repeat_byte8(0b10000000);
931
551k
                        if (next == 0) {
932
283k
                           start += 8;
933
283k
                           p += 8;
934
283k
                           continue;
935
283k
                        }
936
937
268k
                        next = countr_zero(next) >> 3;
938
268k
                        start += next;
939
268k
                        if (start >= it) {
940
414
                           break;
941
414
                        }
942
943
267k
                        if ((*start & 0b11100000) == 0) [[unlikely]] {
944
24
                           ctx.error = error_code::syntax_error;
945
24
                           return;
946
24
                        }
947
267k
                        ++start; // skip the escape
948
267k
                        if (*start == 'u') {
949
225k
                           ++start;
950
225k
                           p += next;
951
225k
                           const auto mark = start;
952
225k
                           const auto offset = handle_unicode_code_point(start, p, end);
953
225k
                           if (offset == 0) [[unlikely]] {
954
3
                              ctx.error = error_code::unicode_escape_conversion_failure;
955
3
                              return;
956
3
                           }
957
225k
                           n += offset;
958
                           // escape + u + unicode code points
959
225k
                           n -= 2 + uint32_t(start - mark);
960
225k
                        }
961
41.9k
                        else {
962
41.9k
                           p += next;
963
41.9k
                           *p = char_unescape_table[uint8_t(*start)];
964
41.9k
                           if (*p == 0) [[unlikely]] {
965
8
                              ctx.error = error_code::invalid_escape;
966
8
                              return;
967
8
                           }
968
41.9k
                           ++p;
969
41.9k
                           ++start;
970
41.9k
                           --n;
971
41.9k
                        }
972
267k
                     }
973
974
3.80k
                     value.resize(n);
975
3.80k
                     ++it;
976
3.80k
                  }
977
227
                  else {
978
                     // For large inputs this case of running out of buffer is very rare
979
227
                     value.resize(n);
980
227
                     auto* p = value.data();
981
982
227
                     it = start;
983
2.73M
                     while (it < end) [[likely]] {
984
2.73M
                        if (*it == '"') {
985
173
                           value.resize(size_t(p - value.data()));
986
173
                           ++it;
987
173
                           return;
988
173
                        }
989
990
2.73M
                        *p = *it;
991
992
2.73M
                        if (*it == '\\') {
993
33.6k
                           ++it; // skip the escape
994
33.6k
                           if (*it == 'u') {
995
30.9k
                              ++it;
996
30.9k
                              if (!handle_unicode_code_point(it, p, end)) [[unlikely]] {
997
41
                                 ctx.error = error_code::unicode_escape_conversion_failure;
998
41
                                 return;
999
41
                              }
1000
30.9k
                           }
1001
2.75k
                           else {
1002
2.75k
                              *p = char_unescape_table[uint8_t(*it)];
1003
2.75k
                              if (*p == 0) [[unlikely]] {
1004
13
                                 ctx.error = error_code::invalid_escape;
1005
13
                                 return;
1006
13
                              }
1007
2.74k
                              ++p;
1008
2.74k
                              ++it;
1009
2.74k
                           }
1010
33.6k
                        }
1011
2.69M
                        else {
1012
2.69M
                           ++it;
1013
2.69M
                           ++p;
1014
2.69M
                        }
1015
2.73M
                     }
1016
1017
0
                     ctx.error = error_code::unexpected_end;
1018
0
                  }
1019
4.06k
               }
1020
364
               else {
1021
                  // For short strings
1022
1023
364
                  std::array<char, 8> buffer{};
1024
1025
364
                  auto* p = buffer.data();
1026
1027
585
                  while (it < end) [[likely]] {
1028
497
                     *p = *it;
1029
497
                     if (*it == '"') {
1030
235
                        value.assign(buffer.data(), size_t(p - buffer.data()));
1031
235
                        ++it;
1032
235
                        if constexpr (not Opts.null_terminated) {
1033
235
                           if (it == end) {
1034
63
                              ctx.error = error_code::end_reached;
1035
63
                              return;
1036
63
                           }
1037
235
                        }
1038
172
                        return;
1039
235
                     }
1040
262
                     else if (*it == '\\') {
1041
95
                        ++it; // skip the escape
1042
95
                        if constexpr (not Opts.null_terminated) {
1043
95
                           if (it == end) [[unlikely]] {
1044
4
                              ctx.error = error_code::unexpected_end;
1045
4
                              return;
1046
4
                           }
1047
95
                        }
1048
95
                        if (*it == 'u') {
1049
39
                           ++it;
1050
39
                           if constexpr (not Opts.null_terminated) {
1051
39
                              if (it == end) [[unlikely]] {
1052
1
                                 ctx.error = error_code::unexpected_end;
1053
1
                                 return;
1054
1
                              }
1055
39
                           }
1056
39
                           if (!handle_unicode_code_point(it, p, end)) [[unlikely]] {
1057
32
                              ctx.error = error_code::unicode_escape_conversion_failure;
1058
32
                              return;
1059
32
                           }
1060
39
                        }
1061
56
                        else {
1062
56
                           *p = char_unescape_table[uint8_t(*it)];
1063
56
                           if (*p == 0) [[unlikely]] {
1064
9
                              ctx.error = error_code::invalid_escape;
1065
9
                              return;
1066
9
                           }
1067
47
                           ++p;
1068
47
                           ++it;
1069
47
                        }
1070
95
                     }
1071
167
                     else {
1072
167
                        ++it;
1073
167
                        ++p;
1074
167
                     }
1075
497
                  }
1076
1077
88
                  ctx.error = error_code::unexpected_end;
1078
88
               }
1079
            }
1080
            else {
1081
               // raw_string
1082
               auto start = it;
1083
               skip_string_view<Opts>(ctx, it, end);
1084
               if (bool(ctx.error)) [[unlikely]]
1085
                  return;
1086
1087
               value.assign(start, size_t(it - start));
1088
               ++it;
1089
            }
1090
4.47k
         }
1091
4.47k
      }
_ZN3glz4fromILj10ENSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj4EEERPKcSD_S7_TkNS_10is_contextERNS_7contextEQntcl15check_is_paddedTL0__EEEvRT2_OT3_OT0_OT1_
Line
Count
Source
828
4.47k
      {
829
         if constexpr (Opts.number) {
830
            auto start = it;
831
            skip_number<Opts>(ctx, it, end);
832
            if (bool(ctx.error)) [[unlikely]] {
833
               return;
834
            }
835
            if (start == it) [[unlikely]] {
836
               ctx.error = error_code::parse_number_failure;
837
               return;
838
            }
839
            value.append(start, size_t(it - start));
840
         }
841
4.47k
         else {
842
4.47k
            if constexpr (!check_opening_handled(Opts)) {
843
               if constexpr (!check_ws_handled(Opts)) {
844
                  if (skip_ws<Opts>(ctx, it, end)) {
845
                     return;
846
                  }
847
               }
848
849
4.47k
               if (match_invalid_end<'"', Opts>(ctx, it, end)) {
850
0
                  return;
851
0
               }
852
4.47k
            }
853
854
4.47k
            if constexpr (not Opts.raw_string) {
855
4.47k
               static constexpr auto string_padding_bytes = 8;
856
857
4.47k
               if (size_t(end - it) >= 8) {
858
4.18k
                  auto start = it;
859
4.18k
                  const auto end8 = end - 8;
860
1.23M
                  while (true) {
861
1.23M
                     if (it >= end8) [[unlikely]] {
862
251
                        break;
863
251
                     }
864
865
1.23M
                     uint64_t chunk;
866
1.23M
                     std::memcpy(&chunk, it, 8);
867
1.23M
                     const uint64_t test_chars = has_quote(chunk);
868
1.23M
                     if (test_chars) {
869
5.45k
                        it += (countr_zero(test_chars) >> 3);
870
871
5.45k
                        auto* prev = it - 1;
872
8.22k
                        while (*prev == '\\') {
873
2.77k
                           --prev;
874
2.77k
                        }
875
5.45k
                        if (size_t(it - prev) % 2) {
876
3.93k
                           goto continue_decode;
877
3.93k
                        }
878
1.52k
                        ++it; // skip the escaped quote
879
1.52k
                     }
880
1.23M
                     else {
881
1.23M
                        it += 8;
882
1.23M
                     }
883
1.23M
                  }
884
885
1.46k
                  while (it[-1] == '\\') [[unlikely]] {
886
                     // if we ended on an escape character then we need to rewind
887
                     // because we lost our context
888
1.21k
                     --it;
889
1.21k
                  }
890
891
2.12k
                  for (; it < end; ++it) {
892
2.07k
                     if (*it == '"') {
893
249
                        auto* prev = it - 1;
894
865
                        while (*prev == '\\') {
895
616
                           --prev;
896
616
                        }
897
249
                        if (size_t(it - prev) % 2) {
898
195
                           goto continue_decode;
899
195
                        }
900
249
                     }
901
2.07k
                  }
902
903
56
                  ctx.error = error_code::unexpected_end;
904
56
                  return;
905
906
4.12k
               continue_decode:
907
908
4.12k
                  const auto available_padding = size_t(end - it);
909
4.12k
                  auto n = size_t(it - start);
910
4.12k
                  if (available_padding >= 8) [[likely]] {
911
3.93k
                     value.resize(n + string_padding_bytes);
912
913
3.93k
                     auto* p = value.data();
914
915
569k
                     while (true) {
916
569k
                        if (start >= it) {
917
3.45k
                           break;
918
3.45k
                        }
919
920
566k
                        std::memcpy(p, start, 8);
921
566k
                        uint64_t swar;
922
566k
                        std::memcpy(&swar, p, 8);
923
924
566k
                        constexpr uint64_t lo7_mask = repeat_byte8(0b01111111);
925
566k
                        const uint64_t lo7 = swar & lo7_mask;
926
566k
                        const uint64_t backslash = (lo7 ^ repeat_byte8('\\')) + lo7_mask;
927
566k
                        const uint64_t less_32 = (swar & repeat_byte8(0b01100000)) + lo7_mask;
928
566k
                        uint64_t next = ~((backslash & less_32) | swar);
929
930
566k
                        next &= repeat_byte8(0b10000000);
931
566k
                        if (next == 0) {
932
297k
                           start += 8;
933
297k
                           p += 8;
934
297k
                           continue;
935
297k
                        }
936
937
268k
                        next = countr_zero(next) >> 3;
938
268k
                        start += next;
939
268k
                        if (start >= it) {
940
424
                           break;
941
424
                        }
942
943
268k
                        if ((*start & 0b11100000) == 0) [[unlikely]] {
944
46
                           ctx.error = error_code::syntax_error;
945
46
                           return;
946
46
                        }
947
268k
                        ++start; // skip the escape
948
268k
                        if (*start == 'u') {
949
225k
                           ++start;
950
225k
                           p += next;
951
225k
                           const auto mark = start;
952
225k
                           const auto offset = handle_unicode_code_point(start, p, end);
953
225k
                           if (offset == 0) [[unlikely]] {
954
4
                              ctx.error = error_code::unicode_escape_conversion_failure;
955
4
                              return;
956
4
                           }
957
225k
                           n += offset;
958
                           // escape + u + unicode code points
959
225k
                           n -= 2 + uint32_t(start - mark);
960
225k
                        }
961
42.3k
                        else {
962
42.3k
                           p += next;
963
42.3k
                           *p = char_unescape_table[uint8_t(*start)];
964
42.3k
                           if (*p == 0) [[unlikely]] {
965
11
                              ctx.error = error_code::invalid_escape;
966
11
                              return;
967
11
                           }
968
42.3k
                           ++p;
969
42.3k
                           ++start;
970
42.3k
                           --n;
971
42.3k
                        }
972
268k
                     }
973
974
3.87k
                     value.resize(n);
975
3.87k
                     ++it;
976
3.87k
                  }
977
186
                  else {
978
                     // For large inputs this case of running out of buffer is very rare
979
186
                     value.resize(n);
980
186
                     auto* p = value.data();
981
982
186
                     it = start;
983
2.10M
                     while (it < end) [[likely]] {
984
2.10M
                        if (*it == '"') {
985
136
                           value.resize(size_t(p - value.data()));
986
136
                           ++it;
987
136
                           return;
988
136
                        }
989
990
2.10M
                        *p = *it;
991
992
2.10M
                        if (*it == '\\') {
993
33.2k
                           ++it; // skip the escape
994
33.2k
                           if (*it == 'u') {
995
30.8k
                              ++it;
996
30.8k
                              if (!handle_unicode_code_point(it, p, end)) [[unlikely]] {
997
40
                                 ctx.error = error_code::unicode_escape_conversion_failure;
998
40
                                 return;
999
40
                              }
1000
30.8k
                           }
1001
2.34k
                           else {
1002
2.34k
                              *p = char_unescape_table[uint8_t(*it)];
1003
2.34k
                              if (*p == 0) [[unlikely]] {
1004
10
                                 ctx.error = error_code::invalid_escape;
1005
10
                                 return;
1006
10
                              }
1007
2.33k
                              ++p;
1008
2.33k
                              ++it;
1009
2.33k
                           }
1010
33.2k
                        }
1011
2.07M
                        else {
1012
2.07M
                           ++it;
1013
2.07M
                           ++p;
1014
2.07M
                        }
1015
2.10M
                     }
1016
1017
0
                     ctx.error = error_code::unexpected_end;
1018
0
                  }
1019
4.12k
               }
1020
298
               else {
1021
                  // For short strings
1022
1023
298
                  std::array<char, 8> buffer{};
1024
1025
298
                  auto* p = buffer.data();
1026
1027
571
                  while (it < end) [[likely]] {
1028
466
                     *p = *it;
1029
466
                     if (*it == '"') {
1030
181
                        value.assign(buffer.data(), size_t(p - buffer.data()));
1031
181
                        ++it;
1032
                        if constexpr (not Opts.null_terminated) {
1033
                           if (it == end) {
1034
                              ctx.error = error_code::end_reached;
1035
                              return;
1036
                           }
1037
                        }
1038
181
                        return;
1039
181
                     }
1040
285
                     else if (*it == '\\') {
1041
65
                        ++it; // skip the escape
1042
                        if constexpr (not Opts.null_terminated) {
1043
                           if (it == end) [[unlikely]] {
1044
                              ctx.error = error_code::unexpected_end;
1045
                              return;
1046
                           }
1047
                        }
1048
65
                        if (*it == 'u') {
1049
30
                           ++it;
1050
                           if constexpr (not Opts.null_terminated) {
1051
                              if (it == end) [[unlikely]] {
1052
                                 ctx.error = error_code::unexpected_end;
1053
                                 return;
1054
                              }
1055
                           }
1056
30
                           if (!handle_unicode_code_point(it, p, end)) [[unlikely]] {
1057
5
                              ctx.error = error_code::unicode_escape_conversion_failure;
1058
5
                              return;
1059
5
                           }
1060
30
                        }
1061
35
                        else {
1062
35
                           *p = char_unescape_table[uint8_t(*it)];
1063
35
                           if (*p == 0) [[unlikely]] {
1064
7
                              ctx.error = error_code::invalid_escape;
1065
7
                              return;
1066
7
                           }
1067
28
                           ++p;
1068
28
                           ++it;
1069
28
                        }
1070
65
                     }
1071
220
                     else {
1072
220
                        ++it;
1073
220
                        ++p;
1074
220
                     }
1075
466
                  }
1076
1077
105
                  ctx.error = error_code::unexpected_end;
1078
105
               }
1079
            }
1080
            else {
1081
               // raw_string
1082
               auto start = it;
1083
               skip_string_view<Opts>(ctx, it, end);
1084
               if (bool(ctx.error)) [[unlikely]]
1085
                  return;
1086
1087
               value.assign(start, size_t(it - start));
1088
               ++it;
1089
            }
1090
4.47k
         }
1091
4.47k
      }
Unexecuted instantiation: _ZN3glz4fromILj10ENSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEE2opITnDaXtlNS_4optsELj10ELb1ELb1ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj4EEERPKcSD_S7_TkNS_10is_contextERNS_7contextEQntcl15check_is_paddedTL0__EEEvRT2_OT3_OT0_OT1_
_ZN3glz4fromILj10ENSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1EEERPKcSD_S7_TkNS_10is_contextERNS_7contextEQntcl15check_is_paddedTL0__EEEvRT2_OT3_OT0_OT1_
Line
Count
Source
828
40.6k
      {
829
         if constexpr (Opts.number) {
830
            auto start = it;
831
            skip_number<Opts>(ctx, it, end);
832
            if (bool(ctx.error)) [[unlikely]] {
833
               return;
834
            }
835
            if (start == it) [[unlikely]] {
836
               ctx.error = error_code::parse_number_failure;
837
               return;
838
            }
839
            value.append(start, size_t(it - start));
840
         }
841
40.6k
         else {
842
40.6k
            if constexpr (!check_opening_handled(Opts)) {
843
40.6k
               if constexpr (!check_ws_handled(Opts)) {
844
40.6k
                  if (skip_ws<Opts>(ctx, it, end)) {
845
0
                     return;
846
0
                  }
847
40.6k
               }
848
849
40.6k
               if (match_invalid_end<'"', Opts>(ctx, it, end)) {
850
65
                  return;
851
65
               }
852
40.6k
            }
853
854
40.6k
            if constexpr (not Opts.raw_string) {
855
40.6k
               static constexpr auto string_padding_bytes = 8;
856
857
40.6k
               if (size_t(end - it) >= 8) {
858
39.8k
                  auto start = it;
859
39.8k
                  const auto end8 = end - 8;
860
2.53M
                  while (true) {
861
2.53M
                     if (it >= end8) [[unlikely]] {
862
297
                        break;
863
297
                     }
864
865
2.53M
                     uint64_t chunk;
866
2.53M
                     std::memcpy(&chunk, it, 8);
867
2.53M
                     const uint64_t test_chars = has_quote(chunk);
868
2.53M
                     if (test_chars) {
869
40.3k
                        it += (countr_zero(test_chars) >> 3);
870
871
40.3k
                        auto* prev = it - 1;
872
42.4k
                        while (*prev == '\\') {
873
2.10k
                           --prev;
874
2.10k
                        }
875
40.3k
                        if (size_t(it - prev) % 2) {
876
39.5k
                           goto continue_decode;
877
39.5k
                        }
878
779
                        ++it; // skip the escaped quote
879
779
                     }
880
2.49M
                     else {
881
2.49M
                        it += 8;
882
2.49M
                     }
883
2.53M
                  }
884
885
1.37k
                  while (it[-1] == '\\') [[unlikely]] {
886
                     // if we ended on an escape character then we need to rewind
887
                     // because we lost our context
888
1.07k
                     --it;
889
1.07k
                  }
890
891
2.12k
                  for (; it < end; ++it) {
892
2.07k
                     if (*it == '"') {
893
308
                        auto* prev = it - 1;
894
831
                        while (*prev == '\\') {
895
523
                           --prev;
896
523
                        }
897
308
                        if (size_t(it - prev) % 2) {
898
255
                           goto continue_decode;
899
255
                        }
900
308
                     }
901
2.07k
                  }
902
903
42
                  ctx.error = error_code::unexpected_end;
904
42
                  return;
905
906
39.8k
               continue_decode:
907
908
39.8k
                  const auto available_padding = size_t(end - it);
909
39.8k
                  auto n = size_t(it - start);
910
39.8k
                  if (available_padding >= 8) [[likely]] {
911
39.5k
                     value.resize(n + string_padding_bytes);
912
913
39.5k
                     auto* p = value.data();
914
915
1.18M
                     while (true) {
916
1.18M
                        if (start >= it) {
917
38.6k
                           break;
918
38.6k
                        }
919
920
1.15M
                        std::memcpy(p, start, 8);
921
1.15M
                        uint64_t swar;
922
1.15M
                        std::memcpy(&swar, p, 8);
923
924
1.15M
                        constexpr uint64_t lo7_mask = repeat_byte8(0b01111111);
925
1.15M
                        const uint64_t lo7 = swar & lo7_mask;
926
1.15M
                        const uint64_t backslash = (lo7 ^ repeat_byte8('\\')) + lo7_mask;
927
1.15M
                        const uint64_t less_32 = (swar & repeat_byte8(0b01100000)) + lo7_mask;
928
1.15M
                        uint64_t next = ~((backslash & less_32) | swar);
929
930
1.15M
                        next &= repeat_byte8(0b10000000);
931
1.15M
                        if (next == 0) {
932
850k
                           start += 8;
933
850k
                           p += 8;
934
850k
                           continue;
935
850k
                        }
936
937
300k
                        next = countr_zero(next) >> 3;
938
300k
                        start += next;
939
300k
                        if (start >= it) {
940
936
                           break;
941
936
                        }
942
943
299k
                        if ((*start & 0b11100000) == 0) [[unlikely]] {
944
8
                           ctx.error = error_code::syntax_error;
945
8
                           return;
946
8
                        }
947
299k
                        ++start; // skip the escape
948
299k
                        if (*start == 'u') {
949
231k
                           ++start;
950
231k
                           p += next;
951
231k
                           const auto mark = start;
952
231k
                           const auto offset = handle_unicode_code_point(start, p, end);
953
231k
                           if (offset == 0) [[unlikely]] {
954
4
                              ctx.error = error_code::unicode_escape_conversion_failure;
955
4
                              return;
956
4
                           }
957
231k
                           n += offset;
958
                           // escape + u + unicode code points
959
231k
                           n -= 2 + uint32_t(start - mark);
960
231k
                        }
961
68.0k
                        else {
962
68.0k
                           p += next;
963
68.0k
                           *p = char_unescape_table[uint8_t(*start)];
964
68.0k
                           if (*p == 0) [[unlikely]] {
965
2
                              ctx.error = error_code::invalid_escape;
966
2
                              return;
967
2
                           }
968
68.0k
                           ++p;
969
68.0k
                           ++start;
970
68.0k
                           --n;
971
68.0k
                        }
972
299k
                     }
973
974
39.5k
                     value.resize(n);
975
39.5k
                     ++it;
976
39.5k
                  }
977
276
                  else {
978
                     // For large inputs this case of running out of buffer is very rare
979
276
                     value.resize(n);
980
276
                     auto* p = value.data();
981
982
276
                     it = start;
983
11.6M
                     while (it < end) [[likely]] {
984
11.6M
                        if (*it == '"') {
985
266
                           value.resize(size_t(p - value.data()));
986
266
                           ++it;
987
266
                           return;
988
266
                        }
989
990
11.6M
                        *p = *it;
991
992
11.6M
                        if (*it == '\\') {
993
2.81k
                           ++it; // skip the escape
994
2.81k
                           if (*it == 'u') {
995
2.01k
                              ++it;
996
2.01k
                              if (!handle_unicode_code_point(it, p, end)) [[unlikely]] {
997
2
                                 ctx.error = error_code::unicode_escape_conversion_failure;
998
2
                                 return;
999
2
                              }
1000
2.01k
                           }
1001
806
                           else {
1002
806
                              *p = char_unescape_table[uint8_t(*it)];
1003
806
                              if (*p == 0) [[unlikely]] {
1004
8
                                 ctx.error = error_code::invalid_escape;
1005
8
                                 return;
1006
8
                              }
1007
798
                              ++p;
1008
798
                              ++it;
1009
798
                           }
1010
2.81k
                        }
1011
11.6M
                        else {
1012
11.6M
                           ++it;
1013
11.6M
                           ++p;
1014
11.6M
                        }
1015
11.6M
                     }
1016
1017
0
                     ctx.error = error_code::unexpected_end;
1018
0
                  }
1019
39.8k
               }
1020
770
               else {
1021
                  // For short strings
1022
1023
770
                  std::array<char, 8> buffer{};
1024
1025
770
                  auto* p = buffer.data();
1026
1027
1.27k
                  while (it < end) [[likely]] {
1028
1.16k
                     *p = *it;
1029
1.16k
                     if (*it == '"') {
1030
648
                        value.assign(buffer.data(), size_t(p - buffer.data()));
1031
648
                        ++it;
1032
648
                        if constexpr (not Opts.null_terminated) {
1033
648
                           if (it == end) {
1034
40
                              ctx.error = error_code::end_reached;
1035
40
                              return;
1036
40
                           }
1037
648
                        }
1038
608
                        return;
1039
648
                     }
1040
521
                     else if (*it == '\\') {
1041
50
                        ++it; // skip the escape
1042
50
                        if constexpr (not Opts.null_terminated) {
1043
50
                           if (it == end) [[unlikely]] {
1044
1
                              ctx.error = error_code::unexpected_end;
1045
1
                              return;
1046
1
                           }
1047
50
                        }
1048
50
                        if (*it == 'u') {
1049
7
                           ++it;
1050
7
                           if constexpr (not Opts.null_terminated) {
1051
7
                              if (it == end) [[unlikely]] {
1052
1
                                 ctx.error = error_code::unexpected_end;
1053
1
                                 return;
1054
1
                              }
1055
7
                           }
1056
7
                           if (!handle_unicode_code_point(it, p, end)) [[unlikely]] {
1057
3
                              ctx.error = error_code::unicode_escape_conversion_failure;
1058
3
                              return;
1059
3
                           }
1060
7
                        }
1061
43
                        else {
1062
43
                           *p = char_unescape_table[uint8_t(*it)];
1063
43
                           if (*p == 0) [[unlikely]] {
1064
10
                              ctx.error = error_code::invalid_escape;
1065
10
                              return;
1066
10
                           }
1067
33
                           ++p;
1068
33
                           ++it;
1069
33
                        }
1070
50
                     }
1071
471
                     else {
1072
471
                        ++it;
1073
471
                        ++p;
1074
471
                     }
1075
1.16k
                  }
1076
1077
109
                  ctx.error = error_code::unexpected_end;
1078
109
               }
1079
            }
1080
            else {
1081
               // raw_string
1082
               auto start = it;
1083
               skip_string_view<Opts>(ctx, it, end);
1084
               if (bool(ctx.error)) [[unlikely]]
1085
                  return;
1086
1087
               value.assign(start, size_t(it - start));
1088
               ++it;
1089
            }
1090
40.6k
         }
1091
40.6k
      }
_ZN3glz4fromILj10ENSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1EEERPKcSD_S7_TkNS_10is_contextERNS_7contextEQntcl15check_is_paddedTL0__EEEvRT2_OT3_OT0_OT1_
Line
Count
Source
828
40.7k
      {
829
         if constexpr (Opts.number) {
830
            auto start = it;
831
            skip_number<Opts>(ctx, it, end);
832
            if (bool(ctx.error)) [[unlikely]] {
833
               return;
834
            }
835
            if (start == it) [[unlikely]] {
836
               ctx.error = error_code::parse_number_failure;
837
               return;
838
            }
839
            value.append(start, size_t(it - start));
840
         }
841
40.7k
         else {
842
40.7k
            if constexpr (!check_opening_handled(Opts)) {
843
40.7k
               if constexpr (!check_ws_handled(Opts)) {
844
40.7k
                  if (skip_ws<Opts>(ctx, it, end)) {
845
0
                     return;
846
0
                  }
847
40.7k
               }
848
849
40.7k
               if (match_invalid_end<'"', Opts>(ctx, it, end)) {
850
143
                  return;
851
143
               }
852
40.7k
            }
853
854
40.7k
            if constexpr (not Opts.raw_string) {
855
40.7k
               static constexpr auto string_padding_bytes = 8;
856
857
40.7k
               if (size_t(end - it) >= 8) {
858
39.9k
                  auto start = it;
859
39.9k
                  const auto end8 = end - 8;
860
2.53M
                  while (true) {
861
2.53M
                     if (it >= end8) [[unlikely]] {
862
266
                        break;
863
266
                     }
864
865
2.53M
                     uint64_t chunk;
866
2.53M
                     std::memcpy(&chunk, it, 8);
867
2.53M
                     const uint64_t test_chars = has_quote(chunk);
868
2.53M
                     if (test_chars) {
869
40.4k
                        it += (countr_zero(test_chars) >> 3);
870
871
40.4k
                        auto* prev = it - 1;
872
42.6k
                        while (*prev == '\\') {
873
2.11k
                           --prev;
874
2.11k
                        }
875
40.4k
                        if (size_t(it - prev) % 2) {
876
39.7k
                           goto continue_decode;
877
39.7k
                        }
878
791
                        ++it; // skip the escaped quote
879
791
                     }
880
2.49M
                     else {
881
2.49M
                        it += 8;
882
2.49M
                     }
883
2.53M
                  }
884
885
1.22k
                  while (it[-1] == '\\') [[unlikely]] {
886
                     // if we ended on an escape character then we need to rewind
887
                     // because we lost our context
888
963
                     --it;
889
963
                  }
890
891
1.75k
                  for (; it < end; ++it) {
892
1.70k
                     if (*it == '"') {
893
266
                        auto* prev = it - 1;
894
779
                        while (*prev == '\\') {
895
513
                           --prev;
896
513
                        }
897
266
                        if (size_t(it - prev) % 2) {
898
223
                           goto continue_decode;
899
223
                        }
900
266
                     }
901
1.70k
                  }
902
903
43
                  ctx.error = error_code::unexpected_end;
904
43
                  return;
905
906
39.9k
               continue_decode:
907
908
39.9k
                  const auto available_padding = size_t(end - it);
909
39.9k
                  auto n = size_t(it - start);
910
39.9k
                  if (available_padding >= 8) [[likely]] {
911
39.6k
                     value.resize(n + string_padding_bytes);
912
913
39.6k
                     auto* p = value.data();
914
915
1.19M
                     while (true) {
916
1.19M
                        if (start >= it) {
917
38.6k
                           break;
918
38.6k
                        }
919
920
1.15M
                        std::memcpy(p, start, 8);
921
1.15M
                        uint64_t swar;
922
1.15M
                        std::memcpy(&swar, p, 8);
923
924
1.15M
                        constexpr uint64_t lo7_mask = repeat_byte8(0b01111111);
925
1.15M
                        const uint64_t lo7 = swar & lo7_mask;
926
1.15M
                        const uint64_t backslash = (lo7 ^ repeat_byte8('\\')) + lo7_mask;
927
1.15M
                        const uint64_t less_32 = (swar & repeat_byte8(0b01100000)) + lo7_mask;
928
1.15M
                        uint64_t next = ~((backslash & less_32) | swar);
929
930
1.15M
                        next &= repeat_byte8(0b10000000);
931
1.15M
                        if (next == 0) {
932
850k
                           start += 8;
933
850k
                           p += 8;
934
850k
                           continue;
935
850k
                        }
936
937
300k
                        next = countr_zero(next) >> 3;
938
300k
                        start += next;
939
300k
                        if (start >= it) {
940
945
                           break;
941
945
                        }
942
943
299k
                        if ((*start & 0b11100000) == 0) [[unlikely]] {
944
29
                           ctx.error = error_code::syntax_error;
945
29
                           return;
946
29
                        }
947
299k
                        ++start; // skip the escape
948
299k
                        if (*start == 'u') {
949
231k
                           ++start;
950
231k
                           p += next;
951
231k
                           const auto mark = start;
952
231k
                           const auto offset = handle_unicode_code_point(start, p, end);
953
231k
                           if (offset == 0) [[unlikely]] {
954
5
                              ctx.error = error_code::unicode_escape_conversion_failure;
955
5
                              return;
956
5
                           }
957
231k
                           n += offset;
958
                           // escape + u + unicode code points
959
231k
                           n -= 2 + uint32_t(start - mark);
960
231k
                        }
961
68.2k
                        else {
962
68.2k
                           p += next;
963
68.2k
                           *p = char_unescape_table[uint8_t(*start)];
964
68.2k
                           if (*p == 0) [[unlikely]] {
965
4
                              ctx.error = error_code::invalid_escape;
966
4
                              return;
967
4
                           }
968
68.2k
                           ++p;
969
68.2k
                           ++start;
970
68.2k
                           --n;
971
68.2k
                        }
972
299k
                     }
973
974
39.6k
                     value.resize(n);
975
39.6k
                     ++it;
976
39.6k
                  }
977
247
                  else {
978
                     // For large inputs this case of running out of buffer is very rare
979
247
                     value.resize(n);
980
247
                     auto* p = value.data();
981
982
247
                     it = start;
983
11.5M
                     while (it < end) [[likely]] {
984
11.5M
                        if (*it == '"') {
985
236
                           value.resize(size_t(p - value.data()));
986
236
                           ++it;
987
236
                           return;
988
236
                        }
989
990
11.5M
                        *p = *it;
991
992
11.5M
                        if (*it == '\\') {
993
2.49k
                           ++it; // skip the escape
994
2.49k
                           if (*it == 'u') {
995
1.86k
                              ++it;
996
1.86k
                              if (!handle_unicode_code_point(it, p, end)) [[unlikely]] {
997
2
                                 ctx.error = error_code::unicode_escape_conversion_failure;
998
2
                                 return;
999
2
                              }
1000
1.86k
                           }
1001
630
                           else {
1002
630
                              *p = char_unescape_table[uint8_t(*it)];
1003
630
                              if (*p == 0) [[unlikely]] {
1004
9
                                 ctx.error = error_code::invalid_escape;
1005
9
                                 return;
1006
9
                              }
1007
621
                              ++p;
1008
621
                              ++it;
1009
621
                           }
1010
2.49k
                        }
1011
11.5M
                        else {
1012
11.5M
                           ++it;
1013
11.5M
                           ++p;
1014
11.5M
                        }
1015
11.5M
                     }
1016
1017
0
                     ctx.error = error_code::unexpected_end;
1018
0
                  }
1019
39.9k
               }
1020
768
               else {
1021
                  // For short strings
1022
1023
768
                  std::array<char, 8> buffer{};
1024
1025
768
                  auto* p = buffer.data();
1026
1027
1.23k
                  while (it < end) [[likely]] {
1028
1.03k
                     *p = *it;
1029
1.03k
                     if (*it == '"') {
1030
561
                        value.assign(buffer.data(), size_t(p - buffer.data()));
1031
561
                        ++it;
1032
                        if constexpr (not Opts.null_terminated) {
1033
                           if (it == end) {
1034
                              ctx.error = error_code::end_reached;
1035
                              return;
1036
                           }
1037
                        }
1038
561
                        return;
1039
561
                     }
1040
478
                     else if (*it == '\\') {
1041
41
                        ++it; // skip the escape
1042
                        if constexpr (not Opts.null_terminated) {
1043
                           if (it == end) [[unlikely]] {
1044
                              ctx.error = error_code::unexpected_end;
1045
                              return;
1046
                           }
1047
                        }
1048
41
                        if (*it == 'u') {
1049
3
                           ++it;
1050
                           if constexpr (not Opts.null_terminated) {
1051
                              if (it == end) [[unlikely]] {
1052
                                 ctx.error = error_code::unexpected_end;
1053
                                 return;
1054
                              }
1055
                           }
1056
3
                           if (!handle_unicode_code_point(it, p, end)) [[unlikely]] {
1057
2
                              ctx.error = error_code::unicode_escape_conversion_failure;
1058
2
                              return;
1059
2
                           }
1060
3
                        }
1061
38
                        else {
1062
38
                           *p = char_unescape_table[uint8_t(*it)];
1063
38
                           if (*p == 0) [[unlikely]] {
1064
8
                              ctx.error = error_code::invalid_escape;
1065
8
                              return;
1066
8
                           }
1067
30
                           ++p;
1068
30
                           ++it;
1069
30
                        }
1070
41
                     }
1071
437
                     else {
1072
437
                        ++it;
1073
437
                        ++p;
1074
437
                     }
1075
1.03k
                  }
1076
1077
197
                  ctx.error = error_code::unexpected_end;
1078
197
               }
1079
            }
1080
            else {
1081
               // raw_string
1082
               auto start = it;
1083
               skip_string_view<Opts>(ctx, it, end);
1084
               if (bool(ctx.error)) [[unlikely]]
1085
                  return;
1086
1087
               value.assign(start, size_t(it - start));
1088
               ++it;
1089
            }
1090
40.7k
         }
1091
40.7k
      }
1092
   };
1093
1094
   template <class T>
1095
      requires(string_view_t<T> || char_array_t<T> || array_char_t<T> || static_string_t<T>)
1096
   struct from<JSON, T>
1097
   {
1098
      template <auto Opts, class It, class End>
1099
      GLZ_ALWAYS_INLINE static void op(auto& value, is_context auto&& ctx, It&& it, End&& end) noexcept
1100
      {
1101
         if constexpr (!check_opening_handled(Opts)) {
1102
            if constexpr (!check_ws_handled(Opts)) {
1103
               if (skip_ws<Opts>(ctx, it, end)) {
1104
                  return;
1105
               }
1106
            }
1107
1108
            if (match_invalid_end<'"', Opts>(ctx, it, end)) {
1109
               return;
1110
            }
1111
         }
1112
1113
         auto start = it;
1114
         skip_string_view<Opts>(ctx, it, end);
1115
         if (bool(ctx.error)) [[unlikely]]
1116
            return;
1117
1118
         if constexpr (string_view_t<T>) {
1119
            value = {start, size_t(it - start)};
1120
         }
1121
         else if constexpr (char_array_t<T>) {
1122
            const size_t n = it - start;
1123
            if ((n + 1) > sizeof(value)) {
1124
               ctx.error = error_code::unexpected_end;
1125
               return;
1126
            }
1127
            std::memcpy(value, start, n);
1128
            value[n] = '\0';
1129
         }
1130
         else if constexpr (array_char_t<T>) {
1131
            const size_t n = it - start;
1132
            if ((n + 1) > value.size()) {
1133
               ctx.error = error_code::unexpected_end;
1134
               return;
1135
            }
1136
            std::memcpy(value.data(), start, n);
1137
            value[n] = '\0';
1138
         }
1139
         else if constexpr (static_string_t<T>) {
1140
            const size_t n = it - start;
1141
            if (n > value.capacity()) {
1142
               ctx.error = error_code::unexpected_end;
1143
               return;
1144
            }
1145
            value.assign(start, n);
1146
         }
1147
         ++it; // skip closing quote
1148
         if constexpr (not Opts.null_terminated) {
1149
            if (it == end) {
1150
               ctx.error = error_code::end_reached;
1151
               return;
1152
            }
1153
         }
1154
      }
1155
   };
1156
1157
   template <char_t T>
1158
   struct from<JSON, T>
1159
   {
1160
      template <auto Opts>
1161
      static void op(auto& value, is_context auto&& ctx, auto&& it, auto&& end) noexcept
1162
      {
1163
         if constexpr (!check_opening_handled(Opts)) {
1164
            if constexpr (!check_ws_handled(Opts)) {
1165
               if (skip_ws<Opts>(ctx, it, end)) {
1166
                  return;
1167
               }
1168
            }
1169
1170
            if (match_invalid_end<'"', Opts>(ctx, it, end)) {
1171
               return;
1172
            }
1173
         }
1174
1175
         if (*it == '\\') [[unlikely]] {
1176
            ++it;
1177
            switch (*it) {
1178
            case '\0': {
1179
               ctx.error = error_code::unexpected_end;
1180
               return;
1181
            }
1182
            case '"':
1183
            case '\\':
1184
            case '/':
1185
               value = *it++;
1186
               break;
1187
            case 'b':
1188
               value = '\b';
1189
               ++it;
1190
               break;
1191
            case 'f':
1192
               value = '\f';
1193
               ++it;
1194
               break;
1195
            case 'n':
1196
               value = '\n';
1197
               ++it;
1198
               break;
1199
            case 'r':
1200
               value = '\r';
1201
               ++it;
1202
               break;
1203
            case 't':
1204
               value = '\t';
1205
               ++it;
1206
               break;
1207
            case 'u': {
1208
               ctx.error = error_code::unicode_escape_conversion_failure;
1209
               return;
1210
            }
1211
            default: {
1212
               ctx.error = error_code::invalid_escape;
1213
               return;
1214
            }
1215
            }
1216
         }
1217
         else {
1218
            if (it == end) [[unlikely]] {
1219
               ctx.error = error_code::unexpected_end;
1220
               return;
1221
            }
1222
            value = *it++;
1223
         }
1224
         if constexpr (not Opts.null_terminated) {
1225
            if (it == end) [[unlikely]] {
1226
               ctx.error = error_code::unexpected_end;
1227
               return;
1228
            }
1229
         }
1230
         if (match<'"'>(ctx, it)) {
1231
            return;
1232
         }
1233
         if constexpr (not Opts.null_terminated) {
1234
            if (it == end) {
1235
               ctx.error = error_code::end_reached;
1236
               return;
1237
            }
1238
         }
1239
      }
1240
   };
1241
1242
   template <class T>
1243
      requires(is_named_enum<T>)
1244
   struct from<JSON, T>
1245
   {
1246
      template <auto Opts>
1247
      static void op(auto& value, is_context auto&& ctx, auto&& it, auto&& end) noexcept
1248
      {
1249
         if constexpr (!check_ws_handled(Opts)) {
1250
            if (skip_ws<Opts>(ctx, it, end)) {
1251
               return;
1252
            }
1253
         }
1254
1255
         constexpr auto N = reflect<T>::size;
1256
1257
         if (*it != '"') [[unlikely]] {
1258
            ctx.error = error_code::expected_quote;
1259
            return;
1260
         }
1261
         ++it;
1262
         if constexpr (not Opts.null_terminated) {
1263
            if (it == end) [[unlikely]] {
1264
               ctx.error = error_code::unexpected_end;
1265
               return;
1266
            }
1267
         }
1268
1269
         if constexpr (N == 1) {
1270
            decode_index<Opts, T, 0>(value, ctx, it, end);
1271
         }
1272
         else {
1273
            static constexpr auto HashInfo = hash_info<T>;
1274
1275
            const auto index = decode_hash<JSON, T, HashInfo, HashInfo.type>::op(it, end);
1276
1277
            if (index >= N) [[unlikely]] {
1278
               ctx.error = error_code::unexpected_enum;
1279
               return;
1280
            }
1281
1282
            visit<N>([&]<size_t I>() { decode_index<Opts, T, I>(value, ctx, it, end); }, index);
1283
         }
1284
      }
1285
   };
1286
1287
   template <class T>
1288
      requires(std::is_enum_v<T> && !glaze_enum_t<T> && !meta_keys<T> && !custom_read<T>)
1289
   struct from<JSON, T>
1290
   {
1291
      template <auto Opts>
1292
      static void op(auto& value, is_context auto&& ctx, auto&& it, auto&& end) noexcept
1293
      {
1294
         // TODO: use std::bit_cast???
1295
         std::underlying_type_t<std::decay_t<T>> x{};
1296
         parse<JSON>::op<Opts>(x, ctx, it, end);
1297
         value = static_cast<std::decay_t<T>>(x);
1298
      }
1299
   };
1300
1301
   template <func_t T>
1302
   struct from<JSON, T>
1303
   {
1304
      template <auto Opts>
1305
      static void op(auto& /*value*/, is_context auto&& ctx, auto&& it, auto&& end)
1306
      {
1307
         if constexpr (!check_ws_handled(Opts)) {
1308
            if (skip_ws<Opts>(ctx, it, end)) {
1309
               return;
1310
            }
1311
         }
1312
         if (match_invalid_end<'"', Opts>(ctx, it, end)) {
1313
            return;
1314
         }
1315
         skip_string_view<Opts>(ctx, it, end);
1316
         if (bool(ctx.error)) [[unlikely]]
1317
            return;
1318
         if (match<'"'>(ctx, it)) {
1319
            return;
1320
         }
1321
         if constexpr (not Opts.null_terminated) {
1322
            if (it == end) {
1323
               ctx.error = error_code::end_reached;
1324
               return;
1325
            }
1326
         }
1327
      }
1328
   };
1329
1330
   template <class T>
1331
   struct from<JSON, basic_raw_json<T>>
1332
   {
1333
      template <auto Opts>
1334
      GLZ_ALWAYS_INLINE static void op(auto&& value, is_context auto&& ctx, auto&& it, auto&& end)
1335
      {
1336
         auto it_start = it;
1337
         if (*it == 'n') {
1338
            match<"null", Opts>(ctx, it, end);
1339
         }
1340
         else if (is_digit(uint8_t(*it))) {
1341
            skip_number<Opts>(ctx, it, end);
1342
         }
1343
         else {
1344
            skip_value<JSON>::op<Opts>(ctx, it, end);
1345
         }
1346
         if (bool(ctx.error)) [[unlikely]]
1347
            return;
1348
         value.str = {it_start, static_cast<size_t>(it - it_start)};
1349
      }
1350
   };
1351
1352
   template <class T>
1353
   struct from<JSON, basic_text<T>>
1354
   {
1355
      template <auto Opts>
1356
      GLZ_ALWAYS_INLINE static void op(auto&& value, is_context auto&&, auto&& it, auto&& end)
1357
      {
1358
         value.str = {it, static_cast<size_t>(end - it)}; // read entire contents as string
1359
         it = end;
1360
      }
1361
   };
1362
1363
   // for set types
1364
   template <class T>
1365
      requires(readable_array_t<T> && !emplace_backable<T> && !resizable<T> && emplaceable<T>)
1366
   struct from<JSON, T>
1367
   {
1368
      template <auto Options>
1369
      static void op(auto& value, is_context auto&& ctx, auto&& it, auto&& end)
1370
      {
1371
         constexpr auto Opts = ws_handled_off<Options>();
1372
         if constexpr (!check_ws_handled(Options)) {
1373
            if (skip_ws<Opts>(ctx, it, end)) {
1374
               return;
1375
            }
1376
         }
1377
1378
         if (match_invalid_end<'[', Opts>(ctx, it, end)) {
1379
            return;
1380
         }
1381
         if constexpr (not Opts.null_terminated) {
1382
            ++ctx.indentation_level;
1383
         }
1384
         if (skip_ws<Opts>(ctx, it, end)) {
1385
            return;
1386
         }
1387
1388
         value.clear();
1389
         if (*it == ']') [[unlikely]] {
1390
            if constexpr (not Opts.null_terminated) {
1391
               --ctx.indentation_level;
1392
            }
1393
            ++it;
1394
            return;
1395
         }
1396
1397
         while (true) {
1398
            using V = range_value_t<T>;
1399
            V v;
1400
            parse<JSON>::op<Opts>(v, ctx, it, end);
1401
            if (bool(ctx.error)) [[unlikely]]
1402
               return;
1403
            value.emplace(std::move(v));
1404
            if (skip_ws<Opts>(ctx, it, end)) {
1405
               return;
1406
            }
1407
            if (*it == ']') {
1408
               if constexpr (not Opts.null_terminated) {
1409
                  --ctx.indentation_level;
1410
               }
1411
               ++it;
1412
               return;
1413
            }
1414
            if (match_invalid_end<',', Opts>(ctx, it, end)) {
1415
               return;
1416
            }
1417
            if (skip_ws<Opts>(ctx, it, end)) {
1418
               return;
1419
            }
1420
         }
1421
      }
1422
   };
1423
1424
   // for types like std::vector, std::array, std::deque, etc.
1425
   template <class T>
1426
      requires(readable_array_t<T> && (emplace_backable<T> || !resizable<T>) && !emplaceable<T>)
1427
   struct from<JSON, T>
1428
   {
1429
      template <auto Options>
1430
      static void op(auto&& value, is_context auto&& ctx, auto&& it, auto&& end)
1431
78.5k
      {
1432
78.5k
         constexpr auto Opts = ws_handled_off<Options>();
1433
         if constexpr (!check_ws_handled(Options)) {
1434
            if (skip_ws<Opts>(ctx, it, end)) {
1435
               return;
1436
            }
1437
         }
1438
1439
78.5k
         if (match_invalid_end<'[', Opts>(ctx, it, end)) {
1440
168
            return;
1441
168
         }
1442
78.3k
         if constexpr (not Opts.null_terminated) {
1443
25.9k
            ++ctx.indentation_level;
1444
25.9k
         }
1445
1446
78.3k
         const auto ws_start = it;
1447
78.3k
         if (skip_ws<Opts>(ctx, it, end)) {
1448
79
            return;
1449
79
         }
1450
1451
78.2k
         if (*it == ']') {
1452
5.85k
            if constexpr (not Opts.null_terminated) {
1453
1.98k
               --ctx.indentation_level;
1454
1.98k
            }
1455
5.85k
            ++it;
1456
5.85k
            if constexpr (resizable<T> && not Opts.append_arrays) {
1457
3.55k
               value.clear();
1458
1459
               if constexpr (check_shrink_to_fit(Opts)) {
1460
                  value.shrink_to_fit();
1461
               }
1462
3.55k
            }
1463
5.85k
            return;
1464
5.85k
         }
1465
1466
72.4k
         const size_t ws_size = size_t(it - ws_start);
1467
1468
72.4k
         static constexpr bool should_append = resizable<T> && Opts.append_arrays;
1469
72.4k
         if constexpr (not should_append) {
1470
72.4k
            const auto n = value.size();
1471
1472
72.4k
            auto value_it = value.begin();
1473
1474
271k
            for (size_t i = 0; i < n; ++i) {
1475
228k
               parse<JSON>::op<ws_handled<Opts>()>(*value_it++, ctx, it, end);
1476
228k
               if (bool(ctx.error)) [[unlikely]]
1477
3.03k
                  return;
1478
225k
               if (skip_ws<Opts>(ctx, it, end)) {
1479
61
                  return;
1480
61
               }
1481
225k
               if (*it == ',') {
1482
199k
                  ++it;
1483
1484
199k
                  if constexpr (!Opts.minified) {
1485
199k
                     if (ws_size && ws_size < size_t(end - it)) {
1486
172k
                        skip_matching_ws(ws_start, it, ws_size);
1487
172k
                     }
1488
199k
                  }
1489
1490
199k
                  if (skip_ws<Opts>(ctx, it, end)) {
1491
164
                     return;
1492
164
                  }
1493
199k
               }
1494
26.0k
               else if (*it == ']') {
1495
24.8k
                  if constexpr (not Opts.null_terminated) {
1496
8.26k
                     --ctx.indentation_level;
1497
8.26k
                  }
1498
24.8k
                  ++it;
1499
24.8k
                  if constexpr (erasable<T>) {
1500
2.59k
                     value.erase(value_it,
1501
2.59k
                                 value.end()); // use erase rather than resize for non-default constructible elements
1502
1503
                     if constexpr (check_shrink_to_fit(Opts)) {
1504
                        value.shrink_to_fit();
1505
                     }
1506
2.59k
                  }
1507
24.8k
                  return;
1508
24.8k
               }
1509
1.17k
               else [[unlikely]] {
1510
1.17k
                  ctx.error = error_code::expected_bracket;
1511
1.17k
                  return;
1512
1.17k
               }
1513
225k
            }
1514
72.4k
         }
1515
1516
         if constexpr (Opts.partial_read) {
1517
            return;
1518
         }
1519
72.4k
         else {
1520
            // growing
1521
72.4k
            if constexpr (emplace_backable<T>) {
1522
4.97M
               while (it < end) {
1523
4.97M
                  parse<JSON>::op<ws_handled<Opts>()>(value.emplace_back(), ctx, it, end);
1524
4.97M
                  if (bool(ctx.error)) [[unlikely]]
1525
32.1k
                     return;
1526
4.94M
                  if (skip_ws<Opts>(ctx, it, end)) {
1527
42
                     return;
1528
42
                  }
1529
4.94M
                  if (*it == ',') [[likely]] {
1530
4.93M
                     ++it;
1531
1532
4.93M
                     if constexpr (!Opts.minified) {
1533
4.93M
                        if (ws_size && ws_size < size_t(end - it)) {
1534
53.9k
                           skip_matching_ws(ws_start, it, ws_size);
1535
53.9k
                        }
1536
4.93M
                     }
1537
1538
4.93M
                     if (skip_ws<Opts>(ctx, it, end)) {
1539
152
                        return;
1540
152
                     }
1541
4.93M
                  }
1542
10.6k
                  else if (*it == ']') {
1543
8.51k
                     if constexpr (not Opts.null_terminated) {
1544
2.83k
                        --ctx.indentation_level;
1545
2.83k
                     }
1546
8.51k
                     ++it;
1547
8.51k
                     return;
1548
8.51k
                  }
1549
2.17k
                  else [[unlikely]] {
1550
2.17k
                     ctx.error = error_code::expected_bracket;
1551
2.17k
                     return;
1552
2.17k
                  }
1553
4.94M
               }
1554
            }
1555
24.8k
            else {
1556
24.8k
               ctx.error = error_code::exceeded_static_array_size;
1557
24.8k
            }
1558
72.4k
         }
1559
72.4k
      }
_ZN3glz4fromILj10ENSt3__15arrayImLm3EEEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj4EEERS3_TkNS_10is_contextERNS_7contextERPKcSC_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
1431
8.97k
      {
1432
8.97k
         constexpr auto Opts = ws_handled_off<Options>();
1433
         if constexpr (!check_ws_handled(Options)) {
1434
            if (skip_ws<Opts>(ctx, it, end)) {
1435
               return;
1436
            }
1437
         }
1438
1439
8.97k
         if (match_invalid_end<'[', Opts>(ctx, it, end)) {
1440
18
            return;
1441
18
         }
1442
8.96k
         if constexpr (not Opts.null_terminated) {
1443
8.96k
            ++ctx.indentation_level;
1444
8.96k
         }
1445
1446
8.96k
         const auto ws_start = it;
1447
8.96k
         if (skip_ws<Opts>(ctx, it, end)) {
1448
35
            return;
1449
35
         }
1450
1451
8.92k
         if (*it == ']') {
1452
804
            if constexpr (not Opts.null_terminated) {
1453
804
               --ctx.indentation_level;
1454
804
            }
1455
804
            ++it;
1456
            if constexpr (resizable<T> && not Opts.append_arrays) {
1457
               value.clear();
1458
1459
               if constexpr (check_shrink_to_fit(Opts)) {
1460
                  value.shrink_to_fit();
1461
               }
1462
            }
1463
804
            return;
1464
804
         }
1465
1466
8.12k
         const size_t ws_size = size_t(it - ws_start);
1467
1468
8.12k
         static constexpr bool should_append = resizable<T> && Opts.append_arrays;
1469
8.12k
         if constexpr (not should_append) {
1470
8.12k
            const auto n = value.size();
1471
1472
8.12k
            auto value_it = value.begin();
1473
1474
16.7k
            for (size_t i = 0; i < n; ++i) {
1475
16.7k
               parse<JSON>::op<ws_handled<Opts>()>(*value_it++, ctx, it, end);
1476
16.7k
               if (bool(ctx.error)) [[unlikely]]
1477
499
                  return;
1478
16.2k
               if (skip_ws<Opts>(ctx, it, end)) {
1479
17
                  return;
1480
17
               }
1481
16.1k
               if (*it == ',') {
1482
8.66k
                  ++it;
1483
1484
8.66k
                  if constexpr (!Opts.minified) {
1485
8.66k
                     if (ws_size && ws_size < size_t(end - it)) {
1486
2.90k
                        skip_matching_ws(ws_start, it, ws_size);
1487
2.90k
                     }
1488
8.66k
                  }
1489
1490
8.66k
                  if (skip_ws<Opts>(ctx, it, end)) {
1491
53
                     return;
1492
53
                  }
1493
8.66k
               }
1494
7.53k
               else if (*it == ']') {
1495
7.39k
                  if constexpr (not Opts.null_terminated) {
1496
7.39k
                     --ctx.indentation_level;
1497
7.39k
                  }
1498
7.39k
                  ++it;
1499
                  if constexpr (erasable<T>) {
1500
                     value.erase(value_it,
1501
                                 value.end()); // use erase rather than resize for non-default constructible elements
1502
1503
                     if constexpr (check_shrink_to_fit(Opts)) {
1504
                        value.shrink_to_fit();
1505
                     }
1506
                  }
1507
7.39k
                  return;
1508
7.39k
               }
1509
137
               else [[unlikely]] {
1510
137
                  ctx.error = error_code::expected_bracket;
1511
137
                  return;
1512
137
               }
1513
16.1k
            }
1514
8.12k
         }
1515
1516
         if constexpr (Opts.partial_read) {
1517
            return;
1518
         }
1519
8.12k
         else {
1520
            // growing
1521
            if constexpr (emplace_backable<T>) {
1522
               while (it < end) {
1523
                  parse<JSON>::op<ws_handled<Opts>()>(value.emplace_back(), ctx, it, end);
1524
                  if (bool(ctx.error)) [[unlikely]]
1525
                     return;
1526
                  if (skip_ws<Opts>(ctx, it, end)) {
1527
                     return;
1528
                  }
1529
                  if (*it == ',') [[likely]] {
1530
                     ++it;
1531
1532
                     if constexpr (!Opts.minified) {
1533
                        if (ws_size && ws_size < size_t(end - it)) {
1534
                           skip_matching_ws(ws_start, it, ws_size);
1535
                        }
1536
                     }
1537
1538
                     if (skip_ws<Opts>(ctx, it, end)) {
1539
                        return;
1540
                     }
1541
                  }
1542
                  else if (*it == ']') {
1543
                     if constexpr (not Opts.null_terminated) {
1544
                        --ctx.indentation_level;
1545
                     }
1546
                     ++it;
1547
                     return;
1548
                  }
1549
                  else [[unlikely]] {
1550
                     ctx.error = error_code::expected_bracket;
1551
                     return;
1552
                  }
1553
               }
1554
            }
1555
8.12k
            else {
1556
8.12k
               ctx.error = error_code::exceeded_static_array_size;
1557
8.12k
            }
1558
8.12k
         }
1559
8.12k
      }
_ZN3glz4fromILj10ENSt3__15arrayImLm3EEEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj4EEERS3_TkNS_10is_contextERNS_7contextERPKcSC_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
1431
9.00k
      {
1432
9.00k
         constexpr auto Opts = ws_handled_off<Options>();
1433
         if constexpr (!check_ws_handled(Options)) {
1434
            if (skip_ws<Opts>(ctx, it, end)) {
1435
               return;
1436
            }
1437
         }
1438
1439
9.00k
         if (match_invalid_end<'[', Opts>(ctx, it, end)) {
1440
34
            return;
1441
34
         }
1442
         if constexpr (not Opts.null_terminated) {
1443
            ++ctx.indentation_level;
1444
         }
1445
1446
8.96k
         const auto ws_start = it;
1447
8.96k
         if (skip_ws<Opts>(ctx, it, end)) {
1448
0
            return;
1449
0
         }
1450
1451
8.96k
         if (*it == ']') {
1452
            if constexpr (not Opts.null_terminated) {
1453
               --ctx.indentation_level;
1454
            }
1455
804
            ++it;
1456
            if constexpr (resizable<T> && not Opts.append_arrays) {
1457
               value.clear();
1458
1459
               if constexpr (check_shrink_to_fit(Opts)) {
1460
                  value.shrink_to_fit();
1461
               }
1462
            }
1463
804
            return;
1464
804
         }
1465
1466
8.16k
         const size_t ws_size = size_t(it - ws_start);
1467
1468
8.16k
         static constexpr bool should_append = resizable<T> && Opts.append_arrays;
1469
8.16k
         if constexpr (not should_append) {
1470
8.16k
            const auto n = value.size();
1471
1472
8.16k
            auto value_it = value.begin();
1473
1474
16.8k
            for (size_t i = 0; i < n; ++i) {
1475
16.7k
               parse<JSON>::op<ws_handled<Opts>()>(*value_it++, ctx, it, end);
1476
16.7k
               if (bool(ctx.error)) [[unlikely]]
1477
386
                  return;
1478
16.4k
               if (skip_ws<Opts>(ctx, it, end)) {
1479
0
                  return;
1480
0
               }
1481
16.4k
               if (*it == ',') {
1482
8.66k
                  ++it;
1483
1484
8.66k
                  if constexpr (!Opts.minified) {
1485
8.66k
                     if (ws_size && ws_size < size_t(end - it)) {
1486
2.90k
                        skip_matching_ws(ws_start, it, ws_size);
1487
2.90k
                     }
1488
8.66k
                  }
1489
1490
8.66k
                  if (skip_ws<Opts>(ctx, it, end)) {
1491
0
                     return;
1492
0
                  }
1493
8.66k
               }
1494
7.74k
               else if (*it == ']') {
1495
                  if constexpr (not Opts.null_terminated) {
1496
                     --ctx.indentation_level;
1497
                  }
1498
7.39k
                  ++it;
1499
                  if constexpr (erasable<T>) {
1500
                     value.erase(value_it,
1501
                                 value.end()); // use erase rather than resize for non-default constructible elements
1502
1503
                     if constexpr (check_shrink_to_fit(Opts)) {
1504
                        value.shrink_to_fit();
1505
                     }
1506
                  }
1507
7.39k
                  return;
1508
7.39k
               }
1509
355
               else [[unlikely]] {
1510
355
                  ctx.error = error_code::expected_bracket;
1511
355
                  return;
1512
355
               }
1513
16.4k
            }
1514
8.16k
         }
1515
1516
         if constexpr (Opts.partial_read) {
1517
            return;
1518
         }
1519
8.16k
         else {
1520
            // growing
1521
            if constexpr (emplace_backable<T>) {
1522
               while (it < end) {
1523
                  parse<JSON>::op<ws_handled<Opts>()>(value.emplace_back(), ctx, it, end);
1524
                  if (bool(ctx.error)) [[unlikely]]
1525
                     return;
1526
                  if (skip_ws<Opts>(ctx, it, end)) {
1527
                     return;
1528
                  }
1529
                  if (*it == ',') [[likely]] {
1530
                     ++it;
1531
1532
                     if constexpr (!Opts.minified) {
1533
                        if (ws_size && ws_size < size_t(end - it)) {
1534
                           skip_matching_ws(ws_start, it, ws_size);
1535
                        }
1536
                     }
1537
1538
                     if (skip_ws<Opts>(ctx, it, end)) {
1539
                        return;
1540
                     }
1541
                  }
1542
                  else if (*it == ']') {
1543
                     if constexpr (not Opts.null_terminated) {
1544
                        --ctx.indentation_level;
1545
                     }
1546
                     ++it;
1547
                     return;
1548
                  }
1549
                  else [[unlikely]] {
1550
                     ctx.error = error_code::expected_bracket;
1551
                     return;
1552
                  }
1553
               }
1554
            }
1555
8.16k
            else {
1556
8.16k
               ctx.error = error_code::exceeded_static_array_size;
1557
8.16k
            }
1558
8.16k
         }
1559
8.16k
      }
_ZN3glz4fromILj10ENSt3__15arrayImLm3EEEE2opITnDaXtlNS_4optsELj10ELb1ELb1ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj4EEERS3_TkNS_10is_contextERNS_7contextERPKcSC_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
1431
9.30k
      {
1432
9.30k
         constexpr auto Opts = ws_handled_off<Options>();
1433
         if constexpr (!check_ws_handled(Options)) {
1434
            if (skip_ws<Opts>(ctx, it, end)) {
1435
               return;
1436
            }
1437
         }
1438
1439
9.30k
         if (match_invalid_end<'[', Opts>(ctx, it, end)) {
1440
45
            return;
1441
45
         }
1442
         if constexpr (not Opts.null_terminated) {
1443
            ++ctx.indentation_level;
1444
         }
1445
1446
9.25k
         const auto ws_start = it;
1447
9.25k
         if (skip_ws<Opts>(ctx, it, end)) {
1448
2
            return;
1449
2
         }
1450
1451
9.25k
         if (*it == ']') {
1452
            if constexpr (not Opts.null_terminated) {
1453
               --ctx.indentation_level;
1454
            }
1455
689
            ++it;
1456
            if constexpr (resizable<T> && not Opts.append_arrays) {
1457
               value.clear();
1458
1459
               if constexpr (check_shrink_to_fit(Opts)) {
1460
                  value.shrink_to_fit();
1461
               }
1462
            }
1463
689
            return;
1464
689
         }
1465
1466
8.56k
         const size_t ws_size = size_t(it - ws_start);
1467
1468
8.56k
         static constexpr bool should_append = resizable<T> && Opts.append_arrays;
1469
8.56k
         if constexpr (not should_append) {
1470
8.56k
            const auto n = value.size();
1471
1472
8.56k
            auto value_it = value.begin();
1473
1474
17.7k
            for (size_t i = 0; i < n; ++i) {
1475
17.6k
               parse<JSON>::op<ws_handled<Opts>()>(*value_it++, ctx, it, end);
1476
17.6k
               if (bool(ctx.error)) [[unlikely]]
1477
468
                  return;
1478
17.2k
               if (skip_ws<Opts>(ctx, it, end)) {
1479
18
                  return;
1480
18
               }
1481
17.1k
               if (*it == ',') {
1482
9.16k
                  ++it;
1483
1484
9.16k
                  if constexpr (!Opts.minified) {
1485
9.16k
                     if (ws_size && ws_size < size_t(end - it)) {
1486
3.07k
                        skip_matching_ws(ws_start, it, ws_size);
1487
3.07k
                     }
1488
9.16k
                  }
1489
1490
9.16k
                  if (skip_ws<Opts>(ctx, it, end)) {
1491
8
                     return;
1492
8
                  }
1493
9.16k
               }
1494
8.03k
               else if (*it == ']') {
1495
                  if constexpr (not Opts.null_terminated) {
1496
                     --ctx.indentation_level;
1497
                  }
1498
7.50k
                  ++it;
1499
                  if constexpr (erasable<T>) {
1500
                     value.erase(value_it,
1501
                                 value.end()); // use erase rather than resize for non-default constructible elements
1502
1503
                     if constexpr (check_shrink_to_fit(Opts)) {
1504
                        value.shrink_to_fit();
1505
                     }
1506
                  }
1507
7.50k
                  return;
1508
7.50k
               }
1509
523
               else [[unlikely]] {
1510
523
                  ctx.error = error_code::expected_bracket;
1511
523
                  return;
1512
523
               }
1513
17.1k
            }
1514
8.56k
         }
1515
1516
         if constexpr (Opts.partial_read) {
1517
            return;
1518
         }
1519
8.56k
         else {
1520
            // growing
1521
            if constexpr (emplace_backable<T>) {
1522
               while (it < end) {
1523
                  parse<JSON>::op<ws_handled<Opts>()>(value.emplace_back(), ctx, it, end);
1524
                  if (bool(ctx.error)) [[unlikely]]
1525
                     return;
1526
                  if (skip_ws<Opts>(ctx, it, end)) {
1527
                     return;
1528
                  }
1529
                  if (*it == ',') [[likely]] {
1530
                     ++it;
1531
1532
                     if constexpr (!Opts.minified) {
1533
                        if (ws_size && ws_size < size_t(end - it)) {
1534
                           skip_matching_ws(ws_start, it, ws_size);
1535
                        }
1536
                     }
1537
1538
                     if (skip_ws<Opts>(ctx, it, end)) {
1539
                        return;
1540
                     }
1541
                  }
1542
                  else if (*it == ']') {
1543
                     if constexpr (not Opts.null_terminated) {
1544
                        --ctx.indentation_level;
1545
                     }
1546
                     ++it;
1547
                     return;
1548
                  }
1549
                  else [[unlikely]] {
1550
                     ctx.error = error_code::expected_bracket;
1551
                     return;
1552
                  }
1553
               }
1554
            }
1555
8.56k
            else {
1556
8.56k
               ctx.error = error_code::exceeded_static_array_size;
1557
8.56k
            }
1558
8.56k
         }
1559
8.56k
      }
_ZN3glz4fromILj10ENSt3__16vectorINS_6json_tENS1_9allocatorIS3_EEEEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj4EEERS6_TkNS_10is_contextERNS_7contextERPKcSF_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
1431
17.0k
      {
1432
17.0k
         constexpr auto Opts = ws_handled_off<Options>();
1433
         if constexpr (!check_ws_handled(Options)) {
1434
            if (skip_ws<Opts>(ctx, it, end)) {
1435
               return;
1436
            }
1437
         }
1438
1439
17.0k
         if (match_invalid_end<'[', Opts>(ctx, it, end)) {
1440
71
            return;
1441
71
         }
1442
17.0k
         if constexpr (not Opts.null_terminated) {
1443
17.0k
            ++ctx.indentation_level;
1444
17.0k
         }
1445
1446
17.0k
         const auto ws_start = it;
1447
17.0k
         if (skip_ws<Opts>(ctx, it, end)) {
1448
42
            return;
1449
42
         }
1450
1451
16.9k
         if (*it == ']') {
1452
1.18k
            if constexpr (not Opts.null_terminated) {
1453
1.18k
               --ctx.indentation_level;
1454
1.18k
            }
1455
1.18k
            ++it;
1456
1.18k
            if constexpr (resizable<T> && not Opts.append_arrays) {
1457
1.18k
               value.clear();
1458
1459
               if constexpr (check_shrink_to_fit(Opts)) {
1460
                  value.shrink_to_fit();
1461
               }
1462
1.18k
            }
1463
1.18k
            return;
1464
1.18k
         }
1465
1466
15.7k
         const size_t ws_size = size_t(it - ws_start);
1467
1468
15.7k
         static constexpr bool should_append = resizable<T> && Opts.append_arrays;
1469
15.7k
         if constexpr (not should_append) {
1470
15.7k
            const auto n = value.size();
1471
1472
15.7k
            auto value_it = value.begin();
1473
1474
73.3k
            for (size_t i = 0; i < n; ++i) {
1475
59.0k
               parse<JSON>::op<ws_handled<Opts>()>(*value_it++, ctx, it, end);
1476
59.0k
               if (bool(ctx.error)) [[unlikely]]
1477
539
                  return;
1478
58.5k
               if (skip_ws<Opts>(ctx, it, end)) {
1479
26
                  return;
1480
26
               }
1481
58.5k
               if (*it == ',') {
1482
57.6k
                  ++it;
1483
1484
57.6k
                  if constexpr (!Opts.minified) {
1485
57.6k
                     if (ws_size && ws_size < size_t(end - it)) {
1486
54.3k
                        skip_matching_ws(ws_start, it, ws_size);
1487
54.3k
                     }
1488
57.6k
                  }
1489
1490
57.6k
                  if (skip_ws<Opts>(ctx, it, end)) {
1491
103
                     return;
1492
103
                  }
1493
57.6k
               }
1494
891
               else if (*it == ']') {
1495
867
                  if constexpr (not Opts.null_terminated) {
1496
867
                     --ctx.indentation_level;
1497
867
                  }
1498
867
                  ++it;
1499
867
                  if constexpr (erasable<T>) {
1500
867
                     value.erase(value_it,
1501
867
                                 value.end()); // use erase rather than resize for non-default constructible elements
1502
1503
                     if constexpr (check_shrink_to_fit(Opts)) {
1504
                        value.shrink_to_fit();
1505
                     }
1506
867
                  }
1507
867
                  return;
1508
867
               }
1509
24
               else [[unlikely]] {
1510
24
                  ctx.error = error_code::expected_bracket;
1511
24
                  return;
1512
24
               }
1513
58.5k
            }
1514
15.7k
         }
1515
1516
         if constexpr (Opts.partial_read) {
1517
            return;
1518
         }
1519
15.7k
         else {
1520
            // growing
1521
15.7k
            if constexpr (emplace_backable<T>) {
1522
1.65M
               while (it < end) {
1523
1.65M
                  parse<JSON>::op<ws_handled<Opts>()>(value.emplace_back(), ctx, it, end);
1524
1.65M
                  if (bool(ctx.error)) [[unlikely]]
1525
10.8k
                     return;
1526
1.64M
                  if (skip_ws<Opts>(ctx, it, end)) {
1527
42
                     return;
1528
42
                  }
1529
1.64M
                  if (*it == ',') [[likely]] {
1530
1.64M
                     ++it;
1531
1532
1.64M
                     if constexpr (!Opts.minified) {
1533
1.64M
                        if (ws_size && ws_size < size_t(end - it)) {
1534
17.9k
                           skip_matching_ws(ws_start, it, ws_size);
1535
17.9k
                        }
1536
1.64M
                     }
1537
1538
1.64M
                     if (skip_ws<Opts>(ctx, it, end)) {
1539
152
                        return;
1540
152
                     }
1541
1.64M
                  }
1542
3.15k
                  else if (*it == ']') {
1543
2.83k
                     if constexpr (not Opts.null_terminated) {
1544
2.83k
                        --ctx.indentation_level;
1545
2.83k
                     }
1546
2.83k
                     ++it;
1547
2.83k
                     return;
1548
2.83k
                  }
1549
313
                  else [[unlikely]] {
1550
313
                     ctx.error = error_code::expected_bracket;
1551
313
                     return;
1552
313
                  }
1553
1.64M
               }
1554
            }
1555
            else {
1556
               ctx.error = error_code::exceeded_static_array_size;
1557
            }
1558
15.7k
         }
1559
15.7k
      }
_ZN3glz4fromILj10ENSt3__16vectorINS_6json_tENS1_9allocatorIS3_EEEEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj4EEERS6_TkNS_10is_contextERNS_7contextERPKcSF_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
1431
17.0k
      {
1432
17.0k
         constexpr auto Opts = ws_handled_off<Options>();
1433
         if constexpr (!check_ws_handled(Options)) {
1434
            if (skip_ws<Opts>(ctx, it, end)) {
1435
               return;
1436
            }
1437
         }
1438
1439
17.0k
         if (match_invalid_end<'[', Opts>(ctx, it, end)) {
1440
0
            return;
1441
0
         }
1442
         if constexpr (not Opts.null_terminated) {
1443
            ++ctx.indentation_level;
1444
         }
1445
1446
17.0k
         const auto ws_start = it;
1447
17.0k
         if (skip_ws<Opts>(ctx, it, end)) {
1448
0
            return;
1449
0
         }
1450
1451
17.0k
         if (*it == ']') {
1452
            if constexpr (not Opts.null_terminated) {
1453
               --ctx.indentation_level;
1454
            }
1455
1.18k
            ++it;
1456
1.18k
            if constexpr (resizable<T> && not Opts.append_arrays) {
1457
1.18k
               value.clear();
1458
1459
               if constexpr (check_shrink_to_fit(Opts)) {
1460
                  value.shrink_to_fit();
1461
               }
1462
1.18k
            }
1463
1.18k
            return;
1464
1.18k
         }
1465
1466
15.9k
         const size_t ws_size = size_t(it - ws_start);
1467
1468
15.9k
         static constexpr bool should_append = resizable<T> && Opts.append_arrays;
1469
15.9k
         if constexpr (not should_append) {
1470
15.9k
            const auto n = value.size();
1471
1472
15.9k
            auto value_it = value.begin();
1473
1474
73.5k
            for (size_t i = 0; i < n; ++i) {
1475
59.1k
               parse<JSON>::op<ws_handled<Opts>()>(*value_it++, ctx, it, end);
1476
59.1k
               if (bool(ctx.error)) [[unlikely]]
1477
569
                  return;
1478
58.5k
               if (skip_ws<Opts>(ctx, it, end)) {
1479
0
                  return;
1480
0
               }
1481
58.5k
               if (*it == ',') {
1482
57.6k
                  ++it;
1483
1484
57.6k
                  if constexpr (!Opts.minified) {
1485
57.6k
                     if (ws_size && ws_size < size_t(end - it)) {
1486
54.4k
                        skip_matching_ws(ws_start, it, ws_size);
1487
54.4k
                     }
1488
57.6k
                  }
1489
1490
57.6k
                  if (skip_ws<Opts>(ctx, it, end)) {
1491
0
                     return;
1492
0
                  }
1493
57.6k
               }
1494
934
               else if (*it == ']') {
1495
                  if constexpr (not Opts.null_terminated) {
1496
                     --ctx.indentation_level;
1497
                  }
1498
865
                  ++it;
1499
865
                  if constexpr (erasable<T>) {
1500
865
                     value.erase(value_it,
1501
865
                                 value.end()); // use erase rather than resize for non-default constructible elements
1502
1503
                     if constexpr (check_shrink_to_fit(Opts)) {
1504
                        value.shrink_to_fit();
1505
                     }
1506
865
                  }
1507
865
                  return;
1508
865
               }
1509
69
               else [[unlikely]] {
1510
69
                  ctx.error = error_code::expected_bracket;
1511
69
                  return;
1512
69
               }
1513
58.5k
            }
1514
15.9k
         }
1515
1516
         if constexpr (Opts.partial_read) {
1517
            return;
1518
         }
1519
15.9k
         else {
1520
            // growing
1521
15.9k
            if constexpr (emplace_backable<T>) {
1522
1.65M
               while (it < end) {
1523
1.65M
                  parse<JSON>::op<ws_handled<Opts>()>(value.emplace_back(), ctx, it, end);
1524
1.65M
                  if (bool(ctx.error)) [[unlikely]]
1525
10.6k
                     return;
1526
1.64M
                  if (skip_ws<Opts>(ctx, it, end)) {
1527
0
                     return;
1528
0
                  }
1529
1.64M
                  if (*it == ',') [[likely]] {
1530
1.64M
                     ++it;
1531
1532
1.64M
                     if constexpr (!Opts.minified) {
1533
1.64M
                        if (ws_size && ws_size < size_t(end - it)) {
1534
18.0k
                           skip_matching_ws(ws_start, it, ws_size);
1535
18.0k
                        }
1536
1.64M
                     }
1537
1538
1.64M
                     if (skip_ws<Opts>(ctx, it, end)) {
1539
0
                        return;
1540
0
                     }
1541
1.64M
                  }
1542
3.78k
                  else if (*it == ']') {
1543
                     if constexpr (not Opts.null_terminated) {
1544
                        --ctx.indentation_level;
1545
                     }
1546
2.83k
                     ++it;
1547
2.83k
                     return;
1548
2.83k
                  }
1549
942
                  else [[unlikely]] {
1550
942
                     ctx.error = error_code::expected_bracket;
1551
942
                     return;
1552
942
                  }
1553
1.64M
               }
1554
            }
1555
            else {
1556
               ctx.error = error_code::exceeded_static_array_size;
1557
            }
1558
15.9k
         }
1559
15.9k
      }
_ZN3glz4fromILj10ENSt3__16vectorINS_6json_tENS1_9allocatorIS3_EEEEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj36EEERS6_TkNS_10is_contextERNS_7contextERPKcSF_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
1431
17.0k
      {
1432
17.0k
         constexpr auto Opts = ws_handled_off<Options>();
1433
         if constexpr (!check_ws_handled(Options)) {
1434
            if (skip_ws<Opts>(ctx, it, end)) {
1435
               return;
1436
            }
1437
         }
1438
1439
17.0k
         if (match_invalid_end<'[', Opts>(ctx, it, end)) {
1440
0
            return;
1441
0
         }
1442
         if constexpr (not Opts.null_terminated) {
1443
            ++ctx.indentation_level;
1444
         }
1445
1446
17.0k
         const auto ws_start = it;
1447
17.0k
         if (skip_ws<Opts>(ctx, it, end)) {
1448
0
            return;
1449
0
         }
1450
1451
17.0k
         if (*it == ']') {
1452
            if constexpr (not Opts.null_terminated) {
1453
               --ctx.indentation_level;
1454
            }
1455
1.18k
            ++it;
1456
1.18k
            if constexpr (resizable<T> && not Opts.append_arrays) {
1457
1.18k
               value.clear();
1458
1459
               if constexpr (check_shrink_to_fit(Opts)) {
1460
                  value.shrink_to_fit();
1461
               }
1462
1.18k
            }
1463
1.18k
            return;
1464
1.18k
         }
1465
1466
15.8k
         const size_t ws_size = size_t(it - ws_start);
1467
1468
15.8k
         static constexpr bool should_append = resizable<T> && Opts.append_arrays;
1469
15.8k
         if constexpr (not should_append) {
1470
15.8k
            const auto n = value.size();
1471
1472
15.8k
            auto value_it = value.begin();
1473
1474
73.5k
            for (size_t i = 0; i < n; ++i) {
1475
59.1k
               parse<JSON>::op<ws_handled<Opts>()>(*value_it++, ctx, it, end);
1476
59.1k
               if (bool(ctx.error)) [[unlikely]]
1477
573
                  return;
1478
58.5k
               if (skip_ws<Opts>(ctx, it, end)) {
1479
0
                  return;
1480
0
               }
1481
58.5k
               if (*it == ',') {
1482
57.6k
                  ++it;
1483
1484
57.6k
                  if constexpr (!Opts.minified) {
1485
57.6k
                     if (ws_size && ws_size < size_t(end - it)) {
1486
54.4k
                        skip_matching_ws(ws_start, it, ws_size);
1487
54.4k
                     }
1488
57.6k
                  }
1489
1490
57.6k
                  if (skip_ws<Opts>(ctx, it, end)) {
1491
0
                     return;
1492
0
                  }
1493
57.6k
               }
1494
930
               else if (*it == ']') {
1495
                  if constexpr (not Opts.null_terminated) {
1496
                     --ctx.indentation_level;
1497
                  }
1498
862
                  ++it;
1499
862
                  if constexpr (erasable<T>) {
1500
862
                     value.erase(value_it,
1501
862
                                 value.end()); // use erase rather than resize for non-default constructible elements
1502
1503
                     if constexpr (check_shrink_to_fit(Opts)) {
1504
                        value.shrink_to_fit();
1505
                     }
1506
862
                  }
1507
862
                  return;
1508
862
               }
1509
68
               else [[unlikely]] {
1510
68
                  ctx.error = error_code::expected_bracket;
1511
68
                  return;
1512
68
               }
1513
58.5k
            }
1514
15.8k
         }
1515
1516
         if constexpr (Opts.partial_read) {
1517
            return;
1518
         }
1519
15.8k
         else {
1520
            // growing
1521
15.8k
            if constexpr (emplace_backable<T>) {
1522
1.65M
               while (it < end) {
1523
1.65M
                  parse<JSON>::op<ws_handled<Opts>()>(value.emplace_back(), ctx, it, end);
1524
1.65M
                  if (bool(ctx.error)) [[unlikely]]
1525
10.6k
                     return;
1526
1.64M
                  if (skip_ws<Opts>(ctx, it, end)) {
1527
0
                     return;
1528
0
                  }
1529
1.64M
                  if (*it == ',') [[likely]] {
1530
1.64M
                     ++it;
1531
1532
1.64M
                     if constexpr (!Opts.minified) {
1533
1.64M
                        if (ws_size && ws_size < size_t(end - it)) {
1534
18.0k
                           skip_matching_ws(ws_start, it, ws_size);
1535
18.0k
                        }
1536
1.64M
                     }
1537
1538
1.64M
                     if (skip_ws<Opts>(ctx, it, end)) {
1539
0
                        return;
1540
0
                     }
1541
1.64M
                  }
1542
3.75k
                  else if (*it == ']') {
1543
                     if constexpr (not Opts.null_terminated) {
1544
                        --ctx.indentation_level;
1545
                     }
1546
2.83k
                     ++it;
1547
2.83k
                     return;
1548
2.83k
                  }
1549
921
                  else [[unlikely]] {
1550
921
                     ctx.error = error_code::expected_bracket;
1551
921
                     return;
1552
921
                  }
1553
1.64M
               }
1554
            }
1555
            else {
1556
               ctx.error = error_code::exceeded_static_array_size;
1557
            }
1558
15.8k
         }
1559
15.8k
      }
1560
1561
      // for types like std::vector<std::pair...> that can't look up with operator[]
1562
      // Intead of hashing or linear searching, we just clear the input and overwrite the entire contents
1563
      template <auto Options>
1564
         requires(pair_t<range_value_t<T>> && check_concatenate(Options) == true)
1565
      static void op(auto&& value, is_context auto&& ctx, auto&& it, auto&& end)
1566
      {
1567
         static constexpr auto Opts = opening_handled_off<ws_handled_off<Options>()>();
1568
         if constexpr (!check_opening_handled(Options)) {
1569
            if constexpr (!check_ws_handled(Options)) {
1570
               if (skip_ws<Opts>(ctx, it, end)) {
1571
                  return;
1572
               }
1573
            }
1574
            if (match_invalid_end<'{', Opts>(ctx, it, end)) {
1575
               return;
1576
            }
1577
            if constexpr (not Opts.null_terminated) {
1578
               if (it == end) [[unlikely]] {
1579
                  ctx.error = error_code::unexpected_end;
1580
                  return;
1581
               }
1582
            }
1583
            if constexpr (not Opts.null_terminated) {
1584
               ++ctx.indentation_level;
1585
            }
1586
         }
1587
1588
         // clear all contents and repopulate
1589
         value.clear();
1590
1591
         while (it < end) {
1592
            if (skip_ws<Opts>(ctx, it, end)) {
1593
               return;
1594
            }
1595
1596
            if (*it == '}') {
1597
               ++it;
1598
               if constexpr (not Opts.null_terminated) {
1599
                  --ctx.indentation_level;
1600
               }
1601
               if constexpr (not Opts.null_terminated) {
1602
                  if (it == end) {
1603
                     ctx.error = error_code::end_reached;
1604
                     return;
1605
                  }
1606
               }
1607
               return;
1608
            }
1609
1610
            auto& item = value.emplace_back();
1611
1612
            using V = std::decay_t<decltype(item)>;
1613
1614
            if constexpr (str_t<typename V::first_type> ||
1615
                          (std::is_enum_v<typename V::first_type> && glaze_t<typename V::first_type>)) {
1616
               parse<JSON>::op<Opts>(item.first, ctx, it, end);
1617
               if (bool(ctx.error)) [[unlikely]]
1618
                  return;
1619
            }
1620
            else {
1621
               std::string_view key;
1622
               parse<JSON>::op<Opts>(key, ctx, it, end);
1623
               if (bool(ctx.error)) [[unlikely]]
1624
                  return;
1625
               if constexpr (Opts.null_terminated) {
1626
                  parse<JSON>::op<Opts>(item.first, ctx, key.data(), key.data() + key.size());
1627
               }
1628
               else {
1629
                  if (size_t(end - it) == key.size()) [[unlikely]] {
1630
                     ctx.error = error_code::unexpected_end;
1631
                     return;
1632
                  }
1633
                  // For the non-null terminated case we just want one more character so that we don't parse
1634
                  // until the end of the buffer and create an end_reached code (unless there is an error).
1635
                  parse<JSON>::op<Opts>(item.first, ctx, key.data(), key.data() + key.size() + 1);
1636
               }
1637
               if (bool(ctx.error)) [[unlikely]]
1638
                  return;
1639
            }
1640
1641
            if (parse_ws_colon<Opts>(ctx, it, end)) {
1642
               return;
1643
            }
1644
1645
            parse<JSON>::op<Opts>(item.second, ctx, it, end);
1646
            if (bool(ctx.error)) [[unlikely]]
1647
               return;
1648
1649
            if (skip_ws<Opts>(ctx, it, end)) {
1650
               return;
1651
            }
1652
1653
            if (*it == ',') {
1654
               ++it;
1655
               if constexpr (not Opts.null_terminated) {
1656
                  if (it == end) [[unlikely]] {
1657
                     ctx.error = error_code::unexpected_end;
1658
                     return;
1659
                  }
1660
               }
1661
            }
1662
         }
1663
1664
         ctx.error = error_code::unexpected_end;
1665
      }
1666
   };
1667
1668
   // counts the number of JSON array elements
1669
   // needed for classes that are resizable, but do not have an emplace_back
1670
   // 'it' is copied so that it does not actually progress the iterator
1671
   // expects the opening brace ([) to have already been consumed
1672
   template <auto Opts>
1673
   [[nodiscard]] size_t number_of_array_elements(is_context auto&& ctx, auto it, auto&& end) noexcept
1674
   {
1675
      skip_ws<Opts>(ctx, it, end);
1676
      if (bool(ctx.error)) [[unlikely]]
1677
         return {};
1678
1679
      if (*it == ']') [[unlikely]] {
1680
         return 0;
1681
      }
1682
      size_t count = 1;
1683
      while (true) {
1684
         switch (*it) {
1685
         case ',': {
1686
            ++count;
1687
            ++it;
1688
            break;
1689
         }
1690
         case '/': {
1691
            skip_comment(ctx, it, end);
1692
            if (bool(ctx.error)) [[unlikely]]
1693
               return {};
1694
            break;
1695
         }
1696
         case '{':
1697
            ++it;
1698
            skip_until_closed<Opts, '{', '}'>(ctx, it, end);
1699
            if (bool(ctx.error)) [[unlikely]]
1700
               return {};
1701
            break;
1702
         case '[':
1703
            ++it;
1704
            skip_until_closed<Opts, '[', ']'>(ctx, it, end);
1705
            if (bool(ctx.error)) [[unlikely]]
1706
               return {};
1707
            break;
1708
         case '"': {
1709
            skip_string<Opts>(ctx, it, end);
1710
            if (bool(ctx.error)) [[unlikely]]
1711
               return {};
1712
            break;
1713
         }
1714
         case ']': {
1715
            return count;
1716
         }
1717
         case '\0': {
1718
            ctx.error = error_code::unexpected_end;
1719
            return {};
1720
         }
1721
         default:
1722
            ++it;
1723
         }
1724
      }
1725
      unreachable();
1726
   }
1727
1728
   // For types like std::forward_list
1729
   template <class T>
1730
      requires readable_array_t<T> && (!emplace_backable<T> && resizable<T>)
1731
   struct from<JSON, T>
1732
   {
1733
      template <auto Options>
1734
      static void op(auto& value, is_context auto&& ctx, auto&& it, auto&& end)
1735
      {
1736
         constexpr auto Opts = ws_handled_off<Options>();
1737
         if constexpr (!check_ws_handled(Options)) {
1738
            if (skip_ws<Opts>(ctx, it, end)) {
1739
               return;
1740
            }
1741
         }
1742
1743
         if (match_invalid_end<'[', Opts>(ctx, it, end)) {
1744
            return;
1745
         }
1746
         if constexpr (not Opts.null_terminated) {
1747
            ++ctx.indentation_level;
1748
         }
1749
         const auto n = number_of_array_elements<Opts>(ctx, it, end);
1750
         if (bool(ctx.error)) [[unlikely]]
1751
            return;
1752
         value.resize(n);
1753
         size_t i = 0;
1754
         for (auto& x : value) {
1755
            parse<JSON>::op<Opts>(x, ctx, it, end);
1756
            if (bool(ctx.error)) [[unlikely]]
1757
               return;
1758
1759
            if (skip_ws<Opts>(ctx, it, end)) {
1760
               return;
1761
            }
1762
            if (i < n - 1) {
1763
               if (match_invalid_end<',', Opts>(ctx, it, end)) {
1764
                  return;
1765
               }
1766
            }
1767
            ++i;
1768
         }
1769
         match<']'>(ctx, it);
1770
         if constexpr (not Opts.null_terminated) {
1771
            --ctx.indentation_level;
1772
         }
1773
      }
1774
   };
1775
1776
   template <class T>
1777
      requires glaze_array_t<T> || tuple_t<T> || is_std_tuple<T>
1778
   struct from<JSON, T>
1779
   {
1780
      template <auto Opts>
1781
      static void op(auto& value, is_context auto&& ctx, auto&& it, auto&& end)
1782
      {
1783
         static constexpr auto N = []() constexpr {
1784
            if constexpr (glaze_array_t<T>) {
1785
               return reflect<T>::size;
1786
            }
1787
            else {
1788
               return glz::tuple_size_v<T>;
1789
            }
1790
         }();
1791
1792
         if constexpr (!check_ws_handled(Opts)) {
1793
            if (skip_ws<Opts>(ctx, it, end)) {
1794
               return;
1795
            }
1796
         }
1797
1798
         if (match_invalid_end<'[', Opts>(ctx, it, end)) {
1799
            return;
1800
         }
1801
         if constexpr (not Opts.null_terminated) {
1802
            ++ctx.indentation_level;
1803
         }
1804
         if (skip_ws<Opts>(ctx, it, end)) {
1805
            return;
1806
         }
1807
1808
         for_each<N>([&]<size_t I>() {
1809
            if (bool(ctx.error)) [[unlikely]]
1810
               return;
1811
1812
            if (*it == ']') {
1813
               if constexpr (not Opts.null_terminated) {
1814
                  --ctx.indentation_level;
1815
               }
1816
               return;
1817
            }
1818
            if constexpr (I != 0) {
1819
               if (match_invalid_end<',', Opts>(ctx, it, end)) {
1820
                  return;
1821
               }
1822
               if (skip_ws<Opts>(ctx, it, end)) {
1823
                  return;
1824
               }
1825
            }
1826
            if constexpr (is_std_tuple<T>) {
1827
               parse<JSON>::op<ws_handled<Opts>()>(std::get<I>(value), ctx, it, end);
1828
               if (bool(ctx.error)) [[unlikely]]
1829
                  return;
1830
            }
1831
            else if constexpr (glaze_array_t<T>) {
1832
               parse<JSON>::op<ws_handled<Opts>()>(get_member(value, glz::get<I>(meta_v<T>)), ctx, it, end);
1833
               if (bool(ctx.error)) [[unlikely]]
1834
                  return;
1835
            }
1836
            else {
1837
               parse<JSON>::op<ws_handled<Opts>()>(glz::get<I>(value), ctx, it, end);
1838
               if (bool(ctx.error)) [[unlikely]]
1839
                  return;
1840
            }
1841
            if (skip_ws<Opts>(ctx, it, end)) {
1842
               return;
1843
            }
1844
         });
1845
1846
         if constexpr (Opts.partial_read) {
1847
            return;
1848
         }
1849
         else {
1850
            if (bool(ctx.error)) [[unlikely]]
1851
               return;
1852
            match<']'>(ctx, it);
1853
            if constexpr (not Opts.null_terminated) {
1854
               --ctx.indentation_level;
1855
            }
1856
            if constexpr (not Opts.null_terminated) {
1857
               if (it == end) {
1858
                  ctx.error = error_code::end_reached;
1859
                  return;
1860
               }
1861
            }
1862
         }
1863
      }
1864
   };
1865
1866
   template <glaze_flags_t T>
1867
   struct from<JSON, T>
1868
   {
1869
      template <auto Opts>
1870
      static void op(auto&& value, is_context auto&& ctx, auto&& it, auto&& end)
1871
      {
1872
         if constexpr (!check_ws_handled(Opts)) {
1873
            if (skip_ws<Opts>(ctx, it, end)) {
1874
               return;
1875
            }
1876
         }
1877
1878
         if (match_invalid_end<'[', Opts>(ctx, it, end)) {
1879
            return;
1880
         }
1881
         if constexpr (not Opts.null_terminated) {
1882
            ++ctx.indentation_level;
1883
         }
1884
1885
         std::string& s = string_buffer();
1886
1887
         constexpr auto& HashInfo = hash_info<T>;
1888
         static_assert(bool(HashInfo.type));
1889
1890
         while (true) {
1891
            parse<JSON>::op<ws_handled_off<Opts>()>(s, ctx, it, end);
1892
            if (bool(ctx.error)) [[unlikely]]
1893
               return;
1894
1895
            const auto index =
1896
               decode_hash_with_size<JSON, T, HashInfo, HashInfo.type>::op(s.data(), s.data() + s.size(), s.size());
1897
1898
            constexpr auto N = reflect<T>::size;
1899
            if (index < N) [[likely]] {
1900
               visit<N>([&]<size_t I>() { get_member(value, get<I>(reflect<T>::values)) = true; }, index);
1901
            }
1902
            else [[unlikely]] {
1903
               ctx.error = error_code::invalid_flag_input;
1904
               return;
1905
            }
1906
1907
            if (skip_ws<Opts>(ctx, it, end)) {
1908
               return;
1909
            }
1910
            if (*it == ']') {
1911
               if constexpr (not Opts.null_terminated) {
1912
                  --ctx.indentation_level;
1913
               }
1914
               ++it;
1915
               if constexpr (not Opts.null_terminated) {
1916
                  if (it == end) {
1917
                     ctx.error = error_code::end_reached;
1918
                     return;
1919
                  }
1920
               }
1921
               return;
1922
            }
1923
            if (match_invalid_end<',', Opts>(ctx, it, end)) {
1924
               return;
1925
            }
1926
         }
1927
      }
1928
   };
1929
1930
   template <class T>
1931
   struct from<JSON, includer<T>>
1932
   {
1933
      template <auto Options>
1934
      static void op(auto&& value, is_context auto&& ctx, auto&& it, auto&& end)
1935
      {
1936
         constexpr auto Opts = ws_handled_off<Options>();
1937
         std::string buffer{};
1938
         parse<JSON>::op<Opts>(buffer, ctx, it, end);
1939
         if (bool(ctx.error)) [[unlikely]]
1940
            return;
1941
1942
         const auto file_path = relativize_if_not_absolute(std::filesystem::path(ctx.current_file).parent_path(),
1943
                                                           std::filesystem::path{buffer});
1944
1945
         const auto string_file_path = file_path.string();
1946
         const auto ec = file_to_buffer(buffer, string_file_path);
1947
1948
         if (bool(ec)) [[unlikely]] {
1949
            ctx.error = error_code::includer_error;
1950
            auto& error_msg = error_buffer();
1951
            error_msg = "file failed to open: " + string_file_path;
1952
            ctx.includer_error = error_msg;
1953
            return;
1954
         }
1955
1956
         const auto current_file = ctx.current_file;
1957
         ctx.current_file = string_file_path;
1958
1959
         // We need to allocate a new buffer here because we could call another includer that uses the buffer
1960
         std::string nested_buffer = buffer;
1961
         static constexpr auto NestedOpts = opt_true<disable_padding_on<Opts>(), &opts::null_terminated>;
1962
         const auto ecode = glz::read<NestedOpts>(value.value, nested_buffer, ctx);
1963
         if (bool(ctx.error)) [[unlikely]] {
1964
            ctx.error = error_code::includer_error;
1965
            auto& error_msg = error_buffer();
1966
            error_msg = glz::format_error(ecode, nested_buffer);
1967
            ctx.includer_error = error_msg;
1968
            return;
1969
         }
1970
1971
         ctx.current_file = current_file;
1972
      }
1973
   };
1974
1975
   template <pair_t T>
1976
   struct from<JSON, T>
1977
   {
1978
      template <auto Options, string_literal tag = "">
1979
      static void op(T& value, is_context auto&& ctx, auto&& it, auto&& end)
1980
      {
1981
         constexpr auto Opts = opening_handled_off<ws_handled_off<Options>()>();
1982
         if constexpr (!check_opening_handled(Options)) {
1983
            if constexpr (!check_ws_handled(Options)) {
1984
               if (skip_ws<Opts>(ctx, it, end)) {
1985
                  return;
1986
               }
1987
            }
1988
            if (match_invalid_end<'{', Opts>(ctx, it, end)) {
1989
               return;
1990
            }
1991
            if constexpr (not Opts.null_terminated) {
1992
               ++ctx.indentation_level;
1993
            }
1994
         }
1995
         if (skip_ws<Opts>(ctx, it, end)) {
1996
            return;
1997
         }
1998
1999
         if (*it == '}') {
2000
            if constexpr (not Opts.null_terminated) {
2001
               --ctx.indentation_level;
2002
            }
2003
            if constexpr (Opts.error_on_missing_keys) {
2004
               ctx.error = error_code::missing_key;
2005
            }
2006
            return;
2007
         }
2008
2009
         using first_type = typename T::first_type;
2010
         if constexpr (str_t<first_type> || is_named_enum<first_type>) {
2011
            parse<JSON>::op<Opts>(value.first, ctx, it, end);
2012
            if (bool(ctx.error)) [[unlikely]]
2013
               return;
2014
         }
2015
         else {
2016
            std::string_view key;
2017
            parse<JSON>::op<Opts>(key, ctx, it, end);
2018
            if (bool(ctx.error)) [[unlikely]]
2019
               return;
2020
            if constexpr (Opts.null_terminated) {
2021
               parse<JSON>::op<Opts>(value.first, ctx, key.data(), key.data() + key.size());
2022
            }
2023
            else {
2024
               if (size_t(end - it) == key.size()) [[unlikely]] {
2025
                  ctx.error = error_code::unexpected_end;
2026
                  return;
2027
               }
2028
               // For the non-null terminated case we just want one more character so that we don't parse
2029
               // until the end of the buffer and create an end_reached code (unless there is an error).
2030
               parse<JSON>::op<Opts>(value.first, ctx, key.data(), key.data() + key.size() + 1);
2031
            }
2032
            if (bool(ctx.error)) [[unlikely]]
2033
               return;
2034
         }
2035
2036
         if (parse_ws_colon<Opts>(ctx, it, end)) {
2037
            return;
2038
         }
2039
2040
         parse<JSON>::op<Opts>(value.second, ctx, it, end);
2041
         if (bool(ctx.error)) [[unlikely]]
2042
            return;
2043
2044
         if (skip_ws<Opts>(ctx, it, end)) {
2045
            return;
2046
         }
2047
2048
         match<'}'>(ctx, it);
2049
         if constexpr (not Opts.null_terminated) {
2050
            --ctx.indentation_level;
2051
         }
2052
         if constexpr (not Opts.null_terminated) {
2053
            if (it == end) {
2054
               ctx.error = error_code::end_reached;
2055
               return;
2056
            }
2057
         }
2058
      }
2059
   };
2060
2061
   template <class T, string_literal Tag>
2062
   inline consteval bool contains_tag()
2063
   {
2064
      auto& keys = reflect<T>::keys;
2065
      for (size_t i = 0; i < keys.size(); ++i) {
2066
         if (Tag.sv() == keys[i]) {
2067
            return true;
2068
         }
2069
      }
2070
      return false;
2071
   }
2072
2073
   template <class T>
2074
      requires((readable_map_t<T> || glaze_object_t<T> || reflectable<T>) && not custom_read<T>)
2075
   struct from<JSON, T>
2076
   {
2077
      template <auto Options, string_literal tag = "">
2078
      static void op(auto&& value, is_context auto&& ctx, auto&& it, auto&& end)
2079
42.5k
      {
2080
42.5k
         static constexpr auto num_members = reflect<T>::size;
2081
2082
42.5k
         static constexpr auto Opts = opening_handled_off<ws_handled_off<Options>()>();
2083
42.5k
         if constexpr (!check_opening_handled(Options)) {
2084
18.9k
            if constexpr (!check_ws_handled(Options)) {
2085
18.9k
               if (skip_ws<Opts>(ctx, it, end)) {
2086
32
                  return;
2087
32
               }
2088
18.9k
            }
2089
18.9k
            if (match_invalid_end<'{', Opts>(ctx, it, end)) {
2090
167
               return;
2091
167
            }
2092
18.8k
            if constexpr (not Opts.null_terminated) {
2093
4.57k
               if (it == end) [[unlikely]] {
2094
0
                  ctx.error = error_code::unexpected_end;
2095
0
                  return;
2096
0
               }
2097
4.57k
            }
2098
4.57k
            if constexpr (not Opts.null_terminated) {
2099
4.57k
               ++ctx.indentation_level;
2100
4.57k
            }
2101
18.8k
         }
2102
14.2k
         const auto ws_start = it;
2103
42.5k
         if (skip_ws<Opts>(ctx, it, end)) {
2104
42
            return;
2105
42
         }
2106
42.4k
         const size_t ws_size = size_t(it - ws_start);
2107
2108
         if constexpr ((glaze_object_t<T> || reflectable<T>) && num_members == 0 && Opts.error_on_unknown_keys) {
2109
            if constexpr (not tag.sv().empty()) {
2110
               if (*it == '"') {
2111
                  ++it;
2112
                  if constexpr (not Opts.null_terminated) {
2113
                     if (it == end) [[unlikely]] {
2114
                        ctx.error = error_code::unexpected_end;
2115
                        return;
2116
                     }
2117
                  }
2118
2119
                  const auto start = it;
2120
                  skip_string_view<Opts>(ctx, it, end);
2121
                  if (bool(ctx.error)) [[unlikely]]
2122
                     return;
2123
                  const sv key{start, size_t(it - start)};
2124
                  ++it;
2125
                  if constexpr (not Opts.null_terminated) {
2126
                     if (it == end) [[unlikely]] {
2127
                        ctx.error = error_code::unexpected_end;
2128
                        return;
2129
                     }
2130
                  }
2131
2132
                  if (key == tag.sv()) {
2133
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2134
                        return;
2135
                     }
2136
2137
                     parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
2138
                     if (bool(ctx.error)) [[unlikely]]
2139
                        return;
2140
2141
                     if (skip_ws<Opts>(ctx, it, end)) {
2142
                        return;
2143
                     }
2144
                  }
2145
                  else {
2146
                     ctx.error = error_code::unknown_key;
2147
                     return;
2148
                  }
2149
               }
2150
            }
2151
2152
            if (*it == '}') [[likely]] {
2153
               if constexpr (not Opts.null_terminated) {
2154
                  --ctx.indentation_level;
2155
               }
2156
               ++it;
2157
               if constexpr (not Opts.null_terminated) {
2158
                  if (it == end) {
2159
                     ctx.error = error_code::end_reached;
2160
                     return;
2161
                  }
2162
               }
2163
               if constexpr (Opts.partial_read) {
2164
                  ctx.error = error_code::partial_read_complete;
2165
               }
2166
               return;
2167
            }
2168
            ctx.error = error_code::unknown_key;
2169
            return;
2170
         }
2171
42.4k
         else {
2172
42.4k
            decltype(auto) fields = [&]() -> decltype(auto) {
2173
               if constexpr ((glaze_object_t<T> || reflectable<T>) &&
2174
                             (Opts.error_on_missing_keys || Opts.partial_read)) {
2175
                  return bit_array<num_members>{};
2176
               }
2177
42.2k
               else {
2178
42.2k
                  return nullptr;
2179
42.2k
               }
2180
42.2k
            }();
_ZZN3glz4fromILj10E9my_structE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1EEETnNS_14string_literalEXtlNS5_ILm1EEEEERS1_TkNS_10is_contextERNS_7contextERPKcSC_EEvOT1_OT2_OT3_OT4_ENKUlvE_clEv
Line
Count
Source
2172
4.53k
            decltype(auto) fields = [&]() -> decltype(auto) {
2173
               if constexpr ((glaze_object_t<T> || reflectable<T>) &&
2174
                             (Opts.error_on_missing_keys || Opts.partial_read)) {
2175
                  return bit_array<num_members>{};
2176
               }
2177
4.53k
               else {
2178
4.53k
                  return nullptr;
2179
4.53k
               }
2180
4.53k
            }();
_ZZN3glz4fromILj10E9my_structE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1EEETnNS_14string_literalEXtlNS5_ILm1EEEEERS1_TkNS_10is_contextERNS_7contextERPKcSC_EEvOT1_OT2_OT3_OT4_ENKUlvE_clEv
Line
Count
Source
2172
4.56k
            decltype(auto) fields = [&]() -> decltype(auto) {
2173
               if constexpr ((glaze_object_t<T> || reflectable<T>) &&
2174
                             (Opts.error_on_missing_keys || Opts.partial_read)) {
2175
                  return bit_array<num_members>{};
2176
               }
2177
4.56k
               else {
2178
4.56k
                  return nullptr;
2179
4.56k
               }
2180
4.56k
            }();
_ZZN3glz4fromILj10E9my_structE2opITnDaXtlNS_4optsELj10ELb1ELb1ELb1ELb1ELb0ELb0ELc32ELh3ELb1EEETnNS_14string_literalEXtlNS5_ILm1EEEEERS1_TkNS_10is_contextERNS_7contextERPKcSC_EEvOT1_OT2_OT3_OT4_ENKUlvE_clEv
Line
Count
Source
2172
5.96k
            decltype(auto) fields = [&]() -> decltype(auto) {
2173
               if constexpr ((glaze_object_t<T> || reflectable<T>) &&
2174
                             (Opts.error_on_missing_keys || Opts.partial_read)) {
2175
                  return bit_array<num_members>{};
2176
               }
2177
5.96k
               else {
2178
5.96k
                  return nullptr;
2179
5.96k
               }
2180
5.96k
            }();
_ZZN3glz4fromILj10E1SE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEETnNS_14string_literalEXtlNS5_ILm1EEEEERS1_TkNS_10is_contextERNS_7contextERPKcSC_EEvOT1_OT2_OT3_OT4_ENKUlvE_clEv
Line
Count
Source
2172
415
            decltype(auto) fields = [&]() -> decltype(auto) {
2173
               if constexpr ((glaze_object_t<T> || reflectable<T>) &&
2174
                             (Opts.error_on_missing_keys || Opts.partial_read)) {
2175
                  return bit_array<num_members>{};
2176
               }
2177
415
               else {
2178
415
                  return nullptr;
2179
415
               }
2180
415
            }();
_ZZN3glz4fromILj10E5ValueIfEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEETnNS_14string_literalEXtlNS6_ILm1EEEEERS2_TkNS_10is_contextERNS_7contextERPKcSD_EEvOT1_OT2_OT3_OT4_ENKUlvE_clEv
Line
Count
Source
2172
488
            decltype(auto) fields = [&]() -> decltype(auto) {
2173
               if constexpr ((glaze_object_t<T> || reflectable<T>) &&
2174
                             (Opts.error_on_missing_keys || Opts.partial_read)) {
2175
                  return bit_array<num_members>{};
2176
               }
2177
488
               else {
2178
488
                  return nullptr;
2179
488
               }
2180
488
            }();
_ZZN3glz4fromILj10E5ValueIdEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEETnNS_14string_literalEXtlNS6_ILm1EEEEERS2_TkNS_10is_contextERNS_7contextERPKcSD_EEvOT1_OT2_OT3_OT4_ENKUlvE_clEv
Line
Count
Source
2172
1.05k
            decltype(auto) fields = [&]() -> decltype(auto) {
2173
               if constexpr ((glaze_object_t<T> || reflectable<T>) &&
2174
                             (Opts.error_on_missing_keys || Opts.partial_read)) {
2175
                  return bit_array<num_members>{};
2176
               }
2177
1.05k
               else {
2178
1.05k
                  return nullptr;
2179
1.05k
               }
2180
1.05k
            }();
_ZZN3glz4fromILj10E5ValueIsEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEETnNS_14string_literalEXtlNS6_ILm1EEEEERS2_TkNS_10is_contextERNS_7contextERPKcSD_EEvOT1_OT2_OT3_OT4_ENKUlvE_clEv
Line
Count
Source
2172
106
            decltype(auto) fields = [&]() -> decltype(auto) {
2173
               if constexpr ((glaze_object_t<T> || reflectable<T>) &&
2174
                             (Opts.error_on_missing_keys || Opts.partial_read)) {
2175
                  return bit_array<num_members>{};
2176
               }
2177
106
               else {
2178
106
                  return nullptr;
2179
106
               }
2180
106
            }();
_ZZN3glz4fromILj10E5ValueItEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEETnNS_14string_literalEXtlNS6_ILm1EEEEERS2_TkNS_10is_contextERNS_7contextERPKcSD_EEvOT1_OT2_OT3_OT4_ENKUlvE_clEv
Line
Count
Source
2172
106
            decltype(auto) fields = [&]() -> decltype(auto) {
2173
               if constexpr ((glaze_object_t<T> || reflectable<T>) &&
2174
                             (Opts.error_on_missing_keys || Opts.partial_read)) {
2175
                  return bit_array<num_members>{};
2176
               }
2177
106
               else {
2178
106
                  return nullptr;
2179
106
               }
2180
106
            }();
_ZZN3glz4fromILj10E5ValueIiEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEETnNS_14string_literalEXtlNS6_ILm1EEEEERS2_TkNS_10is_contextERNS_7contextERPKcSD_EEvOT1_OT2_OT3_OT4_ENKUlvE_clEv
Line
Count
Source
2172
169
            decltype(auto) fields = [&]() -> decltype(auto) {
2173
               if constexpr ((glaze_object_t<T> || reflectable<T>) &&
2174
                             (Opts.error_on_missing_keys || Opts.partial_read)) {
2175
                  return bit_array<num_members>{};
2176
               }
2177
169
               else {
2178
169
                  return nullptr;
2179
169
               }
2180
169
            }();
_ZZN3glz4fromILj10E5ValueIjEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEETnNS_14string_literalEXtlNS6_ILm1EEEEERS2_TkNS_10is_contextERNS_7contextERPKcSD_EEvOT1_OT2_OT3_OT4_ENKUlvE_clEv
Line
Count
Source
2172
169
            decltype(auto) fields = [&]() -> decltype(auto) {
2173
               if constexpr ((glaze_object_t<T> || reflectable<T>) &&
2174
                             (Opts.error_on_missing_keys || Opts.partial_read)) {
2175
                  return bit_array<num_members>{};
2176
               }
2177
169
               else {
2178
169
                  return nullptr;
2179
169
               }
2180
169
            }();
_ZZN3glz4fromILj10E5ValueIlEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEETnNS_14string_literalEXtlNS6_ILm1EEEEERS2_TkNS_10is_contextERNS_7contextERPKcSD_EEvOT1_OT2_OT3_OT4_ENKUlvE_clEv
Line
Count
Source
2172
296
            decltype(auto) fields = [&]() -> decltype(auto) {
2173
               if constexpr ((glaze_object_t<T> || reflectable<T>) &&
2174
                             (Opts.error_on_missing_keys || Opts.partial_read)) {
2175
                  return bit_array<num_members>{};
2176
               }
2177
296
               else {
2178
296
                  return nullptr;
2179
296
               }
2180
296
            }();
_ZZN3glz4fromILj10E5ValueImEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEETnNS_14string_literalEXtlNS6_ILm1EEEEERS2_TkNS_10is_contextERNS_7contextERPKcSD_EEvOT1_OT2_OT3_OT4_ENKUlvE_clEv
Line
Count
Source
2172
296
            decltype(auto) fields = [&]() -> decltype(auto) {
2173
               if constexpr ((glaze_object_t<T> || reflectable<T>) &&
2174
                             (Opts.error_on_missing_keys || Opts.partial_read)) {
2175
                  return bit_array<num_members>{};
2176
               }
2177
296
               else {
2178
296
                  return nullptr;
2179
296
               }
2180
296
            }();
_ZZN3glz4fromILj10E5ValueIxEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEETnNS_14string_literalEXtlNS6_ILm1EEEEERS2_TkNS_10is_contextERNS_7contextERPKcSD_EEvOT1_OT2_OT3_OT4_ENKUlvE_clEv
Line
Count
Source
2172
290
            decltype(auto) fields = [&]() -> decltype(auto) {
2173
               if constexpr ((glaze_object_t<T> || reflectable<T>) &&
2174
                             (Opts.error_on_missing_keys || Opts.partial_read)) {
2175
                  return bit_array<num_members>{};
2176
               }
2177
290
               else {
2178
290
                  return nullptr;
2179
290
               }
2180
290
            }();
_ZZN3glz4fromILj10E5ValueIyEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEETnNS_14string_literalEXtlNS6_ILm1EEEEERS2_TkNS_10is_contextERNS_7contextERPKcSD_EEvOT1_OT2_OT3_OT4_ENKUlvE_clEv
Line
Count
Source
2172
290
            decltype(auto) fields = [&]() -> decltype(auto) {
2173
               if constexpr ((glaze_object_t<T> || reflectable<T>) &&
2174
                             (Opts.error_on_missing_keys || Opts.partial_read)) {
2175
                  return bit_array<num_members>{};
2176
               }
2177
290
               else {
2178
290
                  return nullptr;
2179
290
               }
2180
290
            }();
_ZZN3glz4fromILj10ENSt3__13mapINS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEENS_6json_tENS1_4lessIvEENS6_INS1_4pairIKS8_S9_EEEEEEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj1EEETnNS_14string_literalEXtlNSK_ILm1EEEEERSG_TkNS_10is_contextERNS_7contextERPKcSR_EEvOT1_OT2_OT3_OT4_ENKUlvE_clEv
Line
Count
Source
2172
7.80k
            decltype(auto) fields = [&]() -> decltype(auto) {
2173
               if constexpr ((glaze_object_t<T> || reflectable<T>) &&
2174
                             (Opts.error_on_missing_keys || Opts.partial_read)) {
2175
                  return bit_array<num_members>{};
2176
               }
2177
7.80k
               else {
2178
7.80k
                  return nullptr;
2179
7.80k
               }
2180
7.80k
            }();
_ZZN3glz4fromILj10ENSt3__13mapINS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEENS_6json_tENS1_4lessIvEENS6_INS1_4pairIKS8_S9_EEEEEEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj1EEETnNS_14string_literalEXtlNSK_ILm1EEEEERSG_TkNS_10is_contextERNS_7contextERPKcSR_EEvOT1_OT2_OT3_OT4_ENKUlvE_clEv
Line
Count
Source
2172
7.86k
            decltype(auto) fields = [&]() -> decltype(auto) {
2173
               if constexpr ((glaze_object_t<T> || reflectable<T>) &&
2174
                             (Opts.error_on_missing_keys || Opts.partial_read)) {
2175
                  return bit_array<num_members>{};
2176
               }
2177
7.86k
               else {
2178
7.86k
                  return nullptr;
2179
7.86k
               }
2180
7.86k
            }();
_ZZN3glz4fromILj10ENSt3__13mapINS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEENS_6json_tENS1_4lessIvEENS6_INS1_4pairIKS8_S9_EEEEEEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj33EEETnNS_14string_literalEXtlNSK_ILm1EEEEERSG_TkNS_10is_contextERNS_7contextERPKcSR_EEvOT1_OT2_OT3_OT4_ENKUlvE_clEv
Line
Count
Source
2172
7.86k
            decltype(auto) fields = [&]() -> decltype(auto) {
2173
               if constexpr ((glaze_object_t<T> || reflectable<T>) &&
2174
                             (Opts.error_on_missing_keys || Opts.partial_read)) {
2175
                  return bit_array<num_members>{};
2176
               }
2177
7.86k
               else {
2178
7.86k
                  return nullptr;
2179
7.86k
               }
2180
7.86k
            }();
2181
2182
42.4k
            size_t read_count{}; // for partial_read
2183
2184
42.4k
            bool first = true;
2185
277k
            while (true) {
2186
               if constexpr ((glaze_object_t<T> || reflectable<T>) && Opts.partial_read) {
2187
                  static constexpr bit_array<num_members> all_fields = [] {
2188
                     bit_array<num_members> arr{};
2189
                     for (size_t i = 0; i < num_members; ++i) {
2190
                        arr[i] = true;
2191
                     }
2192
                     return arr;
2193
                  }();
2194
2195
                  if ((all_fields & fields) == all_fields) {
2196
                     ctx.error = error_code::partial_read_complete;
2197
                     return;
2198
                  }
2199
               }
2200
2201
251k
               if (*it == '}') {
2202
9.57k
                  if constexpr (not Opts.null_terminated) {
2203
1.96k
                     --ctx.indentation_level;
2204
1.96k
                  }
2205
                  if constexpr ((glaze_object_t<T> || reflectable<T>) &&
2206
                                (Opts.partial_read && Opts.error_on_missing_keys)) {
2207
                     ctx.error = error_code::missing_key;
2208
                     return;
2209
                  }
2210
9.57k
                  else {
2211
                     if constexpr ((glaze_object_t<T> || reflectable<T>) && Opts.error_on_missing_keys) {
2212
                        constexpr auto req_fields = required_fields<T, Opts>();
2213
                        if ((req_fields & fields) != req_fields) {
2214
                           for (size_t i = 0; i < num_members; ++i) {
2215
                              if (not fields[i]) {
2216
                                 ctx.custom_error_message = reflect<T>::keys[i];
2217
                                 // We just return the first missing key in order to avoid heap allocations
2218
                                 break;
2219
                              }
2220
                           }
2221
2222
                           ctx.error = error_code::missing_key;
2223
                           return;
2224
                        }
2225
                     }
2226
9.57k
                     ++it; // Increment after checking for mising keys so errors are within buffer bounds
2227
9.57k
                     if constexpr (not Opts.null_terminated) {
2228
1.96k
                        if (it == end) {
2229
19
                           ctx.error = error_code::end_reached;
2230
19
                           return;
2231
19
                        }
2232
1.96k
                     }
2233
9.57k
                  }
2234
1.94k
                  return;
2235
9.57k
               }
2236
242k
               else if (first) {
2237
37.4k
                  first = false;
2238
37.4k
               }
2239
204k
               else {
2240
204k
                  if (match_invalid_end<',', Opts>(ctx, it, end)) {
2241
6.93k
                     return;
2242
6.93k
                  }
2243
197k
                  if constexpr (not Opts.null_terminated) {
2244
62.6k
                     if (it == end) [[unlikely]] {
2245
0
                        ctx.error = error_code::unexpected_end;
2246
0
                        return;
2247
0
                     }
2248
62.6k
                  }
2249
2250
94.3k
                  if constexpr ((not Opts.minified) && (num_members > 1 || not Opts.error_on_unknown_keys)) {
2251
94.3k
                     if (ws_size && ws_size < size_t(end - it)) {
2252
16.6k
                        skip_matching_ws(ws_start, it, ws_size);
2253
16.6k
                     }
2254
94.3k
                  }
2255
2256
197k
                  if (skip_ws<Opts>(ctx, it, end)) {
2257
59
                     return;
2258
59
                  }
2259
197k
               }
2260
2261
235k
               constexpr auto reflection_type = glaze_object_t<T> || reflectable<T>;
2262
2263
               if constexpr (reflection_type && (num_members == 0)) {
2264
                  if constexpr (Opts.error_on_unknown_keys) {
2265
                     static_assert(false_v<T>, "This should be unreachable");
2266
                  }
2267
                  else {
2268
                     if (match_invalid_end<'"', Opts>(ctx, it, end)) {
2269
                        return;
2270
                     }
2271
2272
                     // parsing to an empty object, but at this point the JSON presents keys
2273
2274
                     // Unknown key handler does not unescape keys. Unknown escaped keys are
2275
                     // handled by the user.
2276
2277
                     const auto start = it;
2278
                     skip_string_view<Opts>(ctx, it, end);
2279
                     if (bool(ctx.error)) [[unlikely]]
2280
                        return;
2281
                     const sv key{start, size_t(it - start)};
2282
                     ++it;
2283
                     if constexpr (not Opts.null_terminated) {
2284
                        if (it == end) [[unlikely]] {
2285
                           ctx.error = error_code::unexpected_end;
2286
                           return;
2287
                        }
2288
                     }
2289
2290
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2291
                        return;
2292
                     }
2293
2294
                     parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
2295
                     if (bool(ctx.error)) [[unlikely]]
2296
                        return;
2297
                     if constexpr (not Opts.null_terminated) {
2298
                        if (it == end) [[unlikely]] {
2299
                           ctx.error = error_code::unexpected_end;
2300
                           return;
2301
                        }
2302
                     }
2303
                  }
2304
               }
2305
113k
               else if constexpr (reflection_type) {
2306
113k
                  static_assert(bool(hash_info<T>.type));
2307
2308
113k
                  if (*it != '"') [[unlikely]] {
2309
902
                     ctx.error = error_code::expected_quote;
2310
902
                     return;
2311
902
                  }
2312
112k
                  ++it;
2313
112k
                  if constexpr (not Opts.null_terminated) {
2314
32.5k
                     if (it == end) [[unlikely]] {
2315
25
                        ctx.error = error_code::unexpected_end;
2316
25
                        return;
2317
25
                     }
2318
32.5k
                  }
2319
2320
                  if constexpr (not tag.sv().empty() && not contains_tag<T, tag>()) {
2321
                     // For tagged variants we first check to see if the key matches the tag
2322
                     // We only need to do this if the tag is not part of the keys
2323
2324
                     const auto start = it;
2325
                     skip_string_view<Opts>(ctx, it, end);
2326
                     if (bool(ctx.error)) [[unlikely]]
2327
                        return;
2328
                     const sv key{start, size_t(it - start)};
2329
                     ++it;
2330
                     if constexpr (not Opts.null_terminated) {
2331
                        if (it == end) [[unlikely]] {
2332
                           ctx.error = error_code::unexpected_end;
2333
                           return;
2334
                        }
2335
                     }
2336
2337
                     if (key == tag.sv()) {
2338
                        if (parse_ws_colon<Opts>(ctx, it, end)) {
2339
                           return;
2340
                        }
2341
2342
                        parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
2343
                        if (bool(ctx.error)) [[unlikely]]
2344
                           return;
2345
2346
                        if (skip_ws<Opts>(ctx, it, end)) {
2347
                           return;
2348
                        }
2349
                        continue;
2350
                     }
2351
                     else {
2352
                        it = start; // reset the iterator
2353
                     }
2354
                  }
2355
2356
                  if constexpr (Opts.error_on_missing_keys || Opts.partial_read) {
2357
                     size_t index = num_members;
2358
                     parse_and_invoke<Opts, T, hash_info<T>>(value, ctx, it, end, index);
2359
                     if (bool(ctx.error)) [[unlikely]]
2360
                        return;
2361
                     if (index < num_members) {
2362
                        fields[index] = true;
2363
                     }
2364
                  }
2365
112k
                  else {
2366
112k
                     parse_and_invoke<Opts, T, hash_info<T>>(value, ctx, it, end);
2367
112k
                     if (bool(ctx.error)) [[unlikely]]
2368
7.53k
                        return;
2369
112k
                  }
2370
               }
2371
122k
               else {
2372
                  // For types like std::map, std::unordered_map
2373
2374
122k
                  auto reading = [&](auto&& key) {
2375
                     if constexpr (Opts.partial_read) {
2376
                        if (auto element = value.find(key); element != value.end()) {
2377
                           ++read_count;
2378
                           parse<JSON>::op<ws_handled<Opts>()>(element->second, ctx, it, end);
2379
                        }
2380
                        else {
2381
                           skip_value<JSON>::op<Opts>(ctx, it, end);
2382
                        }
2383
                     }
2384
120k
                     else {
2385
120k
                        parse<JSON>::op<ws_handled<Opts>()>(value[key], ctx, it, end);
2386
120k
                     }
2387
120k
                  };
_ZZN3glz4fromILj10ENSt3__13mapINS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEENS_6json_tENS1_4lessIvEENS6_INS1_4pairIKS8_S9_EEEEEEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj1EEETnNS_14string_literalEXtlNSK_ILm1EEEEERSG_TkNS_10is_contextERNS_7contextERPKcSR_EEvOT1_OT2_OT3_OT4_ENKUlOT_E_clIRS8_EEDaS11_
Line
Count
Source
2374
39.9k
                  auto reading = [&](auto&& key) {
2375
                     if constexpr (Opts.partial_read) {
2376
                        if (auto element = value.find(key); element != value.end()) {
2377
                           ++read_count;
2378
                           parse<JSON>::op<ws_handled<Opts>()>(element->second, ctx, it, end);
2379
                        }
2380
                        else {
2381
                           skip_value<JSON>::op<Opts>(ctx, it, end);
2382
                        }
2383
                     }
2384
39.9k
                     else {
2385
39.9k
                        parse<JSON>::op<ws_handled<Opts>()>(value[key], ctx, it, end);
2386
39.9k
                     }
2387
39.9k
                  };
_ZZN3glz4fromILj10ENSt3__13mapINS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEENS_6json_tENS1_4lessIvEENS6_INS1_4pairIKS8_S9_EEEEEEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj1EEETnNS_14string_literalEXtlNSK_ILm1EEEEERSG_TkNS_10is_contextERNS_7contextERPKcSR_EEvOT1_OT2_OT3_OT4_ENKUlOT_E_clIRS8_EEDaS11_
Line
Count
Source
2374
40.2k
                  auto reading = [&](auto&& key) {
2375
                     if constexpr (Opts.partial_read) {
2376
                        if (auto element = value.find(key); element != value.end()) {
2377
                           ++read_count;
2378
                           parse<JSON>::op<ws_handled<Opts>()>(element->second, ctx, it, end);
2379
                        }
2380
                        else {
2381
                           skip_value<JSON>::op<Opts>(ctx, it, end);
2382
                        }
2383
                     }
2384
40.2k
                     else {
2385
40.2k
                        parse<JSON>::op<ws_handled<Opts>()>(value[key], ctx, it, end);
2386
40.2k
                     }
2387
40.2k
                  };
_ZZN3glz4fromILj10ENSt3__13mapINS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEENS_6json_tENS1_4lessIvEENS6_INS1_4pairIKS8_S9_EEEEEEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj33EEETnNS_14string_literalEXtlNSK_ILm1EEEEERSG_TkNS_10is_contextERNS_7contextERPKcSR_EEvOT1_OT2_OT3_OT4_ENKUlOT_E_clIRS8_EEDaS11_
Line
Count
Source
2374
40.1k
                  auto reading = [&](auto&& key) {
2375
                     if constexpr (Opts.partial_read) {
2376
                        if (auto element = value.find(key); element != value.end()) {
2377
                           ++read_count;
2378
                           parse<JSON>::op<ws_handled<Opts>()>(element->second, ctx, it, end);
2379
                        }
2380
                        else {
2381
                           skip_value<JSON>::op<Opts>(ctx, it, end);
2382
                        }
2383
                     }
2384
40.1k
                     else {
2385
40.1k
                        parse<JSON>::op<ws_handled<Opts>()>(value[key], ctx, it, end);
2386
40.1k
                     }
2387
40.1k
                  };
2388
2389
                  // using Key = std::conditional_t<heterogeneous_map<T>, sv, typename T::key_type>;
2390
122k
                  using Key = typename T::key_type;
2391
122k
                  if constexpr (std::is_same_v<Key, std::string>) {
2392
122k
                     static thread_local Key key;
2393
122k
                     parse<JSON>::op<Opts>(key, ctx, it, end);
2394
122k
                     if (bool(ctx.error)) [[unlikely]]
2395
959
                        return;
2396
2397
121k
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2398
894
                        return;
2399
894
                     }
2400
2401
120k
                     reading(key);
2402
                     if constexpr (Opts.partial_read) {
2403
                        if (read_count == value.size()) {
2404
                           return;
2405
                        }
2406
                     }
2407
120k
                     if (bool(ctx.error)) [[unlikely]]
2408
15.2k
                        return;
2409
                  }
2410
                  else if constexpr (str_t<Key>) {
2411
                     Key key;
2412
                     parse<JSON>::op<Opts>(key, ctx, it, end);
2413
                     if (bool(ctx.error)) [[unlikely]]
2414
                        return;
2415
2416
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2417
                        return;
2418
                     }
2419
2420
                     reading(key);
2421
                     if constexpr (Opts.partial_read) {
2422
                        if (read_count == value.size()) {
2423
                           return;
2424
                        }
2425
                     }
2426
                     if (bool(ctx.error)) [[unlikely]]
2427
                        return;
2428
                  }
2429
                  else {
2430
                     Key key_value{};
2431
                     if constexpr (glaze_enum_t<Key>) {
2432
                        parse<JSON>::op<Opts>(key_value, ctx, it, end);
2433
                     }
2434
                     else if constexpr (std::is_arithmetic_v<Key>) {
2435
                        // prefer over quoted_t below to avoid double parsing of quoted_t
2436
                        parse<JSON>::op<opt_true<Opts, &opts::quoted_num>>(key_value, ctx, it, end);
2437
                     }
2438
                     else {
2439
                        parse<JSON>::op<opt_false<Opts, &opts::raw_string>>(quoted_t<Key>{key_value}, ctx, it, end);
2440
                     }
2441
                     if (bool(ctx.error)) [[unlikely]]
2442
                        return;
2443
2444
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2445
                        return;
2446
                     }
2447
2448
                     reading(key_value);
2449
                     if constexpr (Opts.partial_read) {
2450
                        if (read_count == value.size()) {
2451
                           return;
2452
                        }
2453
                     }
2454
                     if (bool(ctx.error)) [[unlikely]]
2455
                        return;
2456
                  }
2457
122k
               }
2458
235k
               if (skip_ws<Opts>(ctx, it, end)) {
2459
127
                  return;
2460
127
               }
2461
235k
            }
2462
42.4k
         }
2463
42.4k
      }
_ZN3glz4fromILj10E9my_structE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1EEETnNS_14string_literalEXtlNS5_ILm1EEEEERS1_TkNS_10is_contextERNS_7contextERPKcSC_EEvOT1_OT2_OT3_OT4_
Line
Count
Source
2079
4.59k
      {
2080
4.59k
         static constexpr auto num_members = reflect<T>::size;
2081
2082
4.59k
         static constexpr auto Opts = opening_handled_off<ws_handled_off<Options>()>();
2083
4.59k
         if constexpr (!check_opening_handled(Options)) {
2084
4.59k
            if constexpr (!check_ws_handled(Options)) {
2085
4.59k
               if (skip_ws<Opts>(ctx, it, end)) {
2086
13
                  return;
2087
13
               }
2088
4.59k
            }
2089
4.59k
            if (match_invalid_end<'{', Opts>(ctx, it, end)) {
2090
20
               return;
2091
20
            }
2092
4.57k
            if constexpr (not Opts.null_terminated) {
2093
4.57k
               if (it == end) [[unlikely]] {
2094
0
                  ctx.error = error_code::unexpected_end;
2095
0
                  return;
2096
0
               }
2097
4.57k
            }
2098
4.57k
            if constexpr (not Opts.null_terminated) {
2099
4.57k
               ++ctx.indentation_level;
2100
4.57k
            }
2101
4.57k
         }
2102
0
         const auto ws_start = it;
2103
4.59k
         if (skip_ws<Opts>(ctx, it, end)) {
2104
24
            return;
2105
24
         }
2106
4.57k
         const size_t ws_size = size_t(it - ws_start);
2107
2108
         if constexpr ((glaze_object_t<T> || reflectable<T>) && num_members == 0 && Opts.error_on_unknown_keys) {
2109
            if constexpr (not tag.sv().empty()) {
2110
               if (*it == '"') {
2111
                  ++it;
2112
                  if constexpr (not Opts.null_terminated) {
2113
                     if (it == end) [[unlikely]] {
2114
                        ctx.error = error_code::unexpected_end;
2115
                        return;
2116
                     }
2117
                  }
2118
2119
                  const auto start = it;
2120
                  skip_string_view<Opts>(ctx, it, end);
2121
                  if (bool(ctx.error)) [[unlikely]]
2122
                     return;
2123
                  const sv key{start, size_t(it - start)};
2124
                  ++it;
2125
                  if constexpr (not Opts.null_terminated) {
2126
                     if (it == end) [[unlikely]] {
2127
                        ctx.error = error_code::unexpected_end;
2128
                        return;
2129
                     }
2130
                  }
2131
2132
                  if (key == tag.sv()) {
2133
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2134
                        return;
2135
                     }
2136
2137
                     parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
2138
                     if (bool(ctx.error)) [[unlikely]]
2139
                        return;
2140
2141
                     if (skip_ws<Opts>(ctx, it, end)) {
2142
                        return;
2143
                     }
2144
                  }
2145
                  else {
2146
                     ctx.error = error_code::unknown_key;
2147
                     return;
2148
                  }
2149
               }
2150
            }
2151
2152
            if (*it == '}') [[likely]] {
2153
               if constexpr (not Opts.null_terminated) {
2154
                  --ctx.indentation_level;
2155
               }
2156
               ++it;
2157
               if constexpr (not Opts.null_terminated) {
2158
                  if (it == end) {
2159
                     ctx.error = error_code::end_reached;
2160
                     return;
2161
                  }
2162
               }
2163
               if constexpr (Opts.partial_read) {
2164
                  ctx.error = error_code::partial_read_complete;
2165
               }
2166
               return;
2167
            }
2168
            ctx.error = error_code::unknown_key;
2169
            return;
2170
         }
2171
4.57k
         else {
2172
4.57k
            decltype(auto) fields = [&]() -> decltype(auto) {
2173
4.57k
               if constexpr ((glaze_object_t<T> || reflectable<T>) &&
2174
4.57k
                             (Opts.error_on_missing_keys || Opts.partial_read)) {
2175
4.57k
                  return bit_array<num_members>{};
2176
4.57k
               }
2177
4.57k
               else {
2178
4.57k
                  return nullptr;
2179
4.57k
               }
2180
4.57k
            }();
2181
2182
4.57k
            size_t read_count{}; // for partial_read
2183
2184
4.57k
            bool first = true;
2185
37.2k
            while (true) {
2186
               if constexpr ((glaze_object_t<T> || reflectable<T>) && Opts.partial_read) {
2187
                  static constexpr bit_array<num_members> all_fields = [] {
2188
                     bit_array<num_members> arr{};
2189
                     for (size_t i = 0; i < num_members; ++i) {
2190
                        arr[i] = true;
2191
                     }
2192
                     return arr;
2193
                  }();
2194
2195
                  if ((all_fields & fields) == all_fields) {
2196
                     ctx.error = error_code::partial_read_complete;
2197
                     return;
2198
                  }
2199
               }
2200
2201
33.0k
               if (*it == '}') {
2202
3
                  if constexpr (not Opts.null_terminated) {
2203
3
                     --ctx.indentation_level;
2204
3
                  }
2205
                  if constexpr ((glaze_object_t<T> || reflectable<T>) &&
2206
                                (Opts.partial_read && Opts.error_on_missing_keys)) {
2207
                     ctx.error = error_code::missing_key;
2208
                     return;
2209
                  }
2210
3
                  else {
2211
                     if constexpr ((glaze_object_t<T> || reflectable<T>) && Opts.error_on_missing_keys) {
2212
                        constexpr auto req_fields = required_fields<T, Opts>();
2213
                        if ((req_fields & fields) != req_fields) {
2214
                           for (size_t i = 0; i < num_members; ++i) {
2215
                              if (not fields[i]) {
2216
                                 ctx.custom_error_message = reflect<T>::keys[i];
2217
                                 // We just return the first missing key in order to avoid heap allocations
2218
                                 break;
2219
                              }
2220
                           }
2221
2222
                           ctx.error = error_code::missing_key;
2223
                           return;
2224
                        }
2225
                     }
2226
3
                     ++it; // Increment after checking for mising keys so errors are within buffer bounds
2227
3
                     if constexpr (not Opts.null_terminated) {
2228
3
                        if (it == end) {
2229
2
                           ctx.error = error_code::end_reached;
2230
2
                           return;
2231
2
                        }
2232
3
                     }
2233
3
                  }
2234
1
                  return;
2235
3
               }
2236
33.0k
               else if (first) {
2237
4.53k
                  first = false;
2238
4.53k
               }
2239
28.5k
               else {
2240
28.5k
                  if (match_invalid_end<',', Opts>(ctx, it, end)) {
2241
335
                     return;
2242
335
                  }
2243
28.2k
                  if constexpr (not Opts.null_terminated) {
2244
28.2k
                     if (it == end) [[unlikely]] {
2245
0
                        ctx.error = error_code::unexpected_end;
2246
0
                        return;
2247
0
                     }
2248
28.2k
                  }
2249
2250
28.2k
                  if constexpr ((not Opts.minified) && (num_members > 1 || not Opts.error_on_unknown_keys)) {
2251
28.2k
                     if (ws_size && ws_size < size_t(end - it)) {
2252
6.06k
                        skip_matching_ws(ws_start, it, ws_size);
2253
6.06k
                     }
2254
28.2k
                  }
2255
2256
28.2k
                  if (skip_ws<Opts>(ctx, it, end)) {
2257
25
                     return;
2258
25
                  }
2259
28.2k
               }
2260
2261
32.7k
               constexpr auto reflection_type = glaze_object_t<T> || reflectable<T>;
2262
2263
               if constexpr (reflection_type && (num_members == 0)) {
2264
                  if constexpr (Opts.error_on_unknown_keys) {
2265
                     static_assert(false_v<T>, "This should be unreachable");
2266
                  }
2267
                  else {
2268
                     if (match_invalid_end<'"', Opts>(ctx, it, end)) {
2269
                        return;
2270
                     }
2271
2272
                     // parsing to an empty object, but at this point the JSON presents keys
2273
2274
                     // Unknown key handler does not unescape keys. Unknown escaped keys are
2275
                     // handled by the user.
2276
2277
                     const auto start = it;
2278
                     skip_string_view<Opts>(ctx, it, end);
2279
                     if (bool(ctx.error)) [[unlikely]]
2280
                        return;
2281
                     const sv key{start, size_t(it - start)};
2282
                     ++it;
2283
                     if constexpr (not Opts.null_terminated) {
2284
                        if (it == end) [[unlikely]] {
2285
                           ctx.error = error_code::unexpected_end;
2286
                           return;
2287
                        }
2288
                     }
2289
2290
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2291
                        return;
2292
                     }
2293
2294
                     parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
2295
                     if (bool(ctx.error)) [[unlikely]]
2296
                        return;
2297
                     if constexpr (not Opts.null_terminated) {
2298
                        if (it == end) [[unlikely]] {
2299
                           ctx.error = error_code::unexpected_end;
2300
                           return;
2301
                        }
2302
                     }
2303
                  }
2304
               }
2305
32.7k
               else if constexpr (reflection_type) {
2306
32.7k
                  static_assert(bool(hash_info<T>.type));
2307
2308
32.7k
                  if (*it != '"') [[unlikely]] {
2309
204
                     ctx.error = error_code::expected_quote;
2310
204
                     return;
2311
204
                  }
2312
32.5k
                  ++it;
2313
32.5k
                  if constexpr (not Opts.null_terminated) {
2314
32.5k
                     if (it == end) [[unlikely]] {
2315
25
                        ctx.error = error_code::unexpected_end;
2316
25
                        return;
2317
25
                     }
2318
32.5k
                  }
2319
2320
                  if constexpr (not tag.sv().empty() && not contains_tag<T, tag>()) {
2321
                     // For tagged variants we first check to see if the key matches the tag
2322
                     // We only need to do this if the tag is not part of the keys
2323
2324
                     const auto start = it;
2325
                     skip_string_view<Opts>(ctx, it, end);
2326
                     if (bool(ctx.error)) [[unlikely]]
2327
                        return;
2328
                     const sv key{start, size_t(it - start)};
2329
                     ++it;
2330
                     if constexpr (not Opts.null_terminated) {
2331
                        if (it == end) [[unlikely]] {
2332
                           ctx.error = error_code::unexpected_end;
2333
                           return;
2334
                        }
2335
                     }
2336
2337
                     if (key == tag.sv()) {
2338
                        if (parse_ws_colon<Opts>(ctx, it, end)) {
2339
                           return;
2340
                        }
2341
2342
                        parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
2343
                        if (bool(ctx.error)) [[unlikely]]
2344
                           return;
2345
2346
                        if (skip_ws<Opts>(ctx, it, end)) {
2347
                           return;
2348
                        }
2349
                        continue;
2350
                     }
2351
                     else {
2352
                        it = start; // reset the iterator
2353
                     }
2354
                  }
2355
2356
                  if constexpr (Opts.error_on_missing_keys || Opts.partial_read) {
2357
                     size_t index = num_members;
2358
                     parse_and_invoke<Opts, T, hash_info<T>>(value, ctx, it, end, index);
2359
                     if (bool(ctx.error)) [[unlikely]]
2360
                        return;
2361
                     if (index < num_members) {
2362
                        fields[index] = true;
2363
                     }
2364
                  }
2365
32.5k
                  else {
2366
32.5k
                     parse_and_invoke<Opts, T, hash_info<T>>(value, ctx, it, end);
2367
32.5k
                     if (bool(ctx.error)) [[unlikely]]
2368
3.88k
                        return;
2369
32.5k
                  }
2370
               }
2371
               else {
2372
                  // For types like std::map, std::unordered_map
2373
2374
                  auto reading = [&](auto&& key) {
2375
                     if constexpr (Opts.partial_read) {
2376
                        if (auto element = value.find(key); element != value.end()) {
2377
                           ++read_count;
2378
                           parse<JSON>::op<ws_handled<Opts>()>(element->second, ctx, it, end);
2379
                        }
2380
                        else {
2381
                           skip_value<JSON>::op<Opts>(ctx, it, end);
2382
                        }
2383
                     }
2384
                     else {
2385
                        parse<JSON>::op<ws_handled<Opts>()>(value[key], ctx, it, end);
2386
                     }
2387
                  };
2388
2389
                  // using Key = std::conditional_t<heterogeneous_map<T>, sv, typename T::key_type>;
2390
                  using Key = typename T::key_type;
2391
                  if constexpr (std::is_same_v<Key, std::string>) {
2392
                     static thread_local Key key;
2393
                     parse<JSON>::op<Opts>(key, ctx, it, end);
2394
                     if (bool(ctx.error)) [[unlikely]]
2395
                        return;
2396
2397
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2398
                        return;
2399
                     }
2400
2401
                     reading(key);
2402
                     if constexpr (Opts.partial_read) {
2403
                        if (read_count == value.size()) {
2404
                           return;
2405
                        }
2406
                     }
2407
                     if (bool(ctx.error)) [[unlikely]]
2408
                        return;
2409
                  }
2410
                  else if constexpr (str_t<Key>) {
2411
                     Key key;
2412
                     parse<JSON>::op<Opts>(key, ctx, it, end);
2413
                     if (bool(ctx.error)) [[unlikely]]
2414
                        return;
2415
2416
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2417
                        return;
2418
                     }
2419
2420
                     reading(key);
2421
                     if constexpr (Opts.partial_read) {
2422
                        if (read_count == value.size()) {
2423
                           return;
2424
                        }
2425
                     }
2426
                     if (bool(ctx.error)) [[unlikely]]
2427
                        return;
2428
                  }
2429
                  else {
2430
                     Key key_value{};
2431
                     if constexpr (glaze_enum_t<Key>) {
2432
                        parse<JSON>::op<Opts>(key_value, ctx, it, end);
2433
                     }
2434
                     else if constexpr (std::is_arithmetic_v<Key>) {
2435
                        // prefer over quoted_t below to avoid double parsing of quoted_t
2436
                        parse<JSON>::op<opt_true<Opts, &opts::quoted_num>>(key_value, ctx, it, end);
2437
                     }
2438
                     else {
2439
                        parse<JSON>::op<opt_false<Opts, &opts::raw_string>>(quoted_t<Key>{key_value}, ctx, it, end);
2440
                     }
2441
                     if (bool(ctx.error)) [[unlikely]]
2442
                        return;
2443
2444
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2445
                        return;
2446
                     }
2447
2448
                     reading(key_value);
2449
                     if constexpr (Opts.partial_read) {
2450
                        if (read_count == value.size()) {
2451
                           return;
2452
                        }
2453
                     }
2454
                     if (bool(ctx.error)) [[unlikely]]
2455
                        return;
2456
                  }
2457
               }
2458
32.7k
               if (skip_ws<Opts>(ctx, it, end)) {
2459
61
                  return;
2460
61
               }
2461
32.7k
            }
2462
4.57k
         }
2463
4.57k
      }
_ZN3glz4fromILj10E9my_structE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1EEETnNS_14string_literalEXtlNS5_ILm1EEEEERS1_TkNS_10is_contextERNS_7contextERPKcSC_EEvOT1_OT2_OT3_OT4_
Line
Count
Source
2079
4.59k
      {
2080
4.59k
         static constexpr auto num_members = reflect<T>::size;
2081
2082
4.59k
         static constexpr auto Opts = opening_handled_off<ws_handled_off<Options>()>();
2083
4.59k
         if constexpr (!check_opening_handled(Options)) {
2084
4.59k
            if constexpr (!check_ws_handled(Options)) {
2085
4.59k
               if (skip_ws<Opts>(ctx, it, end)) {
2086
0
                  return;
2087
0
               }
2088
4.59k
            }
2089
4.59k
            if (match_invalid_end<'{', Opts>(ctx, it, end)) {
2090
31
               return;
2091
31
            }
2092
            if constexpr (not Opts.null_terminated) {
2093
               if (it == end) [[unlikely]] {
2094
                  ctx.error = error_code::unexpected_end;
2095
                  return;
2096
               }
2097
            }
2098
            if constexpr (not Opts.null_terminated) {
2099
               ++ctx.indentation_level;
2100
            }
2101
4.56k
         }
2102
4.56k
         const auto ws_start = it;
2103
4.59k
         if (skip_ws<Opts>(ctx, it, end)) {
2104
0
            return;
2105
0
         }
2106
4.59k
         const size_t ws_size = size_t(it - ws_start);
2107
2108
         if constexpr ((glaze_object_t<T> || reflectable<T>) && num_members == 0 && Opts.error_on_unknown_keys) {
2109
            if constexpr (not tag.sv().empty()) {
2110
               if (*it == '"') {
2111
                  ++it;
2112
                  if constexpr (not Opts.null_terminated) {
2113
                     if (it == end) [[unlikely]] {
2114
                        ctx.error = error_code::unexpected_end;
2115
                        return;
2116
                     }
2117
                  }
2118
2119
                  const auto start = it;
2120
                  skip_string_view<Opts>(ctx, it, end);
2121
                  if (bool(ctx.error)) [[unlikely]]
2122
                     return;
2123
                  const sv key{start, size_t(it - start)};
2124
                  ++it;
2125
                  if constexpr (not Opts.null_terminated) {
2126
                     if (it == end) [[unlikely]] {
2127
                        ctx.error = error_code::unexpected_end;
2128
                        return;
2129
                     }
2130
                  }
2131
2132
                  if (key == tag.sv()) {
2133
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2134
                        return;
2135
                     }
2136
2137
                     parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
2138
                     if (bool(ctx.error)) [[unlikely]]
2139
                        return;
2140
2141
                     if (skip_ws<Opts>(ctx, it, end)) {
2142
                        return;
2143
                     }
2144
                  }
2145
                  else {
2146
                     ctx.error = error_code::unknown_key;
2147
                     return;
2148
                  }
2149
               }
2150
            }
2151
2152
            if (*it == '}') [[likely]] {
2153
               if constexpr (not Opts.null_terminated) {
2154
                  --ctx.indentation_level;
2155
               }
2156
               ++it;
2157
               if constexpr (not Opts.null_terminated) {
2158
                  if (it == end) {
2159
                     ctx.error = error_code::end_reached;
2160
                     return;
2161
                  }
2162
               }
2163
               if constexpr (Opts.partial_read) {
2164
                  ctx.error = error_code::partial_read_complete;
2165
               }
2166
               return;
2167
            }
2168
            ctx.error = error_code::unknown_key;
2169
            return;
2170
         }
2171
4.59k
         else {
2172
4.59k
            decltype(auto) fields = [&]() -> decltype(auto) {
2173
4.59k
               if constexpr ((glaze_object_t<T> || reflectable<T>) &&
2174
4.59k
                             (Opts.error_on_missing_keys || Opts.partial_read)) {
2175
4.59k
                  return bit_array<num_members>{};
2176
4.59k
               }
2177
4.59k
               else {
2178
4.59k
                  return nullptr;
2179
4.59k
               }
2180
4.59k
            }();
2181
2182
4.59k
            size_t read_count{}; // for partial_read
2183
2184
4.59k
            bool first = true;
2185
37.4k
            while (true) {
2186
               if constexpr ((glaze_object_t<T> || reflectable<T>) && Opts.partial_read) {
2187
                  static constexpr bit_array<num_members> all_fields = [] {
2188
                     bit_array<num_members> arr{};
2189
                     for (size_t i = 0; i < num_members; ++i) {
2190
                        arr[i] = true;
2191
                     }
2192
                     return arr;
2193
                  }();
2194
2195
                  if ((all_fields & fields) == all_fields) {
2196
                     ctx.error = error_code::partial_read_complete;
2197
                     return;
2198
                  }
2199
               }
2200
2201
35.4k
               if (*it == '}') {
2202
                  if constexpr (not Opts.null_terminated) {
2203
                     --ctx.indentation_level;
2204
                  }
2205
                  if constexpr ((glaze_object_t<T> || reflectable<T>) &&
2206
                                (Opts.partial_read && Opts.error_on_missing_keys)) {
2207
                     ctx.error = error_code::missing_key;
2208
                     return;
2209
                  }
2210
3
                  else {
2211
                     if constexpr ((glaze_object_t<T> || reflectable<T>) && Opts.error_on_missing_keys) {
2212
                        constexpr auto req_fields = required_fields<T, Opts>();
2213
                        if ((req_fields & fields) != req_fields) {
2214
                           for (size_t i = 0; i < num_members; ++i) {
2215
                              if (not fields[i]) {
2216
                                 ctx.custom_error_message = reflect<T>::keys[i];
2217
                                 // We just return the first missing key in order to avoid heap allocations
2218
                                 break;
2219
                              }
2220
                           }
2221
2222
                           ctx.error = error_code::missing_key;
2223
                           return;
2224
                        }
2225
                     }
2226
3
                     ++it; // Increment after checking for mising keys so errors are within buffer bounds
2227
                     if constexpr (not Opts.null_terminated) {
2228
                        if (it == end) {
2229
                           ctx.error = error_code::end_reached;
2230
                           return;
2231
                        }
2232
                     }
2233
3
                  }
2234
3
                  return;
2235
3
               }
2236
35.4k
               else if (first) {
2237
4.56k
                  first = false;
2238
4.56k
               }
2239
30.9k
               else {
2240
30.9k
                  if (match_invalid_end<',', Opts>(ctx, it, end)) {
2241
2.67k
                     return;
2242
2.67k
                  }
2243
                  if constexpr (not Opts.null_terminated) {
2244
                     if (it == end) [[unlikely]] {
2245
                        ctx.error = error_code::unexpected_end;
2246
                        return;
2247
                     }
2248
                  }
2249
2250
28.2k
                  if constexpr ((not Opts.minified) && (num_members > 1 || not Opts.error_on_unknown_keys)) {
2251
28.2k
                     if (ws_size && ws_size < size_t(end - it)) {
2252
6.06k
                        skip_matching_ws(ws_start, it, ws_size);
2253
6.06k
                     }
2254
28.2k
                  }
2255
2256
28.2k
                  if (skip_ws<Opts>(ctx, it, end)) {
2257
0
                     return;
2258
0
                  }
2259
28.2k
               }
2260
2261
32.8k
               constexpr auto reflection_type = glaze_object_t<T> || reflectable<T>;
2262
2263
               if constexpr (reflection_type && (num_members == 0)) {
2264
                  if constexpr (Opts.error_on_unknown_keys) {
2265
                     static_assert(false_v<T>, "This should be unreachable");
2266
                  }
2267
                  else {
2268
                     if (match_invalid_end<'"', Opts>(ctx, it, end)) {
2269
                        return;
2270
                     }
2271
2272
                     // parsing to an empty object, but at this point the JSON presents keys
2273
2274
                     // Unknown key handler does not unescape keys. Unknown escaped keys are
2275
                     // handled by the user.
2276
2277
                     const auto start = it;
2278
                     skip_string_view<Opts>(ctx, it, end);
2279
                     if (bool(ctx.error)) [[unlikely]]
2280
                        return;
2281
                     const sv key{start, size_t(it - start)};
2282
                     ++it;
2283
                     if constexpr (not Opts.null_terminated) {
2284
                        if (it == end) [[unlikely]] {
2285
                           ctx.error = error_code::unexpected_end;
2286
                           return;
2287
                        }
2288
                     }
2289
2290
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2291
                        return;
2292
                     }
2293
2294
                     parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
2295
                     if (bool(ctx.error)) [[unlikely]]
2296
                        return;
2297
                     if constexpr (not Opts.null_terminated) {
2298
                        if (it == end) [[unlikely]] {
2299
                           ctx.error = error_code::unexpected_end;
2300
                           return;
2301
                        }
2302
                     }
2303
                  }
2304
               }
2305
32.8k
               else if constexpr (reflection_type) {
2306
32.8k
                  static_assert(bool(hash_info<T>.type));
2307
2308
32.8k
                  if (*it != '"') [[unlikely]] {
2309
302
                     ctx.error = error_code::expected_quote;
2310
302
                     return;
2311
302
                  }
2312
32.5k
                  ++it;
2313
                  if constexpr (not Opts.null_terminated) {
2314
                     if (it == end) [[unlikely]] {
2315
                        ctx.error = error_code::unexpected_end;
2316
                        return;
2317
                     }
2318
                  }
2319
2320
                  if constexpr (not tag.sv().empty() && not contains_tag<T, tag>()) {
2321
                     // For tagged variants we first check to see if the key matches the tag
2322
                     // We only need to do this if the tag is not part of the keys
2323
2324
                     const auto start = it;
2325
                     skip_string_view<Opts>(ctx, it, end);
2326
                     if (bool(ctx.error)) [[unlikely]]
2327
                        return;
2328
                     const sv key{start, size_t(it - start)};
2329
                     ++it;
2330
                     if constexpr (not Opts.null_terminated) {
2331
                        if (it == end) [[unlikely]] {
2332
                           ctx.error = error_code::unexpected_end;
2333
                           return;
2334
                        }
2335
                     }
2336
2337
                     if (key == tag.sv()) {
2338
                        if (parse_ws_colon<Opts>(ctx, it, end)) {
2339
                           return;
2340
                        }
2341
2342
                        parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
2343
                        if (bool(ctx.error)) [[unlikely]]
2344
                           return;
2345
2346
                        if (skip_ws<Opts>(ctx, it, end)) {
2347
                           return;
2348
                        }
2349
                        continue;
2350
                     }
2351
                     else {
2352
                        it = start; // reset the iterator
2353
                     }
2354
                  }
2355
2356
                  if constexpr (Opts.error_on_missing_keys || Opts.partial_read) {
2357
                     size_t index = num_members;
2358
                     parse_and_invoke<Opts, T, hash_info<T>>(value, ctx, it, end, index);
2359
                     if (bool(ctx.error)) [[unlikely]]
2360
                        return;
2361
                     if (index < num_members) {
2362
                        fields[index] = true;
2363
                     }
2364
                  }
2365
32.5k
                  else {
2366
32.5k
                     parse_and_invoke<Opts, T, hash_info<T>>(value, ctx, it, end);
2367
32.5k
                     if (bool(ctx.error)) [[unlikely]]
2368
1.58k
                        return;
2369
32.5k
                  }
2370
               }
2371
               else {
2372
                  // For types like std::map, std::unordered_map
2373
2374
                  auto reading = [&](auto&& key) {
2375
                     if constexpr (Opts.partial_read) {
2376
                        if (auto element = value.find(key); element != value.end()) {
2377
                           ++read_count;
2378
                           parse<JSON>::op<ws_handled<Opts>()>(element->second, ctx, it, end);
2379
                        }
2380
                        else {
2381
                           skip_value<JSON>::op<Opts>(ctx, it, end);
2382
                        }
2383
                     }
2384
                     else {
2385
                        parse<JSON>::op<ws_handled<Opts>()>(value[key], ctx, it, end);
2386
                     }
2387
                  };
2388
2389
                  // using Key = std::conditional_t<heterogeneous_map<T>, sv, typename T::key_type>;
2390
                  using Key = typename T::key_type;
2391
                  if constexpr (std::is_same_v<Key, std::string>) {
2392
                     static thread_local Key key;
2393
                     parse<JSON>::op<Opts>(key, ctx, it, end);
2394
                     if (bool(ctx.error)) [[unlikely]]
2395
                        return;
2396
2397
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2398
                        return;
2399
                     }
2400
2401
                     reading(key);
2402
                     if constexpr (Opts.partial_read) {
2403
                        if (read_count == value.size()) {
2404
                           return;
2405
                        }
2406
                     }
2407
                     if (bool(ctx.error)) [[unlikely]]
2408
                        return;
2409
                  }
2410
                  else if constexpr (str_t<Key>) {
2411
                     Key key;
2412
                     parse<JSON>::op<Opts>(key, ctx, it, end);
2413
                     if (bool(ctx.error)) [[unlikely]]
2414
                        return;
2415
2416
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2417
                        return;
2418
                     }
2419
2420
                     reading(key);
2421
                     if constexpr (Opts.partial_read) {
2422
                        if (read_count == value.size()) {
2423
                           return;
2424
                        }
2425
                     }
2426
                     if (bool(ctx.error)) [[unlikely]]
2427
                        return;
2428
                  }
2429
                  else {
2430
                     Key key_value{};
2431
                     if constexpr (glaze_enum_t<Key>) {
2432
                        parse<JSON>::op<Opts>(key_value, ctx, it, end);
2433
                     }
2434
                     else if constexpr (std::is_arithmetic_v<Key>) {
2435
                        // prefer over quoted_t below to avoid double parsing of quoted_t
2436
                        parse<JSON>::op<opt_true<Opts, &opts::quoted_num>>(key_value, ctx, it, end);
2437
                     }
2438
                     else {
2439
                        parse<JSON>::op<opt_false<Opts, &opts::raw_string>>(quoted_t<Key>{key_value}, ctx, it, end);
2440
                     }
2441
                     if (bool(ctx.error)) [[unlikely]]
2442
                        return;
2443
2444
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2445
                        return;
2446
                     }
2447
2448
                     reading(key_value);
2449
                     if constexpr (Opts.partial_read) {
2450
                        if (read_count == value.size()) {
2451
                           return;
2452
                        }
2453
                     }
2454
                     if (bool(ctx.error)) [[unlikely]]
2455
                        return;
2456
                  }
2457
               }
2458
32.8k
               if (skip_ws<Opts>(ctx, it, end)) {
2459
0
                  return;
2460
0
               }
2461
32.8k
            }
2462
4.59k
         }
2463
4.59k
      }
_ZN3glz4fromILj10E9my_structE2opITnDaXtlNS_4optsELj10ELb1ELb1ELb1ELb1ELb0ELb0ELc32ELh3ELb1EEETnNS_14string_literalEXtlNS5_ILm1EEEEERS1_TkNS_10is_contextERNS_7contextERPKcSC_EEvOT1_OT2_OT3_OT4_
Line
Count
Source
2079
6.10k
      {
2080
6.10k
         static constexpr auto num_members = reflect<T>::size;
2081
2082
6.10k
         static constexpr auto Opts = opening_handled_off<ws_handled_off<Options>()>();
2083
6.10k
         if constexpr (!check_opening_handled(Options)) {
2084
6.10k
            if constexpr (!check_ws_handled(Options)) {
2085
6.10k
               if (skip_ws<Opts>(ctx, it, end)) {
2086
19
                  return;
2087
19
               }
2088
6.10k
            }
2089
6.10k
            if (match_invalid_end<'{', Opts>(ctx, it, end)) {
2090
116
               return;
2091
116
            }
2092
            if constexpr (not Opts.null_terminated) {
2093
               if (it == end) [[unlikely]] {
2094
                  ctx.error = error_code::unexpected_end;
2095
                  return;
2096
               }
2097
            }
2098
            if constexpr (not Opts.null_terminated) {
2099
               ++ctx.indentation_level;
2100
            }
2101
5.98k
         }
2102
5.98k
         const auto ws_start = it;
2103
6.10k
         if (skip_ws<Opts>(ctx, it, end)) {
2104
3
            return;
2105
3
         }
2106
6.10k
         const size_t ws_size = size_t(it - ws_start);
2107
2108
         if constexpr ((glaze_object_t<T> || reflectable<T>) && num_members == 0 && Opts.error_on_unknown_keys) {
2109
            if constexpr (not tag.sv().empty()) {
2110
               if (*it == '"') {
2111
                  ++it;
2112
                  if constexpr (not Opts.null_terminated) {
2113
                     if (it == end) [[unlikely]] {
2114
                        ctx.error = error_code::unexpected_end;
2115
                        return;
2116
                     }
2117
                  }
2118
2119
                  const auto start = it;
2120
                  skip_string_view<Opts>(ctx, it, end);
2121
                  if (bool(ctx.error)) [[unlikely]]
2122
                     return;
2123
                  const sv key{start, size_t(it - start)};
2124
                  ++it;
2125
                  if constexpr (not Opts.null_terminated) {
2126
                     if (it == end) [[unlikely]] {
2127
                        ctx.error = error_code::unexpected_end;
2128
                        return;
2129
                     }
2130
                  }
2131
2132
                  if (key == tag.sv()) {
2133
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2134
                        return;
2135
                     }
2136
2137
                     parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
2138
                     if (bool(ctx.error)) [[unlikely]]
2139
                        return;
2140
2141
                     if (skip_ws<Opts>(ctx, it, end)) {
2142
                        return;
2143
                     }
2144
                  }
2145
                  else {
2146
                     ctx.error = error_code::unknown_key;
2147
                     return;
2148
                  }
2149
               }
2150
            }
2151
2152
            if (*it == '}') [[likely]] {
2153
               if constexpr (not Opts.null_terminated) {
2154
                  --ctx.indentation_level;
2155
               }
2156
               ++it;
2157
               if constexpr (not Opts.null_terminated) {
2158
                  if (it == end) {
2159
                     ctx.error = error_code::end_reached;
2160
                     return;
2161
                  }
2162
               }
2163
               if constexpr (Opts.partial_read) {
2164
                  ctx.error = error_code::partial_read_complete;
2165
               }
2166
               return;
2167
            }
2168
            ctx.error = error_code::unknown_key;
2169
            return;
2170
         }
2171
6.10k
         else {
2172
6.10k
            decltype(auto) fields = [&]() -> decltype(auto) {
2173
6.10k
               if constexpr ((glaze_object_t<T> || reflectable<T>) &&
2174
6.10k
                             (Opts.error_on_missing_keys || Opts.partial_read)) {
2175
6.10k
                  return bit_array<num_members>{};
2176
6.10k
               }
2177
6.10k
               else {
2178
6.10k
                  return nullptr;
2179
6.10k
               }
2180
6.10k
            }();
2181
2182
6.10k
            size_t read_count{}; // for partial_read
2183
2184
6.10k
            bool first = true;
2185
49.8k
            while (true) {
2186
               if constexpr ((glaze_object_t<T> || reflectable<T>) && Opts.partial_read) {
2187
                  static constexpr bit_array<num_members> all_fields = [] {
2188
                     bit_array<num_members> arr{};
2189
                     for (size_t i = 0; i < num_members; ++i) {
2190
                        arr[i] = true;
2191
                     }
2192
                     return arr;
2193
                  }();
2194
2195
                  if ((all_fields & fields) == all_fields) {
2196
                     ctx.error = error_code::partial_read_complete;
2197
                     return;
2198
                  }
2199
               }
2200
2201
47.2k
               if (*it == '}') {
2202
                  if constexpr (not Opts.null_terminated) {
2203
                     --ctx.indentation_level;
2204
                  }
2205
                  if constexpr ((glaze_object_t<T> || reflectable<T>) &&
2206
                                (Opts.partial_read && Opts.error_on_missing_keys)) {
2207
                     ctx.error = error_code::missing_key;
2208
                     return;
2209
                  }
2210
2
                  else {
2211
                     if constexpr ((glaze_object_t<T> || reflectable<T>) && Opts.error_on_missing_keys) {
2212
                        constexpr auto req_fields = required_fields<T, Opts>();
2213
                        if ((req_fields & fields) != req_fields) {
2214
                           for (size_t i = 0; i < num_members; ++i) {
2215
                              if (not fields[i]) {
2216
                                 ctx.custom_error_message = reflect<T>::keys[i];
2217
                                 // We just return the first missing key in order to avoid heap allocations
2218
                                 break;
2219
                              }
2220
                           }
2221
2222
                           ctx.error = error_code::missing_key;
2223
                           return;
2224
                        }
2225
                     }
2226
2
                     ++it; // Increment after checking for mising keys so errors are within buffer bounds
2227
                     if constexpr (not Opts.null_terminated) {
2228
                        if (it == end) {
2229
                           ctx.error = error_code::end_reached;
2230
                           return;
2231
                        }
2232
                     }
2233
2
                  }
2234
2
                  return;
2235
2
               }
2236
47.2k
               else if (first) {
2237
5.96k
                  first = false;
2238
5.96k
               }
2239
41.3k
               else {
2240
41.3k
                  if (match_invalid_end<',', Opts>(ctx, it, end)) {
2241
3.47k
                     return;
2242
3.47k
                  }
2243
                  if constexpr (not Opts.null_terminated) {
2244
                     if (it == end) [[unlikely]] {
2245
                        ctx.error = error_code::unexpected_end;
2246
                        return;
2247
                     }
2248
                  }
2249
2250
37.8k
                  if constexpr ((not Opts.minified) && (num_members > 1 || not Opts.error_on_unknown_keys)) {
2251
37.8k
                     if (ws_size && ws_size < size_t(end - it)) {
2252
4.51k
                        skip_matching_ws(ws_start, it, ws_size);
2253
4.51k
                     }
2254
37.8k
                  }
2255
2256
37.8k
                  if (skip_ws<Opts>(ctx, it, end)) {
2257
18
                     return;
2258
18
                  }
2259
37.8k
               }
2260
2261
43.7k
               constexpr auto reflection_type = glaze_object_t<T> || reflectable<T>;
2262
2263
               if constexpr (reflection_type && (num_members == 0)) {
2264
                  if constexpr (Opts.error_on_unknown_keys) {
2265
                     static_assert(false_v<T>, "This should be unreachable");
2266
                  }
2267
                  else {
2268
                     if (match_invalid_end<'"', Opts>(ctx, it, end)) {
2269
                        return;
2270
                     }
2271
2272
                     // parsing to an empty object, but at this point the JSON presents keys
2273
2274
                     // Unknown key handler does not unescape keys. Unknown escaped keys are
2275
                     // handled by the user.
2276
2277
                     const auto start = it;
2278
                     skip_string_view<Opts>(ctx, it, end);
2279
                     if (bool(ctx.error)) [[unlikely]]
2280
                        return;
2281
                     const sv key{start, size_t(it - start)};
2282
                     ++it;
2283
                     if constexpr (not Opts.null_terminated) {
2284
                        if (it == end) [[unlikely]] {
2285
                           ctx.error = error_code::unexpected_end;
2286
                           return;
2287
                        }
2288
                     }
2289
2290
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2291
                        return;
2292
                     }
2293
2294
                     parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
2295
                     if (bool(ctx.error)) [[unlikely]]
2296
                        return;
2297
                     if constexpr (not Opts.null_terminated) {
2298
                        if (it == end) [[unlikely]] {
2299
                           ctx.error = error_code::unexpected_end;
2300
                           return;
2301
                        }
2302
                     }
2303
                  }
2304
               }
2305
43.7k
               else if constexpr (reflection_type) {
2306
43.7k
                  static_assert(bool(hash_info<T>.type));
2307
2308
43.7k
                  if (*it != '"') [[unlikely]] {
2309
396
                     ctx.error = error_code::expected_quote;
2310
396
                     return;
2311
396
                  }
2312
43.4k
                  ++it;
2313
                  if constexpr (not Opts.null_terminated) {
2314
                     if (it == end) [[unlikely]] {
2315
                        ctx.error = error_code::unexpected_end;
2316
                        return;
2317
                     }
2318
                  }
2319
2320
                  if constexpr (not tag.sv().empty() && not contains_tag<T, tag>()) {
2321
                     // For tagged variants we first check to see if the key matches the tag
2322
                     // We only need to do this if the tag is not part of the keys
2323
2324
                     const auto start = it;
2325
                     skip_string_view<Opts>(ctx, it, end);
2326
                     if (bool(ctx.error)) [[unlikely]]
2327
                        return;
2328
                     const sv key{start, size_t(it - start)};
2329
                     ++it;
2330
                     if constexpr (not Opts.null_terminated) {
2331
                        if (it == end) [[unlikely]] {
2332
                           ctx.error = error_code::unexpected_end;
2333
                           return;
2334
                        }
2335
                     }
2336
2337
                     if (key == tag.sv()) {
2338
                        if (parse_ws_colon<Opts>(ctx, it, end)) {
2339
                           return;
2340
                        }
2341
2342
                        parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
2343
                        if (bool(ctx.error)) [[unlikely]]
2344
                           return;
2345
2346
                        if (skip_ws<Opts>(ctx, it, end)) {
2347
                           return;
2348
                        }
2349
                        continue;
2350
                     }
2351
                     else {
2352
                        it = start; // reset the iterator
2353
                     }
2354
                  }
2355
2356
                  if constexpr (Opts.error_on_missing_keys || Opts.partial_read) {
2357
                     size_t index = num_members;
2358
                     parse_and_invoke<Opts, T, hash_info<T>>(value, ctx, it, end, index);
2359
                     if (bool(ctx.error)) [[unlikely]]
2360
                        return;
2361
                     if (index < num_members) {
2362
                        fields[index] = true;
2363
                     }
2364
                  }
2365
43.4k
                  else {
2366
43.4k
                     parse_and_invoke<Opts, T, hash_info<T>>(value, ctx, it, end);
2367
43.4k
                     if (bool(ctx.error)) [[unlikely]]
2368
2.06k
                        return;
2369
43.4k
                  }
2370
               }
2371
               else {
2372
                  // For types like std::map, std::unordered_map
2373
2374
                  auto reading = [&](auto&& key) {
2375
                     if constexpr (Opts.partial_read) {
2376
                        if (auto element = value.find(key); element != value.end()) {
2377
                           ++read_count;
2378
                           parse<JSON>::op<ws_handled<Opts>()>(element->second, ctx, it, end);
2379
                        }
2380
                        else {
2381
                           skip_value<JSON>::op<Opts>(ctx, it, end);
2382
                        }
2383
                     }
2384
                     else {
2385
                        parse<JSON>::op<ws_handled<Opts>()>(value[key], ctx, it, end);
2386
                     }
2387
                  };
2388
2389
                  // using Key = std::conditional_t<heterogeneous_map<T>, sv, typename T::key_type>;
2390
                  using Key = typename T::key_type;
2391
                  if constexpr (std::is_same_v<Key, std::string>) {
2392
                     static thread_local Key key;
2393
                     parse<JSON>::op<Opts>(key, ctx, it, end);
2394
                     if (bool(ctx.error)) [[unlikely]]
2395
                        return;
2396
2397
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2398
                        return;
2399
                     }
2400
2401
                     reading(key);
2402
                     if constexpr (Opts.partial_read) {
2403
                        if (read_count == value.size()) {
2404
                           return;
2405
                        }
2406
                     }
2407
                     if (bool(ctx.error)) [[unlikely]]
2408
                        return;
2409
                  }
2410
                  else if constexpr (str_t<Key>) {
2411
                     Key key;
2412
                     parse<JSON>::op<Opts>(key, ctx, it, end);
2413
                     if (bool(ctx.error)) [[unlikely]]
2414
                        return;
2415
2416
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2417
                        return;
2418
                     }
2419
2420
                     reading(key);
2421
                     if constexpr (Opts.partial_read) {
2422
                        if (read_count == value.size()) {
2423
                           return;
2424
                        }
2425
                     }
2426
                     if (bool(ctx.error)) [[unlikely]]
2427
                        return;
2428
                  }
2429
                  else {
2430
                     Key key_value{};
2431
                     if constexpr (glaze_enum_t<Key>) {
2432
                        parse<JSON>::op<Opts>(key_value, ctx, it, end);
2433
                     }
2434
                     else if constexpr (std::is_arithmetic_v<Key>) {
2435
                        // prefer over quoted_t below to avoid double parsing of quoted_t
2436
                        parse<JSON>::op<opt_true<Opts, &opts::quoted_num>>(key_value, ctx, it, end);
2437
                     }
2438
                     else {
2439
                        parse<JSON>::op<opt_false<Opts, &opts::raw_string>>(quoted_t<Key>{key_value}, ctx, it, end);
2440
                     }
2441
                     if (bool(ctx.error)) [[unlikely]]
2442
                        return;
2443
2444
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2445
                        return;
2446
                     }
2447
2448
                     reading(key_value);
2449
                     if constexpr (Opts.partial_read) {
2450
                        if (read_count == value.size()) {
2451
                           return;
2452
                        }
2453
                     }
2454
                     if (bool(ctx.error)) [[unlikely]]
2455
                        return;
2456
                  }
2457
               }
2458
43.7k
               if (skip_ws<Opts>(ctx, it, end)) {
2459
8
                  return;
2460
8
               }
2461
43.7k
            }
2462
6.10k
         }
2463
6.10k
      }
_ZN3glz4fromILj10E1SE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEETnNS_14string_literalEXtlNS5_ILm1EEEEERS1_TkNS_10is_contextERNS_7contextERPKcSC_EEvOT1_OT2_OT3_OT4_
Line
Count
Source
2079
415
      {
2080
415
         static constexpr auto num_members = reflect<T>::size;
2081
2082
415
         static constexpr auto Opts = opening_handled_off<ws_handled_off<Options>()>();
2083
415
         if constexpr (!check_opening_handled(Options)) {
2084
415
            if constexpr (!check_ws_handled(Options)) {
2085
415
               if (skip_ws<Opts>(ctx, it, end)) {
2086
0
                  return;
2087
0
               }
2088
415
            }
2089
415
            if (match_invalid_end<'{', Opts>(ctx, it, end)) {
2090
0
               return;
2091
0
            }
2092
            if constexpr (not Opts.null_terminated) {
2093
               if (it == end) [[unlikely]] {
2094
                  ctx.error = error_code::unexpected_end;
2095
                  return;
2096
               }
2097
            }
2098
            if constexpr (not Opts.null_terminated) {
2099
               ++ctx.indentation_level;
2100
            }
2101
415
         }
2102
415
         const auto ws_start = it;
2103
415
         if (skip_ws<Opts>(ctx, it, end)) {
2104
0
            return;
2105
0
         }
2106
415
         const size_t ws_size = size_t(it - ws_start);
2107
2108
         if constexpr ((glaze_object_t<T> || reflectable<T>) && num_members == 0 && Opts.error_on_unknown_keys) {
2109
            if constexpr (not tag.sv().empty()) {
2110
               if (*it == '"') {
2111
                  ++it;
2112
                  if constexpr (not Opts.null_terminated) {
2113
                     if (it == end) [[unlikely]] {
2114
                        ctx.error = error_code::unexpected_end;
2115
                        return;
2116
                     }
2117
                  }
2118
2119
                  const auto start = it;
2120
                  skip_string_view<Opts>(ctx, it, end);
2121
                  if (bool(ctx.error)) [[unlikely]]
2122
                     return;
2123
                  const sv key{start, size_t(it - start)};
2124
                  ++it;
2125
                  if constexpr (not Opts.null_terminated) {
2126
                     if (it == end) [[unlikely]] {
2127
                        ctx.error = error_code::unexpected_end;
2128
                        return;
2129
                     }
2130
                  }
2131
2132
                  if (key == tag.sv()) {
2133
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2134
                        return;
2135
                     }
2136
2137
                     parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
2138
                     if (bool(ctx.error)) [[unlikely]]
2139
                        return;
2140
2141
                     if (skip_ws<Opts>(ctx, it, end)) {
2142
                        return;
2143
                     }
2144
                  }
2145
                  else {
2146
                     ctx.error = error_code::unknown_key;
2147
                     return;
2148
                  }
2149
               }
2150
            }
2151
2152
            if (*it == '}') [[likely]] {
2153
               if constexpr (not Opts.null_terminated) {
2154
                  --ctx.indentation_level;
2155
               }
2156
               ++it;
2157
               if constexpr (not Opts.null_terminated) {
2158
                  if (it == end) {
2159
                     ctx.error = error_code::end_reached;
2160
                     return;
2161
                  }
2162
               }
2163
               if constexpr (Opts.partial_read) {
2164
                  ctx.error = error_code::partial_read_complete;
2165
               }
2166
               return;
2167
            }
2168
            ctx.error = error_code::unknown_key;
2169
            return;
2170
         }
2171
415
         else {
2172
415
            decltype(auto) fields = [&]() -> decltype(auto) {
2173
415
               if constexpr ((glaze_object_t<T> || reflectable<T>) &&
2174
415
                             (Opts.error_on_missing_keys || Opts.partial_read)) {
2175
415
                  return bit_array<num_members>{};
2176
415
               }
2177
415
               else {
2178
415
                  return nullptr;
2179
415
               }
2180
415
            }();
2181
2182
415
            size_t read_count{}; // for partial_read
2183
2184
415
            bool first = true;
2185
830
            while (true) {
2186
               if constexpr ((glaze_object_t<T> || reflectable<T>) && Opts.partial_read) {
2187
                  static constexpr bit_array<num_members> all_fields = [] {
2188
                     bit_array<num_members> arr{};
2189
                     for (size_t i = 0; i < num_members; ++i) {
2190
                        arr[i] = true;
2191
                     }
2192
                     return arr;
2193
                  }();
2194
2195
                  if ((all_fields & fields) == all_fields) {
2196
                     ctx.error = error_code::partial_read_complete;
2197
                     return;
2198
                  }
2199
               }
2200
2201
830
               if (*it == '}') {
2202
                  if constexpr (not Opts.null_terminated) {
2203
                     --ctx.indentation_level;
2204
                  }
2205
                  if constexpr ((glaze_object_t<T> || reflectable<T>) &&
2206
                                (Opts.partial_read && Opts.error_on_missing_keys)) {
2207
                     ctx.error = error_code::missing_key;
2208
                     return;
2209
                  }
2210
415
                  else {
2211
                     if constexpr ((glaze_object_t<T> || reflectable<T>) && Opts.error_on_missing_keys) {
2212
                        constexpr auto req_fields = required_fields<T, Opts>();
2213
                        if ((req_fields & fields) != req_fields) {
2214
                           for (size_t i = 0; i < num_members; ++i) {
2215
                              if (not fields[i]) {
2216
                                 ctx.custom_error_message = reflect<T>::keys[i];
2217
                                 // We just return the first missing key in order to avoid heap allocations
2218
                                 break;
2219
                              }
2220
                           }
2221
2222
                           ctx.error = error_code::missing_key;
2223
                           return;
2224
                        }
2225
                     }
2226
415
                     ++it; // Increment after checking for mising keys so errors are within buffer bounds
2227
                     if constexpr (not Opts.null_terminated) {
2228
                        if (it == end) {
2229
                           ctx.error = error_code::end_reached;
2230
                           return;
2231
                        }
2232
                     }
2233
415
                  }
2234
415
                  return;
2235
415
               }
2236
415
               else if (first) {
2237
415
                  first = false;
2238
415
               }
2239
0
               else {
2240
0
                  if (match_invalid_end<',', Opts>(ctx, it, end)) {
2241
0
                     return;
2242
0
                  }
2243
                  if constexpr (not Opts.null_terminated) {
2244
                     if (it == end) [[unlikely]] {
2245
                        ctx.error = error_code::unexpected_end;
2246
                        return;
2247
                     }
2248
                  }
2249
2250
                  if constexpr ((not Opts.minified) && (num_members > 1 || not Opts.error_on_unknown_keys)) {
2251
                     if (ws_size && ws_size < size_t(end - it)) {
2252
                        skip_matching_ws(ws_start, it, ws_size);
2253
                     }
2254
                  }
2255
2256
0
                  if (skip_ws<Opts>(ctx, it, end)) {
2257
0
                     return;
2258
0
                  }
2259
0
               }
2260
2261
415
               constexpr auto reflection_type = glaze_object_t<T> || reflectable<T>;
2262
2263
               if constexpr (reflection_type && (num_members == 0)) {
2264
                  if constexpr (Opts.error_on_unknown_keys) {
2265
                     static_assert(false_v<T>, "This should be unreachable");
2266
                  }
2267
                  else {
2268
                     if (match_invalid_end<'"', Opts>(ctx, it, end)) {
2269
                        return;
2270
                     }
2271
2272
                     // parsing to an empty object, but at this point the JSON presents keys
2273
2274
                     // Unknown key handler does not unescape keys. Unknown escaped keys are
2275
                     // handled by the user.
2276
2277
                     const auto start = it;
2278
                     skip_string_view<Opts>(ctx, it, end);
2279
                     if (bool(ctx.error)) [[unlikely]]
2280
                        return;
2281
                     const sv key{start, size_t(it - start)};
2282
                     ++it;
2283
                     if constexpr (not Opts.null_terminated) {
2284
                        if (it == end) [[unlikely]] {
2285
                           ctx.error = error_code::unexpected_end;
2286
                           return;
2287
                        }
2288
                     }
2289
2290
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2291
                        return;
2292
                     }
2293
2294
                     parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
2295
                     if (bool(ctx.error)) [[unlikely]]
2296
                        return;
2297
                     if constexpr (not Opts.null_terminated) {
2298
                        if (it == end) [[unlikely]] {
2299
                           ctx.error = error_code::unexpected_end;
2300
                           return;
2301
                        }
2302
                     }
2303
                  }
2304
               }
2305
415
               else if constexpr (reflection_type) {
2306
415
                  static_assert(bool(hash_info<T>.type));
2307
2308
415
                  if (*it != '"') [[unlikely]] {
2309
0
                     ctx.error = error_code::expected_quote;
2310
0
                     return;
2311
0
                  }
2312
415
                  ++it;
2313
                  if constexpr (not Opts.null_terminated) {
2314
                     if (it == end) [[unlikely]] {
2315
                        ctx.error = error_code::unexpected_end;
2316
                        return;
2317
                     }
2318
                  }
2319
2320
                  if constexpr (not tag.sv().empty() && not contains_tag<T, tag>()) {
2321
                     // For tagged variants we first check to see if the key matches the tag
2322
                     // We only need to do this if the tag is not part of the keys
2323
2324
                     const auto start = it;
2325
                     skip_string_view<Opts>(ctx, it, end);
2326
                     if (bool(ctx.error)) [[unlikely]]
2327
                        return;
2328
                     const sv key{start, size_t(it - start)};
2329
                     ++it;
2330
                     if constexpr (not Opts.null_terminated) {
2331
                        if (it == end) [[unlikely]] {
2332
                           ctx.error = error_code::unexpected_end;
2333
                           return;
2334
                        }
2335
                     }
2336
2337
                     if (key == tag.sv()) {
2338
                        if (parse_ws_colon<Opts>(ctx, it, end)) {
2339
                           return;
2340
                        }
2341
2342
                        parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
2343
                        if (bool(ctx.error)) [[unlikely]]
2344
                           return;
2345
2346
                        if (skip_ws<Opts>(ctx, it, end)) {
2347
                           return;
2348
                        }
2349
                        continue;
2350
                     }
2351
                     else {
2352
                        it = start; // reset the iterator
2353
                     }
2354
                  }
2355
2356
                  if constexpr (Opts.error_on_missing_keys || Opts.partial_read) {
2357
                     size_t index = num_members;
2358
                     parse_and_invoke<Opts, T, hash_info<T>>(value, ctx, it, end, index);
2359
                     if (bool(ctx.error)) [[unlikely]]
2360
                        return;
2361
                     if (index < num_members) {
2362
                        fields[index] = true;
2363
                     }
2364
                  }
2365
415
                  else {
2366
415
                     parse_and_invoke<Opts, T, hash_info<T>>(value, ctx, it, end);
2367
415
                     if (bool(ctx.error)) [[unlikely]]
2368
0
                        return;
2369
415
                  }
2370
               }
2371
               else {
2372
                  // For types like std::map, std::unordered_map
2373
2374
                  auto reading = [&](auto&& key) {
2375
                     if constexpr (Opts.partial_read) {
2376
                        if (auto element = value.find(key); element != value.end()) {
2377
                           ++read_count;
2378
                           parse<JSON>::op<ws_handled<Opts>()>(element->second, ctx, it, end);
2379
                        }
2380
                        else {
2381
                           skip_value<JSON>::op<Opts>(ctx, it, end);
2382
                        }
2383
                     }
2384
                     else {
2385
                        parse<JSON>::op<ws_handled<Opts>()>(value[key], ctx, it, end);
2386
                     }
2387
                  };
2388
2389
                  // using Key = std::conditional_t<heterogeneous_map<T>, sv, typename T::key_type>;
2390
                  using Key = typename T::key_type;
2391
                  if constexpr (std::is_same_v<Key, std::string>) {
2392
                     static thread_local Key key;
2393
                     parse<JSON>::op<Opts>(key, ctx, it, end);
2394
                     if (bool(ctx.error)) [[unlikely]]
2395
                        return;
2396
2397
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2398
                        return;
2399
                     }
2400
2401
                     reading(key);
2402
                     if constexpr (Opts.partial_read) {
2403
                        if (read_count == value.size()) {
2404
                           return;
2405
                        }
2406
                     }
2407
                     if (bool(ctx.error)) [[unlikely]]
2408
                        return;
2409
                  }
2410
                  else if constexpr (str_t<Key>) {
2411
                     Key key;
2412
                     parse<JSON>::op<Opts>(key, ctx, it, end);
2413
                     if (bool(ctx.error)) [[unlikely]]
2414
                        return;
2415
2416
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2417
                        return;
2418
                     }
2419
2420
                     reading(key);
2421
                     if constexpr (Opts.partial_read) {
2422
                        if (read_count == value.size()) {
2423
                           return;
2424
                        }
2425
                     }
2426
                     if (bool(ctx.error)) [[unlikely]]
2427
                        return;
2428
                  }
2429
                  else {
2430
                     Key key_value{};
2431
                     if constexpr (glaze_enum_t<Key>) {
2432
                        parse<JSON>::op<Opts>(key_value, ctx, it, end);
2433
                     }
2434
                     else if constexpr (std::is_arithmetic_v<Key>) {
2435
                        // prefer over quoted_t below to avoid double parsing of quoted_t
2436
                        parse<JSON>::op<opt_true<Opts, &opts::quoted_num>>(key_value, ctx, it, end);
2437
                     }
2438
                     else {
2439
                        parse<JSON>::op<opt_false<Opts, &opts::raw_string>>(quoted_t<Key>{key_value}, ctx, it, end);
2440
                     }
2441
                     if (bool(ctx.error)) [[unlikely]]
2442
                        return;
2443
2444
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2445
                        return;
2446
                     }
2447
2448
                     reading(key_value);
2449
                     if constexpr (Opts.partial_read) {
2450
                        if (read_count == value.size()) {
2451
                           return;
2452
                        }
2453
                     }
2454
                     if (bool(ctx.error)) [[unlikely]]
2455
                        return;
2456
                  }
2457
               }
2458
415
               if (skip_ws<Opts>(ctx, it, end)) {
2459
0
                  return;
2460
0
               }
2461
415
            }
2462
415
         }
2463
415
      }
_ZN3glz4fromILj10E5ValueIfEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEETnNS_14string_literalEXtlNS6_ILm1EEEEERS2_TkNS_10is_contextERNS_7contextERPKcSD_EEvOT1_OT2_OT3_OT4_
Line
Count
Source
2079
488
      {
2080
488
         static constexpr auto num_members = reflect<T>::size;
2081
2082
488
         static constexpr auto Opts = opening_handled_off<ws_handled_off<Options>()>();
2083
488
         if constexpr (!check_opening_handled(Options)) {
2084
488
            if constexpr (!check_ws_handled(Options)) {
2085
488
               if (skip_ws<Opts>(ctx, it, end)) {
2086
0
                  return;
2087
0
               }
2088
488
            }
2089
488
            if (match_invalid_end<'{', Opts>(ctx, it, end)) {
2090
0
               return;
2091
0
            }
2092
            if constexpr (not Opts.null_terminated) {
2093
               if (it == end) [[unlikely]] {
2094
                  ctx.error = error_code::unexpected_end;
2095
                  return;
2096
               }
2097
            }
2098
            if constexpr (not Opts.null_terminated) {
2099
               ++ctx.indentation_level;
2100
            }
2101
488
         }
2102
488
         const auto ws_start = it;
2103
488
         if (skip_ws<Opts>(ctx, it, end)) {
2104
0
            return;
2105
0
         }
2106
488
         const size_t ws_size = size_t(it - ws_start);
2107
2108
         if constexpr ((glaze_object_t<T> || reflectable<T>) && num_members == 0 && Opts.error_on_unknown_keys) {
2109
            if constexpr (not tag.sv().empty()) {
2110
               if (*it == '"') {
2111
                  ++it;
2112
                  if constexpr (not Opts.null_terminated) {
2113
                     if (it == end) [[unlikely]] {
2114
                        ctx.error = error_code::unexpected_end;
2115
                        return;
2116
                     }
2117
                  }
2118
2119
                  const auto start = it;
2120
                  skip_string_view<Opts>(ctx, it, end);
2121
                  if (bool(ctx.error)) [[unlikely]]
2122
                     return;
2123
                  const sv key{start, size_t(it - start)};
2124
                  ++it;
2125
                  if constexpr (not Opts.null_terminated) {
2126
                     if (it == end) [[unlikely]] {
2127
                        ctx.error = error_code::unexpected_end;
2128
                        return;
2129
                     }
2130
                  }
2131
2132
                  if (key == tag.sv()) {
2133
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2134
                        return;
2135
                     }
2136
2137
                     parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
2138
                     if (bool(ctx.error)) [[unlikely]]
2139
                        return;
2140
2141
                     if (skip_ws<Opts>(ctx, it, end)) {
2142
                        return;
2143
                     }
2144
                  }
2145
                  else {
2146
                     ctx.error = error_code::unknown_key;
2147
                     return;
2148
                  }
2149
               }
2150
            }
2151
2152
            if (*it == '}') [[likely]] {
2153
               if constexpr (not Opts.null_terminated) {
2154
                  --ctx.indentation_level;
2155
               }
2156
               ++it;
2157
               if constexpr (not Opts.null_terminated) {
2158
                  if (it == end) {
2159
                     ctx.error = error_code::end_reached;
2160
                     return;
2161
                  }
2162
               }
2163
               if constexpr (Opts.partial_read) {
2164
                  ctx.error = error_code::partial_read_complete;
2165
               }
2166
               return;
2167
            }
2168
            ctx.error = error_code::unknown_key;
2169
            return;
2170
         }
2171
488
         else {
2172
488
            decltype(auto) fields = [&]() -> decltype(auto) {
2173
488
               if constexpr ((glaze_object_t<T> || reflectable<T>) &&
2174
488
                             (Opts.error_on_missing_keys || Opts.partial_read)) {
2175
488
                  return bit_array<num_members>{};
2176
488
               }
2177
488
               else {
2178
488
                  return nullptr;
2179
488
               }
2180
488
            }();
2181
2182
488
            size_t read_count{}; // for partial_read
2183
2184
488
            bool first = true;
2185
976
            while (true) {
2186
               if constexpr ((glaze_object_t<T> || reflectable<T>) && Opts.partial_read) {
2187
                  static constexpr bit_array<num_members> all_fields = [] {
2188
                     bit_array<num_members> arr{};
2189
                     for (size_t i = 0; i < num_members; ++i) {
2190
                        arr[i] = true;
2191
                     }
2192
                     return arr;
2193
                  }();
2194
2195
                  if ((all_fields & fields) == all_fields) {
2196
                     ctx.error = error_code::partial_read_complete;
2197
                     return;
2198
                  }
2199
               }
2200
2201
976
               if (*it == '}') {
2202
                  if constexpr (not Opts.null_terminated) {
2203
                     --ctx.indentation_level;
2204
                  }
2205
                  if constexpr ((glaze_object_t<T> || reflectable<T>) &&
2206
                                (Opts.partial_read && Opts.error_on_missing_keys)) {
2207
                     ctx.error = error_code::missing_key;
2208
                     return;
2209
                  }
2210
488
                  else {
2211
                     if constexpr ((glaze_object_t<T> || reflectable<T>) && Opts.error_on_missing_keys) {
2212
                        constexpr auto req_fields = required_fields<T, Opts>();
2213
                        if ((req_fields & fields) != req_fields) {
2214
                           for (size_t i = 0; i < num_members; ++i) {
2215
                              if (not fields[i]) {
2216
                                 ctx.custom_error_message = reflect<T>::keys[i];
2217
                                 // We just return the first missing key in order to avoid heap allocations
2218
                                 break;
2219
                              }
2220
                           }
2221
2222
                           ctx.error = error_code::missing_key;
2223
                           return;
2224
                        }
2225
                     }
2226
488
                     ++it; // Increment after checking for mising keys so errors are within buffer bounds
2227
                     if constexpr (not Opts.null_terminated) {
2228
                        if (it == end) {
2229
                           ctx.error = error_code::end_reached;
2230
                           return;
2231
                        }
2232
                     }
2233
488
                  }
2234
488
                  return;
2235
488
               }
2236
488
               else if (first) {
2237
488
                  first = false;
2238
488
               }
2239
0
               else {
2240
0
                  if (match_invalid_end<',', Opts>(ctx, it, end)) {
2241
0
                     return;
2242
0
                  }
2243
                  if constexpr (not Opts.null_terminated) {
2244
                     if (it == end) [[unlikely]] {
2245
                        ctx.error = error_code::unexpected_end;
2246
                        return;
2247
                     }
2248
                  }
2249
2250
                  if constexpr ((not Opts.minified) && (num_members > 1 || not Opts.error_on_unknown_keys)) {
2251
                     if (ws_size && ws_size < size_t(end - it)) {
2252
                        skip_matching_ws(ws_start, it, ws_size);
2253
                     }
2254
                  }
2255
2256
0
                  if (skip_ws<Opts>(ctx, it, end)) {
2257
0
                     return;
2258
0
                  }
2259
0
               }
2260
2261
488
               constexpr auto reflection_type = glaze_object_t<T> || reflectable<T>;
2262
2263
               if constexpr (reflection_type && (num_members == 0)) {
2264
                  if constexpr (Opts.error_on_unknown_keys) {
2265
                     static_assert(false_v<T>, "This should be unreachable");
2266
                  }
2267
                  else {
2268
                     if (match_invalid_end<'"', Opts>(ctx, it, end)) {
2269
                        return;
2270
                     }
2271
2272
                     // parsing to an empty object, but at this point the JSON presents keys
2273
2274
                     // Unknown key handler does not unescape keys. Unknown escaped keys are
2275
                     // handled by the user.
2276
2277
                     const auto start = it;
2278
                     skip_string_view<Opts>(ctx, it, end);
2279
                     if (bool(ctx.error)) [[unlikely]]
2280
                        return;
2281
                     const sv key{start, size_t(it - start)};
2282
                     ++it;
2283
                     if constexpr (not Opts.null_terminated) {
2284
                        if (it == end) [[unlikely]] {
2285
                           ctx.error = error_code::unexpected_end;
2286
                           return;
2287
                        }
2288
                     }
2289
2290
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2291
                        return;
2292
                     }
2293
2294
                     parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
2295
                     if (bool(ctx.error)) [[unlikely]]
2296
                        return;
2297
                     if constexpr (not Opts.null_terminated) {
2298
                        if (it == end) [[unlikely]] {
2299
                           ctx.error = error_code::unexpected_end;
2300
                           return;
2301
                        }
2302
                     }
2303
                  }
2304
               }
2305
488
               else if constexpr (reflection_type) {
2306
488
                  static_assert(bool(hash_info<T>.type));
2307
2308
488
                  if (*it != '"') [[unlikely]] {
2309
0
                     ctx.error = error_code::expected_quote;
2310
0
                     return;
2311
0
                  }
2312
488
                  ++it;
2313
                  if constexpr (not Opts.null_terminated) {
2314
                     if (it == end) [[unlikely]] {
2315
                        ctx.error = error_code::unexpected_end;
2316
                        return;
2317
                     }
2318
                  }
2319
2320
                  if constexpr (not tag.sv().empty() && not contains_tag<T, tag>()) {
2321
                     // For tagged variants we first check to see if the key matches the tag
2322
                     // We only need to do this if the tag is not part of the keys
2323
2324
                     const auto start = it;
2325
                     skip_string_view<Opts>(ctx, it, end);
2326
                     if (bool(ctx.error)) [[unlikely]]
2327
                        return;
2328
                     const sv key{start, size_t(it - start)};
2329
                     ++it;
2330
                     if constexpr (not Opts.null_terminated) {
2331
                        if (it == end) [[unlikely]] {
2332
                           ctx.error = error_code::unexpected_end;
2333
                           return;
2334
                        }
2335
                     }
2336
2337
                     if (key == tag.sv()) {
2338
                        if (parse_ws_colon<Opts>(ctx, it, end)) {
2339
                           return;
2340
                        }
2341
2342
                        parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
2343
                        if (bool(ctx.error)) [[unlikely]]
2344
                           return;
2345
2346
                        if (skip_ws<Opts>(ctx, it, end)) {
2347
                           return;
2348
                        }
2349
                        continue;
2350
                     }
2351
                     else {
2352
                        it = start; // reset the iterator
2353
                     }
2354
                  }
2355
2356
                  if constexpr (Opts.error_on_missing_keys || Opts.partial_read) {
2357
                     size_t index = num_members;
2358
                     parse_and_invoke<Opts, T, hash_info<T>>(value, ctx, it, end, index);
2359
                     if (bool(ctx.error)) [[unlikely]]
2360
                        return;
2361
                     if (index < num_members) {
2362
                        fields[index] = true;
2363
                     }
2364
                  }
2365
488
                  else {
2366
488
                     parse_and_invoke<Opts, T, hash_info<T>>(value, ctx, it, end);
2367
488
                     if (bool(ctx.error)) [[unlikely]]
2368
0
                        return;
2369
488
                  }
2370
               }
2371
               else {
2372
                  // For types like std::map, std::unordered_map
2373
2374
                  auto reading = [&](auto&& key) {
2375
                     if constexpr (Opts.partial_read) {
2376
                        if (auto element = value.find(key); element != value.end()) {
2377
                           ++read_count;
2378
                           parse<JSON>::op<ws_handled<Opts>()>(element->second, ctx, it, end);
2379
                        }
2380
                        else {
2381
                           skip_value<JSON>::op<Opts>(ctx, it, end);
2382
                        }
2383
                     }
2384
                     else {
2385
                        parse<JSON>::op<ws_handled<Opts>()>(value[key], ctx, it, end);
2386
                     }
2387
                  };
2388
2389
                  // using Key = std::conditional_t<heterogeneous_map<T>, sv, typename T::key_type>;
2390
                  using Key = typename T::key_type;
2391
                  if constexpr (std::is_same_v<Key, std::string>) {
2392
                     static thread_local Key key;
2393
                     parse<JSON>::op<Opts>(key, ctx, it, end);
2394
                     if (bool(ctx.error)) [[unlikely]]
2395
                        return;
2396
2397
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2398
                        return;
2399
                     }
2400
2401
                     reading(key);
2402
                     if constexpr (Opts.partial_read) {
2403
                        if (read_count == value.size()) {
2404
                           return;
2405
                        }
2406
                     }
2407
                     if (bool(ctx.error)) [[unlikely]]
2408
                        return;
2409
                  }
2410
                  else if constexpr (str_t<Key>) {
2411
                     Key key;
2412
                     parse<JSON>::op<Opts>(key, ctx, it, end);
2413
                     if (bool(ctx.error)) [[unlikely]]
2414
                        return;
2415
2416
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2417
                        return;
2418
                     }
2419
2420
                     reading(key);
2421
                     if constexpr (Opts.partial_read) {
2422
                        if (read_count == value.size()) {
2423
                           return;
2424
                        }
2425
                     }
2426
                     if (bool(ctx.error)) [[unlikely]]
2427
                        return;
2428
                  }
2429
                  else {
2430
                     Key key_value{};
2431
                     if constexpr (glaze_enum_t<Key>) {
2432
                        parse<JSON>::op<Opts>(key_value, ctx, it, end);
2433
                     }
2434
                     else if constexpr (std::is_arithmetic_v<Key>) {
2435
                        // prefer over quoted_t below to avoid double parsing of quoted_t
2436
                        parse<JSON>::op<opt_true<Opts, &opts::quoted_num>>(key_value, ctx, it, end);
2437
                     }
2438
                     else {
2439
                        parse<JSON>::op<opt_false<Opts, &opts::raw_string>>(quoted_t<Key>{key_value}, ctx, it, end);
2440
                     }
2441
                     if (bool(ctx.error)) [[unlikely]]
2442
                        return;
2443
2444
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2445
                        return;
2446
                     }
2447
2448
                     reading(key_value);
2449
                     if constexpr (Opts.partial_read) {
2450
                        if (read_count == value.size()) {
2451
                           return;
2452
                        }
2453
                     }
2454
                     if (bool(ctx.error)) [[unlikely]]
2455
                        return;
2456
                  }
2457
               }
2458
488
               if (skip_ws<Opts>(ctx, it, end)) {
2459
0
                  return;
2460
0
               }
2461
488
            }
2462
488
         }
2463
488
      }
_ZN3glz4fromILj10E5ValueIdEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEETnNS_14string_literalEXtlNS6_ILm1EEEEERS2_TkNS_10is_contextERNS_7contextERPKcSD_EEvOT1_OT2_OT3_OT4_
Line
Count
Source
2079
1.05k
      {
2080
1.05k
         static constexpr auto num_members = reflect<T>::size;
2081
2082
1.05k
         static constexpr auto Opts = opening_handled_off<ws_handled_off<Options>()>();
2083
1.05k
         if constexpr (!check_opening_handled(Options)) {
2084
1.05k
            if constexpr (!check_ws_handled(Options)) {
2085
1.05k
               if (skip_ws<Opts>(ctx, it, end)) {
2086
0
                  return;
2087
0
               }
2088
1.05k
            }
2089
1.05k
            if (match_invalid_end<'{', Opts>(ctx, it, end)) {
2090
0
               return;
2091
0
            }
2092
            if constexpr (not Opts.null_terminated) {
2093
               if (it == end) [[unlikely]] {
2094
                  ctx.error = error_code::unexpected_end;
2095
                  return;
2096
               }
2097
            }
2098
            if constexpr (not Opts.null_terminated) {
2099
               ++ctx.indentation_level;
2100
            }
2101
1.05k
         }
2102
1.05k
         const auto ws_start = it;
2103
1.05k
         if (skip_ws<Opts>(ctx, it, end)) {
2104
0
            return;
2105
0
         }
2106
1.05k
         const size_t ws_size = size_t(it - ws_start);
2107
2108
         if constexpr ((glaze_object_t<T> || reflectable<T>) && num_members == 0 && Opts.error_on_unknown_keys) {
2109
            if constexpr (not tag.sv().empty()) {
2110
               if (*it == '"') {
2111
                  ++it;
2112
                  if constexpr (not Opts.null_terminated) {
2113
                     if (it == end) [[unlikely]] {
2114
                        ctx.error = error_code::unexpected_end;
2115
                        return;
2116
                     }
2117
                  }
2118
2119
                  const auto start = it;
2120
                  skip_string_view<Opts>(ctx, it, end);
2121
                  if (bool(ctx.error)) [[unlikely]]
2122
                     return;
2123
                  const sv key{start, size_t(it - start)};
2124
                  ++it;
2125
                  if constexpr (not Opts.null_terminated) {
2126
                     if (it == end) [[unlikely]] {
2127
                        ctx.error = error_code::unexpected_end;
2128
                        return;
2129
                     }
2130
                  }
2131
2132
                  if (key == tag.sv()) {
2133
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2134
                        return;
2135
                     }
2136
2137
                     parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
2138
                     if (bool(ctx.error)) [[unlikely]]
2139
                        return;
2140
2141
                     if (skip_ws<Opts>(ctx, it, end)) {
2142
                        return;
2143
                     }
2144
                  }
2145
                  else {
2146
                     ctx.error = error_code::unknown_key;
2147
                     return;
2148
                  }
2149
               }
2150
            }
2151
2152
            if (*it == '}') [[likely]] {
2153
               if constexpr (not Opts.null_terminated) {
2154
                  --ctx.indentation_level;
2155
               }
2156
               ++it;
2157
               if constexpr (not Opts.null_terminated) {
2158
                  if (it == end) {
2159
                     ctx.error = error_code::end_reached;
2160
                     return;
2161
                  }
2162
               }
2163
               if constexpr (Opts.partial_read) {
2164
                  ctx.error = error_code::partial_read_complete;
2165
               }
2166
               return;
2167
            }
2168
            ctx.error = error_code::unknown_key;
2169
            return;
2170
         }
2171
1.05k
         else {
2172
1.05k
            decltype(auto) fields = [&]() -> decltype(auto) {
2173
1.05k
               if constexpr ((glaze_object_t<T> || reflectable<T>) &&
2174
1.05k
                             (Opts.error_on_missing_keys || Opts.partial_read)) {
2175
1.05k
                  return bit_array<num_members>{};
2176
1.05k
               }
2177
1.05k
               else {
2178
1.05k
                  return nullptr;
2179
1.05k
               }
2180
1.05k
            }();
2181
2182
1.05k
            size_t read_count{}; // for partial_read
2183
2184
1.05k
            bool first = true;
2185
2.10k
            while (true) {
2186
               if constexpr ((glaze_object_t<T> || reflectable<T>) && Opts.partial_read) {
2187
                  static constexpr bit_array<num_members> all_fields = [] {
2188
                     bit_array<num_members> arr{};
2189
                     for (size_t i = 0; i < num_members; ++i) {
2190
                        arr[i] = true;
2191
                     }
2192
                     return arr;
2193
                  }();
2194
2195
                  if ((all_fields & fields) == all_fields) {
2196
                     ctx.error = error_code::partial_read_complete;
2197
                     return;
2198
                  }
2199
               }
2200
2201
2.10k
               if (*it == '}') {
2202
                  if constexpr (not Opts.null_terminated) {
2203
                     --ctx.indentation_level;
2204
                  }
2205
                  if constexpr ((glaze_object_t<T> || reflectable<T>) &&
2206
                                (Opts.partial_read && Opts.error_on_missing_keys)) {
2207
                     ctx.error = error_code::missing_key;
2208
                     return;
2209
                  }
2210
1.05k
                  else {
2211
                     if constexpr ((glaze_object_t<T> || reflectable<T>) && Opts.error_on_missing_keys) {
2212
                        constexpr auto req_fields = required_fields<T, Opts>();
2213
                        if ((req_fields & fields) != req_fields) {
2214
                           for (size_t i = 0; i < num_members; ++i) {
2215
                              if (not fields[i]) {
2216
                                 ctx.custom_error_message = reflect<T>::keys[i];
2217
                                 // We just return the first missing key in order to avoid heap allocations
2218
                                 break;
2219
                              }
2220
                           }
2221
2222
                           ctx.error = error_code::missing_key;
2223
                           return;
2224
                        }
2225
                     }
2226
1.05k
                     ++it; // Increment after checking for mising keys so errors are within buffer bounds
2227
                     if constexpr (not Opts.null_terminated) {
2228
                        if (it == end) {
2229
                           ctx.error = error_code::end_reached;
2230
                           return;
2231
                        }
2232
                     }
2233
1.05k
                  }
2234
1.05k
                  return;
2235
1.05k
               }
2236
1.05k
               else if (first) {
2237
1.05k
                  first = false;
2238
1.05k
               }
2239
0
               else {
2240
0
                  if (match_invalid_end<',', Opts>(ctx, it, end)) {
2241
0
                     return;
2242
0
                  }
2243
                  if constexpr (not Opts.null_terminated) {
2244
                     if (it == end) [[unlikely]] {
2245
                        ctx.error = error_code::unexpected_end;
2246
                        return;
2247
                     }
2248
                  }
2249
2250
                  if constexpr ((not Opts.minified) && (num_members > 1 || not Opts.error_on_unknown_keys)) {
2251
                     if (ws_size && ws_size < size_t(end - it)) {
2252
                        skip_matching_ws(ws_start, it, ws_size);
2253
                     }
2254
                  }
2255
2256
0
                  if (skip_ws<Opts>(ctx, it, end)) {
2257
0
                     return;
2258
0
                  }
2259
0
               }
2260
2261
1.05k
               constexpr auto reflection_type = glaze_object_t<T> || reflectable<T>;
2262
2263
               if constexpr (reflection_type && (num_members == 0)) {
2264
                  if constexpr (Opts.error_on_unknown_keys) {
2265
                     static_assert(false_v<T>, "This should be unreachable");
2266
                  }
2267
                  else {
2268
                     if (match_invalid_end<'"', Opts>(ctx, it, end)) {
2269
                        return;
2270
                     }
2271
2272
                     // parsing to an empty object, but at this point the JSON presents keys
2273
2274
                     // Unknown key handler does not unescape keys. Unknown escaped keys are
2275
                     // handled by the user.
2276
2277
                     const auto start = it;
2278
                     skip_string_view<Opts>(ctx, it, end);
2279
                     if (bool(ctx.error)) [[unlikely]]
2280
                        return;
2281
                     const sv key{start, size_t(it - start)};
2282
                     ++it;
2283
                     if constexpr (not Opts.null_terminated) {
2284
                        if (it == end) [[unlikely]] {
2285
                           ctx.error = error_code::unexpected_end;
2286
                           return;
2287
                        }
2288
                     }
2289
2290
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2291
                        return;
2292
                     }
2293
2294
                     parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
2295
                     if (bool(ctx.error)) [[unlikely]]
2296
                        return;
2297
                     if constexpr (not Opts.null_terminated) {
2298
                        if (it == end) [[unlikely]] {
2299
                           ctx.error = error_code::unexpected_end;
2300
                           return;
2301
                        }
2302
                     }
2303
                  }
2304
               }
2305
1.05k
               else if constexpr (reflection_type) {
2306
1.05k
                  static_assert(bool(hash_info<T>.type));
2307
2308
1.05k
                  if (*it != '"') [[unlikely]] {
2309
0
                     ctx.error = error_code::expected_quote;
2310
0
                     return;
2311
0
                  }
2312
1.05k
                  ++it;
2313
                  if constexpr (not Opts.null_terminated) {
2314
                     if (it == end) [[unlikely]] {
2315
                        ctx.error = error_code::unexpected_end;
2316
                        return;
2317
                     }
2318
                  }
2319
2320
                  if constexpr (not tag.sv().empty() && not contains_tag<T, tag>()) {
2321
                     // For tagged variants we first check to see if the key matches the tag
2322
                     // We only need to do this if the tag is not part of the keys
2323
2324
                     const auto start = it;
2325
                     skip_string_view<Opts>(ctx, it, end);
2326
                     if (bool(ctx.error)) [[unlikely]]
2327
                        return;
2328
                     const sv key{start, size_t(it - start)};
2329
                     ++it;
2330
                     if constexpr (not Opts.null_terminated) {
2331
                        if (it == end) [[unlikely]] {
2332
                           ctx.error = error_code::unexpected_end;
2333
                           return;
2334
                        }
2335
                     }
2336
2337
                     if (key == tag.sv()) {
2338
                        if (parse_ws_colon<Opts>(ctx, it, end)) {
2339
                           return;
2340
                        }
2341
2342
                        parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
2343
                        if (bool(ctx.error)) [[unlikely]]
2344
                           return;
2345
2346
                        if (skip_ws<Opts>(ctx, it, end)) {
2347
                           return;
2348
                        }
2349
                        continue;
2350
                     }
2351
                     else {
2352
                        it = start; // reset the iterator
2353
                     }
2354
                  }
2355
2356
                  if constexpr (Opts.error_on_missing_keys || Opts.partial_read) {
2357
                     size_t index = num_members;
2358
                     parse_and_invoke<Opts, T, hash_info<T>>(value, ctx, it, end, index);
2359
                     if (bool(ctx.error)) [[unlikely]]
2360
                        return;
2361
                     if (index < num_members) {
2362
                        fields[index] = true;
2363
                     }
2364
                  }
2365
1.05k
                  else {
2366
1.05k
                     parse_and_invoke<Opts, T, hash_info<T>>(value, ctx, it, end);
2367
1.05k
                     if (bool(ctx.error)) [[unlikely]]
2368
0
                        return;
2369
1.05k
                  }
2370
               }
2371
               else {
2372
                  // For types like std::map, std::unordered_map
2373
2374
                  auto reading = [&](auto&& key) {
2375
                     if constexpr (Opts.partial_read) {
2376
                        if (auto element = value.find(key); element != value.end()) {
2377
                           ++read_count;
2378
                           parse<JSON>::op<ws_handled<Opts>()>(element->second, ctx, it, end);
2379
                        }
2380
                        else {
2381
                           skip_value<JSON>::op<Opts>(ctx, it, end);
2382
                        }
2383
                     }
2384
                     else {
2385
                        parse<JSON>::op<ws_handled<Opts>()>(value[key], ctx, it, end);
2386
                     }
2387
                  };
2388
2389
                  // using Key = std::conditional_t<heterogeneous_map<T>, sv, typename T::key_type>;
2390
                  using Key = typename T::key_type;
2391
                  if constexpr (std::is_same_v<Key, std::string>) {
2392
                     static thread_local Key key;
2393
                     parse<JSON>::op<Opts>(key, ctx, it, end);
2394
                     if (bool(ctx.error)) [[unlikely]]
2395
                        return;
2396
2397
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2398
                        return;
2399
                     }
2400
2401
                     reading(key);
2402
                     if constexpr (Opts.partial_read) {
2403
                        if (read_count == value.size()) {
2404
                           return;
2405
                        }
2406
                     }
2407
                     if (bool(ctx.error)) [[unlikely]]
2408
                        return;
2409
                  }
2410
                  else if constexpr (str_t<Key>) {
2411
                     Key key;
2412
                     parse<JSON>::op<Opts>(key, ctx, it, end);
2413
                     if (bool(ctx.error)) [[unlikely]]
2414
                        return;
2415
2416
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2417
                        return;
2418
                     }
2419
2420
                     reading(key);
2421
                     if constexpr (Opts.partial_read) {
2422
                        if (read_count == value.size()) {
2423
                           return;
2424
                        }
2425
                     }
2426
                     if (bool(ctx.error)) [[unlikely]]
2427
                        return;
2428
                  }
2429
                  else {
2430
                     Key key_value{};
2431
                     if constexpr (glaze_enum_t<Key>) {
2432
                        parse<JSON>::op<Opts>(key_value, ctx, it, end);
2433
                     }
2434
                     else if constexpr (std::is_arithmetic_v<Key>) {
2435
                        // prefer over quoted_t below to avoid double parsing of quoted_t
2436
                        parse<JSON>::op<opt_true<Opts, &opts::quoted_num>>(key_value, ctx, it, end);
2437
                     }
2438
                     else {
2439
                        parse<JSON>::op<opt_false<Opts, &opts::raw_string>>(quoted_t<Key>{key_value}, ctx, it, end);
2440
                     }
2441
                     if (bool(ctx.error)) [[unlikely]]
2442
                        return;
2443
2444
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2445
                        return;
2446
                     }
2447
2448
                     reading(key_value);
2449
                     if constexpr (Opts.partial_read) {
2450
                        if (read_count == value.size()) {
2451
                           return;
2452
                        }
2453
                     }
2454
                     if (bool(ctx.error)) [[unlikely]]
2455
                        return;
2456
                  }
2457
               }
2458
1.05k
               if (skip_ws<Opts>(ctx, it, end)) {
2459
0
                  return;
2460
0
               }
2461
1.05k
            }
2462
1.05k
         }
2463
1.05k
      }
_ZN3glz4fromILj10E5ValueIsEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEETnNS_14string_literalEXtlNS6_ILm1EEEEERS2_TkNS_10is_contextERNS_7contextERPKcSD_EEvOT1_OT2_OT3_OT4_
Line
Count
Source
2079
106
      {
2080
106
         static constexpr auto num_members = reflect<T>::size;
2081
2082
106
         static constexpr auto Opts = opening_handled_off<ws_handled_off<Options>()>();
2083
106
         if constexpr (!check_opening_handled(Options)) {
2084
106
            if constexpr (!check_ws_handled(Options)) {
2085
106
               if (skip_ws<Opts>(ctx, it, end)) {
2086
0
                  return;
2087
0
               }
2088
106
            }
2089
106
            if (match_invalid_end<'{', Opts>(ctx, it, end)) {
2090
0
               return;
2091
0
            }
2092
            if constexpr (not Opts.null_terminated) {
2093
               if (it == end) [[unlikely]] {
2094
                  ctx.error = error_code::unexpected_end;
2095
                  return;
2096
               }
2097
            }
2098
            if constexpr (not Opts.null_terminated) {
2099
               ++ctx.indentation_level;
2100
            }
2101
106
         }
2102
106
         const auto ws_start = it;
2103
106
         if (skip_ws<Opts>(ctx, it, end)) {
2104
0
            return;
2105
0
         }
2106
106
         const size_t ws_size = size_t(it - ws_start);
2107
2108
         if constexpr ((glaze_object_t<T> || reflectable<T>) && num_members == 0 && Opts.error_on_unknown_keys) {
2109
            if constexpr (not tag.sv().empty()) {
2110
               if (*it == '"') {
2111
                  ++it;
2112
                  if constexpr (not Opts.null_terminated) {
2113
                     if (it == end) [[unlikely]] {
2114
                        ctx.error = error_code::unexpected_end;
2115
                        return;
2116
                     }
2117
                  }
2118
2119
                  const auto start = it;
2120
                  skip_string_view<Opts>(ctx, it, end);
2121
                  if (bool(ctx.error)) [[unlikely]]
2122
                     return;
2123
                  const sv key{start, size_t(it - start)};
2124
                  ++it;
2125
                  if constexpr (not Opts.null_terminated) {
2126
                     if (it == end) [[unlikely]] {
2127
                        ctx.error = error_code::unexpected_end;
2128
                        return;
2129
                     }
2130
                  }
2131
2132
                  if (key == tag.sv()) {
2133
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2134
                        return;
2135
                     }
2136
2137
                     parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
2138
                     if (bool(ctx.error)) [[unlikely]]
2139
                        return;
2140
2141
                     if (skip_ws<Opts>(ctx, it, end)) {
2142
                        return;
2143
                     }
2144
                  }
2145
                  else {
2146
                     ctx.error = error_code::unknown_key;
2147
                     return;
2148
                  }
2149
               }
2150
            }
2151
2152
            if (*it == '}') [[likely]] {
2153
               if constexpr (not Opts.null_terminated) {
2154
                  --ctx.indentation_level;
2155
               }
2156
               ++it;
2157
               if constexpr (not Opts.null_terminated) {
2158
                  if (it == end) {
2159
                     ctx.error = error_code::end_reached;
2160
                     return;
2161
                  }
2162
               }
2163
               if constexpr (Opts.partial_read) {
2164
                  ctx.error = error_code::partial_read_complete;
2165
               }
2166
               return;
2167
            }
2168
            ctx.error = error_code::unknown_key;
2169
            return;
2170
         }
2171
106
         else {
2172
106
            decltype(auto) fields = [&]() -> decltype(auto) {
2173
106
               if constexpr ((glaze_object_t<T> || reflectable<T>) &&
2174
106
                             (Opts.error_on_missing_keys || Opts.partial_read)) {
2175
106
                  return bit_array<num_members>{};
2176
106
               }
2177
106
               else {
2178
106
                  return nullptr;
2179
106
               }
2180
106
            }();
2181
2182
106
            size_t read_count{}; // for partial_read
2183
2184
106
            bool first = true;
2185
212
            while (true) {
2186
               if constexpr ((glaze_object_t<T> || reflectable<T>) && Opts.partial_read) {
2187
                  static constexpr bit_array<num_members> all_fields = [] {
2188
                     bit_array<num_members> arr{};
2189
                     for (size_t i = 0; i < num_members; ++i) {
2190
                        arr[i] = true;
2191
                     }
2192
                     return arr;
2193
                  }();
2194
2195
                  if ((all_fields & fields) == all_fields) {
2196
                     ctx.error = error_code::partial_read_complete;
2197
                     return;
2198
                  }
2199
               }
2200
2201
212
               if (*it == '}') {
2202
                  if constexpr (not Opts.null_terminated) {
2203
                     --ctx.indentation_level;
2204
                  }
2205
                  if constexpr ((glaze_object_t<T> || reflectable<T>) &&
2206
                                (Opts.partial_read && Opts.error_on_missing_keys)) {
2207
                     ctx.error = error_code::missing_key;
2208
                     return;
2209
                  }
2210
106
                  else {
2211
                     if constexpr ((glaze_object_t<T> || reflectable<T>) && Opts.error_on_missing_keys) {
2212
                        constexpr auto req_fields = required_fields<T, Opts>();
2213
                        if ((req_fields & fields) != req_fields) {
2214
                           for (size_t i = 0; i < num_members; ++i) {
2215
                              if (not fields[i]) {
2216
                                 ctx.custom_error_message = reflect<T>::keys[i];
2217
                                 // We just return the first missing key in order to avoid heap allocations
2218
                                 break;
2219
                              }
2220
                           }
2221
2222
                           ctx.error = error_code::missing_key;
2223
                           return;
2224
                        }
2225
                     }
2226
106
                     ++it; // Increment after checking for mising keys so errors are within buffer bounds
2227
                     if constexpr (not Opts.null_terminated) {
2228
                        if (it == end) {
2229
                           ctx.error = error_code::end_reached;
2230
                           return;
2231
                        }
2232
                     }
2233
106
                  }
2234
106
                  return;
2235
106
               }
2236
106
               else if (first) {
2237
106
                  first = false;
2238
106
               }
2239
0
               else {
2240
0
                  if (match_invalid_end<',', Opts>(ctx, it, end)) {
2241
0
                     return;
2242
0
                  }
2243
                  if constexpr (not Opts.null_terminated) {
2244
                     if (it == end) [[unlikely]] {
2245
                        ctx.error = error_code::unexpected_end;
2246
                        return;
2247
                     }
2248
                  }
2249
2250
                  if constexpr ((not Opts.minified) && (num_members > 1 || not Opts.error_on_unknown_keys)) {
2251
                     if (ws_size && ws_size < size_t(end - it)) {
2252
                        skip_matching_ws(ws_start, it, ws_size);
2253
                     }
2254
                  }
2255
2256
0
                  if (skip_ws<Opts>(ctx, it, end)) {
2257
0
                     return;
2258
0
                  }
2259
0
               }
2260
2261
106
               constexpr auto reflection_type = glaze_object_t<T> || reflectable<T>;
2262
2263
               if constexpr (reflection_type && (num_members == 0)) {
2264
                  if constexpr (Opts.error_on_unknown_keys) {
2265
                     static_assert(false_v<T>, "This should be unreachable");
2266
                  }
2267
                  else {
2268
                     if (match_invalid_end<'"', Opts>(ctx, it, end)) {
2269
                        return;
2270
                     }
2271
2272
                     // parsing to an empty object, but at this point the JSON presents keys
2273
2274
                     // Unknown key handler does not unescape keys. Unknown escaped keys are
2275
                     // handled by the user.
2276
2277
                     const auto start = it;
2278
                     skip_string_view<Opts>(ctx, it, end);
2279
                     if (bool(ctx.error)) [[unlikely]]
2280
                        return;
2281
                     const sv key{start, size_t(it - start)};
2282
                     ++it;
2283
                     if constexpr (not Opts.null_terminated) {
2284
                        if (it == end) [[unlikely]] {
2285
                           ctx.error = error_code::unexpected_end;
2286
                           return;
2287
                        }
2288
                     }
2289
2290
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2291
                        return;
2292
                     }
2293
2294
                     parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
2295
                     if (bool(ctx.error)) [[unlikely]]
2296
                        return;
2297
                     if constexpr (not Opts.null_terminated) {
2298
                        if (it == end) [[unlikely]] {
2299
                           ctx.error = error_code::unexpected_end;
2300
                           return;
2301
                        }
2302
                     }
2303
                  }
2304
               }
2305
106
               else if constexpr (reflection_type) {
2306
106
                  static_assert(bool(hash_info<T>.type));
2307
2308
106
                  if (*it != '"') [[unlikely]] {
2309
0
                     ctx.error = error_code::expected_quote;
2310
0
                     return;
2311
0
                  }
2312
106
                  ++it;
2313
                  if constexpr (not Opts.null_terminated) {
2314
                     if (it == end) [[unlikely]] {
2315
                        ctx.error = error_code::unexpected_end;
2316
                        return;
2317
                     }
2318
                  }
2319
2320
                  if constexpr (not tag.sv().empty() && not contains_tag<T, tag>()) {
2321
                     // For tagged variants we first check to see if the key matches the tag
2322
                     // We only need to do this if the tag is not part of the keys
2323
2324
                     const auto start = it;
2325
                     skip_string_view<Opts>(ctx, it, end);
2326
                     if (bool(ctx.error)) [[unlikely]]
2327
                        return;
2328
                     const sv key{start, size_t(it - start)};
2329
                     ++it;
2330
                     if constexpr (not Opts.null_terminated) {
2331
                        if (it == end) [[unlikely]] {
2332
                           ctx.error = error_code::unexpected_end;
2333
                           return;
2334
                        }
2335
                     }
2336
2337
                     if (key == tag.sv()) {
2338
                        if (parse_ws_colon<Opts>(ctx, it, end)) {
2339
                           return;
2340
                        }
2341
2342
                        parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
2343
                        if (bool(ctx.error)) [[unlikely]]
2344
                           return;
2345
2346
                        if (skip_ws<Opts>(ctx, it, end)) {
2347
                           return;
2348
                        }
2349
                        continue;
2350
                     }
2351
                     else {
2352
                        it = start; // reset the iterator
2353
                     }
2354
                  }
2355
2356
                  if constexpr (Opts.error_on_missing_keys || Opts.partial_read) {
2357
                     size_t index = num_members;
2358
                     parse_and_invoke<Opts, T, hash_info<T>>(value, ctx, it, end, index);
2359
                     if (bool(ctx.error)) [[unlikely]]
2360
                        return;
2361
                     if (index < num_members) {
2362
                        fields[index] = true;
2363
                     }
2364
                  }
2365
106
                  else {
2366
106
                     parse_and_invoke<Opts, T, hash_info<T>>(value, ctx, it, end);
2367
106
                     if (bool(ctx.error)) [[unlikely]]
2368
0
                        return;
2369
106
                  }
2370
               }
2371
               else {
2372
                  // For types like std::map, std::unordered_map
2373
2374
                  auto reading = [&](auto&& key) {
2375
                     if constexpr (Opts.partial_read) {
2376
                        if (auto element = value.find(key); element != value.end()) {
2377
                           ++read_count;
2378
                           parse<JSON>::op<ws_handled<Opts>()>(element->second, ctx, it, end);
2379
                        }
2380
                        else {
2381
                           skip_value<JSON>::op<Opts>(ctx, it, end);
2382
                        }
2383
                     }
2384
                     else {
2385
                        parse<JSON>::op<ws_handled<Opts>()>(value[key], ctx, it, end);
2386
                     }
2387
                  };
2388
2389
                  // using Key = std::conditional_t<heterogeneous_map<T>, sv, typename T::key_type>;
2390
                  using Key = typename T::key_type;
2391
                  if constexpr (std::is_same_v<Key, std::string>) {
2392
                     static thread_local Key key;
2393
                     parse<JSON>::op<Opts>(key, ctx, it, end);
2394
                     if (bool(ctx.error)) [[unlikely]]
2395
                        return;
2396
2397
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2398
                        return;
2399
                     }
2400
2401
                     reading(key);
2402
                     if constexpr (Opts.partial_read) {
2403
                        if (read_count == value.size()) {
2404
                           return;
2405
                        }
2406
                     }
2407
                     if (bool(ctx.error)) [[unlikely]]
2408
                        return;
2409
                  }
2410
                  else if constexpr (str_t<Key>) {
2411
                     Key key;
2412
                     parse<JSON>::op<Opts>(key, ctx, it, end);
2413
                     if (bool(ctx.error)) [[unlikely]]
2414
                        return;
2415
2416
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2417
                        return;
2418
                     }
2419
2420
                     reading(key);
2421
                     if constexpr (Opts.partial_read) {
2422
                        if (read_count == value.size()) {
2423
                           return;
2424
                        }
2425
                     }
2426
                     if (bool(ctx.error)) [[unlikely]]
2427
                        return;
2428
                  }
2429
                  else {
2430
                     Key key_value{};
2431
                     if constexpr (glaze_enum_t<Key>) {
2432
                        parse<JSON>::op<Opts>(key_value, ctx, it, end);
2433
                     }
2434
                     else if constexpr (std::is_arithmetic_v<Key>) {
2435
                        // prefer over quoted_t below to avoid double parsing of quoted_t
2436
                        parse<JSON>::op<opt_true<Opts, &opts::quoted_num>>(key_value, ctx, it, end);
2437
                     }
2438
                     else {
2439
                        parse<JSON>::op<opt_false<Opts, &opts::raw_string>>(quoted_t<Key>{key_value}, ctx, it, end);
2440
                     }
2441
                     if (bool(ctx.error)) [[unlikely]]
2442
                        return;
2443
2444
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2445
                        return;
2446
                     }
2447
2448
                     reading(key_value);
2449
                     if constexpr (Opts.partial_read) {
2450
                        if (read_count == value.size()) {
2451
                           return;
2452
                        }
2453
                     }
2454
                     if (bool(ctx.error)) [[unlikely]]
2455
                        return;
2456
                  }
2457
               }
2458
106
               if (skip_ws<Opts>(ctx, it, end)) {
2459
0
                  return;
2460
0
               }
2461
106
            }
2462
106
         }
2463
106
      }
_ZN3glz4fromILj10E5ValueItEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEETnNS_14string_literalEXtlNS6_ILm1EEEEERS2_TkNS_10is_contextERNS_7contextERPKcSD_EEvOT1_OT2_OT3_OT4_
Line
Count
Source
2079
106
      {
2080
106
         static constexpr auto num_members = reflect<T>::size;
2081
2082
106
         static constexpr auto Opts = opening_handled_off<ws_handled_off<Options>()>();
2083
106
         if constexpr (!check_opening_handled(Options)) {
2084
106
            if constexpr (!check_ws_handled(Options)) {
2085
106
               if (skip_ws<Opts>(ctx, it, end)) {
2086
0
                  return;
2087
0
               }
2088
106
            }
2089
106
            if (match_invalid_end<'{', Opts>(ctx, it, end)) {
2090
0
               return;
2091
0
            }
2092
            if constexpr (not Opts.null_terminated) {
2093
               if (it == end) [[unlikely]] {
2094
                  ctx.error = error_code::unexpected_end;
2095
                  return;
2096
               }
2097
            }
2098
            if constexpr (not Opts.null_terminated) {
2099
               ++ctx.indentation_level;
2100
            }
2101
106
         }
2102
106
         const auto ws_start = it;
2103
106
         if (skip_ws<Opts>(ctx, it, end)) {
2104
0
            return;
2105
0
         }
2106
106
         const size_t ws_size = size_t(it - ws_start);
2107
2108
         if constexpr ((glaze_object_t<T> || reflectable<T>) && num_members == 0 && Opts.error_on_unknown_keys) {
2109
            if constexpr (not tag.sv().empty()) {
2110
               if (*it == '"') {
2111
                  ++it;
2112
                  if constexpr (not Opts.null_terminated) {
2113
                     if (it == end) [[unlikely]] {
2114
                        ctx.error = error_code::unexpected_end;
2115
                        return;
2116
                     }
2117
                  }
2118
2119
                  const auto start = it;
2120
                  skip_string_view<Opts>(ctx, it, end);
2121
                  if (bool(ctx.error)) [[unlikely]]
2122
                     return;
2123
                  const sv key{start, size_t(it - start)};
2124
                  ++it;
2125
                  if constexpr (not Opts.null_terminated) {
2126
                     if (it == end) [[unlikely]] {
2127
                        ctx.error = error_code::unexpected_end;
2128
                        return;
2129
                     }
2130
                  }
2131
2132
                  if (key == tag.sv()) {
2133
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2134
                        return;
2135
                     }
2136
2137
                     parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
2138
                     if (bool(ctx.error)) [[unlikely]]
2139
                        return;
2140
2141
                     if (skip_ws<Opts>(ctx, it, end)) {
2142
                        return;
2143
                     }
2144
                  }
2145
                  else {
2146
                     ctx.error = error_code::unknown_key;
2147
                     return;
2148
                  }
2149
               }
2150
            }
2151
2152
            if (*it == '}') [[likely]] {
2153
               if constexpr (not Opts.null_terminated) {
2154
                  --ctx.indentation_level;
2155
               }
2156
               ++it;
2157
               if constexpr (not Opts.null_terminated) {
2158
                  if (it == end) {
2159
                     ctx.error = error_code::end_reached;
2160
                     return;
2161
                  }
2162
               }
2163
               if constexpr (Opts.partial_read) {
2164
                  ctx.error = error_code::partial_read_complete;
2165
               }
2166
               return;
2167
            }
2168
            ctx.error = error_code::unknown_key;
2169
            return;
2170
         }
2171
106
         else {
2172
106
            decltype(auto) fields = [&]() -> decltype(auto) {
2173
106
               if constexpr ((glaze_object_t<T> || reflectable<T>) &&
2174
106
                             (Opts.error_on_missing_keys || Opts.partial_read)) {
2175
106
                  return bit_array<num_members>{};
2176
106
               }
2177
106
               else {
2178
106
                  return nullptr;
2179
106
               }
2180
106
            }();
2181
2182
106
            size_t read_count{}; // for partial_read
2183
2184
106
            bool first = true;
2185
212
            while (true) {
2186
               if constexpr ((glaze_object_t<T> || reflectable<T>) && Opts.partial_read) {
2187
                  static constexpr bit_array<num_members> all_fields = [] {
2188
                     bit_array<num_members> arr{};
2189
                     for (size_t i = 0; i < num_members; ++i) {
2190
                        arr[i] = true;
2191
                     }
2192
                     return arr;
2193
                  }();
2194
2195
                  if ((all_fields & fields) == all_fields) {
2196
                     ctx.error = error_code::partial_read_complete;
2197
                     return;
2198
                  }
2199
               }
2200
2201
212
               if (*it == '}') {
2202
                  if constexpr (not Opts.null_terminated) {
2203
                     --ctx.indentation_level;
2204
                  }
2205
                  if constexpr ((glaze_object_t<T> || reflectable<T>) &&
2206
                                (Opts.partial_read && Opts.error_on_missing_keys)) {
2207
                     ctx.error = error_code::missing_key;
2208
                     return;
2209
                  }
2210
106
                  else {
2211
                     if constexpr ((glaze_object_t<T> || reflectable<T>) && Opts.error_on_missing_keys) {
2212
                        constexpr auto req_fields = required_fields<T, Opts>();
2213
                        if ((req_fields & fields) != req_fields) {
2214
                           for (size_t i = 0; i < num_members; ++i) {
2215
                              if (not fields[i]) {
2216
                                 ctx.custom_error_message = reflect<T>::keys[i];
2217
                                 // We just return the first missing key in order to avoid heap allocations
2218
                                 break;
2219
                              }
2220
                           }
2221
2222
                           ctx.error = error_code::missing_key;
2223
                           return;
2224
                        }
2225
                     }
2226
106
                     ++it; // Increment after checking for mising keys so errors are within buffer bounds
2227
                     if constexpr (not Opts.null_terminated) {
2228
                        if (it == end) {
2229
                           ctx.error = error_code::end_reached;
2230
                           return;
2231
                        }
2232
                     }
2233
106
                  }
2234
106
                  return;
2235
106
               }
2236
106
               else if (first) {
2237
106
                  first = false;
2238
106
               }
2239
0
               else {
2240
0
                  if (match_invalid_end<',', Opts>(ctx, it, end)) {
2241
0
                     return;
2242
0
                  }
2243
                  if constexpr (not Opts.null_terminated) {
2244
                     if (it == end) [[unlikely]] {
2245
                        ctx.error = error_code::unexpected_end;
2246
                        return;
2247
                     }
2248
                  }
2249
2250
                  if constexpr ((not Opts.minified) && (num_members > 1 || not Opts.error_on_unknown_keys)) {
2251
                     if (ws_size && ws_size < size_t(end - it)) {
2252
                        skip_matching_ws(ws_start, it, ws_size);
2253
                     }
2254
                  }
2255
2256
0
                  if (skip_ws<Opts>(ctx, it, end)) {
2257
0
                     return;
2258
0
                  }
2259
0
               }
2260
2261
106
               constexpr auto reflection_type = glaze_object_t<T> || reflectable<T>;
2262
2263
               if constexpr (reflection_type && (num_members == 0)) {
2264
                  if constexpr (Opts.error_on_unknown_keys) {
2265
                     static_assert(false_v<T>, "This should be unreachable");
2266
                  }
2267
                  else {
2268
                     if (match_invalid_end<'"', Opts>(ctx, it, end)) {
2269
                        return;
2270
                     }
2271
2272
                     // parsing to an empty object, but at this point the JSON presents keys
2273
2274
                     // Unknown key handler does not unescape keys. Unknown escaped keys are
2275
                     // handled by the user.
2276
2277
                     const auto start = it;
2278
                     skip_string_view<Opts>(ctx, it, end);
2279
                     if (bool(ctx.error)) [[unlikely]]
2280
                        return;
2281
                     const sv key{start, size_t(it - start)};
2282
                     ++it;
2283
                     if constexpr (not Opts.null_terminated) {
2284
                        if (it == end) [[unlikely]] {
2285
                           ctx.error = error_code::unexpected_end;
2286
                           return;
2287
                        }
2288
                     }
2289
2290
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2291
                        return;
2292
                     }
2293
2294
                     parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
2295
                     if (bool(ctx.error)) [[unlikely]]
2296
                        return;
2297
                     if constexpr (not Opts.null_terminated) {
2298
                        if (it == end) [[unlikely]] {
2299
                           ctx.error = error_code::unexpected_end;
2300
                           return;
2301
                        }
2302
                     }
2303
                  }
2304
               }
2305
106
               else if constexpr (reflection_type) {
2306
106
                  static_assert(bool(hash_info<T>.type));
2307
2308
106
                  if (*it != '"') [[unlikely]] {
2309
0
                     ctx.error = error_code::expected_quote;
2310
0
                     return;
2311
0
                  }
2312
106
                  ++it;
2313
                  if constexpr (not Opts.null_terminated) {
2314
                     if (it == end) [[unlikely]] {
2315
                        ctx.error = error_code::unexpected_end;
2316
                        return;
2317
                     }
2318
                  }
2319
2320
                  if constexpr (not tag.sv().empty() && not contains_tag<T, tag>()) {
2321
                     // For tagged variants we first check to see if the key matches the tag
2322
                     // We only need to do this if the tag is not part of the keys
2323
2324
                     const auto start = it;
2325
                     skip_string_view<Opts>(ctx, it, end);
2326
                     if (bool(ctx.error)) [[unlikely]]
2327
                        return;
2328
                     const sv key{start, size_t(it - start)};
2329
                     ++it;
2330
                     if constexpr (not Opts.null_terminated) {
2331
                        if (it == end) [[unlikely]] {
2332
                           ctx.error = error_code::unexpected_end;
2333
                           return;
2334
                        }
2335
                     }
2336
2337
                     if (key == tag.sv()) {
2338
                        if (parse_ws_colon<Opts>(ctx, it, end)) {
2339
                           return;
2340
                        }
2341
2342
                        parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
2343
                        if (bool(ctx.error)) [[unlikely]]
2344
                           return;
2345
2346
                        if (skip_ws<Opts>(ctx, it, end)) {
2347
                           return;
2348
                        }
2349
                        continue;
2350
                     }
2351
                     else {
2352
                        it = start; // reset the iterator
2353
                     }
2354
                  }
2355
2356
                  if constexpr (Opts.error_on_missing_keys || Opts.partial_read) {
2357
                     size_t index = num_members;
2358
                     parse_and_invoke<Opts, T, hash_info<T>>(value, ctx, it, end, index);
2359
                     if (bool(ctx.error)) [[unlikely]]
2360
                        return;
2361
                     if (index < num_members) {
2362
                        fields[index] = true;
2363
                     }
2364
                  }
2365
106
                  else {
2366
106
                     parse_and_invoke<Opts, T, hash_info<T>>(value, ctx, it, end);
2367
106
                     if (bool(ctx.error)) [[unlikely]]
2368
0
                        return;
2369
106
                  }
2370
               }
2371
               else {
2372
                  // For types like std::map, std::unordered_map
2373
2374
                  auto reading = [&](auto&& key) {
2375
                     if constexpr (Opts.partial_read) {
2376
                        if (auto element = value.find(key); element != value.end()) {
2377
                           ++read_count;
2378
                           parse<JSON>::op<ws_handled<Opts>()>(element->second, ctx, it, end);
2379
                        }
2380
                        else {
2381
                           skip_value<JSON>::op<Opts>(ctx, it, end);
2382
                        }
2383
                     }
2384
                     else {
2385
                        parse<JSON>::op<ws_handled<Opts>()>(value[key], ctx, it, end);
2386
                     }
2387
                  };
2388
2389
                  // using Key = std::conditional_t<heterogeneous_map<T>, sv, typename T::key_type>;
2390
                  using Key = typename T::key_type;
2391
                  if constexpr (std::is_same_v<Key, std::string>) {
2392
                     static thread_local Key key;
2393
                     parse<JSON>::op<Opts>(key, ctx, it, end);
2394
                     if (bool(ctx.error)) [[unlikely]]
2395
                        return;
2396
2397
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2398
                        return;
2399
                     }
2400
2401
                     reading(key);
2402
                     if constexpr (Opts.partial_read) {
2403
                        if (read_count == value.size()) {
2404
                           return;
2405
                        }
2406
                     }
2407
                     if (bool(ctx.error)) [[unlikely]]
2408
                        return;
2409
                  }
2410
                  else if constexpr (str_t<Key>) {
2411
                     Key key;
2412
                     parse<JSON>::op<Opts>(key, ctx, it, end);
2413
                     if (bool(ctx.error)) [[unlikely]]
2414
                        return;
2415
2416
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2417
                        return;
2418
                     }
2419
2420
                     reading(key);
2421
                     if constexpr (Opts.partial_read) {
2422
                        if (read_count == value.size()) {
2423
                           return;
2424
                        }
2425
                     }
2426
                     if (bool(ctx.error)) [[unlikely]]
2427
                        return;
2428
                  }
2429
                  else {
2430
                     Key key_value{};
2431
                     if constexpr (glaze_enum_t<Key>) {
2432
                        parse<JSON>::op<Opts>(key_value, ctx, it, end);
2433
                     }
2434
                     else if constexpr (std::is_arithmetic_v<Key>) {
2435
                        // prefer over quoted_t below to avoid double parsing of quoted_t
2436
                        parse<JSON>::op<opt_true<Opts, &opts::quoted_num>>(key_value, ctx, it, end);
2437
                     }
2438
                     else {
2439
                        parse<JSON>::op<opt_false<Opts, &opts::raw_string>>(quoted_t<Key>{key_value}, ctx, it, end);
2440
                     }
2441
                     if (bool(ctx.error)) [[unlikely]]
2442
                        return;
2443
2444
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2445
                        return;
2446
                     }
2447
2448
                     reading(key_value);
2449
                     if constexpr (Opts.partial_read) {
2450
                        if (read_count == value.size()) {
2451
                           return;
2452
                        }
2453
                     }
2454
                     if (bool(ctx.error)) [[unlikely]]
2455
                        return;
2456
                  }
2457
               }
2458
106
               if (skip_ws<Opts>(ctx, it, end)) {
2459
0
                  return;
2460
0
               }
2461
106
            }
2462
106
         }
2463
106
      }
_ZN3glz4fromILj10E5ValueIiEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEETnNS_14string_literalEXtlNS6_ILm1EEEEERS2_TkNS_10is_contextERNS_7contextERPKcSD_EEvOT1_OT2_OT3_OT4_
Line
Count
Source
2079
169
      {
2080
169
         static constexpr auto num_members = reflect<T>::size;
2081
2082
169
         static constexpr auto Opts = opening_handled_off<ws_handled_off<Options>()>();
2083
169
         if constexpr (!check_opening_handled(Options)) {
2084
169
            if constexpr (!check_ws_handled(Options)) {
2085
169
               if (skip_ws<Opts>(ctx, it, end)) {
2086
0
                  return;
2087
0
               }
2088
169
            }
2089
169
            if (match_invalid_end<'{', Opts>(ctx, it, end)) {
2090
0
               return;
2091
0
            }
2092
            if constexpr (not Opts.null_terminated) {
2093
               if (it == end) [[unlikely]] {
2094
                  ctx.error = error_code::unexpected_end;
2095
                  return;
2096
               }
2097
            }
2098
            if constexpr (not Opts.null_terminated) {
2099
               ++ctx.indentation_level;
2100
            }
2101
169
         }
2102
169
         const auto ws_start = it;
2103
169
         if (skip_ws<Opts>(ctx, it, end)) {
2104
0
            return;
2105
0
         }
2106
169
         const size_t ws_size = size_t(it - ws_start);
2107
2108
         if constexpr ((glaze_object_t<T> || reflectable<T>) && num_members == 0 && Opts.error_on_unknown_keys) {
2109
            if constexpr (not tag.sv().empty()) {
2110
               if (*it == '"') {
2111
                  ++it;
2112
                  if constexpr (not Opts.null_terminated) {
2113
                     if (it == end) [[unlikely]] {
2114
                        ctx.error = error_code::unexpected_end;
2115
                        return;
2116
                     }
2117
                  }
2118
2119
                  const auto start = it;
2120
                  skip_string_view<Opts>(ctx, it, end);
2121
                  if (bool(ctx.error)) [[unlikely]]
2122
                     return;
2123
                  const sv key{start, size_t(it - start)};
2124
                  ++it;
2125
                  if constexpr (not Opts.null_terminated) {
2126
                     if (it == end) [[unlikely]] {
2127
                        ctx.error = error_code::unexpected_end;
2128
                        return;
2129
                     }
2130
                  }
2131
2132
                  if (key == tag.sv()) {
2133
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2134
                        return;
2135
                     }
2136
2137
                     parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
2138
                     if (bool(ctx.error)) [[unlikely]]
2139
                        return;
2140
2141
                     if (skip_ws<Opts>(ctx, it, end)) {
2142
                        return;
2143
                     }
2144
                  }
2145
                  else {
2146
                     ctx.error = error_code::unknown_key;
2147
                     return;
2148
                  }
2149
               }
2150
            }
2151
2152
            if (*it == '}') [[likely]] {
2153
               if constexpr (not Opts.null_terminated) {
2154
                  --ctx.indentation_level;
2155
               }
2156
               ++it;
2157
               if constexpr (not Opts.null_terminated) {
2158
                  if (it == end) {
2159
                     ctx.error = error_code::end_reached;
2160
                     return;
2161
                  }
2162
               }
2163
               if constexpr (Opts.partial_read) {
2164
                  ctx.error = error_code::partial_read_complete;
2165
               }
2166
               return;
2167
            }
2168
            ctx.error = error_code::unknown_key;
2169
            return;
2170
         }
2171
169
         else {
2172
169
            decltype(auto) fields = [&]() -> decltype(auto) {
2173
169
               if constexpr ((glaze_object_t<T> || reflectable<T>) &&
2174
169
                             (Opts.error_on_missing_keys || Opts.partial_read)) {
2175
169
                  return bit_array<num_members>{};
2176
169
               }
2177
169
               else {
2178
169
                  return nullptr;
2179
169
               }
2180
169
            }();
2181
2182
169
            size_t read_count{}; // for partial_read
2183
2184
169
            bool first = true;
2185
338
            while (true) {
2186
               if constexpr ((glaze_object_t<T> || reflectable<T>) && Opts.partial_read) {
2187
                  static constexpr bit_array<num_members> all_fields = [] {
2188
                     bit_array<num_members> arr{};
2189
                     for (size_t i = 0; i < num_members; ++i) {
2190
                        arr[i] = true;
2191
                     }
2192
                     return arr;
2193
                  }();
2194
2195
                  if ((all_fields & fields) == all_fields) {
2196
                     ctx.error = error_code::partial_read_complete;
2197
                     return;
2198
                  }
2199
               }
2200
2201
338
               if (*it == '}') {
2202
                  if constexpr (not Opts.null_terminated) {
2203
                     --ctx.indentation_level;
2204
                  }
2205
                  if constexpr ((glaze_object_t<T> || reflectable<T>) &&
2206
                                (Opts.partial_read && Opts.error_on_missing_keys)) {
2207
                     ctx.error = error_code::missing_key;
2208
                     return;
2209
                  }
2210
169
                  else {
2211
                     if constexpr ((glaze_object_t<T> || reflectable<T>) && Opts.error_on_missing_keys) {
2212
                        constexpr auto req_fields = required_fields<T, Opts>();
2213
                        if ((req_fields & fields) != req_fields) {
2214
                           for (size_t i = 0; i < num_members; ++i) {
2215
                              if (not fields[i]) {
2216
                                 ctx.custom_error_message = reflect<T>::keys[i];
2217
                                 // We just return the first missing key in order to avoid heap allocations
2218
                                 break;
2219
                              }
2220
                           }
2221
2222
                           ctx.error = error_code::missing_key;
2223
                           return;
2224
                        }
2225
                     }
2226
169
                     ++it; // Increment after checking for mising keys so errors are within buffer bounds
2227
                     if constexpr (not Opts.null_terminated) {
2228
                        if (it == end) {
2229
                           ctx.error = error_code::end_reached;
2230
                           return;
2231
                        }
2232
                     }
2233
169
                  }
2234
169
                  return;
2235
169
               }
2236
169
               else if (first) {
2237
169
                  first = false;
2238
169
               }
2239
0
               else {
2240
0
                  if (match_invalid_end<',', Opts>(ctx, it, end)) {
2241
0
                     return;
2242
0
                  }
2243
                  if constexpr (not Opts.null_terminated) {
2244
                     if (it == end) [[unlikely]] {
2245
                        ctx.error = error_code::unexpected_end;
2246
                        return;
2247
                     }
2248
                  }
2249
2250
                  if constexpr ((not Opts.minified) && (num_members > 1 || not Opts.error_on_unknown_keys)) {
2251
                     if (ws_size && ws_size < size_t(end - it)) {
2252
                        skip_matching_ws(ws_start, it, ws_size);
2253
                     }
2254
                  }
2255
2256
0
                  if (skip_ws<Opts>(ctx, it, end)) {
2257
0
                     return;
2258
0
                  }
2259
0
               }
2260
2261
169
               constexpr auto reflection_type = glaze_object_t<T> || reflectable<T>;
2262
2263
               if constexpr (reflection_type && (num_members == 0)) {
2264
                  if constexpr (Opts.error_on_unknown_keys) {
2265
                     static_assert(false_v<T>, "This should be unreachable");
2266
                  }
2267
                  else {
2268
                     if (match_invalid_end<'"', Opts>(ctx, it, end)) {
2269
                        return;
2270
                     }
2271
2272
                     // parsing to an empty object, but at this point the JSON presents keys
2273
2274
                     // Unknown key handler does not unescape keys. Unknown escaped keys are
2275
                     // handled by the user.
2276
2277
                     const auto start = it;
2278
                     skip_string_view<Opts>(ctx, it, end);
2279
                     if (bool(ctx.error)) [[unlikely]]
2280
                        return;
2281
                     const sv key{start, size_t(it - start)};
2282
                     ++it;
2283
                     if constexpr (not Opts.null_terminated) {
2284
                        if (it == end) [[unlikely]] {
2285
                           ctx.error = error_code::unexpected_end;
2286
                           return;
2287
                        }
2288
                     }
2289
2290
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2291
                        return;
2292
                     }
2293
2294
                     parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
2295
                     if (bool(ctx.error)) [[unlikely]]
2296
                        return;
2297
                     if constexpr (not Opts.null_terminated) {
2298
                        if (it == end) [[unlikely]] {
2299
                           ctx.error = error_code::unexpected_end;
2300
                           return;
2301
                        }
2302
                     }
2303
                  }
2304
               }
2305
169
               else if constexpr (reflection_type) {
2306
169
                  static_assert(bool(hash_info<T>.type));
2307
2308
169
                  if (*it != '"') [[unlikely]] {
2309
0
                     ctx.error = error_code::expected_quote;
2310
0
                     return;
2311
0
                  }
2312
169
                  ++it;
2313
                  if constexpr (not Opts.null_terminated) {
2314
                     if (it == end) [[unlikely]] {
2315
                        ctx.error = error_code::unexpected_end;
2316
                        return;
2317
                     }
2318
                  }
2319
2320
                  if constexpr (not tag.sv().empty() && not contains_tag<T, tag>()) {
2321
                     // For tagged variants we first check to see if the key matches the tag
2322
                     // We only need to do this if the tag is not part of the keys
2323
2324
                     const auto start = it;
2325
                     skip_string_view<Opts>(ctx, it, end);
2326
                     if (bool(ctx.error)) [[unlikely]]
2327
                        return;
2328
                     const sv key{start, size_t(it - start)};
2329
                     ++it;
2330
                     if constexpr (not Opts.null_terminated) {
2331
                        if (it == end) [[unlikely]] {
2332
                           ctx.error = error_code::unexpected_end;
2333
                           return;
2334
                        }
2335
                     }
2336
2337
                     if (key == tag.sv()) {
2338
                        if (parse_ws_colon<Opts>(ctx, it, end)) {
2339
                           return;
2340
                        }
2341
2342
                        parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
2343
                        if (bool(ctx.error)) [[unlikely]]
2344
                           return;
2345
2346
                        if (skip_ws<Opts>(ctx, it, end)) {
2347
                           return;
2348
                        }
2349
                        continue;
2350
                     }
2351
                     else {
2352
                        it = start; // reset the iterator
2353
                     }
2354
                  }
2355
2356
                  if constexpr (Opts.error_on_missing_keys || Opts.partial_read) {
2357
                     size_t index = num_members;
2358
                     parse_and_invoke<Opts, T, hash_info<T>>(value, ctx, it, end, index);
2359
                     if (bool(ctx.error)) [[unlikely]]
2360
                        return;
2361
                     if (index < num_members) {
2362
                        fields[index] = true;
2363
                     }
2364
                  }
2365
169
                  else {
2366
169
                     parse_and_invoke<Opts, T, hash_info<T>>(value, ctx, it, end);
2367
169
                     if (bool(ctx.error)) [[unlikely]]
2368
0
                        return;
2369
169
                  }
2370
               }
2371
               else {
2372
                  // For types like std::map, std::unordered_map
2373
2374
                  auto reading = [&](auto&& key) {
2375
                     if constexpr (Opts.partial_read) {
2376
                        if (auto element = value.find(key); element != value.end()) {
2377
                           ++read_count;
2378
                           parse<JSON>::op<ws_handled<Opts>()>(element->second, ctx, it, end);
2379
                        }
2380
                        else {
2381
                           skip_value<JSON>::op<Opts>(ctx, it, end);
2382
                        }
2383
                     }
2384
                     else {
2385
                        parse<JSON>::op<ws_handled<Opts>()>(value[key], ctx, it, end);
2386
                     }
2387
                  };
2388
2389
                  // using Key = std::conditional_t<heterogeneous_map<T>, sv, typename T::key_type>;
2390
                  using Key = typename T::key_type;
2391
                  if constexpr (std::is_same_v<Key, std::string>) {
2392
                     static thread_local Key key;
2393
                     parse<JSON>::op<Opts>(key, ctx, it, end);
2394
                     if (bool(ctx.error)) [[unlikely]]
2395
                        return;
2396
2397
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2398
                        return;
2399
                     }
2400
2401
                     reading(key);
2402
                     if constexpr (Opts.partial_read) {
2403
                        if (read_count == value.size()) {
2404
                           return;
2405
                        }
2406
                     }
2407
                     if (bool(ctx.error)) [[unlikely]]
2408
                        return;
2409
                  }
2410
                  else if constexpr (str_t<Key>) {
2411
                     Key key;
2412
                     parse<JSON>::op<Opts>(key, ctx, it, end);
2413
                     if (bool(ctx.error)) [[unlikely]]
2414
                        return;
2415
2416
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2417
                        return;
2418
                     }
2419
2420
                     reading(key);
2421
                     if constexpr (Opts.partial_read) {
2422
                        if (read_count == value.size()) {
2423
                           return;
2424
                        }
2425
                     }
2426
                     if (bool(ctx.error)) [[unlikely]]
2427
                        return;
2428
                  }
2429
                  else {
2430
                     Key key_value{};
2431
                     if constexpr (glaze_enum_t<Key>) {
2432
                        parse<JSON>::op<Opts>(key_value, ctx, it, end);
2433
                     }
2434
                     else if constexpr (std::is_arithmetic_v<Key>) {
2435
                        // prefer over quoted_t below to avoid double parsing of quoted_t
2436
                        parse<JSON>::op<opt_true<Opts, &opts::quoted_num>>(key_value, ctx, it, end);
2437
                     }
2438
                     else {
2439
                        parse<JSON>::op<opt_false<Opts, &opts::raw_string>>(quoted_t<Key>{key_value}, ctx, it, end);
2440
                     }
2441
                     if (bool(ctx.error)) [[unlikely]]
2442
                        return;
2443
2444
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2445
                        return;
2446
                     }
2447
2448
                     reading(key_value);
2449
                     if constexpr (Opts.partial_read) {
2450
                        if (read_count == value.size()) {
2451
                           return;
2452
                        }
2453
                     }
2454
                     if (bool(ctx.error)) [[unlikely]]
2455
                        return;
2456
                  }
2457
               }
2458
169
               if (skip_ws<Opts>(ctx, it, end)) {
2459
0
                  return;
2460
0
               }
2461
169
            }
2462
169
         }
2463
169
      }
_ZN3glz4fromILj10E5ValueIjEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEETnNS_14string_literalEXtlNS6_ILm1EEEEERS2_TkNS_10is_contextERNS_7contextERPKcSD_EEvOT1_OT2_OT3_OT4_
Line
Count
Source
2079
169
      {
2080
169
         static constexpr auto num_members = reflect<T>::size;
2081
2082
169
         static constexpr auto Opts = opening_handled_off<ws_handled_off<Options>()>();
2083
169
         if constexpr (!check_opening_handled(Options)) {
2084
169
            if constexpr (!check_ws_handled(Options)) {
2085
169
               if (skip_ws<Opts>(ctx, it, end)) {
2086
0
                  return;
2087
0
               }
2088
169
            }
2089
169
            if (match_invalid_end<'{', Opts>(ctx, it, end)) {
2090
0
               return;
2091
0
            }
2092
            if constexpr (not Opts.null_terminated) {
2093
               if (it == end) [[unlikely]] {
2094
                  ctx.error = error_code::unexpected_end;
2095
                  return;
2096
               }
2097
            }
2098
            if constexpr (not Opts.null_terminated) {
2099
               ++ctx.indentation_level;
2100
            }
2101
169
         }
2102
169
         const auto ws_start = it;
2103
169
         if (skip_ws<Opts>(ctx, it, end)) {
2104
0
            return;
2105
0
         }
2106
169
         const size_t ws_size = size_t(it - ws_start);
2107
2108
         if constexpr ((glaze_object_t<T> || reflectable<T>) && num_members == 0 && Opts.error_on_unknown_keys) {
2109
            if constexpr (not tag.sv().empty()) {
2110
               if (*it == '"') {
2111
                  ++it;
2112
                  if constexpr (not Opts.null_terminated) {
2113
                     if (it == end) [[unlikely]] {
2114
                        ctx.error = error_code::unexpected_end;
2115
                        return;
2116
                     }
2117
                  }
2118
2119
                  const auto start = it;
2120
                  skip_string_view<Opts>(ctx, it, end);
2121
                  if (bool(ctx.error)) [[unlikely]]
2122
                     return;
2123
                  const sv key{start, size_t(it - start)};
2124
                  ++it;
2125
                  if constexpr (not Opts.null_terminated) {
2126
                     if (it == end) [[unlikely]] {
2127
                        ctx.error = error_code::unexpected_end;
2128
                        return;
2129
                     }
2130
                  }
2131
2132
                  if (key == tag.sv()) {
2133
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2134
                        return;
2135
                     }
2136
2137
                     parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
2138
                     if (bool(ctx.error)) [[unlikely]]
2139
                        return;
2140
2141
                     if (skip_ws<Opts>(ctx, it, end)) {
2142
                        return;
2143
                     }
2144
                  }
2145
                  else {
2146
                     ctx.error = error_code::unknown_key;
2147
                     return;
2148
                  }
2149
               }
2150
            }
2151
2152
            if (*it == '}') [[likely]] {
2153
               if constexpr (not Opts.null_terminated) {
2154
                  --ctx.indentation_level;
2155
               }
2156
               ++it;
2157
               if constexpr (not Opts.null_terminated) {
2158
                  if (it == end) {
2159
                     ctx.error = error_code::end_reached;
2160
                     return;
2161
                  }
2162
               }
2163
               if constexpr (Opts.partial_read) {
2164
                  ctx.error = error_code::partial_read_complete;
2165
               }
2166
               return;
2167
            }
2168
            ctx.error = error_code::unknown_key;
2169
            return;
2170
         }
2171
169
         else {
2172
169
            decltype(auto) fields = [&]() -> decltype(auto) {
2173
169
               if constexpr ((glaze_object_t<T> || reflectable<T>) &&
2174
169
                             (Opts.error_on_missing_keys || Opts.partial_read)) {
2175
169
                  return bit_array<num_members>{};
2176
169
               }
2177
169
               else {
2178
169
                  return nullptr;
2179
169
               }
2180
169
            }();
2181
2182
169
            size_t read_count{}; // for partial_read
2183
2184
169
            bool first = true;
2185
338
            while (true) {
2186
               if constexpr ((glaze_object_t<T> || reflectable<T>) && Opts.partial_read) {
2187
                  static constexpr bit_array<num_members> all_fields = [] {
2188
                     bit_array<num_members> arr{};
2189
                     for (size_t i = 0; i < num_members; ++i) {
2190
                        arr[i] = true;
2191
                     }
2192
                     return arr;
2193
                  }();
2194
2195
                  if ((all_fields & fields) == all_fields) {
2196
                     ctx.error = error_code::partial_read_complete;
2197
                     return;
2198
                  }
2199
               }
2200
2201
338
               if (*it == '}') {
2202
                  if constexpr (not Opts.null_terminated) {
2203
                     --ctx.indentation_level;
2204
                  }
2205
                  if constexpr ((glaze_object_t<T> || reflectable<T>) &&
2206
                                (Opts.partial_read && Opts.error_on_missing_keys)) {
2207
                     ctx.error = error_code::missing_key;
2208
                     return;
2209
                  }
2210
169
                  else {
2211
                     if constexpr ((glaze_object_t<T> || reflectable<T>) && Opts.error_on_missing_keys) {
2212
                        constexpr auto req_fields = required_fields<T, Opts>();
2213
                        if ((req_fields & fields) != req_fields) {
2214
                           for (size_t i = 0; i < num_members; ++i) {
2215
                              if (not fields[i]) {
2216
                                 ctx.custom_error_message = reflect<T>::keys[i];
2217
                                 // We just return the first missing key in order to avoid heap allocations
2218
                                 break;
2219
                              }
2220
                           }
2221
2222
                           ctx.error = error_code::missing_key;
2223
                           return;
2224
                        }
2225
                     }
2226
169
                     ++it; // Increment after checking for mising keys so errors are within buffer bounds
2227
                     if constexpr (not Opts.null_terminated) {
2228
                        if (it == end) {
2229
                           ctx.error = error_code::end_reached;
2230
                           return;
2231
                        }
2232
                     }
2233
169
                  }
2234
169
                  return;
2235
169
               }
2236
169
               else if (first) {
2237
169
                  first = false;
2238
169
               }
2239
0
               else {
2240
0
                  if (match_invalid_end<',', Opts>(ctx, it, end)) {
2241
0
                     return;
2242
0
                  }
2243
                  if constexpr (not Opts.null_terminated) {
2244
                     if (it == end) [[unlikely]] {
2245
                        ctx.error = error_code::unexpected_end;
2246
                        return;
2247
                     }
2248
                  }
2249
2250
                  if constexpr ((not Opts.minified) && (num_members > 1 || not Opts.error_on_unknown_keys)) {
2251
                     if (ws_size && ws_size < size_t(end - it)) {
2252
                        skip_matching_ws(ws_start, it, ws_size);
2253
                     }
2254
                  }
2255
2256
0
                  if (skip_ws<Opts>(ctx, it, end)) {
2257
0
                     return;
2258
0
                  }
2259
0
               }
2260
2261
169
               constexpr auto reflection_type = glaze_object_t<T> || reflectable<T>;
2262
2263
               if constexpr (reflection_type && (num_members == 0)) {
2264
                  if constexpr (Opts.error_on_unknown_keys) {
2265
                     static_assert(false_v<T>, "This should be unreachable");
2266
                  }
2267
                  else {
2268
                     if (match_invalid_end<'"', Opts>(ctx, it, end)) {
2269
                        return;
2270
                     }
2271
2272
                     // parsing to an empty object, but at this point the JSON presents keys
2273
2274
                     // Unknown key handler does not unescape keys. Unknown escaped keys are
2275
                     // handled by the user.
2276
2277
                     const auto start = it;
2278
                     skip_string_view<Opts>(ctx, it, end);
2279
                     if (bool(ctx.error)) [[unlikely]]
2280
                        return;
2281
                     const sv key{start, size_t(it - start)};
2282
                     ++it;
2283
                     if constexpr (not Opts.null_terminated) {
2284
                        if (it == end) [[unlikely]] {
2285
                           ctx.error = error_code::unexpected_end;
2286
                           return;
2287
                        }
2288
                     }
2289
2290
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2291
                        return;
2292
                     }
2293
2294
                     parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
2295
                     if (bool(ctx.error)) [[unlikely]]
2296
                        return;
2297
                     if constexpr (not Opts.null_terminated) {
2298
                        if (it == end) [[unlikely]] {
2299
                           ctx.error = error_code::unexpected_end;
2300
                           return;
2301
                        }
2302
                     }
2303
                  }
2304
               }
2305
169
               else if constexpr (reflection_type) {
2306
169
                  static_assert(bool(hash_info<T>.type));
2307
2308
169
                  if (*it != '"') [[unlikely]] {
2309
0
                     ctx.error = error_code::expected_quote;
2310
0
                     return;
2311
0
                  }
2312
169
                  ++it;
2313
                  if constexpr (not Opts.null_terminated) {
2314
                     if (it == end) [[unlikely]] {
2315
                        ctx.error = error_code::unexpected_end;
2316
                        return;
2317
                     }
2318
                  }
2319
2320
                  if constexpr (not tag.sv().empty() && not contains_tag<T, tag>()) {
2321
                     // For tagged variants we first check to see if the key matches the tag
2322
                     // We only need to do this if the tag is not part of the keys
2323
2324
                     const auto start = it;
2325
                     skip_string_view<Opts>(ctx, it, end);
2326
                     if (bool(ctx.error)) [[unlikely]]
2327
                        return;
2328
                     const sv key{start, size_t(it - start)};
2329
                     ++it;
2330
                     if constexpr (not Opts.null_terminated) {
2331
                        if (it == end) [[unlikely]] {
2332
                           ctx.error = error_code::unexpected_end;
2333
                           return;
2334
                        }
2335
                     }
2336
2337
                     if (key == tag.sv()) {
2338
                        if (parse_ws_colon<Opts>(ctx, it, end)) {
2339
                           return;
2340
                        }
2341
2342
                        parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
2343
                        if (bool(ctx.error)) [[unlikely]]
2344
                           return;
2345
2346
                        if (skip_ws<Opts>(ctx, it, end)) {
2347
                           return;
2348
                        }
2349
                        continue;
2350
                     }
2351
                     else {
2352
                        it = start; // reset the iterator
2353
                     }
2354
                  }
2355
2356
                  if constexpr (Opts.error_on_missing_keys || Opts.partial_read) {
2357
                     size_t index = num_members;
2358
                     parse_and_invoke<Opts, T, hash_info<T>>(value, ctx, it, end, index);
2359
                     if (bool(ctx.error)) [[unlikely]]
2360
                        return;
2361
                     if (index < num_members) {
2362
                        fields[index] = true;
2363
                     }
2364
                  }
2365
169
                  else {
2366
169
                     parse_and_invoke<Opts, T, hash_info<T>>(value, ctx, it, end);
2367
169
                     if (bool(ctx.error)) [[unlikely]]
2368
0
                        return;
2369
169
                  }
2370
               }
2371
               else {
2372
                  // For types like std::map, std::unordered_map
2373
2374
                  auto reading = [&](auto&& key) {
2375
                     if constexpr (Opts.partial_read) {
2376
                        if (auto element = value.find(key); element != value.end()) {
2377
                           ++read_count;
2378
                           parse<JSON>::op<ws_handled<Opts>()>(element->second, ctx, it, end);
2379
                        }
2380
                        else {
2381
                           skip_value<JSON>::op<Opts>(ctx, it, end);
2382
                        }
2383
                     }
2384
                     else {
2385
                        parse<JSON>::op<ws_handled<Opts>()>(value[key], ctx, it, end);
2386
                     }
2387
                  };
2388
2389
                  // using Key = std::conditional_t<heterogeneous_map<T>, sv, typename T::key_type>;
2390
                  using Key = typename T::key_type;
2391
                  if constexpr (std::is_same_v<Key, std::string>) {
2392
                     static thread_local Key key;
2393
                     parse<JSON>::op<Opts>(key, ctx, it, end);
2394
                     if (bool(ctx.error)) [[unlikely]]
2395
                        return;
2396
2397
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2398
                        return;
2399
                     }
2400
2401
                     reading(key);
2402
                     if constexpr (Opts.partial_read) {
2403
                        if (read_count == value.size()) {
2404
                           return;
2405
                        }
2406
                     }
2407
                     if (bool(ctx.error)) [[unlikely]]
2408
                        return;
2409
                  }
2410
                  else if constexpr (str_t<Key>) {
2411
                     Key key;
2412
                     parse<JSON>::op<Opts>(key, ctx, it, end);
2413
                     if (bool(ctx.error)) [[unlikely]]
2414
                        return;
2415
2416
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2417
                        return;
2418
                     }
2419
2420
                     reading(key);
2421
                     if constexpr (Opts.partial_read) {
2422
                        if (read_count == value.size()) {
2423
                           return;
2424
                        }
2425
                     }
2426
                     if (bool(ctx.error)) [[unlikely]]
2427
                        return;
2428
                  }
2429
                  else {
2430
                     Key key_value{};
2431
                     if constexpr (glaze_enum_t<Key>) {
2432
                        parse<JSON>::op<Opts>(key_value, ctx, it, end);
2433
                     }
2434
                     else if constexpr (std::is_arithmetic_v<Key>) {
2435
                        // prefer over quoted_t below to avoid double parsing of quoted_t
2436
                        parse<JSON>::op<opt_true<Opts, &opts::quoted_num>>(key_value, ctx, it, end);
2437
                     }
2438
                     else {
2439
                        parse<JSON>::op<opt_false<Opts, &opts::raw_string>>(quoted_t<Key>{key_value}, ctx, it, end);
2440
                     }
2441
                     if (bool(ctx.error)) [[unlikely]]
2442
                        return;
2443
2444
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2445
                        return;
2446
                     }
2447
2448
                     reading(key_value);
2449
                     if constexpr (Opts.partial_read) {
2450
                        if (read_count == value.size()) {
2451
                           return;
2452
                        }
2453
                     }
2454
                     if (bool(ctx.error)) [[unlikely]]
2455
                        return;
2456
                  }
2457
               }
2458
169
               if (skip_ws<Opts>(ctx, it, end)) {
2459
0
                  return;
2460
0
               }
2461
169
            }
2462
169
         }
2463
169
      }
_ZN3glz4fromILj10E5ValueIlEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEETnNS_14string_literalEXtlNS6_ILm1EEEEERS2_TkNS_10is_contextERNS_7contextERPKcSD_EEvOT1_OT2_OT3_OT4_
Line
Count
Source
2079
296
      {
2080
296
         static constexpr auto num_members = reflect<T>::size;
2081
2082
296
         static constexpr auto Opts = opening_handled_off<ws_handled_off<Options>()>();
2083
296
         if constexpr (!check_opening_handled(Options)) {
2084
296
            if constexpr (!check_ws_handled(Options)) {
2085
296
               if (skip_ws<Opts>(ctx, it, end)) {
2086
0
                  return;
2087
0
               }
2088
296
            }
2089
296
            if (match_invalid_end<'{', Opts>(ctx, it, end)) {
2090
0
               return;
2091
0
            }
2092
            if constexpr (not Opts.null_terminated) {
2093
               if (it == end) [[unlikely]] {
2094
                  ctx.error = error_code::unexpected_end;
2095
                  return;
2096
               }
2097
            }
2098
            if constexpr (not Opts.null_terminated) {
2099
               ++ctx.indentation_level;
2100
            }
2101
296
         }
2102
296
         const auto ws_start = it;
2103
296
         if (skip_ws<Opts>(ctx, it, end)) {
2104
0
            return;
2105
0
         }
2106
296
         const size_t ws_size = size_t(it - ws_start);
2107
2108
         if constexpr ((glaze_object_t<T> || reflectable<T>) && num_members == 0 && Opts.error_on_unknown_keys) {
2109
            if constexpr (not tag.sv().empty()) {
2110
               if (*it == '"') {
2111
                  ++it;
2112
                  if constexpr (not Opts.null_terminated) {
2113
                     if (it == end) [[unlikely]] {
2114
                        ctx.error = error_code::unexpected_end;
2115
                        return;
2116
                     }
2117
                  }
2118
2119
                  const auto start = it;
2120
                  skip_string_view<Opts>(ctx, it, end);
2121
                  if (bool(ctx.error)) [[unlikely]]
2122
                     return;
2123
                  const sv key{start, size_t(it - start)};
2124
                  ++it;
2125
                  if constexpr (not Opts.null_terminated) {
2126
                     if (it == end) [[unlikely]] {
2127
                        ctx.error = error_code::unexpected_end;
2128
                        return;
2129
                     }
2130
                  }
2131
2132
                  if (key == tag.sv()) {
2133
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2134
                        return;
2135
                     }
2136
2137
                     parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
2138
                     if (bool(ctx.error)) [[unlikely]]
2139
                        return;
2140
2141
                     if (skip_ws<Opts>(ctx, it, end)) {
2142
                        return;
2143
                     }
2144
                  }
2145
                  else {
2146
                     ctx.error = error_code::unknown_key;
2147
                     return;
2148
                  }
2149
               }
2150
            }
2151
2152
            if (*it == '}') [[likely]] {
2153
               if constexpr (not Opts.null_terminated) {
2154
                  --ctx.indentation_level;
2155
               }
2156
               ++it;
2157
               if constexpr (not Opts.null_terminated) {
2158
                  if (it == end) {
2159
                     ctx.error = error_code::end_reached;
2160
                     return;
2161
                  }
2162
               }
2163
               if constexpr (Opts.partial_read) {
2164
                  ctx.error = error_code::partial_read_complete;
2165
               }
2166
               return;
2167
            }
2168
            ctx.error = error_code::unknown_key;
2169
            return;
2170
         }
2171
296
         else {
2172
296
            decltype(auto) fields = [&]() -> decltype(auto) {
2173
296
               if constexpr ((glaze_object_t<T> || reflectable<T>) &&
2174
296
                             (Opts.error_on_missing_keys || Opts.partial_read)) {
2175
296
                  return bit_array<num_members>{};
2176
296
               }
2177
296
               else {
2178
296
                  return nullptr;
2179
296
               }
2180
296
            }();
2181
2182
296
            size_t read_count{}; // for partial_read
2183
2184
296
            bool first = true;
2185
592
            while (true) {
2186
               if constexpr ((glaze_object_t<T> || reflectable<T>) && Opts.partial_read) {
2187
                  static constexpr bit_array<num_members> all_fields = [] {
2188
                     bit_array<num_members> arr{};
2189
                     for (size_t i = 0; i < num_members; ++i) {
2190
                        arr[i] = true;
2191
                     }
2192
                     return arr;
2193
                  }();
2194
2195
                  if ((all_fields & fields) == all_fields) {
2196
                     ctx.error = error_code::partial_read_complete;
2197
                     return;
2198
                  }
2199
               }
2200
2201
592
               if (*it == '}') {
2202
                  if constexpr (not Opts.null_terminated) {
2203
                     --ctx.indentation_level;
2204
                  }
2205
                  if constexpr ((glaze_object_t<T> || reflectable<T>) &&
2206
                                (Opts.partial_read && Opts.error_on_missing_keys)) {
2207
                     ctx.error = error_code::missing_key;
2208
                     return;
2209
                  }
2210
296
                  else {
2211
                     if constexpr ((glaze_object_t<T> || reflectable<T>) && Opts.error_on_missing_keys) {
2212
                        constexpr auto req_fields = required_fields<T, Opts>();
2213
                        if ((req_fields & fields) != req_fields) {
2214
                           for (size_t i = 0; i < num_members; ++i) {
2215
                              if (not fields[i]) {
2216
                                 ctx.custom_error_message = reflect<T>::keys[i];
2217
                                 // We just return the first missing key in order to avoid heap allocations
2218
                                 break;
2219
                              }
2220
                           }
2221
2222
                           ctx.error = error_code::missing_key;
2223
                           return;
2224
                        }
2225
                     }
2226
296
                     ++it; // Increment after checking for mising keys so errors are within buffer bounds
2227
                     if constexpr (not Opts.null_terminated) {
2228
                        if (it == end) {
2229
                           ctx.error = error_code::end_reached;
2230
                           return;
2231
                        }
2232
                     }
2233
296
                  }
2234
296
                  return;
2235
296
               }
2236
296
               else if (first) {
2237
296
                  first = false;
2238
296
               }
2239
0
               else {
2240
0
                  if (match_invalid_end<',', Opts>(ctx, it, end)) {
2241
0
                     return;
2242
0
                  }
2243
                  if constexpr (not Opts.null_terminated) {
2244
                     if (it == end) [[unlikely]] {
2245
                        ctx.error = error_code::unexpected_end;
2246
                        return;
2247
                     }
2248
                  }
2249
2250
                  if constexpr ((not Opts.minified) && (num_members > 1 || not Opts.error_on_unknown_keys)) {
2251
                     if (ws_size && ws_size < size_t(end - it)) {
2252
                        skip_matching_ws(ws_start, it, ws_size);
2253
                     }
2254
                  }
2255
2256
0
                  if (skip_ws<Opts>(ctx, it, end)) {
2257
0
                     return;
2258
0
                  }
2259
0
               }
2260
2261
296
               constexpr auto reflection_type = glaze_object_t<T> || reflectable<T>;
2262
2263
               if constexpr (reflection_type && (num_members == 0)) {
2264
                  if constexpr (Opts.error_on_unknown_keys) {
2265
                     static_assert(false_v<T>, "This should be unreachable");
2266
                  }
2267
                  else {
2268
                     if (match_invalid_end<'"', Opts>(ctx, it, end)) {
2269
                        return;
2270
                     }
2271
2272
                     // parsing to an empty object, but at this point the JSON presents keys
2273
2274
                     // Unknown key handler does not unescape keys. Unknown escaped keys are
2275
                     // handled by the user.
2276
2277
                     const auto start = it;
2278
                     skip_string_view<Opts>(ctx, it, end);
2279
                     if (bool(ctx.error)) [[unlikely]]
2280
                        return;
2281
                     const sv key{start, size_t(it - start)};
2282
                     ++it;
2283
                     if constexpr (not Opts.null_terminated) {
2284
                        if (it == end) [[unlikely]] {
2285
                           ctx.error = error_code::unexpected_end;
2286
                           return;
2287
                        }
2288
                     }
2289
2290
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2291
                        return;
2292
                     }
2293
2294
                     parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
2295
                     if (bool(ctx.error)) [[unlikely]]
2296
                        return;
2297
                     if constexpr (not Opts.null_terminated) {
2298
                        if (it == end) [[unlikely]] {
2299
                           ctx.error = error_code::unexpected_end;
2300
                           return;
2301
                        }
2302
                     }
2303
                  }
2304
               }
2305
296
               else if constexpr (reflection_type) {
2306
296
                  static_assert(bool(hash_info<T>.type));
2307
2308
296
                  if (*it != '"') [[unlikely]] {
2309
0
                     ctx.error = error_code::expected_quote;
2310
0
                     return;
2311
0
                  }
2312
296
                  ++it;
2313
                  if constexpr (not Opts.null_terminated) {
2314
                     if (it == end) [[unlikely]] {
2315
                        ctx.error = error_code::unexpected_end;
2316
                        return;
2317
                     }
2318
                  }
2319
2320
                  if constexpr (not tag.sv().empty() && not contains_tag<T, tag>()) {
2321
                     // For tagged variants we first check to see if the key matches the tag
2322
                     // We only need to do this if the tag is not part of the keys
2323
2324
                     const auto start = it;
2325
                     skip_string_view<Opts>(ctx, it, end);
2326
                     if (bool(ctx.error)) [[unlikely]]
2327
                        return;
2328
                     const sv key{start, size_t(it - start)};
2329
                     ++it;
2330
                     if constexpr (not Opts.null_terminated) {
2331
                        if (it == end) [[unlikely]] {
2332
                           ctx.error = error_code::unexpected_end;
2333
                           return;
2334
                        }
2335
                     }
2336
2337
                     if (key == tag.sv()) {
2338
                        if (parse_ws_colon<Opts>(ctx, it, end)) {
2339
                           return;
2340
                        }
2341
2342
                        parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
2343
                        if (bool(ctx.error)) [[unlikely]]
2344
                           return;
2345
2346
                        if (skip_ws<Opts>(ctx, it, end)) {
2347
                           return;
2348
                        }
2349
                        continue;
2350
                     }
2351
                     else {
2352
                        it = start; // reset the iterator
2353
                     }
2354
                  }
2355
2356
                  if constexpr (Opts.error_on_missing_keys || Opts.partial_read) {
2357
                     size_t index = num_members;
2358
                     parse_and_invoke<Opts, T, hash_info<T>>(value, ctx, it, end, index);
2359
                     if (bool(ctx.error)) [[unlikely]]
2360
                        return;
2361
                     if (index < num_members) {
2362
                        fields[index] = true;
2363
                     }
2364
                  }
2365
296
                  else {
2366
296
                     parse_and_invoke<Opts, T, hash_info<T>>(value, ctx, it, end);
2367
296
                     if (bool(ctx.error)) [[unlikely]]
2368
0
                        return;
2369
296
                  }
2370
               }
2371
               else {
2372
                  // For types like std::map, std::unordered_map
2373
2374
                  auto reading = [&](auto&& key) {
2375
                     if constexpr (Opts.partial_read) {
2376
                        if (auto element = value.find(key); element != value.end()) {
2377
                           ++read_count;
2378
                           parse<JSON>::op<ws_handled<Opts>()>(element->second, ctx, it, end);
2379
                        }
2380
                        else {
2381
                           skip_value<JSON>::op<Opts>(ctx, it, end);
2382
                        }
2383
                     }
2384
                     else {
2385
                        parse<JSON>::op<ws_handled<Opts>()>(value[key], ctx, it, end);
2386
                     }
2387
                  };
2388
2389
                  // using Key = std::conditional_t<heterogeneous_map<T>, sv, typename T::key_type>;
2390
                  using Key = typename T::key_type;
2391
                  if constexpr (std::is_same_v<Key, std::string>) {
2392
                     static thread_local Key key;
2393
                     parse<JSON>::op<Opts>(key, ctx, it, end);
2394
                     if (bool(ctx.error)) [[unlikely]]
2395
                        return;
2396
2397
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2398
                        return;
2399
                     }
2400
2401
                     reading(key);
2402
                     if constexpr (Opts.partial_read) {
2403
                        if (read_count == value.size()) {
2404
                           return;
2405
                        }
2406
                     }
2407
                     if (bool(ctx.error)) [[unlikely]]
2408
                        return;
2409
                  }
2410
                  else if constexpr (str_t<Key>) {
2411
                     Key key;
2412
                     parse<JSON>::op<Opts>(key, ctx, it, end);
2413
                     if (bool(ctx.error)) [[unlikely]]
2414
                        return;
2415
2416
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2417
                        return;
2418
                     }
2419
2420
                     reading(key);
2421
                     if constexpr (Opts.partial_read) {
2422
                        if (read_count == value.size()) {
2423
                           return;
2424
                        }
2425
                     }
2426
                     if (bool(ctx.error)) [[unlikely]]
2427
                        return;
2428
                  }
2429
                  else {
2430
                     Key key_value{};
2431
                     if constexpr (glaze_enum_t<Key>) {
2432
                        parse<JSON>::op<Opts>(key_value, ctx, it, end);
2433
                     }
2434
                     else if constexpr (std::is_arithmetic_v<Key>) {
2435
                        // prefer over quoted_t below to avoid double parsing of quoted_t
2436
                        parse<JSON>::op<opt_true<Opts, &opts::quoted_num>>(key_value, ctx, it, end);
2437
                     }
2438
                     else {
2439
                        parse<JSON>::op<opt_false<Opts, &opts::raw_string>>(quoted_t<Key>{key_value}, ctx, it, end);
2440
                     }
2441
                     if (bool(ctx.error)) [[unlikely]]
2442
                        return;
2443
2444
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2445
                        return;
2446
                     }
2447
2448
                     reading(key_value);
2449
                     if constexpr (Opts.partial_read) {
2450
                        if (read_count == value.size()) {
2451
                           return;
2452
                        }
2453
                     }
2454
                     if (bool(ctx.error)) [[unlikely]]
2455
                        return;
2456
                  }
2457
               }
2458
296
               if (skip_ws<Opts>(ctx, it, end)) {
2459
0
                  return;
2460
0
               }
2461
296
            }
2462
296
         }
2463
296
      }
_ZN3glz4fromILj10E5ValueImEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEETnNS_14string_literalEXtlNS6_ILm1EEEEERS2_TkNS_10is_contextERNS_7contextERPKcSD_EEvOT1_OT2_OT3_OT4_
Line
Count
Source
2079
296
      {
2080
296
         static constexpr auto num_members = reflect<T>::size;
2081
2082
296
         static constexpr auto Opts = opening_handled_off<ws_handled_off<Options>()>();
2083
296
         if constexpr (!check_opening_handled(Options)) {
2084
296
            if constexpr (!check_ws_handled(Options)) {
2085
296
               if (skip_ws<Opts>(ctx, it, end)) {
2086
0
                  return;
2087
0
               }
2088
296
            }
2089
296
            if (match_invalid_end<'{', Opts>(ctx, it, end)) {
2090
0
               return;
2091
0
            }
2092
            if constexpr (not Opts.null_terminated) {
2093
               if (it == end) [[unlikely]] {
2094
                  ctx.error = error_code::unexpected_end;
2095
                  return;
2096
               }
2097
            }
2098
            if constexpr (not Opts.null_terminated) {
2099
               ++ctx.indentation_level;
2100
            }
2101
296
         }
2102
296
         const auto ws_start = it;
2103
296
         if (skip_ws<Opts>(ctx, it, end)) {
2104
0
            return;
2105
0
         }
2106
296
         const size_t ws_size = size_t(it - ws_start);
2107
2108
         if constexpr ((glaze_object_t<T> || reflectable<T>) && num_members == 0 && Opts.error_on_unknown_keys) {
2109
            if constexpr (not tag.sv().empty()) {
2110
               if (*it == '"') {
2111
                  ++it;
2112
                  if constexpr (not Opts.null_terminated) {
2113
                     if (it == end) [[unlikely]] {
2114
                        ctx.error = error_code::unexpected_end;
2115
                        return;
2116
                     }
2117
                  }
2118
2119
                  const auto start = it;
2120
                  skip_string_view<Opts>(ctx, it, end);
2121
                  if (bool(ctx.error)) [[unlikely]]
2122
                     return;
2123
                  const sv key{start, size_t(it - start)};
2124
                  ++it;
2125
                  if constexpr (not Opts.null_terminated) {
2126
                     if (it == end) [[unlikely]] {
2127
                        ctx.error = error_code::unexpected_end;
2128
                        return;
2129
                     }
2130
                  }
2131
2132
                  if (key == tag.sv()) {
2133
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2134
                        return;
2135
                     }
2136
2137
                     parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
2138
                     if (bool(ctx.error)) [[unlikely]]
2139
                        return;
2140
2141
                     if (skip_ws<Opts>(ctx, it, end)) {
2142
                        return;
2143
                     }
2144
                  }
2145
                  else {
2146
                     ctx.error = error_code::unknown_key;
2147
                     return;
2148
                  }
2149
               }
2150
            }
2151
2152
            if (*it == '}') [[likely]] {
2153
               if constexpr (not Opts.null_terminated) {
2154
                  --ctx.indentation_level;
2155
               }
2156
               ++it;
2157
               if constexpr (not Opts.null_terminated) {
2158
                  if (it == end) {
2159
                     ctx.error = error_code::end_reached;
2160
                     return;
2161
                  }
2162
               }
2163
               if constexpr (Opts.partial_read) {
2164
                  ctx.error = error_code::partial_read_complete;
2165
               }
2166
               return;
2167
            }
2168
            ctx.error = error_code::unknown_key;
2169
            return;
2170
         }
2171
296
         else {
2172
296
            decltype(auto) fields = [&]() -> decltype(auto) {
2173
296
               if constexpr ((glaze_object_t<T> || reflectable<T>) &&
2174
296
                             (Opts.error_on_missing_keys || Opts.partial_read)) {
2175
296
                  return bit_array<num_members>{};
2176
296
               }
2177
296
               else {
2178
296
                  return nullptr;
2179
296
               }
2180
296
            }();
2181
2182
296
            size_t read_count{}; // for partial_read
2183
2184
296
            bool first = true;
2185
592
            while (true) {
2186
               if constexpr ((glaze_object_t<T> || reflectable<T>) && Opts.partial_read) {
2187
                  static constexpr bit_array<num_members> all_fields = [] {
2188
                     bit_array<num_members> arr{};
2189
                     for (size_t i = 0; i < num_members; ++i) {
2190
                        arr[i] = true;
2191
                     }
2192
                     return arr;
2193
                  }();
2194
2195
                  if ((all_fields & fields) == all_fields) {
2196
                     ctx.error = error_code::partial_read_complete;
2197
                     return;
2198
                  }
2199
               }
2200
2201
592
               if (*it == '}') {
2202
                  if constexpr (not Opts.null_terminated) {
2203
                     --ctx.indentation_level;
2204
                  }
2205
                  if constexpr ((glaze_object_t<T> || reflectable<T>) &&
2206
                                (Opts.partial_read && Opts.error_on_missing_keys)) {
2207
                     ctx.error = error_code::missing_key;
2208
                     return;
2209
                  }
2210
296
                  else {
2211
                     if constexpr ((glaze_object_t<T> || reflectable<T>) && Opts.error_on_missing_keys) {
2212
                        constexpr auto req_fields = required_fields<T, Opts>();
2213
                        if ((req_fields & fields) != req_fields) {
2214
                           for (size_t i = 0; i < num_members; ++i) {
2215
                              if (not fields[i]) {
2216
                                 ctx.custom_error_message = reflect<T>::keys[i];
2217
                                 // We just return the first missing key in order to avoid heap allocations
2218
                                 break;
2219
                              }
2220
                           }
2221
2222
                           ctx.error = error_code::missing_key;
2223
                           return;
2224
                        }
2225
                     }
2226
296
                     ++it; // Increment after checking for mising keys so errors are within buffer bounds
2227
                     if constexpr (not Opts.null_terminated) {
2228
                        if (it == end) {
2229
                           ctx.error = error_code::end_reached;
2230
                           return;
2231
                        }
2232
                     }
2233
296
                  }
2234
296
                  return;
2235
296
               }
2236
296
               else if (first) {
2237
296
                  first = false;
2238
296
               }
2239
0
               else {
2240
0
                  if (match_invalid_end<',', Opts>(ctx, it, end)) {
2241
0
                     return;
2242
0
                  }
2243
                  if constexpr (not Opts.null_terminated) {
2244
                     if (it == end) [[unlikely]] {
2245
                        ctx.error = error_code::unexpected_end;
2246
                        return;
2247
                     }
2248
                  }
2249
2250
                  if constexpr ((not Opts.minified) && (num_members > 1 || not Opts.error_on_unknown_keys)) {
2251
                     if (ws_size && ws_size < size_t(end - it)) {
2252
                        skip_matching_ws(ws_start, it, ws_size);
2253
                     }
2254
                  }
2255
2256
0
                  if (skip_ws<Opts>(ctx, it, end)) {
2257
0
                     return;
2258
0
                  }
2259
0
               }
2260
2261
296
               constexpr auto reflection_type = glaze_object_t<T> || reflectable<T>;
2262
2263
               if constexpr (reflection_type && (num_members == 0)) {
2264
                  if constexpr (Opts.error_on_unknown_keys) {
2265
                     static_assert(false_v<T>, "This should be unreachable");
2266
                  }
2267
                  else {
2268
                     if (match_invalid_end<'"', Opts>(ctx, it, end)) {
2269
                        return;
2270
                     }
2271
2272
                     // parsing to an empty object, but at this point the JSON presents keys
2273
2274
                     // Unknown key handler does not unescape keys. Unknown escaped keys are
2275
                     // handled by the user.
2276
2277
                     const auto start = it;
2278
                     skip_string_view<Opts>(ctx, it, end);
2279
                     if (bool(ctx.error)) [[unlikely]]
2280
                        return;
2281
                     const sv key{start, size_t(it - start)};
2282
                     ++it;
2283
                     if constexpr (not Opts.null_terminated) {
2284
                        if (it == end) [[unlikely]] {
2285
                           ctx.error = error_code::unexpected_end;
2286
                           return;
2287
                        }
2288
                     }
2289
2290
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2291
                        return;
2292
                     }
2293
2294
                     parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
2295
                     if (bool(ctx.error)) [[unlikely]]
2296
                        return;
2297
                     if constexpr (not Opts.null_terminated) {
2298
                        if (it == end) [[unlikely]] {
2299
                           ctx.error = error_code::unexpected_end;
2300
                           return;
2301
                        }
2302
                     }
2303
                  }
2304
               }
2305
296
               else if constexpr (reflection_type) {
2306
296
                  static_assert(bool(hash_info<T>.type));
2307
2308
296
                  if (*it != '"') [[unlikely]] {
2309
0
                     ctx.error = error_code::expected_quote;
2310
0
                     return;
2311
0
                  }
2312
296
                  ++it;
2313
                  if constexpr (not Opts.null_terminated) {
2314
                     if (it == end) [[unlikely]] {
2315
                        ctx.error = error_code::unexpected_end;
2316
                        return;
2317
                     }
2318
                  }
2319
2320
                  if constexpr (not tag.sv().empty() && not contains_tag<T, tag>()) {
2321
                     // For tagged variants we first check to see if the key matches the tag
2322
                     // We only need to do this if the tag is not part of the keys
2323
2324
                     const auto start = it;
2325
                     skip_string_view<Opts>(ctx, it, end);
2326
                     if (bool(ctx.error)) [[unlikely]]
2327
                        return;
2328
                     const sv key{start, size_t(it - start)};
2329
                     ++it;
2330
                     if constexpr (not Opts.null_terminated) {
2331
                        if (it == end) [[unlikely]] {
2332
                           ctx.error = error_code::unexpected_end;
2333
                           return;
2334
                        }
2335
                     }
2336
2337
                     if (key == tag.sv()) {
2338
                        if (parse_ws_colon<Opts>(ctx, it, end)) {
2339
                           return;
2340
                        }
2341
2342
                        parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
2343
                        if (bool(ctx.error)) [[unlikely]]
2344
                           return;
2345
2346
                        if (skip_ws<Opts>(ctx, it, end)) {
2347
                           return;
2348
                        }
2349
                        continue;
2350
                     }
2351
                     else {
2352
                        it = start; // reset the iterator
2353
                     }
2354
                  }
2355
2356
                  if constexpr (Opts.error_on_missing_keys || Opts.partial_read) {
2357
                     size_t index = num_members;
2358
                     parse_and_invoke<Opts, T, hash_info<T>>(value, ctx, it, end, index);
2359
                     if (bool(ctx.error)) [[unlikely]]
2360
                        return;
2361
                     if (index < num_members) {
2362
                        fields[index] = true;
2363
                     }
2364
                  }
2365
296
                  else {
2366
296
                     parse_and_invoke<Opts, T, hash_info<T>>(value, ctx, it, end);
2367
296
                     if (bool(ctx.error)) [[unlikely]]
2368
0
                        return;
2369
296
                  }
2370
               }
2371
               else {
2372
                  // For types like std::map, std::unordered_map
2373
2374
                  auto reading = [&](auto&& key) {
2375
                     if constexpr (Opts.partial_read) {
2376
                        if (auto element = value.find(key); element != value.end()) {
2377
                           ++read_count;
2378
                           parse<JSON>::op<ws_handled<Opts>()>(element->second, ctx, it, end);
2379
                        }
2380
                        else {
2381
                           skip_value<JSON>::op<Opts>(ctx, it, end);
2382
                        }
2383
                     }
2384
                     else {
2385
                        parse<JSON>::op<ws_handled<Opts>()>(value[key], ctx, it, end);
2386
                     }
2387
                  };
2388
2389
                  // using Key = std::conditional_t<heterogeneous_map<T>, sv, typename T::key_type>;
2390
                  using Key = typename T::key_type;
2391
                  if constexpr (std::is_same_v<Key, std::string>) {
2392
                     static thread_local Key key;
2393
                     parse<JSON>::op<Opts>(key, ctx, it, end);
2394
                     if (bool(ctx.error)) [[unlikely]]
2395
                        return;
2396
2397
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2398
                        return;
2399
                     }
2400
2401
                     reading(key);
2402
                     if constexpr (Opts.partial_read) {
2403
                        if (read_count == value.size()) {
2404
                           return;
2405
                        }
2406
                     }
2407
                     if (bool(ctx.error)) [[unlikely]]
2408
                        return;
2409
                  }
2410
                  else if constexpr (str_t<Key>) {
2411
                     Key key;
2412
                     parse<JSON>::op<Opts>(key, ctx, it, end);
2413
                     if (bool(ctx.error)) [[unlikely]]
2414
                        return;
2415
2416
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2417
                        return;
2418
                     }
2419
2420
                     reading(key);
2421
                     if constexpr (Opts.partial_read) {
2422
                        if (read_count == value.size()) {
2423
                           return;
2424
                        }
2425
                     }
2426
                     if (bool(ctx.error)) [[unlikely]]
2427
                        return;
2428
                  }
2429
                  else {
2430
                     Key key_value{};
2431
                     if constexpr (glaze_enum_t<Key>) {
2432
                        parse<JSON>::op<Opts>(key_value, ctx, it, end);
2433
                     }
2434
                     else if constexpr (std::is_arithmetic_v<Key>) {
2435
                        // prefer over quoted_t below to avoid double parsing of quoted_t
2436
                        parse<JSON>::op<opt_true<Opts, &opts::quoted_num>>(key_value, ctx, it, end);
2437
                     }
2438
                     else {
2439
                        parse<JSON>::op<opt_false<Opts, &opts::raw_string>>(quoted_t<Key>{key_value}, ctx, it, end);
2440
                     }
2441
                     if (bool(ctx.error)) [[unlikely]]
2442
                        return;
2443
2444
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2445
                        return;
2446
                     }
2447
2448
                     reading(key_value);
2449
                     if constexpr (Opts.partial_read) {
2450
                        if (read_count == value.size()) {
2451
                           return;
2452
                        }
2453
                     }
2454
                     if (bool(ctx.error)) [[unlikely]]
2455
                        return;
2456
                  }
2457
               }
2458
296
               if (skip_ws<Opts>(ctx, it, end)) {
2459
0
                  return;
2460
0
               }
2461
296
            }
2462
296
         }
2463
296
      }
_ZN3glz4fromILj10E5ValueIxEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEETnNS_14string_literalEXtlNS6_ILm1EEEEERS2_TkNS_10is_contextERNS_7contextERPKcSD_EEvOT1_OT2_OT3_OT4_
Line
Count
Source
2079
290
      {
2080
290
         static constexpr auto num_members = reflect<T>::size;
2081
2082
290
         static constexpr auto Opts = opening_handled_off<ws_handled_off<Options>()>();
2083
290
         if constexpr (!check_opening_handled(Options)) {
2084
290
            if constexpr (!check_ws_handled(Options)) {
2085
290
               if (skip_ws<Opts>(ctx, it, end)) {
2086
0
                  return;
2087
0
               }
2088
290
            }
2089
290
            if (match_invalid_end<'{', Opts>(ctx, it, end)) {
2090
0
               return;
2091
0
            }
2092
            if constexpr (not Opts.null_terminated) {
2093
               if (it == end) [[unlikely]] {
2094
                  ctx.error = error_code::unexpected_end;
2095
                  return;
2096
               }
2097
            }
2098
            if constexpr (not Opts.null_terminated) {
2099
               ++ctx.indentation_level;
2100
            }
2101
290
         }
2102
290
         const auto ws_start = it;
2103
290
         if (skip_ws<Opts>(ctx, it, end)) {
2104
0
            return;
2105
0
         }
2106
290
         const size_t ws_size = size_t(it - ws_start);
2107
2108
         if constexpr ((glaze_object_t<T> || reflectable<T>) && num_members == 0 && Opts.error_on_unknown_keys) {
2109
            if constexpr (not tag.sv().empty()) {
2110
               if (*it == '"') {
2111
                  ++it;
2112
                  if constexpr (not Opts.null_terminated) {
2113
                     if (it == end) [[unlikely]] {
2114
                        ctx.error = error_code::unexpected_end;
2115
                        return;
2116
                     }
2117
                  }
2118
2119
                  const auto start = it;
2120
                  skip_string_view<Opts>(ctx, it, end);
2121
                  if (bool(ctx.error)) [[unlikely]]
2122
                     return;
2123
                  const sv key{start, size_t(it - start)};
2124
                  ++it;
2125
                  if constexpr (not Opts.null_terminated) {
2126
                     if (it == end) [[unlikely]] {
2127
                        ctx.error = error_code::unexpected_end;
2128
                        return;
2129
                     }
2130
                  }
2131
2132
                  if (key == tag.sv()) {
2133
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2134
                        return;
2135
                     }
2136
2137
                     parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
2138
                     if (bool(ctx.error)) [[unlikely]]
2139
                        return;
2140
2141
                     if (skip_ws<Opts>(ctx, it, end)) {
2142
                        return;
2143
                     }
2144
                  }
2145
                  else {
2146
                     ctx.error = error_code::unknown_key;
2147
                     return;
2148
                  }
2149
               }
2150
            }
2151
2152
            if (*it == '}') [[likely]] {
2153
               if constexpr (not Opts.null_terminated) {
2154
                  --ctx.indentation_level;
2155
               }
2156
               ++it;
2157
               if constexpr (not Opts.null_terminated) {
2158
                  if (it == end) {
2159
                     ctx.error = error_code::end_reached;
2160
                     return;
2161
                  }
2162
               }
2163
               if constexpr (Opts.partial_read) {
2164
                  ctx.error = error_code::partial_read_complete;
2165
               }
2166
               return;
2167
            }
2168
            ctx.error = error_code::unknown_key;
2169
            return;
2170
         }
2171
290
         else {
2172
290
            decltype(auto) fields = [&]() -> decltype(auto) {
2173
290
               if constexpr ((glaze_object_t<T> || reflectable<T>) &&
2174
290
                             (Opts.error_on_missing_keys || Opts.partial_read)) {
2175
290
                  return bit_array<num_members>{};
2176
290
               }
2177
290
               else {
2178
290
                  return nullptr;
2179
290
               }
2180
290
            }();
2181
2182
290
            size_t read_count{}; // for partial_read
2183
2184
290
            bool first = true;
2185
580
            while (true) {
2186
               if constexpr ((glaze_object_t<T> || reflectable<T>) && Opts.partial_read) {
2187
                  static constexpr bit_array<num_members> all_fields = [] {
2188
                     bit_array<num_members> arr{};
2189
                     for (size_t i = 0; i < num_members; ++i) {
2190
                        arr[i] = true;
2191
                     }
2192
                     return arr;
2193
                  }();
2194
2195
                  if ((all_fields & fields) == all_fields) {
2196
                     ctx.error = error_code::partial_read_complete;
2197
                     return;
2198
                  }
2199
               }
2200
2201
580
               if (*it == '}') {
2202
                  if constexpr (not Opts.null_terminated) {
2203
                     --ctx.indentation_level;
2204
                  }
2205
                  if constexpr ((glaze_object_t<T> || reflectable<T>) &&
2206
                                (Opts.partial_read && Opts.error_on_missing_keys)) {
2207
                     ctx.error = error_code::missing_key;
2208
                     return;
2209
                  }
2210
290
                  else {
2211
                     if constexpr ((glaze_object_t<T> || reflectable<T>) && Opts.error_on_missing_keys) {
2212
                        constexpr auto req_fields = required_fields<T, Opts>();
2213
                        if ((req_fields & fields) != req_fields) {
2214
                           for (size_t i = 0; i < num_members; ++i) {
2215
                              if (not fields[i]) {
2216
                                 ctx.custom_error_message = reflect<T>::keys[i];
2217
                                 // We just return the first missing key in order to avoid heap allocations
2218
                                 break;
2219
                              }
2220
                           }
2221
2222
                           ctx.error = error_code::missing_key;
2223
                           return;
2224
                        }
2225
                     }
2226
290
                     ++it; // Increment after checking for mising keys so errors are within buffer bounds
2227
                     if constexpr (not Opts.null_terminated) {
2228
                        if (it == end) {
2229
                           ctx.error = error_code::end_reached;
2230
                           return;
2231
                        }
2232
                     }
2233
290
                  }
2234
290
                  return;
2235
290
               }
2236
290
               else if (first) {
2237
290
                  first = false;
2238
290
               }
2239
0
               else {
2240
0
                  if (match_invalid_end<',', Opts>(ctx, it, end)) {
2241
0
                     return;
2242
0
                  }
2243
                  if constexpr (not Opts.null_terminated) {
2244
                     if (it == end) [[unlikely]] {
2245
                        ctx.error = error_code::unexpected_end;
2246
                        return;
2247
                     }
2248
                  }
2249
2250
                  if constexpr ((not Opts.minified) && (num_members > 1 || not Opts.error_on_unknown_keys)) {
2251
                     if (ws_size && ws_size < size_t(end - it)) {
2252
                        skip_matching_ws(ws_start, it, ws_size);
2253
                     }
2254
                  }
2255
2256
0
                  if (skip_ws<Opts>(ctx, it, end)) {
2257
0
                     return;
2258
0
                  }
2259
0
               }
2260
2261
290
               constexpr auto reflection_type = glaze_object_t<T> || reflectable<T>;
2262
2263
               if constexpr (reflection_type && (num_members == 0)) {
2264
                  if constexpr (Opts.error_on_unknown_keys) {
2265
                     static_assert(false_v<T>, "This should be unreachable");
2266
                  }
2267
                  else {
2268
                     if (match_invalid_end<'"', Opts>(ctx, it, end)) {
2269
                        return;
2270
                     }
2271
2272
                     // parsing to an empty object, but at this point the JSON presents keys
2273
2274
                     // Unknown key handler does not unescape keys. Unknown escaped keys are
2275
                     // handled by the user.
2276
2277
                     const auto start = it;
2278
                     skip_string_view<Opts>(ctx, it, end);
2279
                     if (bool(ctx.error)) [[unlikely]]
2280
                        return;
2281
                     const sv key{start, size_t(it - start)};
2282
                     ++it;
2283
                     if constexpr (not Opts.null_terminated) {
2284
                        if (it == end) [[unlikely]] {
2285
                           ctx.error = error_code::unexpected_end;
2286
                           return;
2287
                        }
2288
                     }
2289
2290
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2291
                        return;
2292
                     }
2293
2294
                     parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
2295
                     if (bool(ctx.error)) [[unlikely]]
2296
                        return;
2297
                     if constexpr (not Opts.null_terminated) {
2298
                        if (it == end) [[unlikely]] {
2299
                           ctx.error = error_code::unexpected_end;
2300
                           return;
2301
                        }
2302
                     }
2303
                  }
2304
               }
2305
290
               else if constexpr (reflection_type) {
2306
290
                  static_assert(bool(hash_info<T>.type));
2307
2308
290
                  if (*it != '"') [[unlikely]] {
2309
0
                     ctx.error = error_code::expected_quote;
2310
0
                     return;
2311
0
                  }
2312
290
                  ++it;
2313
                  if constexpr (not Opts.null_terminated) {
2314
                     if (it == end) [[unlikely]] {
2315
                        ctx.error = error_code::unexpected_end;
2316
                        return;
2317
                     }
2318
                  }
2319
2320
                  if constexpr (not tag.sv().empty() && not contains_tag<T, tag>()) {
2321
                     // For tagged variants we first check to see if the key matches the tag
2322
                     // We only need to do this if the tag is not part of the keys
2323
2324
                     const auto start = it;
2325
                     skip_string_view<Opts>(ctx, it, end);
2326
                     if (bool(ctx.error)) [[unlikely]]
2327
                        return;
2328
                     const sv key{start, size_t(it - start)};
2329
                     ++it;
2330
                     if constexpr (not Opts.null_terminated) {
2331
                        if (it == end) [[unlikely]] {
2332
                           ctx.error = error_code::unexpected_end;
2333
                           return;
2334
                        }
2335
                     }
2336
2337
                     if (key == tag.sv()) {
2338
                        if (parse_ws_colon<Opts>(ctx, it, end)) {
2339
                           return;
2340
                        }
2341
2342
                        parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
2343
                        if (bool(ctx.error)) [[unlikely]]
2344
                           return;
2345
2346
                        if (skip_ws<Opts>(ctx, it, end)) {
2347
                           return;
2348
                        }
2349
                        continue;
2350
                     }
2351
                     else {
2352
                        it = start; // reset the iterator
2353
                     }
2354
                  }
2355
2356
                  if constexpr (Opts.error_on_missing_keys || Opts.partial_read) {
2357
                     size_t index = num_members;
2358
                     parse_and_invoke<Opts, T, hash_info<T>>(value, ctx, it, end, index);
2359
                     if (bool(ctx.error)) [[unlikely]]
2360
                        return;
2361
                     if (index < num_members) {
2362
                        fields[index] = true;
2363
                     }
2364
                  }
2365
290
                  else {
2366
290
                     parse_and_invoke<Opts, T, hash_info<T>>(value, ctx, it, end);
2367
290
                     if (bool(ctx.error)) [[unlikely]]
2368
0
                        return;
2369
290
                  }
2370
               }
2371
               else {
2372
                  // For types like std::map, std::unordered_map
2373
2374
                  auto reading = [&](auto&& key) {
2375
                     if constexpr (Opts.partial_read) {
2376
                        if (auto element = value.find(key); element != value.end()) {
2377
                           ++read_count;
2378
                           parse<JSON>::op<ws_handled<Opts>()>(element->second, ctx, it, end);
2379
                        }
2380
                        else {
2381
                           skip_value<JSON>::op<Opts>(ctx, it, end);
2382
                        }
2383
                     }
2384
                     else {
2385
                        parse<JSON>::op<ws_handled<Opts>()>(value[key], ctx, it, end);
2386
                     }
2387
                  };
2388
2389
                  // using Key = std::conditional_t<heterogeneous_map<T>, sv, typename T::key_type>;
2390
                  using Key = typename T::key_type;
2391
                  if constexpr (std::is_same_v<Key, std::string>) {
2392
                     static thread_local Key key;
2393
                     parse<JSON>::op<Opts>(key, ctx, it, end);
2394
                     if (bool(ctx.error)) [[unlikely]]
2395
                        return;
2396
2397
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2398
                        return;
2399
                     }
2400
2401
                     reading(key);
2402
                     if constexpr (Opts.partial_read) {
2403
                        if (read_count == value.size()) {
2404
                           return;
2405
                        }
2406
                     }
2407
                     if (bool(ctx.error)) [[unlikely]]
2408
                        return;
2409
                  }
2410
                  else if constexpr (str_t<Key>) {
2411
                     Key key;
2412
                     parse<JSON>::op<Opts>(key, ctx, it, end);
2413
                     if (bool(ctx.error)) [[unlikely]]
2414
                        return;
2415
2416
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2417
                        return;
2418
                     }
2419
2420
                     reading(key);
2421
                     if constexpr (Opts.partial_read) {
2422
                        if (read_count == value.size()) {
2423
                           return;
2424
                        }
2425
                     }
2426
                     if (bool(ctx.error)) [[unlikely]]
2427
                        return;
2428
                  }
2429
                  else {
2430
                     Key key_value{};
2431
                     if constexpr (glaze_enum_t<Key>) {
2432
                        parse<JSON>::op<Opts>(key_value, ctx, it, end);
2433
                     }
2434
                     else if constexpr (std::is_arithmetic_v<Key>) {
2435
                        // prefer over quoted_t below to avoid double parsing of quoted_t
2436
                        parse<JSON>::op<opt_true<Opts, &opts::quoted_num>>(key_value, ctx, it, end);
2437
                     }
2438
                     else {
2439
                        parse<JSON>::op<opt_false<Opts, &opts::raw_string>>(quoted_t<Key>{key_value}, ctx, it, end);
2440
                     }
2441
                     if (bool(ctx.error)) [[unlikely]]
2442
                        return;
2443
2444
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2445
                        return;
2446
                     }
2447
2448
                     reading(key_value);
2449
                     if constexpr (Opts.partial_read) {
2450
                        if (read_count == value.size()) {
2451
                           return;
2452
                        }
2453
                     }
2454
                     if (bool(ctx.error)) [[unlikely]]
2455
                        return;
2456
                  }
2457
               }
2458
290
               if (skip_ws<Opts>(ctx, it, end)) {
2459
0
                  return;
2460
0
               }
2461
290
            }
2462
290
         }
2463
290
      }
_ZN3glz4fromILj10E5ValueIyEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEETnNS_14string_literalEXtlNS6_ILm1EEEEERS2_TkNS_10is_contextERNS_7contextERPKcSD_EEvOT1_OT2_OT3_OT4_
Line
Count
Source
2079
290
      {
2080
290
         static constexpr auto num_members = reflect<T>::size;
2081
2082
290
         static constexpr auto Opts = opening_handled_off<ws_handled_off<Options>()>();
2083
290
         if constexpr (!check_opening_handled(Options)) {
2084
290
            if constexpr (!check_ws_handled(Options)) {
2085
290
               if (skip_ws<Opts>(ctx, it, end)) {
2086
0
                  return;
2087
0
               }
2088
290
            }
2089
290
            if (match_invalid_end<'{', Opts>(ctx, it, end)) {
2090
0
               return;
2091
0
            }
2092
            if constexpr (not Opts.null_terminated) {
2093
               if (it == end) [[unlikely]] {
2094
                  ctx.error = error_code::unexpected_end;
2095
                  return;
2096
               }
2097
            }
2098
            if constexpr (not Opts.null_terminated) {
2099
               ++ctx.indentation_level;
2100
            }
2101
290
         }
2102
290
         const auto ws_start = it;
2103
290
         if (skip_ws<Opts>(ctx, it, end)) {
2104
0
            return;
2105
0
         }
2106
290
         const size_t ws_size = size_t(it - ws_start);
2107
2108
         if constexpr ((glaze_object_t<T> || reflectable<T>) && num_members == 0 && Opts.error_on_unknown_keys) {
2109
            if constexpr (not tag.sv().empty()) {
2110
               if (*it == '"') {
2111
                  ++it;
2112
                  if constexpr (not Opts.null_terminated) {
2113
                     if (it == end) [[unlikely]] {
2114
                        ctx.error = error_code::unexpected_end;
2115
                        return;
2116
                     }
2117
                  }
2118
2119
                  const auto start = it;
2120
                  skip_string_view<Opts>(ctx, it, end);
2121
                  if (bool(ctx.error)) [[unlikely]]
2122
                     return;
2123
                  const sv key{start, size_t(it - start)};
2124
                  ++it;
2125
                  if constexpr (not Opts.null_terminated) {
2126
                     if (it == end) [[unlikely]] {
2127
                        ctx.error = error_code::unexpected_end;
2128
                        return;
2129
                     }
2130
                  }
2131
2132
                  if (key == tag.sv()) {
2133
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2134
                        return;
2135
                     }
2136
2137
                     parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
2138
                     if (bool(ctx.error)) [[unlikely]]
2139
                        return;
2140
2141
                     if (skip_ws<Opts>(ctx, it, end)) {
2142
                        return;
2143
                     }
2144
                  }
2145
                  else {
2146
                     ctx.error = error_code::unknown_key;
2147
                     return;
2148
                  }
2149
               }
2150
            }
2151
2152
            if (*it == '}') [[likely]] {
2153
               if constexpr (not Opts.null_terminated) {
2154
                  --ctx.indentation_level;
2155
               }
2156
               ++it;
2157
               if constexpr (not Opts.null_terminated) {
2158
                  if (it == end) {
2159
                     ctx.error = error_code::end_reached;
2160
                     return;
2161
                  }
2162
               }
2163
               if constexpr (Opts.partial_read) {
2164
                  ctx.error = error_code::partial_read_complete;
2165
               }
2166
               return;
2167
            }
2168
            ctx.error = error_code::unknown_key;
2169
            return;
2170
         }
2171
290
         else {
2172
290
            decltype(auto) fields = [&]() -> decltype(auto) {
2173
290
               if constexpr ((glaze_object_t<T> || reflectable<T>) &&
2174
290
                             (Opts.error_on_missing_keys || Opts.partial_read)) {
2175
290
                  return bit_array<num_members>{};
2176
290
               }
2177
290
               else {
2178
290
                  return nullptr;
2179
290
               }
2180
290
            }();
2181
2182
290
            size_t read_count{}; // for partial_read
2183
2184
290
            bool first = true;
2185
580
            while (true) {
2186
               if constexpr ((glaze_object_t<T> || reflectable<T>) && Opts.partial_read) {
2187
                  static constexpr bit_array<num_members> all_fields = [] {
2188
                     bit_array<num_members> arr{};
2189
                     for (size_t i = 0; i < num_members; ++i) {
2190
                        arr[i] = true;
2191
                     }
2192
                     return arr;
2193
                  }();
2194
2195
                  if ((all_fields & fields) == all_fields) {
2196
                     ctx.error = error_code::partial_read_complete;
2197
                     return;
2198
                  }
2199
               }
2200
2201
580
               if (*it == '}') {
2202
                  if constexpr (not Opts.null_terminated) {
2203
                     --ctx.indentation_level;
2204
                  }
2205
                  if constexpr ((glaze_object_t<T> || reflectable<T>) &&
2206
                                (Opts.partial_read && Opts.error_on_missing_keys)) {
2207
                     ctx.error = error_code::missing_key;
2208
                     return;
2209
                  }
2210
290
                  else {
2211
                     if constexpr ((glaze_object_t<T> || reflectable<T>) && Opts.error_on_missing_keys) {
2212
                        constexpr auto req_fields = required_fields<T, Opts>();
2213
                        if ((req_fields & fields) != req_fields) {
2214
                           for (size_t i = 0; i < num_members; ++i) {
2215
                              if (not fields[i]) {
2216
                                 ctx.custom_error_message = reflect<T>::keys[i];
2217
                                 // We just return the first missing key in order to avoid heap allocations
2218
                                 break;
2219
                              }
2220
                           }
2221
2222
                           ctx.error = error_code::missing_key;
2223
                           return;
2224
                        }
2225
                     }
2226
290
                     ++it; // Increment after checking for mising keys so errors are within buffer bounds
2227
                     if constexpr (not Opts.null_terminated) {
2228
                        if (it == end) {
2229
                           ctx.error = error_code::end_reached;
2230
                           return;
2231
                        }
2232
                     }
2233
290
                  }
2234
290
                  return;
2235
290
               }
2236
290
               else if (first) {
2237
290
                  first = false;
2238
290
               }
2239
0
               else {
2240
0
                  if (match_invalid_end<',', Opts>(ctx, it, end)) {
2241
0
                     return;
2242
0
                  }
2243
                  if constexpr (not Opts.null_terminated) {
2244
                     if (it == end) [[unlikely]] {
2245
                        ctx.error = error_code::unexpected_end;
2246
                        return;
2247
                     }
2248
                  }
2249
2250
                  if constexpr ((not Opts.minified) && (num_members > 1 || not Opts.error_on_unknown_keys)) {
2251
                     if (ws_size && ws_size < size_t(end - it)) {
2252
                        skip_matching_ws(ws_start, it, ws_size);
2253
                     }
2254
                  }
2255
2256
0
                  if (skip_ws<Opts>(ctx, it, end)) {
2257
0
                     return;
2258
0
                  }
2259
0
               }
2260
2261
290
               constexpr auto reflection_type = glaze_object_t<T> || reflectable<T>;
2262
2263
               if constexpr (reflection_type && (num_members == 0)) {
2264
                  if constexpr (Opts.error_on_unknown_keys) {
2265
                     static_assert(false_v<T>, "This should be unreachable");
2266
                  }
2267
                  else {
2268
                     if (match_invalid_end<'"', Opts>(ctx, it, end)) {
2269
                        return;
2270
                     }
2271
2272
                     // parsing to an empty object, but at this point the JSON presents keys
2273
2274
                     // Unknown key handler does not unescape keys. Unknown escaped keys are
2275
                     // handled by the user.
2276
2277
                     const auto start = it;
2278
                     skip_string_view<Opts>(ctx, it, end);
2279
                     if (bool(ctx.error)) [[unlikely]]
2280
                        return;
2281
                     const sv key{start, size_t(it - start)};
2282
                     ++it;
2283
                     if constexpr (not Opts.null_terminated) {
2284
                        if (it == end) [[unlikely]] {
2285
                           ctx.error = error_code::unexpected_end;
2286
                           return;
2287
                        }
2288
                     }
2289
2290
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2291
                        return;
2292
                     }
2293
2294
                     parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
2295
                     if (bool(ctx.error)) [[unlikely]]
2296
                        return;
2297
                     if constexpr (not Opts.null_terminated) {
2298
                        if (it == end) [[unlikely]] {
2299
                           ctx.error = error_code::unexpected_end;
2300
                           return;
2301
                        }
2302
                     }
2303
                  }
2304
               }
2305
290
               else if constexpr (reflection_type) {
2306
290
                  static_assert(bool(hash_info<T>.type));
2307
2308
290
                  if (*it != '"') [[unlikely]] {
2309
0
                     ctx.error = error_code::expected_quote;
2310
0
                     return;
2311
0
                  }
2312
290
                  ++it;
2313
                  if constexpr (not Opts.null_terminated) {
2314
                     if (it == end) [[unlikely]] {
2315
                        ctx.error = error_code::unexpected_end;
2316
                        return;
2317
                     }
2318
                  }
2319
2320
                  if constexpr (not tag.sv().empty() && not contains_tag<T, tag>()) {
2321
                     // For tagged variants we first check to see if the key matches the tag
2322
                     // We only need to do this if the tag is not part of the keys
2323
2324
                     const auto start = it;
2325
                     skip_string_view<Opts>(ctx, it, end);
2326
                     if (bool(ctx.error)) [[unlikely]]
2327
                        return;
2328
                     const sv key{start, size_t(it - start)};
2329
                     ++it;
2330
                     if constexpr (not Opts.null_terminated) {
2331
                        if (it == end) [[unlikely]] {
2332
                           ctx.error = error_code::unexpected_end;
2333
                           return;
2334
                        }
2335
                     }
2336
2337
                     if (key == tag.sv()) {
2338
                        if (parse_ws_colon<Opts>(ctx, it, end)) {
2339
                           return;
2340
                        }
2341
2342
                        parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
2343
                        if (bool(ctx.error)) [[unlikely]]
2344
                           return;
2345
2346
                        if (skip_ws<Opts>(ctx, it, end)) {
2347
                           return;
2348
                        }
2349
                        continue;
2350
                     }
2351
                     else {
2352
                        it = start; // reset the iterator
2353
                     }
2354
                  }
2355
2356
                  if constexpr (Opts.error_on_missing_keys || Opts.partial_read) {
2357
                     size_t index = num_members;
2358
                     parse_and_invoke<Opts, T, hash_info<T>>(value, ctx, it, end, index);
2359
                     if (bool(ctx.error)) [[unlikely]]
2360
                        return;
2361
                     if (index < num_members) {
2362
                        fields[index] = true;
2363
                     }
2364
                  }
2365
290
                  else {
2366
290
                     parse_and_invoke<Opts, T, hash_info<T>>(value, ctx, it, end);
2367
290
                     if (bool(ctx.error)) [[unlikely]]
2368
0
                        return;
2369
290
                  }
2370
               }
2371
               else {
2372
                  // For types like std::map, std::unordered_map
2373
2374
                  auto reading = [&](auto&& key) {
2375
                     if constexpr (Opts.partial_read) {
2376
                        if (auto element = value.find(key); element != value.end()) {
2377
                           ++read_count;
2378
                           parse<JSON>::op<ws_handled<Opts>()>(element->second, ctx, it, end);
2379
                        }
2380
                        else {
2381
                           skip_value<JSON>::op<Opts>(ctx, it, end);
2382
                        }
2383
                     }
2384
                     else {
2385
                        parse<JSON>::op<ws_handled<Opts>()>(value[key], ctx, it, end);
2386
                     }
2387
                  };
2388
2389
                  // using Key = std::conditional_t<heterogeneous_map<T>, sv, typename T::key_type>;
2390
                  using Key = typename T::key_type;
2391
                  if constexpr (std::is_same_v<Key, std::string>) {
2392
                     static thread_local Key key;
2393
                     parse<JSON>::op<Opts>(key, ctx, it, end);
2394
                     if (bool(ctx.error)) [[unlikely]]
2395
                        return;
2396
2397
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2398
                        return;
2399
                     }
2400
2401
                     reading(key);
2402
                     if constexpr (Opts.partial_read) {
2403
                        if (read_count == value.size()) {
2404
                           return;
2405
                        }
2406
                     }
2407
                     if (bool(ctx.error)) [[unlikely]]
2408
                        return;
2409
                  }
2410
                  else if constexpr (str_t<Key>) {
2411
                     Key key;
2412
                     parse<JSON>::op<Opts>(key, ctx, it, end);
2413
                     if (bool(ctx.error)) [[unlikely]]
2414
                        return;
2415
2416
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2417
                        return;
2418
                     }
2419
2420
                     reading(key);
2421
                     if constexpr (Opts.partial_read) {
2422
                        if (read_count == value.size()) {
2423
                           return;
2424
                        }
2425
                     }
2426
                     if (bool(ctx.error)) [[unlikely]]
2427
                        return;
2428
                  }
2429
                  else {
2430
                     Key key_value{};
2431
                     if constexpr (glaze_enum_t<Key>) {
2432
                        parse<JSON>::op<Opts>(key_value, ctx, it, end);
2433
                     }
2434
                     else if constexpr (std::is_arithmetic_v<Key>) {
2435
                        // prefer over quoted_t below to avoid double parsing of quoted_t
2436
                        parse<JSON>::op<opt_true<Opts, &opts::quoted_num>>(key_value, ctx, it, end);
2437
                     }
2438
                     else {
2439
                        parse<JSON>::op<opt_false<Opts, &opts::raw_string>>(quoted_t<Key>{key_value}, ctx, it, end);
2440
                     }
2441
                     if (bool(ctx.error)) [[unlikely]]
2442
                        return;
2443
2444
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2445
                        return;
2446
                     }
2447
2448
                     reading(key_value);
2449
                     if constexpr (Opts.partial_read) {
2450
                        if (read_count == value.size()) {
2451
                           return;
2452
                        }
2453
                     }
2454
                     if (bool(ctx.error)) [[unlikely]]
2455
                        return;
2456
                  }
2457
               }
2458
290
               if (skip_ws<Opts>(ctx, it, end)) {
2459
0
                  return;
2460
0
               }
2461
290
            }
2462
290
         }
2463
290
      }
_ZN3glz4fromILj10ENSt3__13mapINS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEENS_6json_tENS1_4lessIvEENS6_INS1_4pairIKS8_S9_EEEEEEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj1EEETnNS_14string_literalEXtlNSK_ILm1EEEEERSG_TkNS_10is_contextERNS_7contextERPKcSR_EEvOT1_OT2_OT3_OT4_
Line
Count
Source
2079
7.82k
      {
2080
7.82k
         static constexpr auto num_members = reflect<T>::size;
2081
2082
7.82k
         static constexpr auto Opts = opening_handled_off<ws_handled_off<Options>()>();
2083
         if constexpr (!check_opening_handled(Options)) {
2084
            if constexpr (!check_ws_handled(Options)) {
2085
               if (skip_ws<Opts>(ctx, it, end)) {
2086
                  return;
2087
               }
2088
            }
2089
            if (match_invalid_end<'{', Opts>(ctx, it, end)) {
2090
               return;
2091
            }
2092
            if constexpr (not Opts.null_terminated) {
2093
               if (it == end) [[unlikely]] {
2094
                  ctx.error = error_code::unexpected_end;
2095
                  return;
2096
               }
2097
            }
2098
            if constexpr (not Opts.null_terminated) {
2099
               ++ctx.indentation_level;
2100
            }
2101
         }
2102
7.82k
         const auto ws_start = it;
2103
7.82k
         if (skip_ws<Opts>(ctx, it, end)) {
2104
15
            return;
2105
15
         }
2106
7.80k
         const size_t ws_size = size_t(it - ws_start);
2107
2108
         if constexpr ((glaze_object_t<T> || reflectable<T>) && num_members == 0 && Opts.error_on_unknown_keys) {
2109
            if constexpr (not tag.sv().empty()) {
2110
               if (*it == '"') {
2111
                  ++it;
2112
                  if constexpr (not Opts.null_terminated) {
2113
                     if (it == end) [[unlikely]] {
2114
                        ctx.error = error_code::unexpected_end;
2115
                        return;
2116
                     }
2117
                  }
2118
2119
                  const auto start = it;
2120
                  skip_string_view<Opts>(ctx, it, end);
2121
                  if (bool(ctx.error)) [[unlikely]]
2122
                     return;
2123
                  const sv key{start, size_t(it - start)};
2124
                  ++it;
2125
                  if constexpr (not Opts.null_terminated) {
2126
                     if (it == end) [[unlikely]] {
2127
                        ctx.error = error_code::unexpected_end;
2128
                        return;
2129
                     }
2130
                  }
2131
2132
                  if (key == tag.sv()) {
2133
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2134
                        return;
2135
                     }
2136
2137
                     parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
2138
                     if (bool(ctx.error)) [[unlikely]]
2139
                        return;
2140
2141
                     if (skip_ws<Opts>(ctx, it, end)) {
2142
                        return;
2143
                     }
2144
                  }
2145
                  else {
2146
                     ctx.error = error_code::unknown_key;
2147
                     return;
2148
                  }
2149
               }
2150
            }
2151
2152
            if (*it == '}') [[likely]] {
2153
               if constexpr (not Opts.null_terminated) {
2154
                  --ctx.indentation_level;
2155
               }
2156
               ++it;
2157
               if constexpr (not Opts.null_terminated) {
2158
                  if (it == end) {
2159
                     ctx.error = error_code::end_reached;
2160
                     return;
2161
                  }
2162
               }
2163
               if constexpr (Opts.partial_read) {
2164
                  ctx.error = error_code::partial_read_complete;
2165
               }
2166
               return;
2167
            }
2168
            ctx.error = error_code::unknown_key;
2169
            return;
2170
         }
2171
7.80k
         else {
2172
7.80k
            decltype(auto) fields = [&]() -> decltype(auto) {
2173
7.80k
               if constexpr ((glaze_object_t<T> || reflectable<T>) &&
2174
7.80k
                             (Opts.error_on_missing_keys || Opts.partial_read)) {
2175
7.80k
                  return bit_array<num_members>{};
2176
7.80k
               }
2177
7.80k
               else {
2178
7.80k
                  return nullptr;
2179
7.80k
               }
2180
7.80k
            }();
2181
2182
7.80k
            size_t read_count{}; // for partial_read
2183
2184
7.80k
            bool first = true;
2185
48.3k
            while (true) {
2186
               if constexpr ((glaze_object_t<T> || reflectable<T>) && Opts.partial_read) {
2187
                  static constexpr bit_array<num_members> all_fields = [] {
2188
                     bit_array<num_members> arr{};
2189
                     for (size_t i = 0; i < num_members; ++i) {
2190
                        arr[i] = true;
2191
                     }
2192
                     return arr;
2193
                  }();
2194
2195
                  if ((all_fields & fields) == all_fields) {
2196
                     ctx.error = error_code::partial_read_complete;
2197
                     return;
2198
                  }
2199
               }
2200
2201
42.7k
               if (*it == '}') {
2202
1.96k
                  if constexpr (not Opts.null_terminated) {
2203
1.96k
                     --ctx.indentation_level;
2204
1.96k
                  }
2205
                  if constexpr ((glaze_object_t<T> || reflectable<T>) &&
2206
                                (Opts.partial_read && Opts.error_on_missing_keys)) {
2207
                     ctx.error = error_code::missing_key;
2208
                     return;
2209
                  }
2210
1.96k
                  else {
2211
                     if constexpr ((glaze_object_t<T> || reflectable<T>) && Opts.error_on_missing_keys) {
2212
                        constexpr auto req_fields = required_fields<T, Opts>();
2213
                        if ((req_fields & fields) != req_fields) {
2214
                           for (size_t i = 0; i < num_members; ++i) {
2215
                              if (not fields[i]) {
2216
                                 ctx.custom_error_message = reflect<T>::keys[i];
2217
                                 // We just return the first missing key in order to avoid heap allocations
2218
                                 break;
2219
                              }
2220
                           }
2221
2222
                           ctx.error = error_code::missing_key;
2223
                           return;
2224
                        }
2225
                     }
2226
1.96k
                     ++it; // Increment after checking for mising keys so errors are within buffer bounds
2227
1.96k
                     if constexpr (not Opts.null_terminated) {
2228
1.96k
                        if (it == end) {
2229
17
                           ctx.error = error_code::end_reached;
2230
17
                           return;
2231
17
                        }
2232
1.96k
                     }
2233
1.96k
                  }
2234
1.94k
                  return;
2235
1.96k
               }
2236
40.7k
               else if (first) {
2237
6.19k
                  first = false;
2238
6.19k
               }
2239
34.5k
               else {
2240
34.5k
                  if (match_invalid_end<',', Opts>(ctx, it, end)) {
2241
94
                     return;
2242
94
                  }
2243
34.4k
                  if constexpr (not Opts.null_terminated) {
2244
34.4k
                     if (it == end) [[unlikely]] {
2245
0
                        ctx.error = error_code::unexpected_end;
2246
0
                        return;
2247
0
                     }
2248
34.4k
                  }
2249
2250
                  if constexpr ((not Opts.minified) && (num_members > 1 || not Opts.error_on_unknown_keys)) {
2251
                     if (ws_size && ws_size < size_t(end - it)) {
2252
                        skip_matching_ws(ws_start, it, ws_size);
2253
                     }
2254
                  }
2255
2256
34.4k
                  if (skip_ws<Opts>(ctx, it, end)) {
2257
16
                     return;
2258
16
                  }
2259
34.4k
               }
2260
2261
40.6k
               constexpr auto reflection_type = glaze_object_t<T> || reflectable<T>;
2262
2263
               if constexpr (reflection_type && (num_members == 0)) {
2264
                  if constexpr (Opts.error_on_unknown_keys) {
2265
                     static_assert(false_v<T>, "This should be unreachable");
2266
                  }
2267
                  else {
2268
                     if (match_invalid_end<'"', Opts>(ctx, it, end)) {
2269
                        return;
2270
                     }
2271
2272
                     // parsing to an empty object, but at this point the JSON presents keys
2273
2274
                     // Unknown key handler does not unescape keys. Unknown escaped keys are
2275
                     // handled by the user.
2276
2277
                     const auto start = it;
2278
                     skip_string_view<Opts>(ctx, it, end);
2279
                     if (bool(ctx.error)) [[unlikely]]
2280
                        return;
2281
                     const sv key{start, size_t(it - start)};
2282
                     ++it;
2283
                     if constexpr (not Opts.null_terminated) {
2284
                        if (it == end) [[unlikely]] {
2285
                           ctx.error = error_code::unexpected_end;
2286
                           return;
2287
                        }
2288
                     }
2289
2290
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2291
                        return;
2292
                     }
2293
2294
                     parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
2295
                     if (bool(ctx.error)) [[unlikely]]
2296
                        return;
2297
                     if constexpr (not Opts.null_terminated) {
2298
                        if (it == end) [[unlikely]] {
2299
                           ctx.error = error_code::unexpected_end;
2300
                           return;
2301
                        }
2302
                     }
2303
                  }
2304
               }
2305
               else if constexpr (reflection_type) {
2306
                  static_assert(bool(hash_info<T>.type));
2307
2308
                  if (*it != '"') [[unlikely]] {
2309
                     ctx.error = error_code::expected_quote;
2310
                     return;
2311
                  }
2312
                  ++it;
2313
                  if constexpr (not Opts.null_terminated) {
2314
                     if (it == end) [[unlikely]] {
2315
                        ctx.error = error_code::unexpected_end;
2316
                        return;
2317
                     }
2318
                  }
2319
2320
                  if constexpr (not tag.sv().empty() && not contains_tag<T, tag>()) {
2321
                     // For tagged variants we first check to see if the key matches the tag
2322
                     // We only need to do this if the tag is not part of the keys
2323
2324
                     const auto start = it;
2325
                     skip_string_view<Opts>(ctx, it, end);
2326
                     if (bool(ctx.error)) [[unlikely]]
2327
                        return;
2328
                     const sv key{start, size_t(it - start)};
2329
                     ++it;
2330
                     if constexpr (not Opts.null_terminated) {
2331
                        if (it == end) [[unlikely]] {
2332
                           ctx.error = error_code::unexpected_end;
2333
                           return;
2334
                        }
2335
                     }
2336
2337
                     if (key == tag.sv()) {
2338
                        if (parse_ws_colon<Opts>(ctx, it, end)) {
2339
                           return;
2340
                        }
2341
2342
                        parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
2343
                        if (bool(ctx.error)) [[unlikely]]
2344
                           return;
2345
2346
                        if (skip_ws<Opts>(ctx, it, end)) {
2347
                           return;
2348
                        }
2349
                        continue;
2350
                     }
2351
                     else {
2352
                        it = start; // reset the iterator
2353
                     }
2354
                  }
2355
2356
                  if constexpr (Opts.error_on_missing_keys || Opts.partial_read) {
2357
                     size_t index = num_members;
2358
                     parse_and_invoke<Opts, T, hash_info<T>>(value, ctx, it, end, index);
2359
                     if (bool(ctx.error)) [[unlikely]]
2360
                        return;
2361
                     if (index < num_members) {
2362
                        fields[index] = true;
2363
                     }
2364
                  }
2365
                  else {
2366
                     parse_and_invoke<Opts, T, hash_info<T>>(value, ctx, it, end);
2367
                     if (bool(ctx.error)) [[unlikely]]
2368
                        return;
2369
                  }
2370
               }
2371
40.6k
               else {
2372
                  // For types like std::map, std::unordered_map
2373
2374
40.6k
                  auto reading = [&](auto&& key) {
2375
40.6k
                     if constexpr (Opts.partial_read) {
2376
40.6k
                        if (auto element = value.find(key); element != value.end()) {
2377
40.6k
                           ++read_count;
2378
40.6k
                           parse<JSON>::op<ws_handled<Opts>()>(element->second, ctx, it, end);
2379
40.6k
                        }
2380
40.6k
                        else {
2381
40.6k
                           skip_value<JSON>::op<Opts>(ctx, it, end);
2382
40.6k
                        }
2383
40.6k
                     }
2384
40.6k
                     else {
2385
40.6k
                        parse<JSON>::op<ws_handled<Opts>()>(value[key], ctx, it, end);
2386
40.6k
                     }
2387
40.6k
                  };
2388
2389
                  // using Key = std::conditional_t<heterogeneous_map<T>, sv, typename T::key_type>;
2390
40.6k
                  using Key = typename T::key_type;
2391
40.6k
                  if constexpr (std::is_same_v<Key, std::string>) {
2392
40.6k
                     static thread_local Key key;
2393
40.6k
                     parse<JSON>::op<Opts>(key, ctx, it, end);
2394
40.6k
                     if (bool(ctx.error)) [[unlikely]]
2395
228
                        return;
2396
2397
40.4k
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2398
510
                        return;
2399
510
                     }
2400
2401
39.9k
                     reading(key);
2402
                     if constexpr (Opts.partial_read) {
2403
                        if (read_count == value.size()) {
2404
                           return;
2405
                        }
2406
                     }
2407
39.9k
                     if (bool(ctx.error)) [[unlikely]]
2408
4.93k
                        return;
2409
                  }
2410
                  else if constexpr (str_t<Key>) {
2411
                     Key key;
2412
                     parse<JSON>::op<Opts>(key, ctx, it, end);
2413
                     if (bool(ctx.error)) [[unlikely]]
2414
                        return;
2415
2416
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2417
                        return;
2418
                     }
2419
2420
                     reading(key);
2421
                     if constexpr (Opts.partial_read) {
2422
                        if (read_count == value.size()) {
2423
                           return;
2424
                        }
2425
                     }
2426
                     if (bool(ctx.error)) [[unlikely]]
2427
                        return;
2428
                  }
2429
                  else {
2430
                     Key key_value{};
2431
                     if constexpr (glaze_enum_t<Key>) {
2432
                        parse<JSON>::op<Opts>(key_value, ctx, it, end);
2433
                     }
2434
                     else if constexpr (std::is_arithmetic_v<Key>) {
2435
                        // prefer over quoted_t below to avoid double parsing of quoted_t
2436
                        parse<JSON>::op<opt_true<Opts, &opts::quoted_num>>(key_value, ctx, it, end);
2437
                     }
2438
                     else {
2439
                        parse<JSON>::op<opt_false<Opts, &opts::raw_string>>(quoted_t<Key>{key_value}, ctx, it, end);
2440
                     }
2441
                     if (bool(ctx.error)) [[unlikely]]
2442
                        return;
2443
2444
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2445
                        return;
2446
                     }
2447
2448
                     reading(key_value);
2449
                     if constexpr (Opts.partial_read) {
2450
                        if (read_count == value.size()) {
2451
                           return;
2452
                        }
2453
                     }
2454
                     if (bool(ctx.error)) [[unlikely]]
2455
                        return;
2456
                  }
2457
40.6k
               }
2458
40.6k
               if (skip_ws<Opts>(ctx, it, end)) {
2459
58
                  return;
2460
58
               }
2461
40.6k
            }
2462
7.80k
         }
2463
7.80k
      }
_ZN3glz4fromILj10ENSt3__13mapINS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEENS_6json_tENS1_4lessIvEENS6_INS1_4pairIKS8_S9_EEEEEEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj1EEETnNS_14string_literalEXtlNSK_ILm1EEEEERSG_TkNS_10is_contextERNS_7contextERPKcSR_EEvOT1_OT2_OT3_OT4_
Line
Count
Source
2079
7.86k
      {
2080
7.86k
         static constexpr auto num_members = reflect<T>::size;
2081
2082
7.86k
         static constexpr auto Opts = opening_handled_off<ws_handled_off<Options>()>();
2083
         if constexpr (!check_opening_handled(Options)) {
2084
            if constexpr (!check_ws_handled(Options)) {
2085
               if (skip_ws<Opts>(ctx, it, end)) {
2086
                  return;
2087
               }
2088
            }
2089
            if (match_invalid_end<'{', Opts>(ctx, it, end)) {
2090
               return;
2091
            }
2092
            if constexpr (not Opts.null_terminated) {
2093
               if (it == end) [[unlikely]] {
2094
                  ctx.error = error_code::unexpected_end;
2095
                  return;
2096
               }
2097
            }
2098
            if constexpr (not Opts.null_terminated) {
2099
               ++ctx.indentation_level;
2100
            }
2101
         }
2102
7.86k
         const auto ws_start = it;
2103
7.86k
         if (skip_ws<Opts>(ctx, it, end)) {
2104
0
            return;
2105
0
         }
2106
7.86k
         const size_t ws_size = size_t(it - ws_start);
2107
2108
         if constexpr ((glaze_object_t<T> || reflectable<T>) && num_members == 0 && Opts.error_on_unknown_keys) {
2109
            if constexpr (not tag.sv().empty()) {
2110
               if (*it == '"') {
2111
                  ++it;
2112
                  if constexpr (not Opts.null_terminated) {
2113
                     if (it == end) [[unlikely]] {
2114
                        ctx.error = error_code::unexpected_end;
2115
                        return;
2116
                     }
2117
                  }
2118
2119
                  const auto start = it;
2120
                  skip_string_view<Opts>(ctx, it, end);
2121
                  if (bool(ctx.error)) [[unlikely]]
2122
                     return;
2123
                  const sv key{start, size_t(it - start)};
2124
                  ++it;
2125
                  if constexpr (not Opts.null_terminated) {
2126
                     if (it == end) [[unlikely]] {
2127
                        ctx.error = error_code::unexpected_end;
2128
                        return;
2129
                     }
2130
                  }
2131
2132
                  if (key == tag.sv()) {
2133
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2134
                        return;
2135
                     }
2136
2137
                     parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
2138
                     if (bool(ctx.error)) [[unlikely]]
2139
                        return;
2140
2141
                     if (skip_ws<Opts>(ctx, it, end)) {
2142
                        return;
2143
                     }
2144
                  }
2145
                  else {
2146
                     ctx.error = error_code::unknown_key;
2147
                     return;
2148
                  }
2149
               }
2150
            }
2151
2152
            if (*it == '}') [[likely]] {
2153
               if constexpr (not Opts.null_terminated) {
2154
                  --ctx.indentation_level;
2155
               }
2156
               ++it;
2157
               if constexpr (not Opts.null_terminated) {
2158
                  if (it == end) {
2159
                     ctx.error = error_code::end_reached;
2160
                     return;
2161
                  }
2162
               }
2163
               if constexpr (Opts.partial_read) {
2164
                  ctx.error = error_code::partial_read_complete;
2165
               }
2166
               return;
2167
            }
2168
            ctx.error = error_code::unknown_key;
2169
            return;
2170
         }
2171
7.86k
         else {
2172
7.86k
            decltype(auto) fields = [&]() -> decltype(auto) {
2173
7.86k
               if constexpr ((glaze_object_t<T> || reflectable<T>) &&
2174
7.86k
                             (Opts.error_on_missing_keys || Opts.partial_read)) {
2175
7.86k
                  return bit_array<num_members>{};
2176
7.86k
               }
2177
7.86k
               else {
2178
7.86k
                  return nullptr;
2179
7.86k
               }
2180
7.86k
            }();
2181
2182
7.86k
            size_t read_count{}; // for partial_read
2183
2184
7.86k
            bool first = true;
2185
48.6k
            while (true) {
2186
               if constexpr ((glaze_object_t<T> || reflectable<T>) && Opts.partial_read) {
2187
                  static constexpr bit_array<num_members> all_fields = [] {
2188
                     bit_array<num_members> arr{};
2189
                     for (size_t i = 0; i < num_members; ++i) {
2190
                        arr[i] = true;
2191
                     }
2192
                     return arr;
2193
                  }();
2194
2195
                  if ((all_fields & fields) == all_fields) {
2196
                     ctx.error = error_code::partial_read_complete;
2197
                     return;
2198
                  }
2199
               }
2200
2201
42.8k
               if (*it == '}') {
2202
                  if constexpr (not Opts.null_terminated) {
2203
                     --ctx.indentation_level;
2204
                  }
2205
                  if constexpr ((glaze_object_t<T> || reflectable<T>) &&
2206
                                (Opts.partial_read && Opts.error_on_missing_keys)) {
2207
                     ctx.error = error_code::missing_key;
2208
                     return;
2209
                  }
2210
1.96k
                  else {
2211
                     if constexpr ((glaze_object_t<T> || reflectable<T>) && Opts.error_on_missing_keys) {
2212
                        constexpr auto req_fields = required_fields<T, Opts>();
2213
                        if ((req_fields & fields) != req_fields) {
2214
                           for (size_t i = 0; i < num_members; ++i) {
2215
                              if (not fields[i]) {
2216
                                 ctx.custom_error_message = reflect<T>::keys[i];
2217
                                 // We just return the first missing key in order to avoid heap allocations
2218
                                 break;
2219
                              }
2220
                           }
2221
2222
                           ctx.error = error_code::missing_key;
2223
                           return;
2224
                        }
2225
                     }
2226
1.96k
                     ++it; // Increment after checking for mising keys so errors are within buffer bounds
2227
                     if constexpr (not Opts.null_terminated) {
2228
                        if (it == end) {
2229
                           ctx.error = error_code::end_reached;
2230
                           return;
2231
                        }
2232
                     }
2233
1.96k
                  }
2234
1.96k
                  return;
2235
1.96k
               }
2236
40.9k
               else if (first) {
2237
6.25k
                  first = false;
2238
6.25k
               }
2239
34.6k
               else {
2240
34.6k
                  if (match_invalid_end<',', Opts>(ctx, it, end)) {
2241
186
                     return;
2242
186
                  }
2243
                  if constexpr (not Opts.null_terminated) {
2244
                     if (it == end) [[unlikely]] {
2245
                        ctx.error = error_code::unexpected_end;
2246
                        return;
2247
                     }
2248
                  }
2249
2250
                  if constexpr ((not Opts.minified) && (num_members > 1 || not Opts.error_on_unknown_keys)) {
2251
                     if (ws_size && ws_size < size_t(end - it)) {
2252
                        skip_matching_ws(ws_start, it, ws_size);
2253
                     }
2254
                  }
2255
2256
34.4k
                  if (skip_ws<Opts>(ctx, it, end)) {
2257
0
                     return;
2258
0
                  }
2259
34.4k
               }
2260
2261
40.7k
               constexpr auto reflection_type = glaze_object_t<T> || reflectable<T>;
2262
2263
               if constexpr (reflection_type && (num_members == 0)) {
2264
                  if constexpr (Opts.error_on_unknown_keys) {
2265
                     static_assert(false_v<T>, "This should be unreachable");
2266
                  }
2267
                  else {
2268
                     if (match_invalid_end<'"', Opts>(ctx, it, end)) {
2269
                        return;
2270
                     }
2271
2272
                     // parsing to an empty object, but at this point the JSON presents keys
2273
2274
                     // Unknown key handler does not unescape keys. Unknown escaped keys are
2275
                     // handled by the user.
2276
2277
                     const auto start = it;
2278
                     skip_string_view<Opts>(ctx, it, end);
2279
                     if (bool(ctx.error)) [[unlikely]]
2280
                        return;
2281
                     const sv key{start, size_t(it - start)};
2282
                     ++it;
2283
                     if constexpr (not Opts.null_terminated) {
2284
                        if (it == end) [[unlikely]] {
2285
                           ctx.error = error_code::unexpected_end;
2286
                           return;
2287
                        }
2288
                     }
2289
2290
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2291
                        return;
2292
                     }
2293
2294
                     parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
2295
                     if (bool(ctx.error)) [[unlikely]]
2296
                        return;
2297
                     if constexpr (not Opts.null_terminated) {
2298
                        if (it == end) [[unlikely]] {
2299
                           ctx.error = error_code::unexpected_end;
2300
                           return;
2301
                        }
2302
                     }
2303
                  }
2304
               }
2305
               else if constexpr (reflection_type) {
2306
                  static_assert(bool(hash_info<T>.type));
2307
2308
                  if (*it != '"') [[unlikely]] {
2309
                     ctx.error = error_code::expected_quote;
2310
                     return;
2311
                  }
2312
                  ++it;
2313
                  if constexpr (not Opts.null_terminated) {
2314
                     if (it == end) [[unlikely]] {
2315
                        ctx.error = error_code::unexpected_end;
2316
                        return;
2317
                     }
2318
                  }
2319
2320
                  if constexpr (not tag.sv().empty() && not contains_tag<T, tag>()) {
2321
                     // For tagged variants we first check to see if the key matches the tag
2322
                     // We only need to do this if the tag is not part of the keys
2323
2324
                     const auto start = it;
2325
                     skip_string_view<Opts>(ctx, it, end);
2326
                     if (bool(ctx.error)) [[unlikely]]
2327
                        return;
2328
                     const sv key{start, size_t(it - start)};
2329
                     ++it;
2330
                     if constexpr (not Opts.null_terminated) {
2331
                        if (it == end) [[unlikely]] {
2332
                           ctx.error = error_code::unexpected_end;
2333
                           return;
2334
                        }
2335
                     }
2336
2337
                     if (key == tag.sv()) {
2338
                        if (parse_ws_colon<Opts>(ctx, it, end)) {
2339
                           return;
2340
                        }
2341
2342
                        parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
2343
                        if (bool(ctx.error)) [[unlikely]]
2344
                           return;
2345
2346
                        if (skip_ws<Opts>(ctx, it, end)) {
2347
                           return;
2348
                        }
2349
                        continue;
2350
                     }
2351
                     else {
2352
                        it = start; // reset the iterator
2353
                     }
2354
                  }
2355
2356
                  if constexpr (Opts.error_on_missing_keys || Opts.partial_read) {
2357
                     size_t index = num_members;
2358
                     parse_and_invoke<Opts, T, hash_info<T>>(value, ctx, it, end, index);
2359
                     if (bool(ctx.error)) [[unlikely]]
2360
                        return;
2361
                     if (index < num_members) {
2362
                        fields[index] = true;
2363
                     }
2364
                  }
2365
                  else {
2366
                     parse_and_invoke<Opts, T, hash_info<T>>(value, ctx, it, end);
2367
                     if (bool(ctx.error)) [[unlikely]]
2368
                        return;
2369
                  }
2370
               }
2371
40.7k
               else {
2372
                  // For types like std::map, std::unordered_map
2373
2374
40.7k
                  auto reading = [&](auto&& key) {
2375
40.7k
                     if constexpr (Opts.partial_read) {
2376
40.7k
                        if (auto element = value.find(key); element != value.end()) {
2377
40.7k
                           ++read_count;
2378
40.7k
                           parse<JSON>::op<ws_handled<Opts>()>(element->second, ctx, it, end);
2379
40.7k
                        }
2380
40.7k
                        else {
2381
40.7k
                           skip_value<JSON>::op<Opts>(ctx, it, end);
2382
40.7k
                        }
2383
40.7k
                     }
2384
40.7k
                     else {
2385
40.7k
                        parse<JSON>::op<ws_handled<Opts>()>(value[key], ctx, it, end);
2386
40.7k
                     }
2387
40.7k
                  };
2388
2389
                  // using Key = std::conditional_t<heterogeneous_map<T>, sv, typename T::key_type>;
2390
40.7k
                  using Key = typename T::key_type;
2391
40.7k
                  if constexpr (std::is_same_v<Key, std::string>) {
2392
40.7k
                     static thread_local Key key;
2393
40.7k
                     parse<JSON>::op<Opts>(key, ctx, it, end);
2394
40.7k
                     if (bool(ctx.error)) [[unlikely]]
2395
299
                        return;
2396
2397
40.4k
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2398
201
                        return;
2399
201
                     }
2400
2401
40.2k
                     reading(key);
2402
                     if constexpr (Opts.partial_read) {
2403
                        if (read_count == value.size()) {
2404
                           return;
2405
                        }
2406
                     }
2407
40.2k
                     if (bool(ctx.error)) [[unlikely]]
2408
5.21k
                        return;
2409
                  }
2410
                  else if constexpr (str_t<Key>) {
2411
                     Key key;
2412
                     parse<JSON>::op<Opts>(key, ctx, it, end);
2413
                     if (bool(ctx.error)) [[unlikely]]
2414
                        return;
2415
2416
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2417
                        return;
2418
                     }
2419
2420
                     reading(key);
2421
                     if constexpr (Opts.partial_read) {
2422
                        if (read_count == value.size()) {
2423
                           return;
2424
                        }
2425
                     }
2426
                     if (bool(ctx.error)) [[unlikely]]
2427
                        return;
2428
                  }
2429
                  else {
2430
                     Key key_value{};
2431
                     if constexpr (glaze_enum_t<Key>) {
2432
                        parse<JSON>::op<Opts>(key_value, ctx, it, end);
2433
                     }
2434
                     else if constexpr (std::is_arithmetic_v<Key>) {
2435
                        // prefer over quoted_t below to avoid double parsing of quoted_t
2436
                        parse<JSON>::op<opt_true<Opts, &opts::quoted_num>>(key_value, ctx, it, end);
2437
                     }
2438
                     else {
2439
                        parse<JSON>::op<opt_false<Opts, &opts::raw_string>>(quoted_t<Key>{key_value}, ctx, it, end);
2440
                     }
2441
                     if (bool(ctx.error)) [[unlikely]]
2442
                        return;
2443
2444
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2445
                        return;
2446
                     }
2447
2448
                     reading(key_value);
2449
                     if constexpr (Opts.partial_read) {
2450
                        if (read_count == value.size()) {
2451
                           return;
2452
                        }
2453
                     }
2454
                     if (bool(ctx.error)) [[unlikely]]
2455
                        return;
2456
                  }
2457
40.7k
               }
2458
40.7k
               if (skip_ws<Opts>(ctx, it, end)) {
2459
0
                  return;
2460
0
               }
2461
40.7k
            }
2462
7.86k
         }
2463
7.86k
      }
_ZN3glz4fromILj10ENSt3__13mapINS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEENS_6json_tENS1_4lessIvEENS6_INS1_4pairIKS8_S9_EEEEEEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj33EEETnNS_14string_literalEXtlNSK_ILm1EEEEERSG_TkNS_10is_contextERNS_7contextERPKcSR_EEvOT1_OT2_OT3_OT4_
Line
Count
Source
2079
7.86k
      {
2080
7.86k
         static constexpr auto num_members = reflect<T>::size;
2081
2082
7.86k
         static constexpr auto Opts = opening_handled_off<ws_handled_off<Options>()>();
2083
         if constexpr (!check_opening_handled(Options)) {
2084
            if constexpr (!check_ws_handled(Options)) {
2085
               if (skip_ws<Opts>(ctx, it, end)) {
2086
                  return;
2087
               }
2088
            }
2089
            if (match_invalid_end<'{', Opts>(ctx, it, end)) {
2090
               return;
2091
            }
2092
            if constexpr (not Opts.null_terminated) {
2093
               if (it == end) [[unlikely]] {
2094
                  ctx.error = error_code::unexpected_end;
2095
                  return;
2096
               }
2097
            }
2098
            if constexpr (not Opts.null_terminated) {
2099
               ++ctx.indentation_level;
2100
            }
2101
         }
2102
7.86k
         const auto ws_start = it;
2103
7.86k
         if (skip_ws<Opts>(ctx, it, end)) {
2104
0
            return;
2105
0
         }
2106
7.86k
         const size_t ws_size = size_t(it - ws_start);
2107
2108
         if constexpr ((glaze_object_t<T> || reflectable<T>) && num_members == 0 && Opts.error_on_unknown_keys) {
2109
            if constexpr (not tag.sv().empty()) {
2110
               if (*it == '"') {
2111
                  ++it;
2112
                  if constexpr (not Opts.null_terminated) {
2113
                     if (it == end) [[unlikely]] {
2114
                        ctx.error = error_code::unexpected_end;
2115
                        return;
2116
                     }
2117
                  }
2118
2119
                  const auto start = it;
2120
                  skip_string_view<Opts>(ctx, it, end);
2121
                  if (bool(ctx.error)) [[unlikely]]
2122
                     return;
2123
                  const sv key{start, size_t(it - start)};
2124
                  ++it;
2125
                  if constexpr (not Opts.null_terminated) {
2126
                     if (it == end) [[unlikely]] {
2127
                        ctx.error = error_code::unexpected_end;
2128
                        return;
2129
                     }
2130
                  }
2131
2132
                  if (key == tag.sv()) {
2133
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2134
                        return;
2135
                     }
2136
2137
                     parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
2138
                     if (bool(ctx.error)) [[unlikely]]
2139
                        return;
2140
2141
                     if (skip_ws<Opts>(ctx, it, end)) {
2142
                        return;
2143
                     }
2144
                  }
2145
                  else {
2146
                     ctx.error = error_code::unknown_key;
2147
                     return;
2148
                  }
2149
               }
2150
            }
2151
2152
            if (*it == '}') [[likely]] {
2153
               if constexpr (not Opts.null_terminated) {
2154
                  --ctx.indentation_level;
2155
               }
2156
               ++it;
2157
               if constexpr (not Opts.null_terminated) {
2158
                  if (it == end) {
2159
                     ctx.error = error_code::end_reached;
2160
                     return;
2161
                  }
2162
               }
2163
               if constexpr (Opts.partial_read) {
2164
                  ctx.error = error_code::partial_read_complete;
2165
               }
2166
               return;
2167
            }
2168
            ctx.error = error_code::unknown_key;
2169
            return;
2170
         }
2171
7.86k
         else {
2172
7.86k
            decltype(auto) fields = [&]() -> decltype(auto) {
2173
7.86k
               if constexpr ((glaze_object_t<T> || reflectable<T>) &&
2174
7.86k
                             (Opts.error_on_missing_keys || Opts.partial_read)) {
2175
7.86k
                  return bit_array<num_members>{};
2176
7.86k
               }
2177
7.86k
               else {
2178
7.86k
                  return nullptr;
2179
7.86k
               }
2180
7.86k
            }();
2181
2182
7.86k
            size_t read_count{}; // for partial_read
2183
2184
7.86k
            bool first = true;
2185
48.5k
            while (true) {
2186
               if constexpr ((glaze_object_t<T> || reflectable<T>) && Opts.partial_read) {
2187
                  static constexpr bit_array<num_members> all_fields = [] {
2188
                     bit_array<num_members> arr{};
2189
                     for (size_t i = 0; i < num_members; ++i) {
2190
                        arr[i] = true;
2191
                     }
2192
                     return arr;
2193
                  }();
2194
2195
                  if ((all_fields & fields) == all_fields) {
2196
                     ctx.error = error_code::partial_read_complete;
2197
                     return;
2198
                  }
2199
               }
2200
2201
42.8k
               if (*it == '}') {
2202
                  if constexpr (not Opts.null_terminated) {
2203
                     --ctx.indentation_level;
2204
                  }
2205
                  if constexpr ((glaze_object_t<T> || reflectable<T>) &&
2206
                                (Opts.partial_read && Opts.error_on_missing_keys)) {
2207
                     ctx.error = error_code::missing_key;
2208
                     return;
2209
                  }
2210
1.96k
                  else {
2211
                     if constexpr ((glaze_object_t<T> || reflectable<T>) && Opts.error_on_missing_keys) {
2212
                        constexpr auto req_fields = required_fields<T, Opts>();
2213
                        if ((req_fields & fields) != req_fields) {
2214
                           for (size_t i = 0; i < num_members; ++i) {
2215
                              if (not fields[i]) {
2216
                                 ctx.custom_error_message = reflect<T>::keys[i];
2217
                                 // We just return the first missing key in order to avoid heap allocations
2218
                                 break;
2219
                              }
2220
                           }
2221
2222
                           ctx.error = error_code::missing_key;
2223
                           return;
2224
                        }
2225
                     }
2226
1.96k
                     ++it; // Increment after checking for mising keys so errors are within buffer bounds
2227
                     if constexpr (not Opts.null_terminated) {
2228
                        if (it == end) {
2229
                           ctx.error = error_code::end_reached;
2230
                           return;
2231
                        }
2232
                     }
2233
1.96k
                  }
2234
1.96k
                  return;
2235
1.96k
               }
2236
40.9k
               else if (first) {
2237
6.25k
                  first = false;
2238
6.25k
               }
2239
34.6k
               else {
2240
34.6k
                  if (match_invalid_end<',', Opts>(ctx, it, end)) {
2241
169
                     return;
2242
169
                  }
2243
                  if constexpr (not Opts.null_terminated) {
2244
                     if (it == end) [[unlikely]] {
2245
                        ctx.error = error_code::unexpected_end;
2246
                        return;
2247
                     }
2248
                  }
2249
2250
                  if constexpr ((not Opts.minified) && (num_members > 1 || not Opts.error_on_unknown_keys)) {
2251
                     if (ws_size && ws_size < size_t(end - it)) {
2252
                        skip_matching_ws(ws_start, it, ws_size);
2253
                     }
2254
                  }
2255
2256
34.4k
                  if (skip_ws<Opts>(ctx, it, end)) {
2257
0
                     return;
2258
0
                  }
2259
34.4k
               }
2260
2261
40.7k
               constexpr auto reflection_type = glaze_object_t<T> || reflectable<T>;
2262
2263
               if constexpr (reflection_type && (num_members == 0)) {
2264
                  if constexpr (Opts.error_on_unknown_keys) {
2265
                     static_assert(false_v<T>, "This should be unreachable");
2266
                  }
2267
                  else {
2268
                     if (match_invalid_end<'"', Opts>(ctx, it, end)) {
2269
                        return;
2270
                     }
2271
2272
                     // parsing to an empty object, but at this point the JSON presents keys
2273
2274
                     // Unknown key handler does not unescape keys. Unknown escaped keys are
2275
                     // handled by the user.
2276
2277
                     const auto start = it;
2278
                     skip_string_view<Opts>(ctx, it, end);
2279
                     if (bool(ctx.error)) [[unlikely]]
2280
                        return;
2281
                     const sv key{start, size_t(it - start)};
2282
                     ++it;
2283
                     if constexpr (not Opts.null_terminated) {
2284
                        if (it == end) [[unlikely]] {
2285
                           ctx.error = error_code::unexpected_end;
2286
                           return;
2287
                        }
2288
                     }
2289
2290
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2291
                        return;
2292
                     }
2293
2294
                     parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
2295
                     if (bool(ctx.error)) [[unlikely]]
2296
                        return;
2297
                     if constexpr (not Opts.null_terminated) {
2298
                        if (it == end) [[unlikely]] {
2299
                           ctx.error = error_code::unexpected_end;
2300
                           return;
2301
                        }
2302
                     }
2303
                  }
2304
               }
2305
               else if constexpr (reflection_type) {
2306
                  static_assert(bool(hash_info<T>.type));
2307
2308
                  if (*it != '"') [[unlikely]] {
2309
                     ctx.error = error_code::expected_quote;
2310
                     return;
2311
                  }
2312
                  ++it;
2313
                  if constexpr (not Opts.null_terminated) {
2314
                     if (it == end) [[unlikely]] {
2315
                        ctx.error = error_code::unexpected_end;
2316
                        return;
2317
                     }
2318
                  }
2319
2320
                  if constexpr (not tag.sv().empty() && not contains_tag<T, tag>()) {
2321
                     // For tagged variants we first check to see if the key matches the tag
2322
                     // We only need to do this if the tag is not part of the keys
2323
2324
                     const auto start = it;
2325
                     skip_string_view<Opts>(ctx, it, end);
2326
                     if (bool(ctx.error)) [[unlikely]]
2327
                        return;
2328
                     const sv key{start, size_t(it - start)};
2329
                     ++it;
2330
                     if constexpr (not Opts.null_terminated) {
2331
                        if (it == end) [[unlikely]] {
2332
                           ctx.error = error_code::unexpected_end;
2333
                           return;
2334
                        }
2335
                     }
2336
2337
                     if (key == tag.sv()) {
2338
                        if (parse_ws_colon<Opts>(ctx, it, end)) {
2339
                           return;
2340
                        }
2341
2342
                        parse<JSON>::handle_unknown<Opts>(key, value, ctx, it, end);
2343
                        if (bool(ctx.error)) [[unlikely]]
2344
                           return;
2345
2346
                        if (skip_ws<Opts>(ctx, it, end)) {
2347
                           return;
2348
                        }
2349
                        continue;
2350
                     }
2351
                     else {
2352
                        it = start; // reset the iterator
2353
                     }
2354
                  }
2355
2356
                  if constexpr (Opts.error_on_missing_keys || Opts.partial_read) {
2357
                     size_t index = num_members;
2358
                     parse_and_invoke<Opts, T, hash_info<T>>(value, ctx, it, end, index);
2359
                     if (bool(ctx.error)) [[unlikely]]
2360
                        return;
2361
                     if (index < num_members) {
2362
                        fields[index] = true;
2363
                     }
2364
                  }
2365
                  else {
2366
                     parse_and_invoke<Opts, T, hash_info<T>>(value, ctx, it, end);
2367
                     if (bool(ctx.error)) [[unlikely]]
2368
                        return;
2369
                  }
2370
               }
2371
40.7k
               else {
2372
                  // For types like std::map, std::unordered_map
2373
2374
40.7k
                  auto reading = [&](auto&& key) {
2375
40.7k
                     if constexpr (Opts.partial_read) {
2376
40.7k
                        if (auto element = value.find(key); element != value.end()) {
2377
40.7k
                           ++read_count;
2378
40.7k
                           parse<JSON>::op<ws_handled<Opts>()>(element->second, ctx, it, end);
2379
40.7k
                        }
2380
40.7k
                        else {
2381
40.7k
                           skip_value<JSON>::op<Opts>(ctx, it, end);
2382
40.7k
                        }
2383
40.7k
                     }
2384
40.7k
                     else {
2385
40.7k
                        parse<JSON>::op<ws_handled<Opts>()>(value[key], ctx, it, end);
2386
40.7k
                     }
2387
40.7k
                  };
2388
2389
                  // using Key = std::conditional_t<heterogeneous_map<T>, sv, typename T::key_type>;
2390
40.7k
                  using Key = typename T::key_type;
2391
40.7k
                  if constexpr (std::is_same_v<Key, std::string>) {
2392
40.7k
                     static thread_local Key key;
2393
40.7k
                     parse<JSON>::op<Opts>(key, ctx, it, end);
2394
40.7k
                     if (bool(ctx.error)) [[unlikely]]
2395
432
                        return;
2396
2397
40.2k
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2398
183
                        return;
2399
183
                     }
2400
2401
40.1k
                     reading(key);
2402
                     if constexpr (Opts.partial_read) {
2403
                        if (read_count == value.size()) {
2404
                           return;
2405
                        }
2406
                     }
2407
40.1k
                     if (bool(ctx.error)) [[unlikely]]
2408
5.11k
                        return;
2409
                  }
2410
                  else if constexpr (str_t<Key>) {
2411
                     Key key;
2412
                     parse<JSON>::op<Opts>(key, ctx, it, end);
2413
                     if (bool(ctx.error)) [[unlikely]]
2414
                        return;
2415
2416
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2417
                        return;
2418
                     }
2419
2420
                     reading(key);
2421
                     if constexpr (Opts.partial_read) {
2422
                        if (read_count == value.size()) {
2423
                           return;
2424
                        }
2425
                     }
2426
                     if (bool(ctx.error)) [[unlikely]]
2427
                        return;
2428
                  }
2429
                  else {
2430
                     Key key_value{};
2431
                     if constexpr (glaze_enum_t<Key>) {
2432
                        parse<JSON>::op<Opts>(key_value, ctx, it, end);
2433
                     }
2434
                     else if constexpr (std::is_arithmetic_v<Key>) {
2435
                        // prefer over quoted_t below to avoid double parsing of quoted_t
2436
                        parse<JSON>::op<opt_true<Opts, &opts::quoted_num>>(key_value, ctx, it, end);
2437
                     }
2438
                     else {
2439
                        parse<JSON>::op<opt_false<Opts, &opts::raw_string>>(quoted_t<Key>{key_value}, ctx, it, end);
2440
                     }
2441
                     if (bool(ctx.error)) [[unlikely]]
2442
                        return;
2443
2444
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2445
                        return;
2446
                     }
2447
2448
                     reading(key_value);
2449
                     if constexpr (Opts.partial_read) {
2450
                        if (read_count == value.size()) {
2451
                           return;
2452
                        }
2453
                     }
2454
                     if (bool(ctx.error)) [[unlikely]]
2455
                        return;
2456
                  }
2457
40.7k
               }
2458
40.7k
               if (skip_ws<Opts>(ctx, it, end)) {
2459
0
                  return;
2460
0
               }
2461
40.7k
            }
2462
7.86k
         }
2463
7.86k
      }
2464
   };
2465
2466
   template <is_variant T>
2467
   consteval auto variant_is_auto_deducible()
2468
   {
2469
      // Contains at most one each of the basic json types bool, numeric, string, object, array
2470
      // If all objects are meta-objects then we can attempt to deduce them as well either through a type tag or
2471
      // unique combinations of keys
2472
      int bools{}, numbers{}, strings{}, objects{}, meta_objects{}, arrays{};
2473
      constexpr auto N = std::variant_size_v<T>;
2474
0
      for_each<N>([&]<auto I>() {
2475
0
         using V = std::decay_t<std::variant_alternative_t<I, T>>;
2476
0
         // ICE workaround
2477
0
         bools += bool_t<V>;
2478
0
         numbers += num_t<V>;
2479
0
         strings += str_t<V>;
2480
0
         strings += glaze_enum_t<V>;
2481
0
         objects += pair_t<V>;
2482
0
         objects += (writable_map_t<V> || readable_map_t<V> || is_memory_object<V>);
2483
0
         objects += glaze_object_t<V>;
2484
0
         meta_objects += glaze_object_t<V> || reflectable<V> || is_memory_object<V>;
2485
0
         arrays += glaze_array_t<V>;
2486
0
         arrays += array_t<V>;
2487
0
         // TODO null
2488
0
      });
Unexecuted instantiation: _ZZN3glz25variant_is_auto_deducibleITkNS_10is_variantENSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_6json_tENS6_ISA_EEEENS1_3mapIS8_SA_NS1_4lessIvEENS6_INS1_4pairIKS8_SA_EEEEEEEEEEEDavENKUlTnDavE_clILm5EEEDav
Unexecuted instantiation: _ZZN3glz25variant_is_auto_deducibleITkNS_10is_variantENSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_6json_tENS6_ISA_EEEENS1_3mapIS8_SA_NS1_4lessIvEENS6_INS1_4pairIKS8_SA_EEEEEEEEEEEDavENKUlTnDavE_clILm4EEEDav
Unexecuted instantiation: _ZZN3glz25variant_is_auto_deducibleITkNS_10is_variantENSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_6json_tENS6_ISA_EEEENS1_3mapIS8_SA_NS1_4lessIvEENS6_INS1_4pairIKS8_SA_EEEEEEEEEEEDavENKUlTnDavE_clILm3EEEDav
Unexecuted instantiation: _ZZN3glz25variant_is_auto_deducibleITkNS_10is_variantENSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_6json_tENS6_ISA_EEEENS1_3mapIS8_SA_NS1_4lessIvEENS6_INS1_4pairIKS8_SA_EEEEEEEEEEEDavENKUlTnDavE_clILm2EEEDav
Unexecuted instantiation: _ZZN3glz25variant_is_auto_deducibleITkNS_10is_variantENSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_6json_tENS6_ISA_EEEENS1_3mapIS8_SA_NS1_4lessIvEENS6_INS1_4pairIKS8_SA_EEEEEEEEEEEDavENKUlTnDavE_clILm1EEEDav
Unexecuted instantiation: _ZZN3glz25variant_is_auto_deducibleITkNS_10is_variantENSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_6json_tENS6_ISA_EEEENS1_3mapIS8_SA_NS1_4lessIvEENS6_INS1_4pairIKS8_SA_EEEEEEEEEEEDavENKUlTnDavE_clILm0EEEDav
2489
      return bools < 2 && numbers < 2 && strings < 2 && (objects < 2 || meta_objects == objects) && arrays < 2;
2490
   }
2491
2492
   template <class>
2493
   struct variant_types;
2494
2495
   template <class... Ts>
2496
   struct variant_types<std::variant<Ts...>>
2497
   {
2498
      // TODO: this way of filtering types is compile time intensive.
2499
      using bool_types =
2500
         decltype(tuplet::tuple_cat(std::conditional_t<bool_t<remove_meta_wrapper_t<Ts>>, tuple<Ts>, tuple<>>{}...));
2501
      using number_types =
2502
         decltype(tuplet::tuple_cat(std::conditional_t<num_t<remove_meta_wrapper_t<Ts>>, tuple<Ts>, tuple<>>{}...));
2503
      using string_types = decltype(tuplet::tuple_cat( // glaze_enum_t remove_meta_wrapper_t supports constexpr
2504
                                                       // types while the other supports non const
2505
         std::conditional_t < str_t<remove_meta_wrapper_t<Ts>> || glaze_enum_t<remove_meta_wrapper_t<Ts>> ||
2506
            glaze_enum_t<Ts>,
2507
         tuple<Ts>, tuple < >> {}...));
2508
      using object_types = decltype(tuplet::tuple_cat(std::conditional_t<json_object<Ts>, tuple<Ts>, tuple<>>{}...));
2509
      using array_types = decltype(tuplet::tuple_cat(
2510
         std::conditional_t < array_t<remove_meta_wrapper_t<Ts>> || glaze_array_t<Ts>, tuple<Ts>, tuple < >> {}...));
2511
      using nullable_types = decltype(tuplet::tuple_cat(std::conditional_t<null_t<Ts>, tuple<Ts>, tuple<>>{}...));
2512
      using nullable_objects =
2513
         decltype(tuplet::tuple_cat(std::conditional_t<is_memory_object<Ts>, tuple<Ts>, tuple<>>{}...));
2514
   };
2515
2516
   // post process output of variant_types
2517
   template <class>
2518
   struct tuple_types;
2519
2520
   template <class... Ts>
2521
   struct tuple_types<tuple<Ts...>>
2522
   {
2523
      using glaze_const_types =
2524
         decltype(tuplet::tuple_cat(std::conditional_t<glaze_const_value_t<Ts>, tuple<Ts>, tuple<>>{}...));
2525
      using glaze_non_const_types =
2526
         decltype(tuplet::tuple_cat(std::conditional_t<!glaze_const_value_t<Ts>, tuple<Ts>, tuple<>>{}...));
2527
   };
2528
2529
   template <class>
2530
   struct variant_type_count;
2531
2532
   template <class... Ts>
2533
   struct variant_type_count<std::variant<Ts...>>
2534
   {
2535
      using V = variant_types<std::variant<Ts...>>;
2536
      static constexpr auto n_bool = glz::tuple_size_v<typename V::bool_types>;
2537
      static constexpr auto n_number = glz::tuple_size_v<typename V::number_types>;
2538
      static constexpr auto n_string = glz::tuple_size_v<typename V::string_types>;
2539
      static constexpr auto n_nullable_object = glz::tuple_size_v<typename V::nullable_objects>;
2540
      static constexpr auto n_object = glz::tuple_size_v<typename V::object_types> + n_nullable_object;
2541
      static constexpr auto n_array = glz::tuple_size_v<typename V::array_types>;
2542
      static constexpr auto n_null = glz::tuple_size_v<typename V::nullable_types>;
2543
   };
2544
2545
   template <class Tuple>
2546
   struct process_arithmetic_boolean_string_or_array
2547
   {
2548
      template <auto Options>
2549
      static void op(auto&& value, is_context auto&& ctx, auto&& it, auto&& end)
2550
5.26M
      {
2551
         if constexpr (glz::tuple_size_v<Tuple> < 1) {
2552
            ctx.error = error_code::no_matching_variant_type;
2553
         }
2554
5.26M
         else {
2555
5.26M
            using const_glaze_types = typename tuple_types<Tuple>::glaze_const_types;
2556
5.26M
            bool found_match{};
2557
5.26M
            for_each<glz::tuple_size_v<const_glaze_types>>([&]<size_t I>() {
2558
5.26M
               if (found_match) {
2559
5.26M
                  return;
2560
5.26M
               }
2561
5.26M
               using V = glz::tuple_element_t<I, const_glaze_types>;
2562
               // run time substitute to compare to const value
2563
5.26M
               std::remove_const_t<std::remove_pointer_t<std::remove_const_t<meta_wrapper_t<V>>>> substitute{};
2564
5.26M
               auto copy_it{it};
2565
5.26M
               parse<JSON>::op<ws_handled<Options>()>(substitute, ctx, it, end);
2566
5.26M
               static constexpr auto const_value{*meta_wrapper_v<V>};
2567
5.26M
               if (substitute == const_value) {
2568
5.26M
                  found_match = true;
2569
5.26M
                  if (!std::holds_alternative<V>(value)) {
2570
5.26M
                     value = V{};
2571
5.26M
                  }
2572
5.26M
               }
2573
5.26M
               else {
2574
5.26M
                  if constexpr (not Options.null_terminated) {
2575
5.26M
                     if (ctx.error == error_code::end_reached) {
2576
                        // reset the context for next attempt
2577
5.26M
                        ctx.error = error_code::none;
2578
5.26M
                     }
2579
5.26M
                  }
2580
5.26M
                  it = copy_it;
2581
5.26M
               }
2582
5.26M
            });
2583
5.26M
            if (found_match) {
2584
0
               return;
2585
0
            }
2586
2587
5.26M
            using non_const_types = typename tuple_types<Tuple>::glaze_non_const_types;
2588
5.26M
            if constexpr (glz::tuple_size_v < non_const_types >> 0) {
2589
5.26M
               using V = glz::tuple_element_t<0, non_const_types>;
2590
5.26M
               if (!std::holds_alternative<V>(value)) value = V{};
2591
5.26M
               parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
2592
            }
2593
            else {
2594
               ctx.error = error_code::no_matching_variant_type;
2595
            }
2596
5.26M
         }
2597
5.26M
      }
_ZN3glz42process_arithmetic_boolean_string_or_arrayINS_5tupleIJNSt3__16vectorINS_6json_tENS2_9allocatorIS4_EEEEEEEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1EEERNS2_7variantIJDndNS2_12basic_stringIcNS2_11char_traitsIcEENS5_IcEEEEbS7_NS2_3mapISH_S4_NS2_4lessIvEENS5_INS2_4pairIKSH_S4_EEEEEEEEETkNS_10is_contextERNS_7contextERPKcSW_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
2550
17.0k
      {
2551
         if constexpr (glz::tuple_size_v<Tuple> < 1) {
2552
            ctx.error = error_code::no_matching_variant_type;
2553
         }
2554
17.0k
         else {
2555
17.0k
            using const_glaze_types = typename tuple_types<Tuple>::glaze_const_types;
2556
17.0k
            bool found_match{};
2557
17.0k
            for_each<glz::tuple_size_v<const_glaze_types>>([&]<size_t I>() {
2558
17.0k
               if (found_match) {
2559
17.0k
                  return;
2560
17.0k
               }
2561
17.0k
               using V = glz::tuple_element_t<I, const_glaze_types>;
2562
               // run time substitute to compare to const value
2563
17.0k
               std::remove_const_t<std::remove_pointer_t<std::remove_const_t<meta_wrapper_t<V>>>> substitute{};
2564
17.0k
               auto copy_it{it};
2565
17.0k
               parse<JSON>::op<ws_handled<Options>()>(substitute, ctx, it, end);
2566
17.0k
               static constexpr auto const_value{*meta_wrapper_v<V>};
2567
17.0k
               if (substitute == const_value) {
2568
17.0k
                  found_match = true;
2569
17.0k
                  if (!std::holds_alternative<V>(value)) {
2570
17.0k
                     value = V{};
2571
17.0k
                  }
2572
17.0k
               }
2573
17.0k
               else {
2574
17.0k
                  if constexpr (not Options.null_terminated) {
2575
17.0k
                     if (ctx.error == error_code::end_reached) {
2576
                        // reset the context for next attempt
2577
17.0k
                        ctx.error = error_code::none;
2578
17.0k
                     }
2579
17.0k
                  }
2580
17.0k
                  it = copy_it;
2581
17.0k
               }
2582
17.0k
            });
2583
17.0k
            if (found_match) {
2584
0
               return;
2585
0
            }
2586
2587
17.0k
            using non_const_types = typename tuple_types<Tuple>::glaze_non_const_types;
2588
17.0k
            if constexpr (glz::tuple_size_v < non_const_types >> 0) {
2589
17.0k
               using V = glz::tuple_element_t<0, non_const_types>;
2590
17.0k
               if (!std::holds_alternative<V>(value)) value = V{};
2591
17.0k
               parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
2592
            }
2593
            else {
2594
               ctx.error = error_code::no_matching_variant_type;
2595
            }
2596
17.0k
         }
2597
17.0k
      }
_ZN3glz42process_arithmetic_boolean_string_or_arrayINS_5tupleIJNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEEEEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1EEERNS2_7variantIJDndS8_bNS2_6vectorINS_6json_tENS6_ISF_EEEENS2_3mapIS8_SF_NS2_4lessIvEENS6_INS2_4pairIKS8_SF_EEEEEEEEETkNS_10is_contextERNS_7contextERPKcSW_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
2550
4.47k
      {
2551
         if constexpr (glz::tuple_size_v<Tuple> < 1) {
2552
            ctx.error = error_code::no_matching_variant_type;
2553
         }
2554
4.47k
         else {
2555
4.47k
            using const_glaze_types = typename tuple_types<Tuple>::glaze_const_types;
2556
4.47k
            bool found_match{};
2557
4.47k
            for_each<glz::tuple_size_v<const_glaze_types>>([&]<size_t I>() {
2558
4.47k
               if (found_match) {
2559
4.47k
                  return;
2560
4.47k
               }
2561
4.47k
               using V = glz::tuple_element_t<I, const_glaze_types>;
2562
               // run time substitute to compare to const value
2563
4.47k
               std::remove_const_t<std::remove_pointer_t<std::remove_const_t<meta_wrapper_t<V>>>> substitute{};
2564
4.47k
               auto copy_it{it};
2565
4.47k
               parse<JSON>::op<ws_handled<Options>()>(substitute, ctx, it, end);
2566
4.47k
               static constexpr auto const_value{*meta_wrapper_v<V>};
2567
4.47k
               if (substitute == const_value) {
2568
4.47k
                  found_match = true;
2569
4.47k
                  if (!std::holds_alternative<V>(value)) {
2570
4.47k
                     value = V{};
2571
4.47k
                  }
2572
4.47k
               }
2573
4.47k
               else {
2574
4.47k
                  if constexpr (not Options.null_terminated) {
2575
4.47k
                     if (ctx.error == error_code::end_reached) {
2576
                        // reset the context for next attempt
2577
4.47k
                        ctx.error = error_code::none;
2578
4.47k
                     }
2579
4.47k
                  }
2580
4.47k
                  it = copy_it;
2581
4.47k
               }
2582
4.47k
            });
2583
4.47k
            if (found_match) {
2584
0
               return;
2585
0
            }
2586
2587
4.47k
            using non_const_types = typename tuple_types<Tuple>::glaze_non_const_types;
2588
4.47k
            if constexpr (glz::tuple_size_v < non_const_types >> 0) {
2589
4.47k
               using V = glz::tuple_element_t<0, non_const_types>;
2590
4.47k
               if (!std::holds_alternative<V>(value)) value = V{};
2591
4.47k
               parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
2592
            }
2593
            else {
2594
               ctx.error = error_code::no_matching_variant_type;
2595
            }
2596
4.47k
         }
2597
4.47k
      }
_ZN3glz42process_arithmetic_boolean_string_or_arrayINS_5tupleIJbEEEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1EEERNSt3__17variantIJDndNS6_12basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEEbNS6_6vectorINS_6json_tENSB_ISF_EEEENS6_3mapISD_SF_NS6_4lessIvEENSB_INS6_4pairIKSD_SF_EEEEEEEEETkNS_10is_contextERNS_7contextERPKcSW_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
2550
1.31k
      {
2551
         if constexpr (glz::tuple_size_v<Tuple> < 1) {
2552
            ctx.error = error_code::no_matching_variant_type;
2553
         }
2554
1.31k
         else {
2555
1.31k
            using const_glaze_types = typename tuple_types<Tuple>::glaze_const_types;
2556
1.31k
            bool found_match{};
2557
1.31k
            for_each<glz::tuple_size_v<const_glaze_types>>([&]<size_t I>() {
2558
1.31k
               if (found_match) {
2559
1.31k
                  return;
2560
1.31k
               }
2561
1.31k
               using V = glz::tuple_element_t<I, const_glaze_types>;
2562
               // run time substitute to compare to const value
2563
1.31k
               std::remove_const_t<std::remove_pointer_t<std::remove_const_t<meta_wrapper_t<V>>>> substitute{};
2564
1.31k
               auto copy_it{it};
2565
1.31k
               parse<JSON>::op<ws_handled<Options>()>(substitute, ctx, it, end);
2566
1.31k
               static constexpr auto const_value{*meta_wrapper_v<V>};
2567
1.31k
               if (substitute == const_value) {
2568
1.31k
                  found_match = true;
2569
1.31k
                  if (!std::holds_alternative<V>(value)) {
2570
1.31k
                     value = V{};
2571
1.31k
                  }
2572
1.31k
               }
2573
1.31k
               else {
2574
1.31k
                  if constexpr (not Options.null_terminated) {
2575
1.31k
                     if (ctx.error == error_code::end_reached) {
2576
                        // reset the context for next attempt
2577
1.31k
                        ctx.error = error_code::none;
2578
1.31k
                     }
2579
1.31k
                  }
2580
1.31k
                  it = copy_it;
2581
1.31k
               }
2582
1.31k
            });
2583
1.31k
            if (found_match) {
2584
0
               return;
2585
0
            }
2586
2587
1.31k
            using non_const_types = typename tuple_types<Tuple>::glaze_non_const_types;
2588
1.31k
            if constexpr (glz::tuple_size_v < non_const_types >> 0) {
2589
1.31k
               using V = glz::tuple_element_t<0, non_const_types>;
2590
1.31k
               if (!std::holds_alternative<V>(value)) value = V{};
2591
1.31k
               parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
2592
            }
2593
            else {
2594
               ctx.error = error_code::no_matching_variant_type;
2595
            }
2596
1.31k
         }
2597
1.31k
      }
_ZN3glz42process_arithmetic_boolean_string_or_arrayINS_5tupleIJdEEEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1EEERNSt3__17variantIJDndNS6_12basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEEbNS6_6vectorINS_6json_tENSB_ISF_EEEENS6_3mapISD_SF_NS6_4lessIvEENSB_INS6_4pairIKSD_SF_EEEEEEEEETkNS_10is_contextERNS_7contextERPKcSW_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
2550
1.73M
      {
2551
         if constexpr (glz::tuple_size_v<Tuple> < 1) {
2552
            ctx.error = error_code::no_matching_variant_type;
2553
         }
2554
1.73M
         else {
2555
1.73M
            using const_glaze_types = typename tuple_types<Tuple>::glaze_const_types;
2556
1.73M
            bool found_match{};
2557
1.73M
            for_each<glz::tuple_size_v<const_glaze_types>>([&]<size_t I>() {
2558
1.73M
               if (found_match) {
2559
1.73M
                  return;
2560
1.73M
               }
2561
1.73M
               using V = glz::tuple_element_t<I, const_glaze_types>;
2562
               // run time substitute to compare to const value
2563
1.73M
               std::remove_const_t<std::remove_pointer_t<std::remove_const_t<meta_wrapper_t<V>>>> substitute{};
2564
1.73M
               auto copy_it{it};
2565
1.73M
               parse<JSON>::op<ws_handled<Options>()>(substitute, ctx, it, end);
2566
1.73M
               static constexpr auto const_value{*meta_wrapper_v<V>};
2567
1.73M
               if (substitute == const_value) {
2568
1.73M
                  found_match = true;
2569
1.73M
                  if (!std::holds_alternative<V>(value)) {
2570
1.73M
                     value = V{};
2571
1.73M
                  }
2572
1.73M
               }
2573
1.73M
               else {
2574
1.73M
                  if constexpr (not Options.null_terminated) {
2575
1.73M
                     if (ctx.error == error_code::end_reached) {
2576
                        // reset the context for next attempt
2577
1.73M
                        ctx.error = error_code::none;
2578
1.73M
                     }
2579
1.73M
                  }
2580
1.73M
                  it = copy_it;
2581
1.73M
               }
2582
1.73M
            });
2583
1.73M
            if (found_match) {
2584
0
               return;
2585
0
            }
2586
2587
1.73M
            using non_const_types = typename tuple_types<Tuple>::glaze_non_const_types;
2588
1.73M
            if constexpr (glz::tuple_size_v < non_const_types >> 0) {
2589
1.73M
               using V = glz::tuple_element_t<0, non_const_types>;
2590
1.73M
               if (!std::holds_alternative<V>(value)) value = V{};
2591
1.73M
               parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
2592
            }
2593
            else {
2594
               ctx.error = error_code::no_matching_variant_type;
2595
            }
2596
1.73M
         }
2597
1.73M
      }
_ZN3glz42process_arithmetic_boolean_string_or_arrayINS_5tupleIJNSt3__16vectorINS_6json_tENS2_9allocatorIS4_EEEEEEEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1EEERNS2_7variantIJDndNS2_12basic_stringIcNS2_11char_traitsIcEENS5_IcEEEEbS7_NS2_3mapISH_S4_NS2_4lessIvEENS5_INS2_4pairIKSH_S4_EEEEEEEEETkNS_10is_contextERNS_7contextERPKcSW_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
2550
17.0k
      {
2551
         if constexpr (glz::tuple_size_v<Tuple> < 1) {
2552
            ctx.error = error_code::no_matching_variant_type;
2553
         }
2554
17.0k
         else {
2555
17.0k
            using const_glaze_types = typename tuple_types<Tuple>::glaze_const_types;
2556
17.0k
            bool found_match{};
2557
17.0k
            for_each<glz::tuple_size_v<const_glaze_types>>([&]<size_t I>() {
2558
17.0k
               if (found_match) {
2559
17.0k
                  return;
2560
17.0k
               }
2561
17.0k
               using V = glz::tuple_element_t<I, const_glaze_types>;
2562
               // run time substitute to compare to const value
2563
17.0k
               std::remove_const_t<std::remove_pointer_t<std::remove_const_t<meta_wrapper_t<V>>>> substitute{};
2564
17.0k
               auto copy_it{it};
2565
17.0k
               parse<JSON>::op<ws_handled<Options>()>(substitute, ctx, it, end);
2566
17.0k
               static constexpr auto const_value{*meta_wrapper_v<V>};
2567
17.0k
               if (substitute == const_value) {
2568
17.0k
                  found_match = true;
2569
17.0k
                  if (!std::holds_alternative<V>(value)) {
2570
17.0k
                     value = V{};
2571
17.0k
                  }
2572
17.0k
               }
2573
17.0k
               else {
2574
17.0k
                  if constexpr (not Options.null_terminated) {
2575
17.0k
                     if (ctx.error == error_code::end_reached) {
2576
                        // reset the context for next attempt
2577
17.0k
                        ctx.error = error_code::none;
2578
17.0k
                     }
2579
17.0k
                  }
2580
17.0k
                  it = copy_it;
2581
17.0k
               }
2582
17.0k
            });
2583
17.0k
            if (found_match) {
2584
0
               return;
2585
0
            }
2586
2587
17.0k
            using non_const_types = typename tuple_types<Tuple>::glaze_non_const_types;
2588
17.0k
            if constexpr (glz::tuple_size_v < non_const_types >> 0) {
2589
17.0k
               using V = glz::tuple_element_t<0, non_const_types>;
2590
17.0k
               if (!std::holds_alternative<V>(value)) value = V{};
2591
17.0k
               parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
2592
            }
2593
            else {
2594
               ctx.error = error_code::no_matching_variant_type;
2595
            }
2596
17.0k
         }
2597
17.0k
      }
_ZN3glz42process_arithmetic_boolean_string_or_arrayINS_5tupleIJNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEEEEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1EEERNS2_7variantIJDndS8_bNS2_6vectorINS_6json_tENS6_ISF_EEEENS2_3mapIS8_SF_NS2_4lessIvEENS6_INS2_4pairIKS8_SF_EEEEEEEEETkNS_10is_contextERNS_7contextERPKcSW_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
2550
4.47k
      {
2551
         if constexpr (glz::tuple_size_v<Tuple> < 1) {
2552
            ctx.error = error_code::no_matching_variant_type;
2553
         }
2554
4.47k
         else {
2555
4.47k
            using const_glaze_types = typename tuple_types<Tuple>::glaze_const_types;
2556
4.47k
            bool found_match{};
2557
4.47k
            for_each<glz::tuple_size_v<const_glaze_types>>([&]<size_t I>() {
2558
4.47k
               if (found_match) {
2559
4.47k
                  return;
2560
4.47k
               }
2561
4.47k
               using V = glz::tuple_element_t<I, const_glaze_types>;
2562
               // run time substitute to compare to const value
2563
4.47k
               std::remove_const_t<std::remove_pointer_t<std::remove_const_t<meta_wrapper_t<V>>>> substitute{};
2564
4.47k
               auto copy_it{it};
2565
4.47k
               parse<JSON>::op<ws_handled<Options>()>(substitute, ctx, it, end);
2566
4.47k
               static constexpr auto const_value{*meta_wrapper_v<V>};
2567
4.47k
               if (substitute == const_value) {
2568
4.47k
                  found_match = true;
2569
4.47k
                  if (!std::holds_alternative<V>(value)) {
2570
4.47k
                     value = V{};
2571
4.47k
                  }
2572
4.47k
               }
2573
4.47k
               else {
2574
4.47k
                  if constexpr (not Options.null_terminated) {
2575
4.47k
                     if (ctx.error == error_code::end_reached) {
2576
                        // reset the context for next attempt
2577
4.47k
                        ctx.error = error_code::none;
2578
4.47k
                     }
2579
4.47k
                  }
2580
4.47k
                  it = copy_it;
2581
4.47k
               }
2582
4.47k
            });
2583
4.47k
            if (found_match) {
2584
0
               return;
2585
0
            }
2586
2587
4.47k
            using non_const_types = typename tuple_types<Tuple>::glaze_non_const_types;
2588
4.47k
            if constexpr (glz::tuple_size_v < non_const_types >> 0) {
2589
4.47k
               using V = glz::tuple_element_t<0, non_const_types>;
2590
4.47k
               if (!std::holds_alternative<V>(value)) value = V{};
2591
4.47k
               parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
2592
            }
2593
            else {
2594
               ctx.error = error_code::no_matching_variant_type;
2595
            }
2596
4.47k
         }
2597
4.47k
      }
_ZN3glz42process_arithmetic_boolean_string_or_arrayINS_5tupleIJbEEEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1EEERNSt3__17variantIJDndNS6_12basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEEbNS6_6vectorINS_6json_tENSB_ISF_EEEENS6_3mapISD_SF_NS6_4lessIvEENSB_INS6_4pairIKSD_SF_EEEEEEEEETkNS_10is_contextERNS_7contextERPKcSW_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
2550
1.31k
      {
2551
         if constexpr (glz::tuple_size_v<Tuple> < 1) {
2552
            ctx.error = error_code::no_matching_variant_type;
2553
         }
2554
1.31k
         else {
2555
1.31k
            using const_glaze_types = typename tuple_types<Tuple>::glaze_const_types;
2556
1.31k
            bool found_match{};
2557
1.31k
            for_each<glz::tuple_size_v<const_glaze_types>>([&]<size_t I>() {
2558
1.31k
               if (found_match) {
2559
1.31k
                  return;
2560
1.31k
               }
2561
1.31k
               using V = glz::tuple_element_t<I, const_glaze_types>;
2562
               // run time substitute to compare to const value
2563
1.31k
               std::remove_const_t<std::remove_pointer_t<std::remove_const_t<meta_wrapper_t<V>>>> substitute{};
2564
1.31k
               auto copy_it{it};
2565
1.31k
               parse<JSON>::op<ws_handled<Options>()>(substitute, ctx, it, end);
2566
1.31k
               static constexpr auto const_value{*meta_wrapper_v<V>};
2567
1.31k
               if (substitute == const_value) {
2568
1.31k
                  found_match = true;
2569
1.31k
                  if (!std::holds_alternative<V>(value)) {
2570
1.31k
                     value = V{};
2571
1.31k
                  }
2572
1.31k
               }
2573
1.31k
               else {
2574
1.31k
                  if constexpr (not Options.null_terminated) {
2575
1.31k
                     if (ctx.error == error_code::end_reached) {
2576
                        // reset the context for next attempt
2577
1.31k
                        ctx.error = error_code::none;
2578
1.31k
                     }
2579
1.31k
                  }
2580
1.31k
                  it = copy_it;
2581
1.31k
               }
2582
1.31k
            });
2583
1.31k
            if (found_match) {
2584
0
               return;
2585
0
            }
2586
2587
1.31k
            using non_const_types = typename tuple_types<Tuple>::glaze_non_const_types;
2588
1.31k
            if constexpr (glz::tuple_size_v < non_const_types >> 0) {
2589
1.31k
               using V = glz::tuple_element_t<0, non_const_types>;
2590
1.31k
               if (!std::holds_alternative<V>(value)) value = V{};
2591
1.31k
               parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
2592
            }
2593
            else {
2594
               ctx.error = error_code::no_matching_variant_type;
2595
            }
2596
1.31k
         }
2597
1.31k
      }
_ZN3glz42process_arithmetic_boolean_string_or_arrayINS_5tupleIJdEEEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1EEERNSt3__17variantIJDndNS6_12basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEEbNS6_6vectorINS_6json_tENSB_ISF_EEEENS6_3mapISD_SF_NS6_4lessIvEENSB_INS6_4pairIKSD_SF_EEEEEEEEETkNS_10is_contextERNS_7contextERPKcSW_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
2550
1.73M
      {
2551
         if constexpr (glz::tuple_size_v<Tuple> < 1) {
2552
            ctx.error = error_code::no_matching_variant_type;
2553
         }
2554
1.73M
         else {
2555
1.73M
            using const_glaze_types = typename tuple_types<Tuple>::glaze_const_types;
2556
1.73M
            bool found_match{};
2557
1.73M
            for_each<glz::tuple_size_v<const_glaze_types>>([&]<size_t I>() {
2558
1.73M
               if (found_match) {
2559
1.73M
                  return;
2560
1.73M
               }
2561
1.73M
               using V = glz::tuple_element_t<I, const_glaze_types>;
2562
               // run time substitute to compare to const value
2563
1.73M
               std::remove_const_t<std::remove_pointer_t<std::remove_const_t<meta_wrapper_t<V>>>> substitute{};
2564
1.73M
               auto copy_it{it};
2565
1.73M
               parse<JSON>::op<ws_handled<Options>()>(substitute, ctx, it, end);
2566
1.73M
               static constexpr auto const_value{*meta_wrapper_v<V>};
2567
1.73M
               if (substitute == const_value) {
2568
1.73M
                  found_match = true;
2569
1.73M
                  if (!std::holds_alternative<V>(value)) {
2570
1.73M
                     value = V{};
2571
1.73M
                  }
2572
1.73M
               }
2573
1.73M
               else {
2574
1.73M
                  if constexpr (not Options.null_terminated) {
2575
1.73M
                     if (ctx.error == error_code::end_reached) {
2576
                        // reset the context for next attempt
2577
1.73M
                        ctx.error = error_code::none;
2578
1.73M
                     }
2579
1.73M
                  }
2580
1.73M
                  it = copy_it;
2581
1.73M
               }
2582
1.73M
            });
2583
1.73M
            if (found_match) {
2584
0
               return;
2585
0
            }
2586
2587
1.73M
            using non_const_types = typename tuple_types<Tuple>::glaze_non_const_types;
2588
1.73M
            if constexpr (glz::tuple_size_v < non_const_types >> 0) {
2589
1.73M
               using V = glz::tuple_element_t<0, non_const_types>;
2590
1.73M
               if (!std::holds_alternative<V>(value)) value = V{};
2591
1.73M
               parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
2592
            }
2593
            else {
2594
               ctx.error = error_code::no_matching_variant_type;
2595
            }
2596
1.73M
         }
2597
1.73M
      }
_ZN3glz42process_arithmetic_boolean_string_or_arrayINS_5tupleIJNSt3__16vectorINS_6json_tENS2_9allocatorIS4_EEEEEEEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEERNS2_7variantIJDndNS2_12basic_stringIcNS2_11char_traitsIcEENS5_IcEEEEbS7_NS2_3mapISH_S4_NS2_4lessIvEENS5_INS2_4pairIKSH_S4_EEEEEEEEETkNS_10is_contextERNS_7contextERPKcSW_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
2550
17.0k
      {
2551
         if constexpr (glz::tuple_size_v<Tuple> < 1) {
2552
            ctx.error = error_code::no_matching_variant_type;
2553
         }
2554
17.0k
         else {
2555
17.0k
            using const_glaze_types = typename tuple_types<Tuple>::glaze_const_types;
2556
17.0k
            bool found_match{};
2557
17.0k
            for_each<glz::tuple_size_v<const_glaze_types>>([&]<size_t I>() {
2558
17.0k
               if (found_match) {
2559
17.0k
                  return;
2560
17.0k
               }
2561
17.0k
               using V = glz::tuple_element_t<I, const_glaze_types>;
2562
               // run time substitute to compare to const value
2563
17.0k
               std::remove_const_t<std::remove_pointer_t<std::remove_const_t<meta_wrapper_t<V>>>> substitute{};
2564
17.0k
               auto copy_it{it};
2565
17.0k
               parse<JSON>::op<ws_handled<Options>()>(substitute, ctx, it, end);
2566
17.0k
               static constexpr auto const_value{*meta_wrapper_v<V>};
2567
17.0k
               if (substitute == const_value) {
2568
17.0k
                  found_match = true;
2569
17.0k
                  if (!std::holds_alternative<V>(value)) {
2570
17.0k
                     value = V{};
2571
17.0k
                  }
2572
17.0k
               }
2573
17.0k
               else {
2574
17.0k
                  if constexpr (not Options.null_terminated) {
2575
17.0k
                     if (ctx.error == error_code::end_reached) {
2576
                        // reset the context for next attempt
2577
17.0k
                        ctx.error = error_code::none;
2578
17.0k
                     }
2579
17.0k
                  }
2580
17.0k
                  it = copy_it;
2581
17.0k
               }
2582
17.0k
            });
2583
17.0k
            if (found_match) {
2584
0
               return;
2585
0
            }
2586
2587
17.0k
            using non_const_types = typename tuple_types<Tuple>::glaze_non_const_types;
2588
17.0k
            if constexpr (glz::tuple_size_v < non_const_types >> 0) {
2589
17.0k
               using V = glz::tuple_element_t<0, non_const_types>;
2590
17.0k
               if (!std::holds_alternative<V>(value)) value = V{};
2591
17.0k
               parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
2592
            }
2593
            else {
2594
               ctx.error = error_code::no_matching_variant_type;
2595
            }
2596
17.0k
         }
2597
17.0k
      }
_ZN3glz42process_arithmetic_boolean_string_or_arrayINS_5tupleIJNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEEEEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEERNS2_7variantIJDndS8_bNS2_6vectorINS_6json_tENS6_ISF_EEEENS2_3mapIS8_SF_NS2_4lessIvEENS6_INS2_4pairIKS8_SF_EEEEEEEEETkNS_10is_contextERNS_7contextERPKcSW_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
2550
4.46k
      {
2551
         if constexpr (glz::tuple_size_v<Tuple> < 1) {
2552
            ctx.error = error_code::no_matching_variant_type;
2553
         }
2554
4.46k
         else {
2555
4.46k
            using const_glaze_types = typename tuple_types<Tuple>::glaze_const_types;
2556
4.46k
            bool found_match{};
2557
4.46k
            for_each<glz::tuple_size_v<const_glaze_types>>([&]<size_t I>() {
2558
4.46k
               if (found_match) {
2559
4.46k
                  return;
2560
4.46k
               }
2561
4.46k
               using V = glz::tuple_element_t<I, const_glaze_types>;
2562
               // run time substitute to compare to const value
2563
4.46k
               std::remove_const_t<std::remove_pointer_t<std::remove_const_t<meta_wrapper_t<V>>>> substitute{};
2564
4.46k
               auto copy_it{it};
2565
4.46k
               parse<JSON>::op<ws_handled<Options>()>(substitute, ctx, it, end);
2566
4.46k
               static constexpr auto const_value{*meta_wrapper_v<V>};
2567
4.46k
               if (substitute == const_value) {
2568
4.46k
                  found_match = true;
2569
4.46k
                  if (!std::holds_alternative<V>(value)) {
2570
4.46k
                     value = V{};
2571
4.46k
                  }
2572
4.46k
               }
2573
4.46k
               else {
2574
4.46k
                  if constexpr (not Options.null_terminated) {
2575
4.46k
                     if (ctx.error == error_code::end_reached) {
2576
                        // reset the context for next attempt
2577
4.46k
                        ctx.error = error_code::none;
2578
4.46k
                     }
2579
4.46k
                  }
2580
4.46k
                  it = copy_it;
2581
4.46k
               }
2582
4.46k
            });
2583
4.46k
            if (found_match) {
2584
0
               return;
2585
0
            }
2586
2587
4.46k
            using non_const_types = typename tuple_types<Tuple>::glaze_non_const_types;
2588
4.46k
            if constexpr (glz::tuple_size_v < non_const_types >> 0) {
2589
4.46k
               using V = glz::tuple_element_t<0, non_const_types>;
2590
4.46k
               if (!std::holds_alternative<V>(value)) value = V{};
2591
4.46k
               parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
2592
            }
2593
            else {
2594
               ctx.error = error_code::no_matching_variant_type;
2595
            }
2596
4.46k
         }
2597
4.46k
      }
_ZN3glz42process_arithmetic_boolean_string_or_arrayINS_5tupleIJbEEEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEERNSt3__17variantIJDndNS6_12basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEEbNS6_6vectorINS_6json_tENSB_ISF_EEEENS6_3mapISD_SF_NS6_4lessIvEENSB_INS6_4pairIKSD_SF_EEEEEEEEETkNS_10is_contextERNS_7contextERPKcSW_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
2550
1.31k
      {
2551
         if constexpr (glz::tuple_size_v<Tuple> < 1) {
2552
            ctx.error = error_code::no_matching_variant_type;
2553
         }
2554
1.31k
         else {
2555
1.31k
            using const_glaze_types = typename tuple_types<Tuple>::glaze_const_types;
2556
1.31k
            bool found_match{};
2557
1.31k
            for_each<glz::tuple_size_v<const_glaze_types>>([&]<size_t I>() {
2558
1.31k
               if (found_match) {
2559
1.31k
                  return;
2560
1.31k
               }
2561
1.31k
               using V = glz::tuple_element_t<I, const_glaze_types>;
2562
               // run time substitute to compare to const value
2563
1.31k
               std::remove_const_t<std::remove_pointer_t<std::remove_const_t<meta_wrapper_t<V>>>> substitute{};
2564
1.31k
               auto copy_it{it};
2565
1.31k
               parse<JSON>::op<ws_handled<Options>()>(substitute, ctx, it, end);
2566
1.31k
               static constexpr auto const_value{*meta_wrapper_v<V>};
2567
1.31k
               if (substitute == const_value) {
2568
1.31k
                  found_match = true;
2569
1.31k
                  if (!std::holds_alternative<V>(value)) {
2570
1.31k
                     value = V{};
2571
1.31k
                  }
2572
1.31k
               }
2573
1.31k
               else {
2574
1.31k
                  if constexpr (not Options.null_terminated) {
2575
1.31k
                     if (ctx.error == error_code::end_reached) {
2576
                        // reset the context for next attempt
2577
1.31k
                        ctx.error = error_code::none;
2578
1.31k
                     }
2579
1.31k
                  }
2580
1.31k
                  it = copy_it;
2581
1.31k
               }
2582
1.31k
            });
2583
1.31k
            if (found_match) {
2584
0
               return;
2585
0
            }
2586
2587
1.31k
            using non_const_types = typename tuple_types<Tuple>::glaze_non_const_types;
2588
1.31k
            if constexpr (glz::tuple_size_v < non_const_types >> 0) {
2589
1.31k
               using V = glz::tuple_element_t<0, non_const_types>;
2590
1.31k
               if (!std::holds_alternative<V>(value)) value = V{};
2591
1.31k
               parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
2592
            }
2593
            else {
2594
               ctx.error = error_code::no_matching_variant_type;
2595
            }
2596
1.31k
         }
2597
1.31k
      }
_ZN3glz42process_arithmetic_boolean_string_or_arrayINS_5tupleIJdEEEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEERNSt3__17variantIJDndNS6_12basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEEbNS6_6vectorINS_6json_tENSB_ISF_EEEENS6_3mapISD_SF_NS6_4lessIvEENSB_INS6_4pairIKSD_SF_EEEEEEEEETkNS_10is_contextERNS_7contextERPKcSW_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
2550
1.73M
      {
2551
         if constexpr (glz::tuple_size_v<Tuple> < 1) {
2552
            ctx.error = error_code::no_matching_variant_type;
2553
         }
2554
1.73M
         else {
2555
1.73M
            using const_glaze_types = typename tuple_types<Tuple>::glaze_const_types;
2556
1.73M
            bool found_match{};
2557
1.73M
            for_each<glz::tuple_size_v<const_glaze_types>>([&]<size_t I>() {
2558
1.73M
               if (found_match) {
2559
1.73M
                  return;
2560
1.73M
               }
2561
1.73M
               using V = glz::tuple_element_t<I, const_glaze_types>;
2562
               // run time substitute to compare to const value
2563
1.73M
               std::remove_const_t<std::remove_pointer_t<std::remove_const_t<meta_wrapper_t<V>>>> substitute{};
2564
1.73M
               auto copy_it{it};
2565
1.73M
               parse<JSON>::op<ws_handled<Options>()>(substitute, ctx, it, end);
2566
1.73M
               static constexpr auto const_value{*meta_wrapper_v<V>};
2567
1.73M
               if (substitute == const_value) {
2568
1.73M
                  found_match = true;
2569
1.73M
                  if (!std::holds_alternative<V>(value)) {
2570
1.73M
                     value = V{};
2571
1.73M
                  }
2572
1.73M
               }
2573
1.73M
               else {
2574
1.73M
                  if constexpr (not Options.null_terminated) {
2575
1.73M
                     if (ctx.error == error_code::end_reached) {
2576
                        // reset the context for next attempt
2577
1.73M
                        ctx.error = error_code::none;
2578
1.73M
                     }
2579
1.73M
                  }
2580
1.73M
                  it = copy_it;
2581
1.73M
               }
2582
1.73M
            });
2583
1.73M
            if (found_match) {
2584
0
               return;
2585
0
            }
2586
2587
1.73M
            using non_const_types = typename tuple_types<Tuple>::glaze_non_const_types;
2588
1.73M
            if constexpr (glz::tuple_size_v < non_const_types >> 0) {
2589
1.73M
               using V = glz::tuple_element_t<0, non_const_types>;
2590
1.73M
               if (!std::holds_alternative<V>(value)) value = V{};
2591
1.73M
               parse<JSON>::op<ws_handled<Options>()>(std::get<V>(value), ctx, it, end);
2592
            }
2593
            else {
2594
               ctx.error = error_code::no_matching_variant_type;
2595
            }
2596
1.73M
         }
2597
1.73M
      }
2598
   };
2599
2600
   template <is_variant T>
2601
   struct from<JSON, T>
2602
   {
2603
      // Note that items in the variant are required to be default constructable for us to switch types
2604
      template <auto Options>
2605
      static void op(auto&& value, is_context auto&& ctx, auto&& it, auto&& end)
2606
5.28M
      {
2607
5.28M
         constexpr auto Opts = ws_handled_off<Options>();
2608
5.28M
         if constexpr (variant_is_auto_deducible<T>()) {
2609
5.28M
            if constexpr (not check_ws_handled(Options)) {
2610
18.5k
               if (skip_ws<Opts>(ctx, it, end)) {
2611
10
                  return;
2612
10
               }
2613
18.5k
            }
2614
2615
18.5k
            switch (*it) {
2616
1.47k
            case '\0':
2617
1.47k
               ctx.error = error_code::unexpected_end;
2618
1.47k
               return;
2619
23.6k
            case '{':
2620
23.6k
               if (ctx.indentation_level >= max_recursive_depth_limit) {
2621
9
                  ctx.error = error_code::exceeded_max_recursive_depth;
2622
9
                  return;
2623
9
               }
2624
               // In the null terminated case this guards for stack overflow
2625
               // Depth counting is done at the object level when not null terminated
2626
23.6k
               ++ctx.indentation_level;
2627
2628
23.6k
               ++it;
2629
23.6k
               if constexpr (not Opts.null_terminated) {
2630
7.87k
                  if (it == end) [[unlikely]] {
2631
50
                     ctx.error = error_code::unexpected_end;
2632
50
                     return;
2633
50
                  }
2634
7.87k
               }
2635
7.82k
               using type_counts = variant_type_count<T>;
2636
23.6k
               using object_types = typename variant_types<T>::object_types;
2637
               if constexpr ((type_counts::n_object < 1) //
2638
                             && (type_counts::n_nullable_object < 1)) {
2639
                  ctx.error = error_code::no_matching_variant_type;
2640
                  return;
2641
               }
2642
23.6k
               else if constexpr ((type_counts::n_object + type_counts::n_nullable_object) == 1 && tag_v<T>.empty()) {
2643
23.6k
                  using V = glz::tuple_element_t<0, object_types>;
2644
23.6k
                  if (!std::holds_alternative<V>(value)) value = V{};
2645
23.6k
                  parse<JSON>::op<opening_handled<Opts>()>(std::get<V>(value), ctx, it, end);
2646
23.6k
                  if constexpr (Opts.null_terminated) {
2647
                     // In the null terminated case this guards for stack overflow
2648
                     // Depth counting is done at the object level when not null terminated
2649
15.7k
                     --ctx.indentation_level;
2650
15.7k
                  }
2651
23.6k
                  return;
2652
               }
2653
               else {
2654
                  auto possible_types = bit_array<std::variant_size_v<T>>{}.flip();
2655
                  static constexpr auto deduction_map = make_variant_deduction_map<T>();
2656
                  static constexpr auto tag_literal = string_literal_from_view<tag_v<T>.size()>(tag_v<T>);
2657
                  if (skip_ws<Opts>(ctx, it, end)) {
2658
                     return;
2659
                  }
2660
                  auto start = it;
2661
                  while (*it != '}') {
2662
                     if (it != start) {
2663
                        if (match_invalid_end<',', Opts>(ctx, it, end)) {
2664
                           return;
2665
                        }
2666
                     }
2667
2668
                     if (skip_ws<Opts>(ctx, it, end)) {
2669
                        return;
2670
                     }
2671
                     if (match_invalid_end<'"', Opts>(ctx, it, end)) {
2672
                        return;
2673
                     }
2674
2675
                     auto* key_start = it;
2676
                     skip_string_view<Opts>(ctx, it, end);
2677
                     if (bool(ctx.error)) [[unlikely]]
2678
                        return;
2679
                     const sv key = {key_start, size_t(it - key_start)};
2680
2681
                     if (match_invalid_end<'"', Opts>(ctx, it, end)) {
2682
                        return;
2683
                     }
2684
2685
                     if constexpr (deduction_map.size()) {
2686
                        // We first check if a tag is defined and see if the key matches the tag
2687
                        if constexpr (not tag_v<T>.empty()) {
2688
                           if (key == tag_v<T>) {
2689
                              if (parse_ws_colon<Opts>(ctx, it, end)) {
2690
                                 return;
2691
                              }
2692
2693
                              using id_type = std::decay_t<decltype(ids_v<T>[0])>;
2694
2695
                              std::conditional_t<std::integral<id_type>, id_type, sv> type_id{};
2696
                              if constexpr (std::integral<id_type>) {
2697
                                 from<JSON, id_type>::template op<ws_handled<Opts>()>(type_id, ctx, it, end);
2698
                              }
2699
                              else {
2700
                                 from<JSON, sv>::template op<ws_handled<Opts>()>(type_id, ctx, it, end);
2701
                              }
2702
                              if (bool(ctx.error)) [[unlikely]]
2703
                                 return;
2704
                              if (skip_ws<Opts>(ctx, it, end)) {
2705
                                 return;
2706
                              }
2707
                              if (!(*it == ',' || *it == '}')) [[unlikely]] {
2708
                                 ctx.error = error_code::syntax_error;
2709
                                 return;
2710
                              }
2711
2712
                              static constexpr auto id_map = make_variant_id_map<T>();
2713
                              auto id_it = id_map.find(type_id);
2714
                              if (id_it != id_map.end()) [[likely]] {
2715
                                 it = start; // we restart our object parsing now that we know the target type
2716
                                 const auto type_index = id_it->second;
2717
                                 if (value.index() != type_index) value = runtime_variant_map<T>()[type_index];
2718
                                 std::visit(
2719
                                    [&](auto&& v) {
2720
                                       using V = std::decay_t<decltype(v)>;
2721
                                       constexpr bool is_object = glaze_object_t<V> || reflectable<V>;
2722
                                       if constexpr (is_object) {
2723
                                          from<JSON, V>::template op<opening_handled<Opts>(), tag_literal>(v, ctx, it,
2724
                                                                                                           end);
2725
                                       }
2726
                                       else if constexpr (is_memory_object<V>) {
2727
                                          if (!v) {
2728
                                             if constexpr (is_specialization_v<V, std::optional>) {
2729
                                                if constexpr (requires { v.emplace(); }) {
2730
                                                   v.emplace();
2731
                                                }
2732
                                                else {
2733
                                                   v = typename V::value_type{};
2734
                                                }
2735
                                             }
2736
                                             else if constexpr (is_specialization_v<V, std::unique_ptr>)
2737
                                                v = std::make_unique<typename V::element_type>();
2738
                                             else if constexpr (is_specialization_v<V, std::shared_ptr>)
2739
                                                v = std::make_shared<typename V::element_type>();
2740
                                             else if constexpr (constructible<V>) {
2741
                                                v = meta_construct_v<V>();
2742
                                             }
2743
                                             else {
2744
                                                ctx.error = error_code::invalid_nullable_read;
2745
                                                return;
2746
                                                // Cannot read into unset nullable that is not std::optional,
2747
                                                // std::unique_ptr, or std::shared_ptr
2748
                                             }
2749
                                          }
2750
                                          from<JSON, memory_type<V>>::template op<opening_handled<Opts>(), tag_literal>(
2751
                                             *v, ctx, it, end);
2752
                                       }
2753
                                    },
2754
                                    value);
2755
2756
                                 if constexpr (Opts.null_terminated) {
2757
                                    // In the null terminated case this guards for stack overflow
2758
                                    // Depth counting is done at the object level when not null terminated
2759
                                    --ctx.indentation_level;
2760
                                 }
2761
                                 return; // we've decoded our target type
2762
                              }
2763
                              else [[unlikely]] {
2764
                                 ctx.error = error_code::no_matching_variant_type;
2765
                                 return;
2766
                              }
2767
                           }
2768
                        }
2769
2770
                        auto deduction_it = deduction_map.find(key);
2771
                        if (deduction_it != deduction_map.end()) [[likely]] {
2772
                           possible_types &= deduction_it->second;
2773
                        }
2774
                        else if constexpr (Opts.error_on_unknown_keys) {
2775
                           ctx.error = error_code::unknown_key;
2776
                           return;
2777
                        }
2778
                     }
2779
                     else if constexpr (not tag_v<T>.empty()) {
2780
                        // empty object case for variant, if there are no normal elements
2781
                        if (key == tag_v<T>) {
2782
                           if (parse_ws_colon<Opts>(ctx, it, end)) {
2783
                              return;
2784
                           }
2785
2786
                           std::string_view type_id{};
2787
                           parse<JSON>::op<ws_handled<Opts>()>(type_id, ctx, it, end);
2788
                           if (bool(ctx.error)) [[unlikely]]
2789
                              return;
2790
                           if (skip_ws<Opts>(ctx, it, end)) {
2791
                              return;
2792
                           }
2793
2794
                           static constexpr auto id_map = make_variant_id_map<T>();
2795
                           auto id_it = id_map.find(type_id);
2796
                           if (id_it != id_map.end()) [[likely]] {
2797
                              it = start;
2798
                              const auto type_index = id_it->second;
2799
                              if (value.index() != type_index) value = runtime_variant_map<T>()[type_index];
2800
                              return;
2801
                           }
2802
                           else {
2803
                              ctx.error = error_code::no_matching_variant_type;
2804
                              return;
2805
                           }
2806
                        }
2807
                        else if constexpr (Opts.error_on_unknown_keys) {
2808
                           ctx.error = error_code::unknown_key;
2809
                           return;
2810
                        }
2811
                     }
2812
                     else if constexpr (Opts.error_on_unknown_keys) {
2813
                        ctx.error = error_code::unknown_key;
2814
                        return;
2815
                     }
2816
2817
                     auto matching_types = possible_types.popcount();
2818
                     if (matching_types == 0) {
2819
                        ctx.error = error_code::no_matching_variant_type;
2820
                        return;
2821
                     }
2822
                     else if (matching_types == 1) {
2823
                        it = start;
2824
                        const auto type_index = possible_types.countr_zero();
2825
                        if (value.index() != static_cast<size_t>(type_index))
2826
                           value = runtime_variant_map<T>()[type_index];
2827
                        std::visit(
2828
                           [&](auto&& v) {
2829
                              using V = std::decay_t<decltype(v)>;
2830
                              constexpr bool is_object = glaze_object_t<V> || reflectable<V>;
2831
                              if constexpr (is_object) {
2832
                                 from<JSON, V>::template op<opening_handled<Opts>(), tag_literal>(v, ctx, it, end);
2833
                              }
2834
                              else if constexpr (is_memory_object<V>) {
2835
                                 if (!v) {
2836
                                    if constexpr (is_specialization_v<V, std::optional>) {
2837
                                       if constexpr (requires { v.emplace(); }) {
2838
                                          v.emplace();
2839
                                       }
2840
                                       else {
2841
                                          v = typename V::value_type{};
2842
                                       }
2843
                                    }
2844
                                    else if constexpr (is_specialization_v<V, std::unique_ptr>)
2845
                                       v = std::make_unique<typename V::element_type>();
2846
                                    else if constexpr (is_specialization_v<V, std::shared_ptr>)
2847
                                       v = std::make_shared<typename V::element_type>();
2848
                                    else if constexpr (constructible<V>) {
2849
                                       v = meta_construct_v<V>();
2850
                                    }
2851
                                    else {
2852
                                       ctx.error = error_code::invalid_nullable_read;
2853
                                       return;
2854
                                       // Cannot read into unset nullable that is not std::optional,
2855
                                       // std::unique_ptr, or std::shared_ptr
2856
                                    }
2857
                                 }
2858
                                 from<JSON, memory_type<V>>::template op<opening_handled<Opts>(), tag_literal>(*v, ctx,
2859
                                                                                                               it, end);
2860
                              }
2861
                           },
2862
                           value);
2863
2864
                        if constexpr (Opts.null_terminated) {
2865
                           // In the null terminated case this guards for stack overflow
2866
                           // Depth counting is done at the object level when not null terminated
2867
                           --ctx.indentation_level;
2868
                        }
2869
                        return; // we've decoded our target type
2870
                     }
2871
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2872
                        return;
2873
                     }
2874
2875
                     skip_value<JSON>::op<Opts>(ctx, it, end);
2876
                     if (bool(ctx.error)) [[unlikely]]
2877
                        return;
2878
                     if (skip_ws<Opts>(ctx, it, end)) {
2879
                        return;
2880
                     }
2881
                  }
2882
                  ctx.error = error_code::no_matching_variant_type;
2883
               }
2884
0
               break;
2885
51.2k
            case '[':
2886
51.2k
               using array_types = typename variant_types<T>::array_types;
2887
2888
51.2k
               if (ctx.indentation_level >= max_recursive_depth_limit) {
2889
3
                  ctx.error = error_code::exceeded_max_recursive_depth;
2890
3
                  return;
2891
3
               }
2892
51.2k
               if constexpr (Opts.null_terminated) {
2893
                  // In the null terminated case this guards for stack overflow
2894
                  // Depth counting is done at the object level when not null terminated
2895
34.1k
                  ++ctx.indentation_level;
2896
34.1k
               }
2897
51.2k
               process_arithmetic_boolean_string_or_array<array_types>::template op<Opts>(value, ctx, it, end);
2898
51.2k
               if constexpr (Opts.null_terminated) {
2899
34.1k
                  --ctx.indentation_level;
2900
34.1k
               }
2901
51.2k
               break;
2902
13.4k
            case '"': {
2903
13.4k
               using string_types = typename variant_types<T>::string_types;
2904
13.4k
               process_arithmetic_boolean_string_or_array<string_types>::template op<Opts>(value, ctx, it, end);
2905
13.4k
               break;
2906
51.2k
            }
2907
2.84k
            case 't':
2908
3.93k
            case 'f': {
2909
3.93k
               using bool_types = typename variant_types<T>::bool_types;
2910
3.93k
               process_arithmetic_boolean_string_or_array<bool_types>::template op<Opts>(value, ctx, it, end);
2911
3.93k
               break;
2912
2.84k
            }
2913
2.70k
            case 'n':
2914
2.70k
               using nullable_types = typename variant_types<T>::nullable_types;
2915
               if constexpr (glz::tuple_size_v<nullable_types> < 1) {
2916
                  ctx.error = error_code::no_matching_variant_type;
2917
               }
2918
2.70k
               else {
2919
2.70k
                  using V = glz::tuple_element_t<0, nullable_types>;
2920
2.70k
                  if (!std::holds_alternative<V>(value)) value = V{};
2921
2.70k
                  match<"null", Opts>(ctx, it, end);
2922
2.70k
               }
2923
2.70k
               break;
2924
5.19M
            default: {
2925
               // Not bool, string, object, or array so must be number or null
2926
5.19M
               using number_types = typename variant_types<T>::number_types;
2927
5.19M
               process_arithmetic_boolean_string_or_array<number_types>::template op<Opts>(value, ctx, it, end);
2928
5.19M
            }
2929
5.28M
            }
2930
         }
2931
         else {
2932
            std::visit([&](auto&& v) { parse<JSON>::op<Options>(v, ctx, it, end); }, value);
2933
         }
2934
5.28M
      }
_ZN3glz4fromILj10ENSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_6json_tENS6_ISA_EEEENS1_3mapIS8_SA_NS1_4lessIvEENS6_INS1_4pairIKS8_SA_EEEEEEEEEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1EEERSL_TkNS_10is_contextERNS_7contextERPKcSU_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
2606
6.19k
      {
2607
6.19k
         constexpr auto Opts = ws_handled_off<Options>();
2608
6.19k
         if constexpr (variant_is_auto_deducible<T>()) {
2609
6.19k
            if constexpr (not check_ws_handled(Options)) {
2610
6.19k
               if (skip_ws<Opts>(ctx, it, end)) {
2611
10
                  return;
2612
10
               }
2613
6.19k
            }
2614
2615
6.18k
            switch (*it) {
2616
3
            case '\0':
2617
3
               ctx.error = error_code::unexpected_end;
2618
3
               return;
2619
1.66k
            case '{':
2620
1.66k
               if (ctx.indentation_level >= max_recursive_depth_limit) {
2621
0
                  ctx.error = error_code::exceeded_max_recursive_depth;
2622
0
                  return;
2623
0
               }
2624
               // In the null terminated case this guards for stack overflow
2625
               // Depth counting is done at the object level when not null terminated
2626
1.66k
               ++ctx.indentation_level;
2627
2628
1.66k
               ++it;
2629
1.66k
               if constexpr (not Opts.null_terminated) {
2630
1.66k
                  if (it == end) [[unlikely]] {
2631
2
                     ctx.error = error_code::unexpected_end;
2632
2
                     return;
2633
2
                  }
2634
1.66k
               }
2635
1.66k
               using type_counts = variant_type_count<T>;
2636
1.66k
               using object_types = typename variant_types<T>::object_types;
2637
               if constexpr ((type_counts::n_object < 1) //
2638
                             && (type_counts::n_nullable_object < 1)) {
2639
                  ctx.error = error_code::no_matching_variant_type;
2640
                  return;
2641
               }
2642
1.66k
               else if constexpr ((type_counts::n_object + type_counts::n_nullable_object) == 1 && tag_v<T>.empty()) {
2643
1.66k
                  using V = glz::tuple_element_t<0, object_types>;
2644
1.66k
                  if (!std::holds_alternative<V>(value)) value = V{};
2645
1.66k
                  parse<JSON>::op<opening_handled<Opts>()>(std::get<V>(value), ctx, it, end);
2646
                  if constexpr (Opts.null_terminated) {
2647
                     // In the null terminated case this guards for stack overflow
2648
                     // Depth counting is done at the object level when not null terminated
2649
                     --ctx.indentation_level;
2650
                  }
2651
1.66k
                  return;
2652
               }
2653
               else {
2654
                  auto possible_types = bit_array<std::variant_size_v<T>>{}.flip();
2655
                  static constexpr auto deduction_map = make_variant_deduction_map<T>();
2656
                  static constexpr auto tag_literal = string_literal_from_view<tag_v<T>.size()>(tag_v<T>);
2657
                  if (skip_ws<Opts>(ctx, it, end)) {
2658
                     return;
2659
                  }
2660
                  auto start = it;
2661
                  while (*it != '}') {
2662
                     if (it != start) {
2663
                        if (match_invalid_end<',', Opts>(ctx, it, end)) {
2664
                           return;
2665
                        }
2666
                     }
2667
2668
                     if (skip_ws<Opts>(ctx, it, end)) {
2669
                        return;
2670
                     }
2671
                     if (match_invalid_end<'"', Opts>(ctx, it, end)) {
2672
                        return;
2673
                     }
2674
2675
                     auto* key_start = it;
2676
                     skip_string_view<Opts>(ctx, it, end);
2677
                     if (bool(ctx.error)) [[unlikely]]
2678
                        return;
2679
                     const sv key = {key_start, size_t(it - key_start)};
2680
2681
                     if (match_invalid_end<'"', Opts>(ctx, it, end)) {
2682
                        return;
2683
                     }
2684
2685
                     if constexpr (deduction_map.size()) {
2686
                        // We first check if a tag is defined and see if the key matches the tag
2687
                        if constexpr (not tag_v<T>.empty()) {
2688
                           if (key == tag_v<T>) {
2689
                              if (parse_ws_colon<Opts>(ctx, it, end)) {
2690
                                 return;
2691
                              }
2692
2693
                              using id_type = std::decay_t<decltype(ids_v<T>[0])>;
2694
2695
                              std::conditional_t<std::integral<id_type>, id_type, sv> type_id{};
2696
                              if constexpr (std::integral<id_type>) {
2697
                                 from<JSON, id_type>::template op<ws_handled<Opts>()>(type_id, ctx, it, end);
2698
                              }
2699
                              else {
2700
                                 from<JSON, sv>::template op<ws_handled<Opts>()>(type_id, ctx, it, end);
2701
                              }
2702
                              if (bool(ctx.error)) [[unlikely]]
2703
                                 return;
2704
                              if (skip_ws<Opts>(ctx, it, end)) {
2705
                                 return;
2706
                              }
2707
                              if (!(*it == ',' || *it == '}')) [[unlikely]] {
2708
                                 ctx.error = error_code::syntax_error;
2709
                                 return;
2710
                              }
2711
2712
                              static constexpr auto id_map = make_variant_id_map<T>();
2713
                              auto id_it = id_map.find(type_id);
2714
                              if (id_it != id_map.end()) [[likely]] {
2715
                                 it = start; // we restart our object parsing now that we know the target type
2716
                                 const auto type_index = id_it->second;
2717
                                 if (value.index() != type_index) value = runtime_variant_map<T>()[type_index];
2718
                                 std::visit(
2719
                                    [&](auto&& v) {
2720
                                       using V = std::decay_t<decltype(v)>;
2721
                                       constexpr bool is_object = glaze_object_t<V> || reflectable<V>;
2722
                                       if constexpr (is_object) {
2723
                                          from<JSON, V>::template op<opening_handled<Opts>(), tag_literal>(v, ctx, it,
2724
                                                                                                           end);
2725
                                       }
2726
                                       else if constexpr (is_memory_object<V>) {
2727
                                          if (!v) {
2728
                                             if constexpr (is_specialization_v<V, std::optional>) {
2729
                                                if constexpr (requires { v.emplace(); }) {
2730
                                                   v.emplace();
2731
                                                }
2732
                                                else {
2733
                                                   v = typename V::value_type{};
2734
                                                }
2735
                                             }
2736
                                             else if constexpr (is_specialization_v<V, std::unique_ptr>)
2737
                                                v = std::make_unique<typename V::element_type>();
2738
                                             else if constexpr (is_specialization_v<V, std::shared_ptr>)
2739
                                                v = std::make_shared<typename V::element_type>();
2740
                                             else if constexpr (constructible<V>) {
2741
                                                v = meta_construct_v<V>();
2742
                                             }
2743
                                             else {
2744
                                                ctx.error = error_code::invalid_nullable_read;
2745
                                                return;
2746
                                                // Cannot read into unset nullable that is not std::optional,
2747
                                                // std::unique_ptr, or std::shared_ptr
2748
                                             }
2749
                                          }
2750
                                          from<JSON, memory_type<V>>::template op<opening_handled<Opts>(), tag_literal>(
2751
                                             *v, ctx, it, end);
2752
                                       }
2753
                                    },
2754
                                    value);
2755
2756
                                 if constexpr (Opts.null_terminated) {
2757
                                    // In the null terminated case this guards for stack overflow
2758
                                    // Depth counting is done at the object level when not null terminated
2759
                                    --ctx.indentation_level;
2760
                                 }
2761
                                 return; // we've decoded our target type
2762
                              }
2763
                              else [[unlikely]] {
2764
                                 ctx.error = error_code::no_matching_variant_type;
2765
                                 return;
2766
                              }
2767
                           }
2768
                        }
2769
2770
                        auto deduction_it = deduction_map.find(key);
2771
                        if (deduction_it != deduction_map.end()) [[likely]] {
2772
                           possible_types &= deduction_it->second;
2773
                        }
2774
                        else if constexpr (Opts.error_on_unknown_keys) {
2775
                           ctx.error = error_code::unknown_key;
2776
                           return;
2777
                        }
2778
                     }
2779
                     else if constexpr (not tag_v<T>.empty()) {
2780
                        // empty object case for variant, if there are no normal elements
2781
                        if (key == tag_v<T>) {
2782
                           if (parse_ws_colon<Opts>(ctx, it, end)) {
2783
                              return;
2784
                           }
2785
2786
                           std::string_view type_id{};
2787
                           parse<JSON>::op<ws_handled<Opts>()>(type_id, ctx, it, end);
2788
                           if (bool(ctx.error)) [[unlikely]]
2789
                              return;
2790
                           if (skip_ws<Opts>(ctx, it, end)) {
2791
                              return;
2792
                           }
2793
2794
                           static constexpr auto id_map = make_variant_id_map<T>();
2795
                           auto id_it = id_map.find(type_id);
2796
                           if (id_it != id_map.end()) [[likely]] {
2797
                              it = start;
2798
                              const auto type_index = id_it->second;
2799
                              if (value.index() != type_index) value = runtime_variant_map<T>()[type_index];
2800
                              return;
2801
                           }
2802
                           else {
2803
                              ctx.error = error_code::no_matching_variant_type;
2804
                              return;
2805
                           }
2806
                        }
2807
                        else if constexpr (Opts.error_on_unknown_keys) {
2808
                           ctx.error = error_code::unknown_key;
2809
                           return;
2810
                        }
2811
                     }
2812
                     else if constexpr (Opts.error_on_unknown_keys) {
2813
                        ctx.error = error_code::unknown_key;
2814
                        return;
2815
                     }
2816
2817
                     auto matching_types = possible_types.popcount();
2818
                     if (matching_types == 0) {
2819
                        ctx.error = error_code::no_matching_variant_type;
2820
                        return;
2821
                     }
2822
                     else if (matching_types == 1) {
2823
                        it = start;
2824
                        const auto type_index = possible_types.countr_zero();
2825
                        if (value.index() != static_cast<size_t>(type_index))
2826
                           value = runtime_variant_map<T>()[type_index];
2827
                        std::visit(
2828
                           [&](auto&& v) {
2829
                              using V = std::decay_t<decltype(v)>;
2830
                              constexpr bool is_object = glaze_object_t<V> || reflectable<V>;
2831
                              if constexpr (is_object) {
2832
                                 from<JSON, V>::template op<opening_handled<Opts>(), tag_literal>(v, ctx, it, end);
2833
                              }
2834
                              else if constexpr (is_memory_object<V>) {
2835
                                 if (!v) {
2836
                                    if constexpr (is_specialization_v<V, std::optional>) {
2837
                                       if constexpr (requires { v.emplace(); }) {
2838
                                          v.emplace();
2839
                                       }
2840
                                       else {
2841
                                          v = typename V::value_type{};
2842
                                       }
2843
                                    }
2844
                                    else if constexpr (is_specialization_v<V, std::unique_ptr>)
2845
                                       v = std::make_unique<typename V::element_type>();
2846
                                    else if constexpr (is_specialization_v<V, std::shared_ptr>)
2847
                                       v = std::make_shared<typename V::element_type>();
2848
                                    else if constexpr (constructible<V>) {
2849
                                       v = meta_construct_v<V>();
2850
                                    }
2851
                                    else {
2852
                                       ctx.error = error_code::invalid_nullable_read;
2853
                                       return;
2854
                                       // Cannot read into unset nullable that is not std::optional,
2855
                                       // std::unique_ptr, or std::shared_ptr
2856
                                    }
2857
                                 }
2858
                                 from<JSON, memory_type<V>>::template op<opening_handled<Opts>(), tag_literal>(*v, ctx,
2859
                                                                                                               it, end);
2860
                              }
2861
                           },
2862
                           value);
2863
2864
                        if constexpr (Opts.null_terminated) {
2865
                           // In the null terminated case this guards for stack overflow
2866
                           // Depth counting is done at the object level when not null terminated
2867
                           --ctx.indentation_level;
2868
                        }
2869
                        return; // we've decoded our target type
2870
                     }
2871
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2872
                        return;
2873
                     }
2874
2875
                     skip_value<JSON>::op<Opts>(ctx, it, end);
2876
                     if (bool(ctx.error)) [[unlikely]]
2877
                        return;
2878
                     if (skip_ws<Opts>(ctx, it, end)) {
2879
                        return;
2880
                     }
2881
                  }
2882
                  ctx.error = error_code::no_matching_variant_type;
2883
               }
2884
0
               break;
2885
1.58k
            case '[':
2886
1.58k
               using array_types = typename variant_types<T>::array_types;
2887
2888
1.58k
               if (ctx.indentation_level >= max_recursive_depth_limit) {
2889
0
                  ctx.error = error_code::exceeded_max_recursive_depth;
2890
0
                  return;
2891
0
               }
2892
               if constexpr (Opts.null_terminated) {
2893
                  // In the null terminated case this guards for stack overflow
2894
                  // Depth counting is done at the object level when not null terminated
2895
                  ++ctx.indentation_level;
2896
               }
2897
1.58k
               process_arithmetic_boolean_string_or_array<array_types>::template op<Opts>(value, ctx, it, end);
2898
               if constexpr (Opts.null_terminated) {
2899
                  --ctx.indentation_level;
2900
               }
2901
1.58k
               break;
2902
412
            case '"': {
2903
412
               using string_types = typename variant_types<T>::string_types;
2904
412
               process_arithmetic_boolean_string_or_array<string_types>::template op<Opts>(value, ctx, it, end);
2905
412
               break;
2906
1.58k
            }
2907
48
            case 't':
2908
124
            case 'f': {
2909
124
               using bool_types = typename variant_types<T>::bool_types;
2910
124
               process_arithmetic_boolean_string_or_array<bool_types>::template op<Opts>(value, ctx, it, end);
2911
124
               break;
2912
48
            }
2913
56
            case 'n':
2914
56
               using nullable_types = typename variant_types<T>::nullable_types;
2915
               if constexpr (glz::tuple_size_v<nullable_types> < 1) {
2916
                  ctx.error = error_code::no_matching_variant_type;
2917
               }
2918
56
               else {
2919
56
                  using V = glz::tuple_element_t<0, nullable_types>;
2920
56
                  if (!std::holds_alternative<V>(value)) value = V{};
2921
56
                  match<"null", Opts>(ctx, it, end);
2922
56
               }
2923
56
               break;
2924
2.34k
            default: {
2925
               // Not bool, string, object, or array so must be number or null
2926
2.34k
               using number_types = typename variant_types<T>::number_types;
2927
2.34k
               process_arithmetic_boolean_string_or_array<number_types>::template op<Opts>(value, ctx, it, end);
2928
2.34k
            }
2929
6.19k
            }
2930
         }
2931
         else {
2932
            std::visit([&](auto&& v) { parse<JSON>::op<Options>(v, ctx, it, end); }, value);
2933
         }
2934
6.19k
      }
_ZN3glz4fromILj10ENSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_6json_tENS6_ISA_EEEENS1_3mapIS8_SA_NS1_4lessIvEENS6_INS1_4pairIKS8_SA_EEEEEEEEEE2opITnDaXtlNS_4optsELj10ELb0ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj4EEERSL_TkNS_10is_contextERNS_7contextERPKcSU_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
2606
1.75M
      {
2607
1.75M
         constexpr auto Opts = ws_handled_off<Options>();
2608
1.75M
         if constexpr (variant_is_auto_deducible<T>()) {
2609
            if constexpr (not check_ws_handled(Options)) {
2610
               if (skip_ws<Opts>(ctx, it, end)) {
2611
                  return;
2612
               }
2613
            }
2614
2615
1.75M
            switch (*it) {
2616
40
            case '\0':
2617
40
               ctx.error = error_code::unexpected_end;
2618
40
               return;
2619
6.20k
            case '{':
2620
6.20k
               if (ctx.indentation_level >= max_recursive_depth_limit) {
2621
3
                  ctx.error = error_code::exceeded_max_recursive_depth;
2622
3
                  return;
2623
3
               }
2624
               // In the null terminated case this guards for stack overflow
2625
               // Depth counting is done at the object level when not null terminated
2626
6.20k
               ++ctx.indentation_level;
2627
2628
6.20k
               ++it;
2629
6.20k
               if constexpr (not Opts.null_terminated) {
2630
6.20k
                  if (it == end) [[unlikely]] {
2631
48
                     ctx.error = error_code::unexpected_end;
2632
48
                     return;
2633
48
                  }
2634
6.20k
               }
2635
6.15k
               using type_counts = variant_type_count<T>;
2636
6.20k
               using object_types = typename variant_types<T>::object_types;
2637
               if constexpr ((type_counts::n_object < 1) //
2638
                             && (type_counts::n_nullable_object < 1)) {
2639
                  ctx.error = error_code::no_matching_variant_type;
2640
                  return;
2641
               }
2642
6.20k
               else if constexpr ((type_counts::n_object + type_counts::n_nullable_object) == 1 && tag_v<T>.empty()) {
2643
6.20k
                  using V = glz::tuple_element_t<0, object_types>;
2644
6.20k
                  if (!std::holds_alternative<V>(value)) value = V{};
2645
6.20k
                  parse<JSON>::op<opening_handled<Opts>()>(std::get<V>(value), ctx, it, end);
2646
                  if constexpr (Opts.null_terminated) {
2647
                     // In the null terminated case this guards for stack overflow
2648
                     // Depth counting is done at the object level when not null terminated
2649
                     --ctx.indentation_level;
2650
                  }
2651
6.20k
                  return;
2652
               }
2653
               else {
2654
                  auto possible_types = bit_array<std::variant_size_v<T>>{}.flip();
2655
                  static constexpr auto deduction_map = make_variant_deduction_map<T>();
2656
                  static constexpr auto tag_literal = string_literal_from_view<tag_v<T>.size()>(tag_v<T>);
2657
                  if (skip_ws<Opts>(ctx, it, end)) {
2658
                     return;
2659
                  }
2660
                  auto start = it;
2661
                  while (*it != '}') {
2662
                     if (it != start) {
2663
                        if (match_invalid_end<',', Opts>(ctx, it, end)) {
2664
                           return;
2665
                        }
2666
                     }
2667
2668
                     if (skip_ws<Opts>(ctx, it, end)) {
2669
                        return;
2670
                     }
2671
                     if (match_invalid_end<'"', Opts>(ctx, it, end)) {
2672
                        return;
2673
                     }
2674
2675
                     auto* key_start = it;
2676
                     skip_string_view<Opts>(ctx, it, end);
2677
                     if (bool(ctx.error)) [[unlikely]]
2678
                        return;
2679
                     const sv key = {key_start, size_t(it - key_start)};
2680
2681
                     if (match_invalid_end<'"', Opts>(ctx, it, end)) {
2682
                        return;
2683
                     }
2684
2685
                     if constexpr (deduction_map.size()) {
2686
                        // We first check if a tag is defined and see if the key matches the tag
2687
                        if constexpr (not tag_v<T>.empty()) {
2688
                           if (key == tag_v<T>) {
2689
                              if (parse_ws_colon<Opts>(ctx, it, end)) {
2690
                                 return;
2691
                              }
2692
2693
                              using id_type = std::decay_t<decltype(ids_v<T>[0])>;
2694
2695
                              std::conditional_t<std::integral<id_type>, id_type, sv> type_id{};
2696
                              if constexpr (std::integral<id_type>) {
2697
                                 from<JSON, id_type>::template op<ws_handled<Opts>()>(type_id, ctx, it, end);
2698
                              }
2699
                              else {
2700
                                 from<JSON, sv>::template op<ws_handled<Opts>()>(type_id, ctx, it, end);
2701
                              }
2702
                              if (bool(ctx.error)) [[unlikely]]
2703
                                 return;
2704
                              if (skip_ws<Opts>(ctx, it, end)) {
2705
                                 return;
2706
                              }
2707
                              if (!(*it == ',' || *it == '}')) [[unlikely]] {
2708
                                 ctx.error = error_code::syntax_error;
2709
                                 return;
2710
                              }
2711
2712
                              static constexpr auto id_map = make_variant_id_map<T>();
2713
                              auto id_it = id_map.find(type_id);
2714
                              if (id_it != id_map.end()) [[likely]] {
2715
                                 it = start; // we restart our object parsing now that we know the target type
2716
                                 const auto type_index = id_it->second;
2717
                                 if (value.index() != type_index) value = runtime_variant_map<T>()[type_index];
2718
                                 std::visit(
2719
                                    [&](auto&& v) {
2720
                                       using V = std::decay_t<decltype(v)>;
2721
                                       constexpr bool is_object = glaze_object_t<V> || reflectable<V>;
2722
                                       if constexpr (is_object) {
2723
                                          from<JSON, V>::template op<opening_handled<Opts>(), tag_literal>(v, ctx, it,
2724
                                                                                                           end);
2725
                                       }
2726
                                       else if constexpr (is_memory_object<V>) {
2727
                                          if (!v) {
2728
                                             if constexpr (is_specialization_v<V, std::optional>) {
2729
                                                if constexpr (requires { v.emplace(); }) {
2730
                                                   v.emplace();
2731
                                                }
2732
                                                else {
2733
                                                   v = typename V::value_type{};
2734
                                                }
2735
                                             }
2736
                                             else if constexpr (is_specialization_v<V, std::unique_ptr>)
2737
                                                v = std::make_unique<typename V::element_type>();
2738
                                             else if constexpr (is_specialization_v<V, std::shared_ptr>)
2739
                                                v = std::make_shared<typename V::element_type>();
2740
                                             else if constexpr (constructible<V>) {
2741
                                                v = meta_construct_v<V>();
2742
                                             }
2743
                                             else {
2744
                                                ctx.error = error_code::invalid_nullable_read;
2745
                                                return;
2746
                                                // Cannot read into unset nullable that is not std::optional,
2747
                                                // std::unique_ptr, or std::shared_ptr
2748
                                             }
2749
                                          }
2750
                                          from<JSON, memory_type<V>>::template op<opening_handled<Opts>(), tag_literal>(
2751
                                             *v, ctx, it, end);
2752
                                       }
2753
                                    },
2754
                                    value);
2755
2756
                                 if constexpr (Opts.null_terminated) {
2757
                                    // In the null terminated case this guards for stack overflow
2758
                                    // Depth counting is done at the object level when not null terminated
2759
                                    --ctx.indentation_level;
2760
                                 }
2761
                                 return; // we've decoded our target type
2762
                              }
2763
                              else [[unlikely]] {
2764
                                 ctx.error = error_code::no_matching_variant_type;
2765
                                 return;
2766
                              }
2767
                           }
2768
                        }
2769
2770
                        auto deduction_it = deduction_map.find(key);
2771
                        if (deduction_it != deduction_map.end()) [[likely]] {
2772
                           possible_types &= deduction_it->second;
2773
                        }
2774
                        else if constexpr (Opts.error_on_unknown_keys) {
2775
                           ctx.error = error_code::unknown_key;
2776
                           return;
2777
                        }
2778
                     }
2779
                     else if constexpr (not tag_v<T>.empty()) {
2780
                        // empty object case for variant, if there are no normal elements
2781
                        if (key == tag_v<T>) {
2782
                           if (parse_ws_colon<Opts>(ctx, it, end)) {
2783
                              return;
2784
                           }
2785
2786
                           std::string_view type_id{};
2787
                           parse<JSON>::op<ws_handled<Opts>()>(type_id, ctx, it, end);
2788
                           if (bool(ctx.error)) [[unlikely]]
2789
                              return;
2790
                           if (skip_ws<Opts>(ctx, it, end)) {
2791
                              return;
2792
                           }
2793
2794
                           static constexpr auto id_map = make_variant_id_map<T>();
2795
                           auto id_it = id_map.find(type_id);
2796
                           if (id_it != id_map.end()) [[likely]] {
2797
                              it = start;
2798
                              const auto type_index = id_it->second;
2799
                              if (value.index() != type_index) value = runtime_variant_map<T>()[type_index];
2800
                              return;
2801
                           }
2802
                           else {
2803
                              ctx.error = error_code::no_matching_variant_type;
2804
                              return;
2805
                           }
2806
                        }
2807
                        else if constexpr (Opts.error_on_unknown_keys) {
2808
                           ctx.error = error_code::unknown_key;
2809
                           return;
2810
                        }
2811
                     }
2812
                     else if constexpr (Opts.error_on_unknown_keys) {
2813
                        ctx.error = error_code::unknown_key;
2814
                        return;
2815
                     }
2816
2817
                     auto matching_types = possible_types.popcount();
2818
                     if (matching_types == 0) {
2819
                        ctx.error = error_code::no_matching_variant_type;
2820
                        return;
2821
                     }
2822
                     else if (matching_types == 1) {
2823
                        it = start;
2824
                        const auto type_index = possible_types.countr_zero();
2825
                        if (value.index() != static_cast<size_t>(type_index))
2826
                           value = runtime_variant_map<T>()[type_index];
2827
                        std::visit(
2828
                           [&](auto&& v) {
2829
                              using V = std::decay_t<decltype(v)>;
2830
                              constexpr bool is_object = glaze_object_t<V> || reflectable<V>;
2831
                              if constexpr (is_object) {
2832
                                 from<JSON, V>::template op<opening_handled<Opts>(), tag_literal>(v, ctx, it, end);
2833
                              }
2834
                              else if constexpr (is_memory_object<V>) {
2835
                                 if (!v) {
2836
                                    if constexpr (is_specialization_v<V, std::optional>) {
2837
                                       if constexpr (requires { v.emplace(); }) {
2838
                                          v.emplace();
2839
                                       }
2840
                                       else {
2841
                                          v = typename V::value_type{};
2842
                                       }
2843
                                    }
2844
                                    else if constexpr (is_specialization_v<V, std::unique_ptr>)
2845
                                       v = std::make_unique<typename V::element_type>();
2846
                                    else if constexpr (is_specialization_v<V, std::shared_ptr>)
2847
                                       v = std::make_shared<typename V::element_type>();
2848
                                    else if constexpr (constructible<V>) {
2849
                                       v = meta_construct_v<V>();
2850
                                    }
2851
                                    else {
2852
                                       ctx.error = error_code::invalid_nullable_read;
2853
                                       return;
2854
                                       // Cannot read into unset nullable that is not std::optional,
2855
                                       // std::unique_ptr, or std::shared_ptr
2856
                                    }
2857
                                 }
2858
                                 from<JSON, memory_type<V>>::template op<opening_handled<Opts>(), tag_literal>(*v, ctx,
2859
                                                                                                               it, end);
2860
                              }
2861
                           },
2862
                           value);
2863
2864
                        if constexpr (Opts.null_terminated) {
2865
                           // In the null terminated case this guards for stack overflow
2866
                           // Depth counting is done at the object level when not null terminated
2867
                           --ctx.indentation_level;
2868
                        }
2869
                        return; // we've decoded our target type
2870
                     }
2871
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2872
                        return;
2873
                     }
2874
2875
                     skip_value<JSON>::op<Opts>(ctx, it, end);
2876
                     if (bool(ctx.error)) [[unlikely]]
2877
                        return;
2878
                     if (skip_ws<Opts>(ctx, it, end)) {
2879
                        return;
2880
                     }
2881
                  }
2882
                  ctx.error = error_code::no_matching_variant_type;
2883
               }
2884
0
               break;
2885
15.5k
            case '[':
2886
15.5k
               using array_types = typename variant_types<T>::array_types;
2887
2888
15.5k
               if (ctx.indentation_level >= max_recursive_depth_limit) {
2889
1
                  ctx.error = error_code::exceeded_max_recursive_depth;
2890
1
                  return;
2891
1
               }
2892
               if constexpr (Opts.null_terminated) {
2893
                  // In the null terminated case this guards for stack overflow
2894
                  // Depth counting is done at the object level when not null terminated
2895
                  ++ctx.indentation_level;
2896
               }
2897
15.5k
               process_arithmetic_boolean_string_or_array<array_types>::template op<Opts>(value, ctx, it, end);
2898
               if constexpr (Opts.null_terminated) {
2899
                  --ctx.indentation_level;
2900
               }
2901
15.5k
               break;
2902
4.06k
            case '"': {
2903
4.06k
               using string_types = typename variant_types<T>::string_types;
2904
4.06k
               process_arithmetic_boolean_string_or_array<string_types>::template op<Opts>(value, ctx, it, end);
2905
4.06k
               break;
2906
15.5k
            }
2907
901
            case 't':
2908
1.18k
            case 'f': {
2909
1.18k
               using bool_types = typename variant_types<T>::bool_types;
2910
1.18k
               process_arithmetic_boolean_string_or_array<bool_types>::template op<Opts>(value, ctx, it, end);
2911
1.18k
               break;
2912
901
            }
2913
845
            case 'n':
2914
845
               using nullable_types = typename variant_types<T>::nullable_types;
2915
               if constexpr (glz::tuple_size_v<nullable_types> < 1) {
2916
                  ctx.error = error_code::no_matching_variant_type;
2917
               }
2918
845
               else {
2919
845
                  using V = glz::tuple_element_t<0, nullable_types>;
2920
845
                  if (!std::holds_alternative<V>(value)) value = V{};
2921
845
                  match<"null", Opts>(ctx, it, end);
2922
845
               }
2923
845
               break;
2924
1.72M
            default: {
2925
               // Not bool, string, object, or array so must be number or null
2926
1.72M
               using number_types = typename variant_types<T>::number_types;
2927
1.72M
               process_arithmetic_boolean_string_or_array<number_types>::template op<Opts>(value, ctx, it, end);
2928
1.72M
            }
2929
1.75M
            }
2930
         }
2931
         else {
2932
            std::visit([&](auto&& v) { parse<JSON>::op<Options>(v, ctx, it, end); }, value);
2933
         }
2934
1.75M
      }
_ZN3glz4fromILj10ENSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_6json_tENS6_ISA_EEEENS1_3mapIS8_SA_NS1_4lessIvEENS6_INS1_4pairIKS8_SA_EEEEEEEEEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1EEERSL_TkNS_10is_contextERNS_7contextERPKcSU_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
2606
6.19k
      {
2607
6.19k
         constexpr auto Opts = ws_handled_off<Options>();
2608
6.19k
         if constexpr (variant_is_auto_deducible<T>()) {
2609
6.19k
            if constexpr (not check_ws_handled(Options)) {
2610
6.19k
               if (skip_ws<Opts>(ctx, it, end)) {
2611
0
                  return;
2612
0
               }
2613
6.19k
            }
2614
2615
6.19k
            switch (*it) {
2616
13
            case '\0':
2617
13
               ctx.error = error_code::unexpected_end;
2618
13
               return;
2619
1.66k
            case '{':
2620
1.66k
               if (ctx.indentation_level >= max_recursive_depth_limit) {
2621
0
                  ctx.error = error_code::exceeded_max_recursive_depth;
2622
0
                  return;
2623
0
               }
2624
               // In the null terminated case this guards for stack overflow
2625
               // Depth counting is done at the object level when not null terminated
2626
1.66k
               ++ctx.indentation_level;
2627
2628
1.66k
               ++it;
2629
               if constexpr (not Opts.null_terminated) {
2630
                  if (it == end) [[unlikely]] {
2631
                     ctx.error = error_code::unexpected_end;
2632
                     return;
2633
                  }
2634
               }
2635
1.66k
               using type_counts = variant_type_count<T>;
2636
1.66k
               using object_types = typename variant_types<T>::object_types;
2637
               if constexpr ((type_counts::n_object < 1) //
2638
                             && (type_counts::n_nullable_object < 1)) {
2639
                  ctx.error = error_code::no_matching_variant_type;
2640
                  return;
2641
               }
2642
1.66k
               else if constexpr ((type_counts::n_object + type_counts::n_nullable_object) == 1 && tag_v<T>.empty()) {
2643
1.66k
                  using V = glz::tuple_element_t<0, object_types>;
2644
1.66k
                  if (!std::holds_alternative<V>(value)) value = V{};
2645
1.66k
                  parse<JSON>::op<opening_handled<Opts>()>(std::get<V>(value), ctx, it, end);
2646
1.66k
                  if constexpr (Opts.null_terminated) {
2647
                     // In the null terminated case this guards for stack overflow
2648
                     // Depth counting is done at the object level when not null terminated
2649
1.66k
                     --ctx.indentation_level;
2650
1.66k
                  }
2651
1.66k
                  return;
2652
               }
2653
               else {
2654
                  auto possible_types = bit_array<std::variant_size_v<T>>{}.flip();
2655
                  static constexpr auto deduction_map = make_variant_deduction_map<T>();
2656
                  static constexpr auto tag_literal = string_literal_from_view<tag_v<T>.size()>(tag_v<T>);
2657
                  if (skip_ws<Opts>(ctx, it, end)) {
2658
                     return;
2659
                  }
2660
                  auto start = it;
2661
                  while (*it != '}') {
2662
                     if (it != start) {
2663
                        if (match_invalid_end<',', Opts>(ctx, it, end)) {
2664
                           return;
2665
                        }
2666
                     }
2667
2668
                     if (skip_ws<Opts>(ctx, it, end)) {
2669
                        return;
2670
                     }
2671
                     if (match_invalid_end<'"', Opts>(ctx, it, end)) {
2672
                        return;
2673
                     }
2674
2675
                     auto* key_start = it;
2676
                     skip_string_view<Opts>(ctx, it, end);
2677
                     if (bool(ctx.error)) [[unlikely]]
2678
                        return;
2679
                     const sv key = {key_start, size_t(it - key_start)};
2680
2681
                     if (match_invalid_end<'"', Opts>(ctx, it, end)) {
2682
                        return;
2683
                     }
2684
2685
                     if constexpr (deduction_map.size()) {
2686
                        // We first check if a tag is defined and see if the key matches the tag
2687
                        if constexpr (not tag_v<T>.empty()) {
2688
                           if (key == tag_v<T>) {
2689
                              if (parse_ws_colon<Opts>(ctx, it, end)) {
2690
                                 return;
2691
                              }
2692
2693
                              using id_type = std::decay_t<decltype(ids_v<T>[0])>;
2694
2695
                              std::conditional_t<std::integral<id_type>, id_type, sv> type_id{};
2696
                              if constexpr (std::integral<id_type>) {
2697
                                 from<JSON, id_type>::template op<ws_handled<Opts>()>(type_id, ctx, it, end);
2698
                              }
2699
                              else {
2700
                                 from<JSON, sv>::template op<ws_handled<Opts>()>(type_id, ctx, it, end);
2701
                              }
2702
                              if (bool(ctx.error)) [[unlikely]]
2703
                                 return;
2704
                              if (skip_ws<Opts>(ctx, it, end)) {
2705
                                 return;
2706
                              }
2707
                              if (!(*it == ',' || *it == '}')) [[unlikely]] {
2708
                                 ctx.error = error_code::syntax_error;
2709
                                 return;
2710
                              }
2711
2712
                              static constexpr auto id_map = make_variant_id_map<T>();
2713
                              auto id_it = id_map.find(type_id);
2714
                              if (id_it != id_map.end()) [[likely]] {
2715
                                 it = start; // we restart our object parsing now that we know the target type
2716
                                 const auto type_index = id_it->second;
2717
                                 if (value.index() != type_index) value = runtime_variant_map<T>()[type_index];
2718
                                 std::visit(
2719
                                    [&](auto&& v) {
2720
                                       using V = std::decay_t<decltype(v)>;
2721
                                       constexpr bool is_object = glaze_object_t<V> || reflectable<V>;
2722
                                       if constexpr (is_object) {
2723
                                          from<JSON, V>::template op<opening_handled<Opts>(), tag_literal>(v, ctx, it,
2724
                                                                                                           end);
2725
                                       }
2726
                                       else if constexpr (is_memory_object<V>) {
2727
                                          if (!v) {
2728
                                             if constexpr (is_specialization_v<V, std::optional>) {
2729
                                                if constexpr (requires { v.emplace(); }) {
2730
                                                   v.emplace();
2731
                                                }
2732
                                                else {
2733
                                                   v = typename V::value_type{};
2734
                                                }
2735
                                             }
2736
                                             else if constexpr (is_specialization_v<V, std::unique_ptr>)
2737
                                                v = std::make_unique<typename V::element_type>();
2738
                                             else if constexpr (is_specialization_v<V, std::shared_ptr>)
2739
                                                v = std::make_shared<typename V::element_type>();
2740
                                             else if constexpr (constructible<V>) {
2741
                                                v = meta_construct_v<V>();
2742
                                             }
2743
                                             else {
2744
                                                ctx.error = error_code::invalid_nullable_read;
2745
                                                return;
2746
                                                // Cannot read into unset nullable that is not std::optional,
2747
                                                // std::unique_ptr, or std::shared_ptr
2748
                                             }
2749
                                          }
2750
                                          from<JSON, memory_type<V>>::template op<opening_handled<Opts>(), tag_literal>(
2751
                                             *v, ctx, it, end);
2752
                                       }
2753
                                    },
2754
                                    value);
2755
2756
                                 if constexpr (Opts.null_terminated) {
2757
                                    // In the null terminated case this guards for stack overflow
2758
                                    // Depth counting is done at the object level when not null terminated
2759
                                    --ctx.indentation_level;
2760
                                 }
2761
                                 return; // we've decoded our target type
2762
                              }
2763
                              else [[unlikely]] {
2764
                                 ctx.error = error_code::no_matching_variant_type;
2765
                                 return;
2766
                              }
2767
                           }
2768
                        }
2769
2770
                        auto deduction_it = deduction_map.find(key);
2771
                        if (deduction_it != deduction_map.end()) [[likely]] {
2772
                           possible_types &= deduction_it->second;
2773
                        }
2774
                        else if constexpr (Opts.error_on_unknown_keys) {
2775
                           ctx.error = error_code::unknown_key;
2776
                           return;
2777
                        }
2778
                     }
2779
                     else if constexpr (not tag_v<T>.empty()) {
2780
                        // empty object case for variant, if there are no normal elements
2781
                        if (key == tag_v<T>) {
2782
                           if (parse_ws_colon<Opts>(ctx, it, end)) {
2783
                              return;
2784
                           }
2785
2786
                           std::string_view type_id{};
2787
                           parse<JSON>::op<ws_handled<Opts>()>(type_id, ctx, it, end);
2788
                           if (bool(ctx.error)) [[unlikely]]
2789
                              return;
2790
                           if (skip_ws<Opts>(ctx, it, end)) {
2791
                              return;
2792
                           }
2793
2794
                           static constexpr auto id_map = make_variant_id_map<T>();
2795
                           auto id_it = id_map.find(type_id);
2796
                           if (id_it != id_map.end()) [[likely]] {
2797
                              it = start;
2798
                              const auto type_index = id_it->second;
2799
                              if (value.index() != type_index) value = runtime_variant_map<T>()[type_index];
2800
                              return;
2801
                           }
2802
                           else {
2803
                              ctx.error = error_code::no_matching_variant_type;
2804
                              return;
2805
                           }
2806
                        }
2807
                        else if constexpr (Opts.error_on_unknown_keys) {
2808
                           ctx.error = error_code::unknown_key;
2809
                           return;
2810
                        }
2811
                     }
2812
                     else if constexpr (Opts.error_on_unknown_keys) {
2813
                        ctx.error = error_code::unknown_key;
2814
                        return;
2815
                     }
2816
2817
                     auto matching_types = possible_types.popcount();
2818
                     if (matching_types == 0) {
2819
                        ctx.error = error_code::no_matching_variant_type;
2820
                        return;
2821
                     }
2822
                     else if (matching_types == 1) {
2823
                        it = start;
2824
                        const auto type_index = possible_types.countr_zero();
2825
                        if (value.index() != static_cast<size_t>(type_index))
2826
                           value = runtime_variant_map<T>()[type_index];
2827
                        std::visit(
2828
                           [&](auto&& v) {
2829
                              using V = std::decay_t<decltype(v)>;
2830
                              constexpr bool is_object = glaze_object_t<V> || reflectable<V>;
2831
                              if constexpr (is_object) {
2832
                                 from<JSON, V>::template op<opening_handled<Opts>(), tag_literal>(v, ctx, it, end);
2833
                              }
2834
                              else if constexpr (is_memory_object<V>) {
2835
                                 if (!v) {
2836
                                    if constexpr (is_specialization_v<V, std::optional>) {
2837
                                       if constexpr (requires { v.emplace(); }) {
2838
                                          v.emplace();
2839
                                       }
2840
                                       else {
2841
                                          v = typename V::value_type{};
2842
                                       }
2843
                                    }
2844
                                    else if constexpr (is_specialization_v<V, std::unique_ptr>)
2845
                                       v = std::make_unique<typename V::element_type>();
2846
                                    else if constexpr (is_specialization_v<V, std::shared_ptr>)
2847
                                       v = std::make_shared<typename V::element_type>();
2848
                                    else if constexpr (constructible<V>) {
2849
                                       v = meta_construct_v<V>();
2850
                                    }
2851
                                    else {
2852
                                       ctx.error = error_code::invalid_nullable_read;
2853
                                       return;
2854
                                       // Cannot read into unset nullable that is not std::optional,
2855
                                       // std::unique_ptr, or std::shared_ptr
2856
                                    }
2857
                                 }
2858
                                 from<JSON, memory_type<V>>::template op<opening_handled<Opts>(), tag_literal>(*v, ctx,
2859
                                                                                                               it, end);
2860
                              }
2861
                           },
2862
                           value);
2863
2864
                        if constexpr (Opts.null_terminated) {
2865
                           // In the null terminated case this guards for stack overflow
2866
                           // Depth counting is done at the object level when not null terminated
2867
                           --ctx.indentation_level;
2868
                        }
2869
                        return; // we've decoded our target type
2870
                     }
2871
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2872
                        return;
2873
                     }
2874
2875
                     skip_value<JSON>::op<Opts>(ctx, it, end);
2876
                     if (bool(ctx.error)) [[unlikely]]
2877
                        return;
2878
                     if (skip_ws<Opts>(ctx, it, end)) {
2879
                        return;
2880
                     }
2881
                  }
2882
                  ctx.error = error_code::no_matching_variant_type;
2883
               }
2884
0
               break;
2885
1.58k
            case '[':
2886
1.58k
               using array_types = typename variant_types<T>::array_types;
2887
2888
1.58k
               if (ctx.indentation_level >= max_recursive_depth_limit) {
2889
0
                  ctx.error = error_code::exceeded_max_recursive_depth;
2890
0
                  return;
2891
0
               }
2892
1.58k
               if constexpr (Opts.null_terminated) {
2893
                  // In the null terminated case this guards for stack overflow
2894
                  // Depth counting is done at the object level when not null terminated
2895
1.58k
                  ++ctx.indentation_level;
2896
1.58k
               }
2897
1.58k
               process_arithmetic_boolean_string_or_array<array_types>::template op<Opts>(value, ctx, it, end);
2898
1.58k
               if constexpr (Opts.null_terminated) {
2899
1.58k
                  --ctx.indentation_level;
2900
1.58k
               }
2901
1.58k
               break;
2902
412
            case '"': {
2903
412
               using string_types = typename variant_types<T>::string_types;
2904
412
               process_arithmetic_boolean_string_or_array<string_types>::template op<Opts>(value, ctx, it, end);
2905
412
               break;
2906
1.58k
            }
2907
48
            case 't':
2908
124
            case 'f': {
2909
124
               using bool_types = typename variant_types<T>::bool_types;
2910
124
               process_arithmetic_boolean_string_or_array<bool_types>::template op<Opts>(value, ctx, it, end);
2911
124
               break;
2912
48
            }
2913
56
            case 'n':
2914
56
               using nullable_types = typename variant_types<T>::nullable_types;
2915
               if constexpr (glz::tuple_size_v<nullable_types> < 1) {
2916
                  ctx.error = error_code::no_matching_variant_type;
2917
               }
2918
56
               else {
2919
56
                  using V = glz::tuple_element_t<0, nullable_types>;
2920
56
                  if (!std::holds_alternative<V>(value)) value = V{};
2921
56
                  match<"null", Opts>(ctx, it, end);
2922
56
               }
2923
56
               break;
2924
2.34k
            default: {
2925
               // Not bool, string, object, or array so must be number or null
2926
2.34k
               using number_types = typename variant_types<T>::number_types;
2927
2.34k
               process_arithmetic_boolean_string_or_array<number_types>::template op<Opts>(value, ctx, it, end);
2928
2.34k
            }
2929
6.19k
            }
2930
         }
2931
         else {
2932
            std::visit([&](auto&& v) { parse<JSON>::op<Options>(v, ctx, it, end); }, value);
2933
         }
2934
6.19k
      }
_ZN3glz4fromILj10ENSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_6json_tENS6_ISA_EEEENS1_3mapIS8_SA_NS1_4lessIvEENS6_INS1_4pairIKS8_SA_EEEEEEEEEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj4EEERSL_TkNS_10is_contextERNS_7contextERPKcSU_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
2606
1.75M
      {
2607
1.75M
         constexpr auto Opts = ws_handled_off<Options>();
2608
1.75M
         if constexpr (variant_is_auto_deducible<T>()) {
2609
            if constexpr (not check_ws_handled(Options)) {
2610
               if (skip_ws<Opts>(ctx, it, end)) {
2611
                  return;
2612
               }
2613
            }
2614
2615
1.75M
            switch (*it) {
2616
750
            case '\0':
2617
750
               ctx.error = error_code::unexpected_end;
2618
750
               return;
2619
6.20k
            case '{':
2620
6.20k
               if (ctx.indentation_level >= max_recursive_depth_limit) {
2621
3
                  ctx.error = error_code::exceeded_max_recursive_depth;
2622
3
                  return;
2623
3
               }
2624
               // In the null terminated case this guards for stack overflow
2625
               // Depth counting is done at the object level when not null terminated
2626
6.19k
               ++ctx.indentation_level;
2627
2628
6.19k
               ++it;
2629
               if constexpr (not Opts.null_terminated) {
2630
                  if (it == end) [[unlikely]] {
2631
                     ctx.error = error_code::unexpected_end;
2632
                     return;
2633
                  }
2634
               }
2635
6.19k
               using type_counts = variant_type_count<T>;
2636
6.19k
               using object_types = typename variant_types<T>::object_types;
2637
               if constexpr ((type_counts::n_object < 1) //
2638
                             && (type_counts::n_nullable_object < 1)) {
2639
                  ctx.error = error_code::no_matching_variant_type;
2640
                  return;
2641
               }
2642
6.19k
               else if constexpr ((type_counts::n_object + type_counts::n_nullable_object) == 1 && tag_v<T>.empty()) {
2643
6.19k
                  using V = glz::tuple_element_t<0, object_types>;
2644
6.19k
                  if (!std::holds_alternative<V>(value)) value = V{};
2645
6.19k
                  parse<JSON>::op<opening_handled<Opts>()>(std::get<V>(value), ctx, it, end);
2646
6.19k
                  if constexpr (Opts.null_terminated) {
2647
                     // In the null terminated case this guards for stack overflow
2648
                     // Depth counting is done at the object level when not null terminated
2649
6.19k
                     --ctx.indentation_level;
2650
6.19k
                  }
2651
6.19k
                  return;
2652
               }
2653
               else {
2654
                  auto possible_types = bit_array<std::variant_size_v<T>>{}.flip();
2655
                  static constexpr auto deduction_map = make_variant_deduction_map<T>();
2656
                  static constexpr auto tag_literal = string_literal_from_view<tag_v<T>.size()>(tag_v<T>);
2657
                  if (skip_ws<Opts>(ctx, it, end)) {
2658
                     return;
2659
                  }
2660
                  auto start = it;
2661
                  while (*it != '}') {
2662
                     if (it != start) {
2663
                        if (match_invalid_end<',', Opts>(ctx, it, end)) {
2664
                           return;
2665
                        }
2666
                     }
2667
2668
                     if (skip_ws<Opts>(ctx, it, end)) {
2669
                        return;
2670
                     }
2671
                     if (match_invalid_end<'"', Opts>(ctx, it, end)) {
2672
                        return;
2673
                     }
2674
2675
                     auto* key_start = it;
2676
                     skip_string_view<Opts>(ctx, it, end);
2677
                     if (bool(ctx.error)) [[unlikely]]
2678
                        return;
2679
                     const sv key = {key_start, size_t(it - key_start)};
2680
2681
                     if (match_invalid_end<'"', Opts>(ctx, it, end)) {
2682
                        return;
2683
                     }
2684
2685
                     if constexpr (deduction_map.size()) {
2686
                        // We first check if a tag is defined and see if the key matches the tag
2687
                        if constexpr (not tag_v<T>.empty()) {
2688
                           if (key == tag_v<T>) {
2689
                              if (parse_ws_colon<Opts>(ctx, it, end)) {
2690
                                 return;
2691
                              }
2692
2693
                              using id_type = std::decay_t<decltype(ids_v<T>[0])>;
2694
2695
                              std::conditional_t<std::integral<id_type>, id_type, sv> type_id{};
2696
                              if constexpr (std::integral<id_type>) {
2697
                                 from<JSON, id_type>::template op<ws_handled<Opts>()>(type_id, ctx, it, end);
2698
                              }
2699
                              else {
2700
                                 from<JSON, sv>::template op<ws_handled<Opts>()>(type_id, ctx, it, end);
2701
                              }
2702
                              if (bool(ctx.error)) [[unlikely]]
2703
                                 return;
2704
                              if (skip_ws<Opts>(ctx, it, end)) {
2705
                                 return;
2706
                              }
2707
                              if (!(*it == ',' || *it == '}')) [[unlikely]] {
2708
                                 ctx.error = error_code::syntax_error;
2709
                                 return;
2710
                              }
2711
2712
                              static constexpr auto id_map = make_variant_id_map<T>();
2713
                              auto id_it = id_map.find(type_id);
2714
                              if (id_it != id_map.end()) [[likely]] {
2715
                                 it = start; // we restart our object parsing now that we know the target type
2716
                                 const auto type_index = id_it->second;
2717
                                 if (value.index() != type_index) value = runtime_variant_map<T>()[type_index];
2718
                                 std::visit(
2719
                                    [&](auto&& v) {
2720
                                       using V = std::decay_t<decltype(v)>;
2721
                                       constexpr bool is_object = glaze_object_t<V> || reflectable<V>;
2722
                                       if constexpr (is_object) {
2723
                                          from<JSON, V>::template op<opening_handled<Opts>(), tag_literal>(v, ctx, it,
2724
                                                                                                           end);
2725
                                       }
2726
                                       else if constexpr (is_memory_object<V>) {
2727
                                          if (!v) {
2728
                                             if constexpr (is_specialization_v<V, std::optional>) {
2729
                                                if constexpr (requires { v.emplace(); }) {
2730
                                                   v.emplace();
2731
                                                }
2732
                                                else {
2733
                                                   v = typename V::value_type{};
2734
                                                }
2735
                                             }
2736
                                             else if constexpr (is_specialization_v<V, std::unique_ptr>)
2737
                                                v = std::make_unique<typename V::element_type>();
2738
                                             else if constexpr (is_specialization_v<V, std::shared_ptr>)
2739
                                                v = std::make_shared<typename V::element_type>();
2740
                                             else if constexpr (constructible<V>) {
2741
                                                v = meta_construct_v<V>();
2742
                                             }
2743
                                             else {
2744
                                                ctx.error = error_code::invalid_nullable_read;
2745
                                                return;
2746
                                                // Cannot read into unset nullable that is not std::optional,
2747
                                                // std::unique_ptr, or std::shared_ptr
2748
                                             }
2749
                                          }
2750
                                          from<JSON, memory_type<V>>::template op<opening_handled<Opts>(), tag_literal>(
2751
                                             *v, ctx, it, end);
2752
                                       }
2753
                                    },
2754
                                    value);
2755
2756
                                 if constexpr (Opts.null_terminated) {
2757
                                    // In the null terminated case this guards for stack overflow
2758
                                    // Depth counting is done at the object level when not null terminated
2759
                                    --ctx.indentation_level;
2760
                                 }
2761
                                 return; // we've decoded our target type
2762
                              }
2763
                              else [[unlikely]] {
2764
                                 ctx.error = error_code::no_matching_variant_type;
2765
                                 return;
2766
                              }
2767
                           }
2768
                        }
2769
2770
                        auto deduction_it = deduction_map.find(key);
2771
                        if (deduction_it != deduction_map.end()) [[likely]] {
2772
                           possible_types &= deduction_it->second;
2773
                        }
2774
                        else if constexpr (Opts.error_on_unknown_keys) {
2775
                           ctx.error = error_code::unknown_key;
2776
                           return;
2777
                        }
2778
                     }
2779
                     else if constexpr (not tag_v<T>.empty()) {
2780
                        // empty object case for variant, if there are no normal elements
2781
                        if (key == tag_v<T>) {
2782
                           if (parse_ws_colon<Opts>(ctx, it, end)) {
2783
                              return;
2784
                           }
2785
2786
                           std::string_view type_id{};
2787
                           parse<JSON>::op<ws_handled<Opts>()>(type_id, ctx, it, end);
2788
                           if (bool(ctx.error)) [[unlikely]]
2789
                              return;
2790
                           if (skip_ws<Opts>(ctx, it, end)) {
2791
                              return;
2792
                           }
2793
2794
                           static constexpr auto id_map = make_variant_id_map<T>();
2795
                           auto id_it = id_map.find(type_id);
2796
                           if (id_it != id_map.end()) [[likely]] {
2797
                              it = start;
2798
                              const auto type_index = id_it->second;
2799
                              if (value.index() != type_index) value = runtime_variant_map<T>()[type_index];
2800
                              return;
2801
                           }
2802
                           else {
2803
                              ctx.error = error_code::no_matching_variant_type;
2804
                              return;
2805
                           }
2806
                        }
2807
                        else if constexpr (Opts.error_on_unknown_keys) {
2808
                           ctx.error = error_code::unknown_key;
2809
                           return;
2810
                        }
2811
                     }
2812
                     else if constexpr (Opts.error_on_unknown_keys) {
2813
                        ctx.error = error_code::unknown_key;
2814
                        return;
2815
                     }
2816
2817
                     auto matching_types = possible_types.popcount();
2818
                     if (matching_types == 0) {
2819
                        ctx.error = error_code::no_matching_variant_type;
2820
                        return;
2821
                     }
2822
                     else if (matching_types == 1) {
2823
                        it = start;
2824
                        const auto type_index = possible_types.countr_zero();
2825
                        if (value.index() != static_cast<size_t>(type_index))
2826
                           value = runtime_variant_map<T>()[type_index];
2827
                        std::visit(
2828
                           [&](auto&& v) {
2829
                              using V = std::decay_t<decltype(v)>;
2830
                              constexpr bool is_object = glaze_object_t<V> || reflectable<V>;
2831
                              if constexpr (is_object) {
2832
                                 from<JSON, V>::template op<opening_handled<Opts>(), tag_literal>(v, ctx, it, end);
2833
                              }
2834
                              else if constexpr (is_memory_object<V>) {
2835
                                 if (!v) {
2836
                                    if constexpr (is_specialization_v<V, std::optional>) {
2837
                                       if constexpr (requires { v.emplace(); }) {
2838
                                          v.emplace();
2839
                                       }
2840
                                       else {
2841
                                          v = typename V::value_type{};
2842
                                       }
2843
                                    }
2844
                                    else if constexpr (is_specialization_v<V, std::unique_ptr>)
2845
                                       v = std::make_unique<typename V::element_type>();
2846
                                    else if constexpr (is_specialization_v<V, std::shared_ptr>)
2847
                                       v = std::make_shared<typename V::element_type>();
2848
                                    else if constexpr (constructible<V>) {
2849
                                       v = meta_construct_v<V>();
2850
                                    }
2851
                                    else {
2852
                                       ctx.error = error_code::invalid_nullable_read;
2853
                                       return;
2854
                                       // Cannot read into unset nullable that is not std::optional,
2855
                                       // std::unique_ptr, or std::shared_ptr
2856
                                    }
2857
                                 }
2858
                                 from<JSON, memory_type<V>>::template op<opening_handled<Opts>(), tag_literal>(*v, ctx,
2859
                                                                                                               it, end);
2860
                              }
2861
                           },
2862
                           value);
2863
2864
                        if constexpr (Opts.null_terminated) {
2865
                           // In the null terminated case this guards for stack overflow
2866
                           // Depth counting is done at the object level when not null terminated
2867
                           --ctx.indentation_level;
2868
                        }
2869
                        return; // we've decoded our target type
2870
                     }
2871
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2872
                        return;
2873
                     }
2874
2875
                     skip_value<JSON>::op<Opts>(ctx, it, end);
2876
                     if (bool(ctx.error)) [[unlikely]]
2877
                        return;
2878
                     if (skip_ws<Opts>(ctx, it, end)) {
2879
                        return;
2880
                     }
2881
                  }
2882
                  ctx.error = error_code::no_matching_variant_type;
2883
               }
2884
0
               break;
2885
15.5k
            case '[':
2886
15.5k
               using array_types = typename variant_types<T>::array_types;
2887
2888
15.5k
               if (ctx.indentation_level >= max_recursive_depth_limit) {
2889
1
                  ctx.error = error_code::exceeded_max_recursive_depth;
2890
1
                  return;
2891
1
               }
2892
15.5k
               if constexpr (Opts.null_terminated) {
2893
                  // In the null terminated case this guards for stack overflow
2894
                  // Depth counting is done at the object level when not null terminated
2895
15.5k
                  ++ctx.indentation_level;
2896
15.5k
               }
2897
15.5k
               process_arithmetic_boolean_string_or_array<array_types>::template op<Opts>(value, ctx, it, end);
2898
15.5k
               if constexpr (Opts.null_terminated) {
2899
15.5k
                  --ctx.indentation_level;
2900
15.5k
               }
2901
15.5k
               break;
2902
4.06k
            case '"': {
2903
4.06k
               using string_types = typename variant_types<T>::string_types;
2904
4.06k
               process_arithmetic_boolean_string_or_array<string_types>::template op<Opts>(value, ctx, it, end);
2905
4.06k
               break;
2906
15.5k
            }
2907
901
            case 't':
2908
1.18k
            case 'f': {
2909
1.18k
               using bool_types = typename variant_types<T>::bool_types;
2910
1.18k
               process_arithmetic_boolean_string_or_array<bool_types>::template op<Opts>(value, ctx, it, end);
2911
1.18k
               break;
2912
901
            }
2913
845
            case 'n':
2914
845
               using nullable_types = typename variant_types<T>::nullable_types;
2915
               if constexpr (glz::tuple_size_v<nullable_types> < 1) {
2916
                  ctx.error = error_code::no_matching_variant_type;
2917
               }
2918
845
               else {
2919
845
                  using V = glz::tuple_element_t<0, nullable_types>;
2920
845
                  if (!std::holds_alternative<V>(value)) value = V{};
2921
845
                  match<"null", Opts>(ctx, it, end);
2922
845
               }
2923
845
               break;
2924
1.72M
            default: {
2925
               // Not bool, string, object, or array so must be number or null
2926
1.72M
               using number_types = typename variant_types<T>::number_types;
2927
1.72M
               process_arithmetic_boolean_string_or_array<number_types>::template op<Opts>(value, ctx, it, end);
2928
1.72M
            }
2929
1.75M
            }
2930
         }
2931
         else {
2932
            std::visit([&](auto&& v) { parse<JSON>::op<Options>(v, ctx, it, end); }, value);
2933
         }
2934
1.75M
      }
_ZN3glz4fromILj10ENSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_6json_tENS6_ISA_EEEENS1_3mapIS8_SA_NS1_4lessIvEENS6_INS1_4pairIKS8_SA_EEEEEEEEEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj32EEERSL_TkNS_10is_contextERNS_7contextERPKcSU_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
2606
6.19k
      {
2607
6.19k
         constexpr auto Opts = ws_handled_off<Options>();
2608
6.19k
         if constexpr (variant_is_auto_deducible<T>()) {
2609
6.19k
            if constexpr (not check_ws_handled(Options)) {
2610
6.19k
               if (skip_ws<Opts>(ctx, it, end)) {
2611
0
                  return;
2612
0
               }
2613
6.19k
            }
2614
2615
6.19k
            switch (*it) {
2616
13
            case '\0':
2617
13
               ctx.error = error_code::unexpected_end;
2618
13
               return;
2619
1.66k
            case '{':
2620
1.66k
               if (ctx.indentation_level >= max_recursive_depth_limit) {
2621
0
                  ctx.error = error_code::exceeded_max_recursive_depth;
2622
0
                  return;
2623
0
               }
2624
               // In the null terminated case this guards for stack overflow
2625
               // Depth counting is done at the object level when not null terminated
2626
1.66k
               ++ctx.indentation_level;
2627
2628
1.66k
               ++it;
2629
               if constexpr (not Opts.null_terminated) {
2630
                  if (it == end) [[unlikely]] {
2631
                     ctx.error = error_code::unexpected_end;
2632
                     return;
2633
                  }
2634
               }
2635
1.66k
               using type_counts = variant_type_count<T>;
2636
1.66k
               using object_types = typename variant_types<T>::object_types;
2637
               if constexpr ((type_counts::n_object < 1) //
2638
                             && (type_counts::n_nullable_object < 1)) {
2639
                  ctx.error = error_code::no_matching_variant_type;
2640
                  return;
2641
               }
2642
1.66k
               else if constexpr ((type_counts::n_object + type_counts::n_nullable_object) == 1 && tag_v<T>.empty()) {
2643
1.66k
                  using V = glz::tuple_element_t<0, object_types>;
2644
1.66k
                  if (!std::holds_alternative<V>(value)) value = V{};
2645
1.66k
                  parse<JSON>::op<opening_handled<Opts>()>(std::get<V>(value), ctx, it, end);
2646
1.66k
                  if constexpr (Opts.null_terminated) {
2647
                     // In the null terminated case this guards for stack overflow
2648
                     // Depth counting is done at the object level when not null terminated
2649
1.66k
                     --ctx.indentation_level;
2650
1.66k
                  }
2651
1.66k
                  return;
2652
               }
2653
               else {
2654
                  auto possible_types = bit_array<std::variant_size_v<T>>{}.flip();
2655
                  static constexpr auto deduction_map = make_variant_deduction_map<T>();
2656
                  static constexpr auto tag_literal = string_literal_from_view<tag_v<T>.size()>(tag_v<T>);
2657
                  if (skip_ws<Opts>(ctx, it, end)) {
2658
                     return;
2659
                  }
2660
                  auto start = it;
2661
                  while (*it != '}') {
2662
                     if (it != start) {
2663
                        if (match_invalid_end<',', Opts>(ctx, it, end)) {
2664
                           return;
2665
                        }
2666
                     }
2667
2668
                     if (skip_ws<Opts>(ctx, it, end)) {
2669
                        return;
2670
                     }
2671
                     if (match_invalid_end<'"', Opts>(ctx, it, end)) {
2672
                        return;
2673
                     }
2674
2675
                     auto* key_start = it;
2676
                     skip_string_view<Opts>(ctx, it, end);
2677
                     if (bool(ctx.error)) [[unlikely]]
2678
                        return;
2679
                     const sv key = {key_start, size_t(it - key_start)};
2680
2681
                     if (match_invalid_end<'"', Opts>(ctx, it, end)) {
2682
                        return;
2683
                     }
2684
2685
                     if constexpr (deduction_map.size()) {
2686
                        // We first check if a tag is defined and see if the key matches the tag
2687
                        if constexpr (not tag_v<T>.empty()) {
2688
                           if (key == tag_v<T>) {
2689
                              if (parse_ws_colon<Opts>(ctx, it, end)) {
2690
                                 return;
2691
                              }
2692
2693
                              using id_type = std::decay_t<decltype(ids_v<T>[0])>;
2694
2695
                              std::conditional_t<std::integral<id_type>, id_type, sv> type_id{};
2696
                              if constexpr (std::integral<id_type>) {
2697
                                 from<JSON, id_type>::template op<ws_handled<Opts>()>(type_id, ctx, it, end);
2698
                              }
2699
                              else {
2700
                                 from<JSON, sv>::template op<ws_handled<Opts>()>(type_id, ctx, it, end);
2701
                              }
2702
                              if (bool(ctx.error)) [[unlikely]]
2703
                                 return;
2704
                              if (skip_ws<Opts>(ctx, it, end)) {
2705
                                 return;
2706
                              }
2707
                              if (!(*it == ',' || *it == '}')) [[unlikely]] {
2708
                                 ctx.error = error_code::syntax_error;
2709
                                 return;
2710
                              }
2711
2712
                              static constexpr auto id_map = make_variant_id_map<T>();
2713
                              auto id_it = id_map.find(type_id);
2714
                              if (id_it != id_map.end()) [[likely]] {
2715
                                 it = start; // we restart our object parsing now that we know the target type
2716
                                 const auto type_index = id_it->second;
2717
                                 if (value.index() != type_index) value = runtime_variant_map<T>()[type_index];
2718
                                 std::visit(
2719
                                    [&](auto&& v) {
2720
                                       using V = std::decay_t<decltype(v)>;
2721
                                       constexpr bool is_object = glaze_object_t<V> || reflectable<V>;
2722
                                       if constexpr (is_object) {
2723
                                          from<JSON, V>::template op<opening_handled<Opts>(), tag_literal>(v, ctx, it,
2724
                                                                                                           end);
2725
                                       }
2726
                                       else if constexpr (is_memory_object<V>) {
2727
                                          if (!v) {
2728
                                             if constexpr (is_specialization_v<V, std::optional>) {
2729
                                                if constexpr (requires { v.emplace(); }) {
2730
                                                   v.emplace();
2731
                                                }
2732
                                                else {
2733
                                                   v = typename V::value_type{};
2734
                                                }
2735
                                             }
2736
                                             else if constexpr (is_specialization_v<V, std::unique_ptr>)
2737
                                                v = std::make_unique<typename V::element_type>();
2738
                                             else if constexpr (is_specialization_v<V, std::shared_ptr>)
2739
                                                v = std::make_shared<typename V::element_type>();
2740
                                             else if constexpr (constructible<V>) {
2741
                                                v = meta_construct_v<V>();
2742
                                             }
2743
                                             else {
2744
                                                ctx.error = error_code::invalid_nullable_read;
2745
                                                return;
2746
                                                // Cannot read into unset nullable that is not std::optional,
2747
                                                // std::unique_ptr, or std::shared_ptr
2748
                                             }
2749
                                          }
2750
                                          from<JSON, memory_type<V>>::template op<opening_handled<Opts>(), tag_literal>(
2751
                                             *v, ctx, it, end);
2752
                                       }
2753
                                    },
2754
                                    value);
2755
2756
                                 if constexpr (Opts.null_terminated) {
2757
                                    // In the null terminated case this guards for stack overflow
2758
                                    // Depth counting is done at the object level when not null terminated
2759
                                    --ctx.indentation_level;
2760
                                 }
2761
                                 return; // we've decoded our target type
2762
                              }
2763
                              else [[unlikely]] {
2764
                                 ctx.error = error_code::no_matching_variant_type;
2765
                                 return;
2766
                              }
2767
                           }
2768
                        }
2769
2770
                        auto deduction_it = deduction_map.find(key);
2771
                        if (deduction_it != deduction_map.end()) [[likely]] {
2772
                           possible_types &= deduction_it->second;
2773
                        }
2774
                        else if constexpr (Opts.error_on_unknown_keys) {
2775
                           ctx.error = error_code::unknown_key;
2776
                           return;
2777
                        }
2778
                     }
2779
                     else if constexpr (not tag_v<T>.empty()) {
2780
                        // empty object case for variant, if there are no normal elements
2781
                        if (key == tag_v<T>) {
2782
                           if (parse_ws_colon<Opts>(ctx, it, end)) {
2783
                              return;
2784
                           }
2785
2786
                           std::string_view type_id{};
2787
                           parse<JSON>::op<ws_handled<Opts>()>(type_id, ctx, it, end);
2788
                           if (bool(ctx.error)) [[unlikely]]
2789
                              return;
2790
                           if (skip_ws<Opts>(ctx, it, end)) {
2791
                              return;
2792
                           }
2793
2794
                           static constexpr auto id_map = make_variant_id_map<T>();
2795
                           auto id_it = id_map.find(type_id);
2796
                           if (id_it != id_map.end()) [[likely]] {
2797
                              it = start;
2798
                              const auto type_index = id_it->second;
2799
                              if (value.index() != type_index) value = runtime_variant_map<T>()[type_index];
2800
                              return;
2801
                           }
2802
                           else {
2803
                              ctx.error = error_code::no_matching_variant_type;
2804
                              return;
2805
                           }
2806
                        }
2807
                        else if constexpr (Opts.error_on_unknown_keys) {
2808
                           ctx.error = error_code::unknown_key;
2809
                           return;
2810
                        }
2811
                     }
2812
                     else if constexpr (Opts.error_on_unknown_keys) {
2813
                        ctx.error = error_code::unknown_key;
2814
                        return;
2815
                     }
2816
2817
                     auto matching_types = possible_types.popcount();
2818
                     if (matching_types == 0) {
2819
                        ctx.error = error_code::no_matching_variant_type;
2820
                        return;
2821
                     }
2822
                     else if (matching_types == 1) {
2823
                        it = start;
2824
                        const auto type_index = possible_types.countr_zero();
2825
                        if (value.index() != static_cast<size_t>(type_index))
2826
                           value = runtime_variant_map<T>()[type_index];
2827
                        std::visit(
2828
                           [&](auto&& v) {
2829
                              using V = std::decay_t<decltype(v)>;
2830
                              constexpr bool is_object = glaze_object_t<V> || reflectable<V>;
2831
                              if constexpr (is_object) {
2832
                                 from<JSON, V>::template op<opening_handled<Opts>(), tag_literal>(v, ctx, it, end);
2833
                              }
2834
                              else if constexpr (is_memory_object<V>) {
2835
                                 if (!v) {
2836
                                    if constexpr (is_specialization_v<V, std::optional>) {
2837
                                       if constexpr (requires { v.emplace(); }) {
2838
                                          v.emplace();
2839
                                       }
2840
                                       else {
2841
                                          v = typename V::value_type{};
2842
                                       }
2843
                                    }
2844
                                    else if constexpr (is_specialization_v<V, std::unique_ptr>)
2845
                                       v = std::make_unique<typename V::element_type>();
2846
                                    else if constexpr (is_specialization_v<V, std::shared_ptr>)
2847
                                       v = std::make_shared<typename V::element_type>();
2848
                                    else if constexpr (constructible<V>) {
2849
                                       v = meta_construct_v<V>();
2850
                                    }
2851
                                    else {
2852
                                       ctx.error = error_code::invalid_nullable_read;
2853
                                       return;
2854
                                       // Cannot read into unset nullable that is not std::optional,
2855
                                       // std::unique_ptr, or std::shared_ptr
2856
                                    }
2857
                                 }
2858
                                 from<JSON, memory_type<V>>::template op<opening_handled<Opts>(), tag_literal>(*v, ctx,
2859
                                                                                                               it, end);
2860
                              }
2861
                           },
2862
                           value);
2863
2864
                        if constexpr (Opts.null_terminated) {
2865
                           // In the null terminated case this guards for stack overflow
2866
                           // Depth counting is done at the object level when not null terminated
2867
                           --ctx.indentation_level;
2868
                        }
2869
                        return; // we've decoded our target type
2870
                     }
2871
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2872
                        return;
2873
                     }
2874
2875
                     skip_value<JSON>::op<Opts>(ctx, it, end);
2876
                     if (bool(ctx.error)) [[unlikely]]
2877
                        return;
2878
                     if (skip_ws<Opts>(ctx, it, end)) {
2879
                        return;
2880
                     }
2881
                  }
2882
                  ctx.error = error_code::no_matching_variant_type;
2883
               }
2884
0
               break;
2885
1.58k
            case '[':
2886
1.58k
               using array_types = typename variant_types<T>::array_types;
2887
2888
1.58k
               if (ctx.indentation_level >= max_recursive_depth_limit) {
2889
0
                  ctx.error = error_code::exceeded_max_recursive_depth;
2890
0
                  return;
2891
0
               }
2892
1.58k
               if constexpr (Opts.null_terminated) {
2893
                  // In the null terminated case this guards for stack overflow
2894
                  // Depth counting is done at the object level when not null terminated
2895
1.58k
                  ++ctx.indentation_level;
2896
1.58k
               }
2897
1.58k
               process_arithmetic_boolean_string_or_array<array_types>::template op<Opts>(value, ctx, it, end);
2898
1.58k
               if constexpr (Opts.null_terminated) {
2899
1.58k
                  --ctx.indentation_level;
2900
1.58k
               }
2901
1.58k
               break;
2902
412
            case '"': {
2903
412
               using string_types = typename variant_types<T>::string_types;
2904
412
               process_arithmetic_boolean_string_or_array<string_types>::template op<Opts>(value, ctx, it, end);
2905
412
               break;
2906
1.58k
            }
2907
48
            case 't':
2908
124
            case 'f': {
2909
124
               using bool_types = typename variant_types<T>::bool_types;
2910
124
               process_arithmetic_boolean_string_or_array<bool_types>::template op<Opts>(value, ctx, it, end);
2911
124
               break;
2912
48
            }
2913
56
            case 'n':
2914
56
               using nullable_types = typename variant_types<T>::nullable_types;
2915
               if constexpr (glz::tuple_size_v<nullable_types> < 1) {
2916
                  ctx.error = error_code::no_matching_variant_type;
2917
               }
2918
56
               else {
2919
56
                  using V = glz::tuple_element_t<0, nullable_types>;
2920
56
                  if (!std::holds_alternative<V>(value)) value = V{};
2921
56
                  match<"null", Opts>(ctx, it, end);
2922
56
               }
2923
56
               break;
2924
2.34k
            default: {
2925
               // Not bool, string, object, or array so must be number or null
2926
2.34k
               using number_types = typename variant_types<T>::number_types;
2927
2.34k
               process_arithmetic_boolean_string_or_array<number_types>::template op<Opts>(value, ctx, it, end);
2928
2.34k
            }
2929
6.19k
            }
2930
         }
2931
         else {
2932
            std::visit([&](auto&& v) { parse<JSON>::op<Options>(v, ctx, it, end); }, value);
2933
         }
2934
6.19k
      }
_ZN3glz4fromILj10ENSt3__17variantIJDndNS1_12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEbNS1_6vectorINS_6json_tENS6_ISA_EEEENS1_3mapIS8_SA_NS1_4lessIvEENS6_INS1_4pairIKS8_SA_EEEEEEEEEE2opITnDaXtlNS_4optsELj10ELb1ELb0ELb1ELb1ELb0ELb0ELc32ELh3ELb1ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELb0ELj36EEERSL_TkNS_10is_contextERNS_7contextERPKcSU_EEvOT0_OT1_OT2_OT3_
Line
Count
Source
2606
1.75M
      {
2607
1.75M
         constexpr auto Opts = ws_handled_off<Options>();
2608
1.75M
         if constexpr (variant_is_auto_deducible<T>()) {
2609
            if constexpr (not check_ws_handled(Options)) {
2610
               if (skip_ws<Opts>(ctx, it, end)) {
2611
                  return;
2612
               }
2613
            }
2614
2615
1.75M
            switch (*it) {
2616
656
            case '\0':
2617
656
               ctx.error = error_code::unexpected_end;
2618
656
               return;
2619
6.20k
            case '{':
2620
6.20k
               if (ctx.indentation_level >= max_recursive_depth_limit) {
2621
3
                  ctx.error = error_code::exceeded_max_recursive_depth;
2622
3
                  return;
2623
3
               }
2624
               // In the null terminated case this guards for stack overflow
2625
               // Depth counting is done at the object level when not null terminated
2626
6.19k
               ++ctx.indentation_level;
2627
2628
6.19k
               ++it;
2629
               if constexpr (not Opts.null_terminated) {
2630
                  if (it == end) [[unlikely]] {
2631
                     ctx.error = error_code::unexpected_end;
2632
                     return;
2633
                  }
2634
               }
2635
6.19k
               using type_counts = variant_type_count<T>;
2636
6.19k
               using object_types = typename variant_types<T>::object_types;
2637
               if constexpr ((type_counts::n_object < 1) //
2638
                             && (type_counts::n_nullable_object < 1)) {
2639
                  ctx.error = error_code::no_matching_variant_type;
2640
                  return;
2641
               }
2642
6.19k
               else if constexpr ((type_counts::n_object + type_counts::n_nullable_object) == 1 && tag_v<T>.empty()) {
2643
6.19k
                  using V = glz::tuple_element_t<0, object_types>;
2644
6.19k
                  if (!std::holds_alternative<V>(value)) value = V{};
2645
6.19k
                  parse<JSON>::op<opening_handled<Opts>()>(std::get<V>(value), ctx, it, end);
2646
6.19k
                  if constexpr (Opts.null_terminated) {
2647
                     // In the null terminated case this guards for stack overflow
2648
                     // Depth counting is done at the object level when not null terminated
2649
6.19k
                     --ctx.indentation_level;
2650
6.19k
                  }
2651
6.19k
                  return;
2652
               }
2653
               else {
2654
                  auto possible_types = bit_array<std::variant_size_v<T>>{}.flip();
2655
                  static constexpr auto deduction_map = make_variant_deduction_map<T>();
2656
                  static constexpr auto tag_literal = string_literal_from_view<tag_v<T>.size()>(tag_v<T>);
2657
                  if (skip_ws<Opts>(ctx, it, end)) {
2658
                     return;
2659
                  }
2660
                  auto start = it;
2661
                  while (*it != '}') {
2662
                     if (it != start) {
2663
                        if (match_invalid_end<',', Opts>(ctx, it, end)) {
2664
                           return;
2665
                        }
2666
                     }
2667
2668
                     if (skip_ws<Opts>(ctx, it, end)) {
2669
                        return;
2670
                     }
2671
                     if (match_invalid_end<'"', Opts>(ctx, it, end)) {
2672
                        return;
2673
                     }
2674
2675
                     auto* key_start = it;
2676
                     skip_string_view<Opts>(ctx, it, end);
2677
                     if (bool(ctx.error)) [[unlikely]]
2678
                        return;
2679
                     const sv key = {key_start, size_t(it - key_start)};
2680
2681
                     if (match_invalid_end<'"', Opts>(ctx, it, end)) {
2682
                        return;
2683
                     }
2684
2685
                     if constexpr (deduction_map.size()) {
2686
                        // We first check if a tag is defined and see if the key matches the tag
2687
                        if constexpr (not tag_v<T>.empty()) {
2688
                           if (key == tag_v<T>) {
2689
                              if (parse_ws_colon<Opts>(ctx, it, end)) {
2690
                                 return;
2691
                              }
2692
2693
                              using id_type = std::decay_t<decltype(ids_v<T>[0])>;
2694
2695
                              std::conditional_t<std::integral<id_type>, id_type, sv> type_id{};
2696
                              if constexpr (std::integral<id_type>) {
2697
                                 from<JSON, id_type>::template op<ws_handled<Opts>()>(type_id, ctx, it, end);
2698
                              }
2699
                              else {
2700
                                 from<JSON, sv>::template op<ws_handled<Opts>()>(type_id, ctx, it, end);
2701
                              }
2702
                              if (bool(ctx.error)) [[unlikely]]
2703
                                 return;
2704
                              if (skip_ws<Opts>(ctx, it, end)) {
2705
                                 return;
2706
                              }
2707
                              if (!(*it == ',' || *it == '}')) [[unlikely]] {
2708
                                 ctx.error = error_code::syntax_error;
2709
                                 return;
2710
                              }
2711
2712
                              static constexpr auto id_map = make_variant_id_map<T>();
2713
                              auto id_it = id_map.find(type_id);
2714
                              if (id_it != id_map.end()) [[likely]] {
2715
                                 it = start; // we restart our object parsing now that we know the target type
2716
                                 const auto type_index = id_it->second;
2717
                                 if (value.index() != type_index) value = runtime_variant_map<T>()[type_index];
2718
                                 std::visit(
2719
                                    [&](auto&& v) {
2720
                                       using V = std::decay_t<decltype(v)>;
2721
                                       constexpr bool is_object = glaze_object_t<V> || reflectable<V>;
2722
                                       if constexpr (is_object) {
2723
                                          from<JSON, V>::template op<opening_handled<Opts>(), tag_literal>(v, ctx, it,
2724
                                                                                                           end);
2725
                                       }
2726
                                       else if constexpr (is_memory_object<V>) {
2727
                                          if (!v) {
2728
                                             if constexpr (is_specialization_v<V, std::optional>) {
2729
                                                if constexpr (requires { v.emplace(); }) {
2730
                                                   v.emplace();
2731
                                                }
2732
                                                else {
2733
                                                   v = typename V::value_type{};
2734
                                                }
2735
                                             }
2736
                                             else if constexpr (is_specialization_v<V, std::unique_ptr>)
2737
                                                v = std::make_unique<typename V::element_type>();
2738
                                             else if constexpr (is_specialization_v<V, std::shared_ptr>)
2739
                                                v = std::make_shared<typename V::element_type>();
2740
                                             else if constexpr (constructible<V>) {
2741
                                                v = meta_construct_v<V>();
2742
                                             }
2743
                                             else {
2744
                                                ctx.error = error_code::invalid_nullable_read;
2745
                                                return;
2746
                                                // Cannot read into unset nullable that is not std::optional,
2747
                                                // std::unique_ptr, or std::shared_ptr
2748
                                             }
2749
                                          }
2750
                                          from<JSON, memory_type<V>>::template op<opening_handled<Opts>(), tag_literal>(
2751
                                             *v, ctx, it, end);
2752
                                       }
2753
                                    },
2754
                                    value);
2755
2756
                                 if constexpr (Opts.null_terminated) {
2757
                                    // In the null terminated case this guards for stack overflow
2758
                                    // Depth counting is done at the object level when not null terminated
2759
                                    --ctx.indentation_level;
2760
                                 }
2761
                                 return; // we've decoded our target type
2762
                              }
2763
                              else [[unlikely]] {
2764
                                 ctx.error = error_code::no_matching_variant_type;
2765
                                 return;
2766
                              }
2767
                           }
2768
                        }
2769
2770
                        auto deduction_it = deduction_map.find(key);
2771
                        if (deduction_it != deduction_map.end()) [[likely]] {
2772
                           possible_types &= deduction_it->second;
2773
                        }
2774
                        else if constexpr (Opts.error_on_unknown_keys) {
2775
                           ctx.error = error_code::unknown_key;
2776
                           return;
2777
                        }
2778
                     }
2779
                     else if constexpr (not tag_v<T>.empty()) {
2780
                        // empty object case for variant, if there are no normal elements
2781
                        if (key == tag_v<T>) {
2782
                           if (parse_ws_colon<Opts>(ctx, it, end)) {
2783
                              return;
2784
                           }
2785
2786
                           std::string_view type_id{};
2787
                           parse<JSON>::op<ws_handled<Opts>()>(type_id, ctx, it, end);
2788
                           if (bool(ctx.error)) [[unlikely]]
2789
                              return;
2790
                           if (skip_ws<Opts>(ctx, it, end)) {
2791
                              return;
2792
                           }
2793
2794
                           static constexpr auto id_map = make_variant_id_map<T>();
2795
                           auto id_it = id_map.find(type_id);
2796
                           if (id_it != id_map.end()) [[likely]] {
2797
                              it = start;
2798
                              const auto type_index = id_it->second;
2799
                              if (value.index() != type_index) value = runtime_variant_map<T>()[type_index];
2800
                              return;
2801
                           }
2802
                           else {
2803
                              ctx.error = error_code::no_matching_variant_type;
2804
                              return;
2805
                           }
2806
                        }
2807
                        else if constexpr (Opts.error_on_unknown_keys) {
2808
                           ctx.error = error_code::unknown_key;
2809
                           return;
2810
                        }
2811
                     }
2812
                     else if constexpr (Opts.error_on_unknown_keys) {
2813
                        ctx.error = error_code::unknown_key;
2814
                        return;
2815
                     }
2816
2817
                     auto matching_types = possible_types.popcount();
2818
                     if (matching_types == 0) {
2819
                        ctx.error = error_code::no_matching_variant_type;
2820
                        return;
2821
                     }
2822
                     else if (matching_types == 1) {
2823
                        it = start;
2824
                        const auto type_index = possible_types.countr_zero();
2825
                        if (value.index() != static_cast<size_t>(type_index))
2826
                           value = runtime_variant_map<T>()[type_index];
2827
                        std::visit(
2828
                           [&](auto&& v) {
2829
                              using V = std::decay_t<decltype(v)>;
2830
                              constexpr bool is_object = glaze_object_t<V> || reflectable<V>;
2831
                              if constexpr (is_object) {
2832
                                 from<JSON, V>::template op<opening_handled<Opts>(), tag_literal>(v, ctx, it, end);
2833
                              }
2834
                              else if constexpr (is_memory_object<V>) {
2835
                                 if (!v) {
2836
                                    if constexpr (is_specialization_v<V, std::optional>) {
2837
                                       if constexpr (requires { v.emplace(); }) {
2838
                                          v.emplace();
2839
                                       }
2840
                                       else {
2841
                                          v = typename V::value_type{};
2842
                                       }
2843
                                    }
2844
                                    else if constexpr (is_specialization_v<V, std::unique_ptr>)
2845
                                       v = std::make_unique<typename V::element_type>();
2846
                                    else if constexpr (is_specialization_v<V, std::shared_ptr>)
2847
                                       v = std::make_shared<typename V::element_type>();
2848
                                    else if constexpr (constructible<V>) {
2849
                                       v = meta_construct_v<V>();
2850
                                    }
2851
                                    else {
2852
                                       ctx.error = error_code::invalid_nullable_read;
2853
                                       return;
2854
                                       // Cannot read into unset nullable that is not std::optional,
2855
                                       // std::unique_ptr, or std::shared_ptr
2856
                                    }
2857
                                 }
2858
                                 from<JSON, memory_type<V>>::template op<opening_handled<Opts>(), tag_literal>(*v, ctx,
2859
                                                                                                               it, end);
2860
                              }
2861
                           },
2862
                           value);
2863
2864
                        if constexpr (Opts.null_terminated) {
2865
                           // In the null terminated case this guards for stack overflow
2866
                           // Depth counting is done at the object level when not null terminated
2867
                           --ctx.indentation_level;
2868
                        }
2869
                        return; // we've decoded our target type
2870
                     }
2871
                     if (parse_ws_colon<Opts>(ctx, it, end)) {
2872
                        return;
2873
                     }
2874
2875
                     skip_value<JSON>::op<Opts>(ctx, it, end);
2876
                     if (bool(ctx.error)) [[unlikely]]
2877
                        return;
2878
                     if (skip_ws<Opts>(ctx, it, end)) {
2879
                        return;
2880
                     }
2881
                  }
2882
                  ctx.error = error_code::no_matching_variant_type;
2883
               }
2884
0
               break;
2885
15.4k
            case '[':
2886
15.4k
               using array_types = typename variant_types<T>::array_types;
2887
2888
15.4k
               if (ctx.indentation_level >= max_recursive_depth_limit) {
2889
1
                  ctx.error = error_code::exceeded_max_recursive_depth;
2890
1
                  return;
2891
1
               }
2892
15.4k
               if constexpr (Opts.null_terminated) {
2893
                  // In the null terminated case this guards for stack overflow
2894
                  // Depth counting is done at the object level when not null terminated
2895
15.4k
                  ++ctx.indentation_level;
2896
15.4k
               }
2897
15.4k
               process_arithmetic_boolean_string_or_array<array_types>::template op<Opts>(value, ctx, it, end);
2898
15.4k
               if constexpr (Opts.null_terminated) {
2899
15.4k
                  --ctx.indentation_level;
2900
15.4k
               }
2901
15.4k
               break;
2902
4.05k
            case '"': {
2903
4.05k
               using string_types = typename variant_types<T>::string_types;
2904
4.05k
               process_arithmetic_boolean_string_or_array<string_types>::template op<Opts>(value, ctx, it, end);
2905
4.05k
               break;
2906
15.4k
            }
2907
901
            case 't':
2908
1.18k
            case 'f': {
2909
1.18k
               using bool_types = typename variant_types<T>::bool_types;
2910
1.18k
               process_arithmetic_boolean_string_or_array<bool_types>::template op<Opts>(value, ctx, it, end);
2911
1.18k
               break;
2912
901
            }
2913
845
            case 'n':
2914
845
               using nullable_types = typename variant_types<T>::nullable_types;
2915
               if constexpr (glz::tuple_size_v<nullable_types> < 1) {
2916
                  ctx.error = error_code::no_matching_variant_type;
2917
               }
2918
845
               else {
2919
845
                  using V = glz::tuple_element_t<0, nullable_types>;
2920
845
                  if (!std::holds_alternative<V>(value)) value = V{};
2921
845
                  match<"null", Opts>(ctx, it, end);
2922
845
               }
2923
845
               break;
2924
1.72M
            default: {
2925
               // Not bool, string, object, or array so must be number or null
2926
1.72M
               using number_types = typename variant_types<T>::number_types;
2927
1.72M
               process_arithmetic_boolean_string_or_array<number_types>::template op<Opts>(value, ctx, it, end);
2928
1.72M
            }
2929
1.75M
            }
2930
         }
2931
         else {
2932
            std::visit([&](auto&& v) { parse<JSON>::op<Options>(v, ctx, it, end); }, value);
2933
         }
2934
1.75M
      }
2935
   };
2936
2937
   template <class T>
2938
   struct from<JSON, array_variant_wrapper<T>>
2939
   {
2940
      template <auto Options>
2941
      static void op(auto&& wrapper, is_context auto&& ctx, auto&& it, auto&& end)
2942
      {
2943
         auto& value = wrapper.value;
2944
2945
         constexpr auto Opts = ws_handled_off<Options>();
2946
         if constexpr (!check_ws_handled(Options)) {
2947
            if (skip_ws<Opts>(ctx, it, end)) {
2948
               return;
2949
            }
2950
         }
2951
2952
         if (match_invalid_end<'[', Opts>(ctx, it, end)) {
2953
            return;
2954
         }
2955
         if constexpr (not Opts.null_terminated) {
2956
            ++ctx.indentation_level;
2957
         }
2958
         if (skip_ws<Opts>(ctx, it, end)) {
2959
            return;
2960
         }
2961
2962
         // TODO Use key parsing for compiletime known keys
2963
         if (match_invalid_end<'"', Opts>(ctx, it, end)) {
2964
            return;
2965
         }
2966
         auto start = it;
2967
         skip_string_view<Opts>(ctx, it, end);
2968
         if (bool(ctx.error)) [[unlikely]]
2969
            return;
2970
         sv type_id = {start, size_t(it - start)};
2971
         if (match<'"'>(ctx, it)) {
2972
            return;
2973
         }
2974
         if constexpr (not Opts.null_terminated) {
2975
            if (it == end) {
2976
               ctx.error = error_code::end_reached;
2977
               return;
2978
            }
2979
         }
2980
2981
         static constexpr auto id_map = make_variant_id_map<T>();
2982
         auto id_it = id_map.find(type_id);
2983
         if (id_it != id_map.end()) [[likely]] {
2984
            if (skip_ws<Opts>(ctx, it, end)) {
2985
               return;
2986
            }
2987
            if (match_invalid_end<',', Opts>(ctx, it, end)) {
2988
               return;
2989
            }
2990
            const auto type_index = id_it->second;
2991
            if (value.index() != type_index) value = runtime_variant_map<T>()[type_index];
2992
            std::visit([&](auto&& v) { parse<JSON>::op<Opts>(v, ctx, it, end); }, value);
2993
            if (bool(ctx.error)) [[unlikely]]
2994
               return;
2995
         }
2996
         else {
2997
            ctx.error = error_code::no_matching_variant_type;
2998
            return;
2999
         }
3000
3001
         if (skip_ws<Opts>(ctx, it, end)) {
3002
            return;
3003
         }
3004
         match<']'>(ctx, it);
3005
         if constexpr (not Opts.null_terminated) {
3006
            --ctx.indentation_level;
3007
         }
3008
      }
3009
   };
3010
3011
   template <is_expected T>
3012
   struct from<JSON, T>
3013
   {
3014
      template <auto Opts, class... Args>
3015
      static void op(auto&& value, is_context auto&& ctx, auto&& it, auto&& end)
3016
      {
3017
         if constexpr (!check_ws_handled(Opts)) {
3018
            if (skip_ws<Opts>(ctx, it, end)) {
3019
               return;
3020
            }
3021
         }
3022
3023
         if (*it == '{') {
3024
            if constexpr (not Opts.null_terminated) {
3025
               ++ctx.indentation_level;
3026
            }
3027
            auto start = it;
3028
            ++it;
3029
            if constexpr (not Opts.null_terminated) {
3030
               if (it == end) [[unlikely]] {
3031
                  ctx.error = error_code::unexpected_end;
3032
                  return;
3033
               }
3034
            }
3035
            if (skip_ws<Opts>(ctx, it, end)) {
3036
               return;
3037
            }
3038
            if (*it == '}') {
3039
               it = start;
3040
               // empty object
3041
               if (value) {
3042
                  parse<JSON>::op<Opts>(*value, ctx, it, end);
3043
               }
3044
               else {
3045
                  value.emplace();
3046
                  parse<JSON>::op<Opts>(*value, ctx, it, end);
3047
               }
3048
            }
3049
            else {
3050
               // either we have an unexpected value or we are decoding an object
3051
               auto& key = string_buffer();
3052
               parse<JSON>::op<Opts>(key, ctx, it, end);
3053
               if (bool(ctx.error)) [[unlikely]]
3054
                  return;
3055
               if (key == "unexpected") {
3056
                  if (skip_ws<Opts>(ctx, it, end)) {
3057
                     return;
3058
                  }
3059
                  if (match_invalid_end<':', Opts>(ctx, it, end)) {
3060
                     return;
3061
                  }
3062
                  // read in unexpected value
3063
                  if (!value) {
3064
                     parse<JSON>::op<Opts>(value.error(), ctx, it, end);
3065
                     if (bool(ctx.error)) [[unlikely]]
3066
                        return;
3067
                  }
3068
                  else {
3069
                     // set value to unexpected
3070
                     using error_ctx = typename std::decay_t<decltype(value)>::error_type;
3071
                     std::decay_t<error_ctx> error{};
3072
                     parse<JSON>::op<Opts>(error, ctx, it, end);
3073
                     if (bool(ctx.error)) [[unlikely]]
3074
                        return;
3075
                     value = glz::unexpected(error);
3076
                  }
3077
                  if (skip_ws<Opts>(ctx, it, end)) {
3078
                     return;
3079
                  }
3080
                  match<'}'>(ctx, it);
3081
                  if constexpr (not Opts.null_terminated) {
3082
                     --ctx.indentation_level;
3083
                  }
3084
               }
3085
               else {
3086
                  it = start;
3087
                  if (value) {
3088
                     parse<JSON>::op<Opts>(*value, ctx, it, end);
3089
                  }
3090
                  else {
3091
                     value.emplace();
3092
                     parse<JSON>::op<Opts>(*value, ctx, it, end);
3093
                  }
3094
               }
3095
            }
3096
         }
3097
         else {
3098
            // this is not an object and therefore cannot be an unexpected value
3099
            if (value) {
3100
               parse<JSON>::op<Opts>(*value, ctx, it, end);
3101
            }
3102
            else {
3103
               value.emplace();
3104
               parse<JSON>::op<Opts>(*value, ctx, it, end);
3105
            }
3106
         }
3107
      }
3108
   };
3109
3110
   template <nullable_t T>
3111
      requires(std::is_array_v<T>)
3112
   struct from<JSON, T>
3113
   {
3114
      template <auto Opts, class V, size_t N>
3115
      GLZ_ALWAYS_INLINE static void op(V (&value)[N], is_context auto&& ctx, auto&& it, auto&& end) noexcept
3116
      {
3117
         parse<JSON>::op<Opts>(std::span{value, N}, ctx, it, end);
3118
      }
3119
   };
3120
3121
   template <class T>
3122
      requires((nullable_t<T> || nullable_value_t<T>) && not is_expected<T> && not std::is_array_v<T> &&
3123
               not custom_read<T>)
3124
   struct from<JSON, T>
3125
   {
3126
      template <auto Options>
3127
      static void op(auto&& value, is_context auto&& ctx, auto&& it, auto&& end)
3128
      {
3129
         constexpr auto Opts = ws_handled_off<Options>();
3130
         if constexpr (!check_ws_handled(Options)) {
3131
            if (skip_ws<Opts>(ctx, it, end)) {
3132
               return;
3133
            }
3134
         }
3135
3136
         if (*it == 'n') {
3137
            ++it;
3138
            if constexpr (not Opts.null_terminated) {
3139
               if (it == end) [[unlikely]] {
3140
                  ctx.error = error_code::unexpected_end;
3141
                  return;
3142
               }
3143
            }
3144
            match<"ull", Opts>(ctx, it, end);
3145
            if (bool(ctx.error)) [[unlikely]]
3146
               return;
3147
            if constexpr (requires { value.reset(); }) {
3148
               value.reset();
3149
            }
3150
         }
3151
         else {
3152
            if constexpr (nullable_value_t<T>) {
3153
               if (not value.has_value()) {
3154
                  if constexpr (constructible<T>) {
3155
                     value = meta_construct_v<T>();
3156
                  }
3157
                  else if constexpr (requires { value.emplace(); }) {
3158
                     value.emplace();
3159
                  }
3160
                  else {
3161
                     static_assert(false_v<T>,
3162
                                   "Your nullable type must have `emplace()` or be glz::meta constructible, or "
3163
                                   "create a custom glz::from specialization");
3164
                  }
3165
               }
3166
               parse<JSON>::op<Opts>(value.value(), ctx, it, end);
3167
            }
3168
            else {
3169
               if (!value) {
3170
                  if constexpr (optional_like<T>) {
3171
                     if constexpr (requires { value.emplace(); }) {
3172
                        value.emplace();
3173
                     }
3174
                     else {
3175
                        value = typename T::value_type{};
3176
                     }
3177
                  }
3178
                  else if constexpr (is_specialization_v<T, std::unique_ptr>)
3179
                     value = std::make_unique<typename T::element_type>();
3180
                  else if constexpr (is_specialization_v<T, std::shared_ptr>)
3181
                     value = std::make_shared<typename T::element_type>();
3182
                  else if constexpr (constructible<T>) {
3183
                     value = meta_construct_v<T>();
3184
                  }
3185
                  else {
3186
                     // Cannot read into a null raw pointer
3187
                     ctx.error = error_code::invalid_nullable_read;
3188
                     return;
3189
                  }
3190
               }
3191
               parse<JSON>::op<Opts>(*value, ctx, it, end);
3192
            }
3193
         }
3194
      }
3195
   };
3196
3197
   template <filesystem_path T>
3198
   struct from<JSON, T>
3199
   {
3200
      template <auto Opts>
3201
      static void op(auto&& value, is_context auto&& ctx, auto&& it, auto&& end)
3202
      {
3203
         std::string& buffer = string_buffer();
3204
         parse<JSON>::op<Opts>(buffer, ctx, it, end);
3205
         if constexpr (Opts.null_terminated) {
3206
            if (bool(ctx.error)) [[unlikely]]
3207
               return;
3208
         }
3209
         else {
3210
            if (size_t(ctx.error) > size_t(error_code::end_reached)) [[unlikely]] {
3211
               return;
3212
            }
3213
         }
3214
         value = buffer;
3215
      }
3216
   };
3217
3218
   struct opts_validate : opts
3219
   {
3220
      bool validate_skipped = true;
3221
      bool validate_trailing_whitespace = true;
3222
   };
3223
3224
   template <is_buffer Buffer>
3225
   [[nodiscard]] error_ctx validate_json(Buffer&& buffer) noexcept
3226
   {
3227
      context ctx{};
3228
      glz::skip skip_value{};
3229
      return read<opts_validate{}>(skip_value, std::forward<Buffer>(buffer), ctx);
3230
   }
3231
3232
   template <is_buffer Buffer>
3233
   [[nodiscard]] error_ctx validate_jsonc(Buffer&& buffer) noexcept
3234
   {
3235
      context ctx{};
3236
      glz::skip skip_value{};
3237
      return read<opts_validate{{opts{.comments = true}}}>(skip_value, std::forward<Buffer>(buffer), ctx);
3238
   }
3239
3240
   template <read_supported<JSON> T, is_buffer Buffer>
3241
   [[nodiscard]] error_ctx read_json(T& value, Buffer&& buffer)
3242
12.3k
   {
3243
12.3k
      context ctx{};
3244
12.3k
      return read<opts{}>(value, std::forward<Buffer>(buffer), ctx);
3245
12.3k
   }
_ZN3glz9read_jsonITkNS_14read_supportedIL_ZNS_4JSONEEEENS_6json_tETkNS_9is_bufferERKNSt3__16vectorIcNS3_9allocatorIcEEEEEENS_9error_ctxERT_OT0_
Line
Count
Source
3242
6.19k
   {
3243
6.19k
      context ctx{};
3244
6.19k
      return read<opts{}>(value, std::forward<Buffer>(buffer), ctx);
3245
6.19k
   }
_ZN3glz9read_jsonITkNS_14read_supportedIL_ZNS_4JSONEEEENS_6json_tETkNS_9is_bufferERNSt3__16vectorIcNS3_9allocatorIcEEEEEENS_9error_ctxERT_OT0_
Line
Count
Source
3242
6.19k
   {
3243
6.19k
      context ctx{};
3244
6.19k
      return read<opts{}>(value, std::forward<Buffer>(buffer), ctx);
3245
6.19k
   }
3246
3247
   template <read_supported<JSON> T, is_buffer Buffer>
3248
   [[nodiscard]] expected<T, error_ctx> read_json(Buffer&& buffer)
3249
8.27k
   {
3250
8.27k
      T value{};
3251
8.27k
      context ctx{};
3252
8.27k
      const error_ctx ec = read<opts{}>(value, std::forward<Buffer>(buffer), ctx);
3253
8.27k
      if (ec) {
3254
4.59k
         return unexpected<error_ctx>(ec);
3255
4.59k
      }
3256
3.68k
      return value;
3257
8.27k
   }
_ZN3glz9read_jsonITkNS_14read_supportedIL_ZNS_4JSONEEEE9my_structTkNS_9is_bufferENSt3__117basic_string_viewIcNS3_11char_traitsIcEEEEEENS3_8expectedIT_NS_9error_ctxEEEOT0_
Line
Count
Source
3249
4.59k
   {
3250
4.59k
      T value{};
3251
4.59k
      context ctx{};
3252
4.59k
      const error_ctx ec = read<opts{}>(value, std::forward<Buffer>(buffer), ctx);
3253
4.59k
      if (ec) {
3254
4.59k
         return unexpected<error_ctx>(ec);
3255
4.59k
      }
3256
3
      return value;
3257
4.59k
   }
_ZN3glz9read_jsonITkNS_14read_supportedIL_ZNS_4JSONEEEE1STkNS_9is_bufferERNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEEENS3_8expectedIT_NS_9error_ctxEEEOT0_
Line
Count
Source
3249
415
   {
3250
415
      T value{};
3251
415
      context ctx{};
3252
415
      const error_ctx ec = read<opts{}>(value, std::forward<Buffer>(buffer), ctx);
3253
415
      if (ec) {
3254
0
         return unexpected<error_ctx>(ec);
3255
0
      }
3256
415
      return value;
3257
415
   }
_ZN3glz9read_jsonITkNS_14read_supportedIL_ZNS_4JSONEEEE5ValueIfETkNS_9is_bufferERNSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEEEENS4_8expectedIT_NS_9error_ctxEEEOT0_
Line
Count
Source
3249
488
   {
3250
488
      T value{};
3251
488
      context ctx{};
3252
488
      const error_ctx ec = read<opts{}>(value, std::forward<Buffer>(buffer), ctx);
3253
488
      if (ec) {
3254
0
         return unexpected<error_ctx>(ec);
3255
0
      }
3256
488
      return value;
3257
488
   }
_ZN3glz9read_jsonITkNS_14read_supportedIL_ZNS_4JSONEEEE5ValueIdETkNS_9is_bufferERNSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEEEENS4_8expectedIT_NS_9error_ctxEEEOT0_
Line
Count
Source
3249
1.05k
   {
3250
1.05k
      T value{};
3251
1.05k
      context ctx{};
3252
1.05k
      const error_ctx ec = read<opts{}>(value, std::forward<Buffer>(buffer), ctx);
3253
1.05k
      if (ec) {
3254
0
         return unexpected<error_ctx>(ec);
3255
0
      }
3256
1.05k
      return value;
3257
1.05k
   }
_ZN3glz9read_jsonITkNS_14read_supportedIL_ZNS_4JSONEEEE5ValueIsETkNS_9is_bufferERNSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEEEENS4_8expectedIT_NS_9error_ctxEEEOT0_
Line
Count
Source
3249
106
   {
3250
106
      T value{};
3251
106
      context ctx{};
3252
106
      const error_ctx ec = read<opts{}>(value, std::forward<Buffer>(buffer), ctx);
3253
106
      if (ec) {
3254
0
         return unexpected<error_ctx>(ec);
3255
0
      }
3256
106
      return value;
3257
106
   }
_ZN3glz9read_jsonITkNS_14read_supportedIL_ZNS_4JSONEEEE5ValueItETkNS_9is_bufferERNSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEEEENS4_8expectedIT_NS_9error_ctxEEEOT0_
Line
Count
Source
3249
106
   {
3250
106
      T value{};
3251
106
      context ctx{};
3252
106
      const error_ctx ec = read<opts{}>(value, std::forward<Buffer>(buffer), ctx);
3253
106
      if (ec) {
3254
0
         return unexpected<error_ctx>(ec);
3255
0
      }
3256
106
      return value;
3257
106
   }
_ZN3glz9read_jsonITkNS_14read_supportedIL_ZNS_4JSONEEEE5ValueIiETkNS_9is_bufferERNSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEEEENS4_8expectedIT_NS_9error_ctxEEEOT0_
Line
Count
Source
3249
169
   {
3250
169
      T value{};
3251
169
      context ctx{};
3252
169
      const error_ctx ec = read<opts{}>(value, std::forward<Buffer>(buffer), ctx);
3253
169
      if (ec) {
3254
0
         return unexpected<error_ctx>(ec);
3255
0
      }
3256
169
      return value;
3257
169
   }
_ZN3glz9read_jsonITkNS_14read_supportedIL_ZNS_4JSONEEEE5ValueIjETkNS_9is_bufferERNSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEEEENS4_8expectedIT_NS_9error_ctxEEEOT0_
Line
Count
Source
3249
169
   {
3250
169
      T value{};
3251
169
      context ctx{};
3252
169
      const error_ctx ec = read<opts{}>(value, std::forward<Buffer>(buffer), ctx);
3253
169
      if (ec) {
3254
0
         return unexpected<error_ctx>(ec);
3255
0
      }
3256
169
      return value;
3257
169
   }
_ZN3glz9read_jsonITkNS_14read_supportedIL_ZNS_4JSONEEEE5ValueIlETkNS_9is_bufferERNSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEEEENS4_8expectedIT_NS_9error_ctxEEEOT0_
Line
Count
Source
3249
296
   {
3250
296
      T value{};
3251
296
      context ctx{};
3252
296
      const error_ctx ec = read<opts{}>(value, std::forward<Buffer>(buffer), ctx);
3253
296
      if (ec) {
3254
0
         return unexpected<error_ctx>(ec);
3255
0
      }
3256
296
      return value;
3257
296
   }
_ZN3glz9read_jsonITkNS_14read_supportedIL_ZNS_4JSONEEEE5ValueImETkNS_9is_bufferERNSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEEEENS4_8expectedIT_NS_9error_ctxEEEOT0_
Line
Count
Source
3249
296
   {
3250
296
      T value{};
3251
296
      context ctx{};
3252
296
      const error_ctx ec = read<opts{}>(value, std::forward<Buffer>(buffer), ctx);
3253
296
      if (ec) {
3254
0
         return unexpected<error_ctx>(ec);
3255
0
      }
3256
296
      return value;
3257
296
   }
_ZN3glz9read_jsonITkNS_14read_supportedIL_ZNS_4JSONEEEE5ValueIxETkNS_9is_bufferERNSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEEEENS4_8expectedIT_NS_9error_ctxEEEOT0_
Line
Count
Source
3249
290
   {
3250
290
      T value{};
3251
290
      context ctx{};
3252
290
      const error_ctx ec = read<opts{}>(value, std::forward<Buffer>(buffer), ctx);
3253
290
      if (ec) {
3254
0
         return unexpected<error_ctx>(ec);
3255
0
      }
3256
290
      return value;
3257
290
   }
_ZN3glz9read_jsonITkNS_14read_supportedIL_ZNS_4JSONEEEE5ValueIyETkNS_9is_bufferERNSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEEEENS4_8expectedIT_NS_9error_ctxEEEOT0_
Line
Count
Source
3249
290
   {
3250
290
      T value{};
3251
290
      context ctx{};
3252
290
      const error_ctx ec = read<opts{}>(value, std::forward<Buffer>(buffer), ctx);
3253
290
      if (ec) {
3254
0
         return unexpected<error_ctx>(ec);
3255
0
      }
3256
290
      return value;
3257
290
   }
3258
3259
   template <read_supported<JSON> T, is_buffer Buffer>
3260
   [[nodiscard]] error_ctx read_jsonc(T& value, Buffer&& buffer)
3261
   {
3262
      context ctx{};
3263
      return read<opts{.comments = true}>(value, std::forward<Buffer>(buffer), ctx);
3264
   }
3265
3266
   template <read_supported<JSON> T, is_buffer Buffer>
3267
   [[nodiscard]] expected<T, error_ctx> read_jsonc(Buffer&& buffer)
3268
6.10k
   {
3269
6.10k
      T value{};
3270
6.10k
      context ctx{};
3271
6.10k
      const error_ctx ec = read<opts{.comments = true}>(value, std::forward<Buffer>(buffer), ctx);
3272
6.10k
      if (ec) {
3273
6.10k
         return unexpected<error_ctx>(ec);
3274
6.10k
      }
3275
2
      return value;
3276
6.10k
   }
3277
3278
   template <auto Opts = opts{}, read_supported<JSON> T, is_buffer Buffer>
3279
   [[nodiscard]] error_ctx read_file_json(T& value, const sv file_name, Buffer&& buffer)
3280
   {
3281
      context ctx{};
3282
      ctx.current_file = file_name;
3283
3284
      const auto ec = file_to_buffer(buffer, ctx.current_file);
3285
3286
      if (bool(ec)) {
3287
         return {ec};
3288
      }
3289
3290
      return read<set_json<Opts>()>(value, buffer, ctx);
3291
   }
3292
3293
   template <auto Opts = opts{}, read_supported<JSON> T, is_buffer Buffer>
3294
   [[nodiscard]] error_ctx read_file_jsonc(T& value, const sv file_name, Buffer&& buffer)
3295
   {
3296
      context ctx{};
3297
      ctx.current_file = file_name;
3298
3299
      const auto ec = file_to_buffer(buffer, ctx.current_file);
3300
3301
      if (bool(ec)) {
3302
         return {ec};
3303
      }
3304
3305
      constexpr auto Options = opt_true<set_json<Opts>(), &opts::comments>;
3306
      return read<Options>(value, buffer, ctx);
3307
   }
3308
}
3309
3310
#ifdef _MSC_VER
3311
// restore disabled warnings
3312
#pragma warning(pop)
3313
#endif