Coverage Report

Created: 2026-09-14 06:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/glaze/include/glaze/util/atoi.hpp
Line
Count
Source
1
#pragma once
2
3
#include <array>
4
#include <bit>
5
#include <cmath>
6
#include <cstdint>
7
#include <cstring>
8
#include <iterator>
9
10
#include "glaze/util/for_each.hpp"
11
#include "glaze/util/inline.hpp"
12
#include "glaze/util/type_traits.hpp"
13
14
// Characters to integer parsing
15
16
// - We don't allow decimals in integer parsing
17
// - We don't allow negative exponents
18
// These cases can produce fractions which slow performance and add confusion
19
// as to how the integer ought to be parsed (truncation, rounding, etc.)
20
// This integer parsing is designed to be straightforward and fast
21
// Values like 1e6 are allowed because it enables less typing from the user
22
// and has a clear integer value
23
24
// Valid JSON integer examples
25
// 1234
26
// 1234e1
27
// 1e9
28
29
// Invalid for this atoi algorithm
30
// 1.234
31
// 1234e-1
32
// 0.0
33
34
// The standard JSON specification for numbers and the associated rules apply
35
36
// *** We ensure that a decimal value being parsed will result in an error
37
// 1.2 should not produce 1, but rather an error, even when a single field is parsed
38
// This ensures that we get proper errors when parsing and don't get confusing errors
39
// It isn't technically required, because end validation would handle it, but it produces
40
// much clearer errors, especially when we don't perform trailing validation.
41
42
#if defined(_MSC_VER) && !defined(__clang__)
43
// Turn off MSVC warning for possible loss of data: we are intentionally allowing well defined unsigned integer
44
// overflows
45
#pragma warning(push)
46
#pragma warning(disable : 4244)
47
#endif
48
49
namespace glz
50
{
51
   inline constexpr std::array<uint64_t, 20> powers_of_ten_int{1ull,
52
                                                               10ull,
53
                                                               100ull,
54
                                                               1000ull,
55
                                                               10000ull,
56
                                                               100000ull,
57
                                                               1000000ull,
58
                                                               10000000ull,
59
                                                               100000000ull,
60
                                                               1000000000ull,
61
                                                               10000000000ull,
62
                                                               100000000000ull,
63
                                                               1000000000000ull,
64
                                                               10000000000000ull,
65
                                                               100000000000000ull,
66
                                                               1000000000000000ull,
67
                                                               10000000000000000ull,
68
                                                               100000000000000000ull,
69
                                                               1000000000000000000ull,
70
                                                               10000000000000000000ull};
71
72
   inline constexpr std::array<bool, 256> exp_dec_table = [] {
73
      std::array<bool, 256> t{};
74
      t['.'] = true;
75
      t['E'] = true;
76
      t['e'] = true;
77
      return t;
78
   }();
79
80
   inline constexpr std::array<bool, 256> non_exp_table = [] {
81
      std::array<bool, 256> t{};
82
      t.fill(true);
83
      t['E'] = false;
84
      t['e'] = false;
85
      return t;
86
   }();
87
88
   inline constexpr std::array<bool, 256> digit_table = [] {
89
      std::array<bool, 256> t{};
90
      t['0'] = true;
91
      t['1'] = true;
92
      t['2'] = true;
93
      t['3'] = true;
94
      t['4'] = true;
95
      t['5'] = true;
96
      t['6'] = true;
97
      t['7'] = true;
98
      t['8'] = true;
99
      t['9'] = true;
100
      return t;
101
   }();
102
103
19.1M
   GLZ_ALWAYS_INLINE constexpr bool is_digit(const uint8_t c) noexcept { return c <= '9' && c >= '0'; }
104
105
   // Exponents at or beyond this magnitude are out of range for every integer width, so the exponent
106
   // accumulators clamp here rather than growing without bound. Sits far above the largest accepted
107
   // exponent (19, for uint64_t) and low enough that a clamped value cannot overflow uint32_t.
108
   inline constexpr uint32_t exponent_clamp = 1000;
109
110
   // Consumes the run of exponent digits starting at `c` and returns its value, clamped at
111
   // exponent_clamp. Clamping is what keeps the result meaningful: a narrow accumulator wraps mod its
112
   // width, which aliases an out-of-range exponent onto an accepted one. Every digit is consumed so
113
   // that leading zeros reach their true value -- JSON forbids a leading zero in the integer part but
114
   // permits any run of digits in the exponent, making "1e007" a valid spelling of 10^7 -- and so the
115
   // caller resumes past the whole exponent rather than mid-number.
116
   //
117
   // Requires *c to be a digit and the buffer to be terminated by a non-digit (the null terminator
118
   // counts); this scan is bounded by the input, not by a digit count.
119
   template <class Char>
120
   GLZ_ALWAYS_INLINE constexpr uint32_t parse_exponent(Char*& c) noexcept
121
157k
   {
122
157k
      uint32_t exp = uint32_t(*c - '0');
123
157k
      ++c;
124
312k
      while (is_digit(*c)) {
125
         // Written as a select rather than a branch: the clamp only ever engages on absurdly long
126
         // exponents, so a branch here would be a mispredict risk on the path that matters.
127
155k
         exp = exp < exponent_clamp ? exp * 10 + uint32_t(*c - '0') : exp;
128
155k
         ++c;
129
155k
      }
130
157k
      return exp;
131
157k
   }
132
133
   // Computed overflow checks - used instead of lookup tables to save 4KB+ of binary size
134
   // Uses adjusted threshold for branch-free single comparison (7-12% faster than bitwise approach)
135
   template <class T>
136
   GLZ_ALWAYS_INLINE constexpr bool would_overflow_positive(std::remove_volatile_t<T> v, uint8_t next_digit) noexcept
137
22.3k
   {
138
22.3k
      using U = std::remove_volatile_t<T>;
139
22.3k
      constexpr auto max_val = static_cast<uint64_t>((std::numeric_limits<U>::max)());
140
22.3k
      constexpr auto threshold = max_val / 10;
141
22.3k
      constexpr auto last_digit = max_val % 10;
142
22.3k
      const auto uv = static_cast<uint64_t>(v);
143
22.3k
      const auto digit = static_cast<uint64_t>(next_digit - '0');
144
      // When digit > last_digit, effective threshold is one less
145
      // This is branch-free and faster than bitwise OR/AND approach
146
22.3k
      return uv > (threshold - uint64_t(digit > last_digit));
147
22.3k
   }
_ZN3glz23would_overflow_positiveIiEEbu17__remove_volatileIT_Eh
Line
Count
Source
137
14.8k
   {
138
14.8k
      using U = std::remove_volatile_t<T>;
139
14.8k
      constexpr auto max_val = static_cast<uint64_t>((std::numeric_limits<U>::max)());
140
14.8k
      constexpr auto threshold = max_val / 10;
141
14.8k
      constexpr auto last_digit = max_val % 10;
142
14.8k
      const auto uv = static_cast<uint64_t>(v);
143
14.8k
      const auto digit = static_cast<uint64_t>(next_digit - '0');
144
      // When digit > last_digit, effective threshold is one less
145
      // This is branch-free and faster than bitwise OR/AND approach
146
14.8k
      return uv > (threshold - uint64_t(digit > last_digit));
147
14.8k
   }
_ZN3glz23would_overflow_positiveImEEbu17__remove_volatileIT_Eh
Line
Count
Source
137
3.98k
   {
138
3.98k
      using U = std::remove_volatile_t<T>;
139
3.98k
      constexpr auto max_val = static_cast<uint64_t>((std::numeric_limits<U>::max)());
140
3.98k
      constexpr auto threshold = max_val / 10;
141
3.98k
      constexpr auto last_digit = max_val % 10;
142
3.98k
      const auto uv = static_cast<uint64_t>(v);
143
3.98k
      const auto digit = static_cast<uint64_t>(next_digit - '0');
144
      // When digit > last_digit, effective threshold is one less
145
      // This is branch-free and faster than bitwise OR/AND approach
146
3.98k
      return uv > (threshold - uint64_t(digit > last_digit));
147
3.98k
   }
_ZN3glz23would_overflow_positiveIlEEbu17__remove_volatileIT_Eh
Line
Count
Source
137
1.46k
   {
138
1.46k
      using U = std::remove_volatile_t<T>;
139
1.46k
      constexpr auto max_val = static_cast<uint64_t>((std::numeric_limits<U>::max)());
140
1.46k
      constexpr auto threshold = max_val / 10;
141
1.46k
      constexpr auto last_digit = max_val % 10;
142
1.46k
      const auto uv = static_cast<uint64_t>(v);
143
1.46k
      const auto digit = static_cast<uint64_t>(next_digit - '0');
144
      // When digit > last_digit, effective threshold is one less
145
      // This is branch-free and faster than bitwise OR/AND approach
146
1.46k
      return uv > (threshold - uint64_t(digit > last_digit));
147
1.46k
   }
_ZN3glz23would_overflow_positiveItEEbu17__remove_volatileIT_Eh
Line
Count
Source
137
1.07k
   {
138
1.07k
      using U = std::remove_volatile_t<T>;
139
1.07k
      constexpr auto max_val = static_cast<uint64_t>((std::numeric_limits<U>::max)());
140
1.07k
      constexpr auto threshold = max_val / 10;
141
1.07k
      constexpr auto last_digit = max_val % 10;
142
1.07k
      const auto uv = static_cast<uint64_t>(v);
143
1.07k
      const auto digit = static_cast<uint64_t>(next_digit - '0');
144
      // When digit > last_digit, effective threshold is one less
145
      // This is branch-free and faster than bitwise OR/AND approach
146
1.07k
      return uv > (threshold - uint64_t(digit > last_digit));
147
1.07k
   }
_ZN3glz23would_overflow_positiveIsEEbu17__remove_volatileIT_Eh
Line
Count
Source
137
50
   {
138
50
      using U = std::remove_volatile_t<T>;
139
50
      constexpr auto max_val = static_cast<uint64_t>((std::numeric_limits<U>::max)());
140
50
      constexpr auto threshold = max_val / 10;
141
50
      constexpr auto last_digit = max_val % 10;
142
50
      const auto uv = static_cast<uint64_t>(v);
143
50
      const auto digit = static_cast<uint64_t>(next_digit - '0');
144
      // When digit > last_digit, effective threshold is one less
145
      // This is branch-free and faster than bitwise OR/AND approach
146
50
      return uv > (threshold - uint64_t(digit > last_digit));
147
50
   }
_ZN3glz23would_overflow_positiveIjEEbu17__remove_volatileIT_Eh
Line
Count
Source
137
360
   {
138
360
      using U = std::remove_volatile_t<T>;
139
360
      constexpr auto max_val = static_cast<uint64_t>((std::numeric_limits<U>::max)());
140
360
      constexpr auto threshold = max_val / 10;
141
360
      constexpr auto last_digit = max_val % 10;
142
360
      const auto uv = static_cast<uint64_t>(v);
143
360
      const auto digit = static_cast<uint64_t>(next_digit - '0');
144
      // When digit > last_digit, effective threshold is one less
145
      // This is branch-free and faster than bitwise OR/AND approach
146
360
      return uv > (threshold - uint64_t(digit > last_digit));
147
360
   }
_ZN3glz23would_overflow_positiveIxEEbu17__remove_volatileIT_Eh
Line
Count
Source
137
182
   {
138
182
      using U = std::remove_volatile_t<T>;
139
182
      constexpr auto max_val = static_cast<uint64_t>((std::numeric_limits<U>::max)());
140
182
      constexpr auto threshold = max_val / 10;
141
182
      constexpr auto last_digit = max_val % 10;
142
182
      const auto uv = static_cast<uint64_t>(v);
143
182
      const auto digit = static_cast<uint64_t>(next_digit - '0');
144
      // When digit > last_digit, effective threshold is one less
145
      // This is branch-free and faster than bitwise OR/AND approach
146
182
      return uv > (threshold - uint64_t(digit > last_digit));
147
182
   }
_ZN3glz23would_overflow_positiveIyEEbu17__remove_volatileIT_Eh
Line
Count
Source
137
316
   {
138
316
      using U = std::remove_volatile_t<T>;
139
316
      constexpr auto max_val = static_cast<uint64_t>((std::numeric_limits<U>::max)());
140
316
      constexpr auto threshold = max_val / 10;
141
316
      constexpr auto last_digit = max_val % 10;
142
316
      const auto uv = static_cast<uint64_t>(v);
143
316
      const auto digit = static_cast<uint64_t>(next_digit - '0');
144
      // When digit > last_digit, effective threshold is one less
145
      // This is branch-free and faster than bitwise OR/AND approach
146
316
      return uv > (threshold - uint64_t(digit > last_digit));
147
316
   }
148
149
   template <class T>
150
   GLZ_ALWAYS_INLINE constexpr bool would_overflow_negative(std::remove_volatile_t<T> v, uint8_t next_digit) noexcept
151
18.6k
   {
152
      // For negative: max magnitude is max + 1 (e.g., -2147483648 for int32)
153
18.6k
      using U = std::remove_volatile_t<T>;
154
18.6k
      constexpr auto max_val = static_cast<uint64_t>((std::numeric_limits<U>::max)()) + 1;
155
18.6k
      constexpr auto threshold = max_val / 10;
156
18.6k
      constexpr auto last_digit = max_val % 10;
157
18.6k
      const auto uv = static_cast<uint64_t>(v);
158
18.6k
      const auto digit = static_cast<uint64_t>(next_digit - '0');
159
      // When digit > last_digit, effective threshold is one less
160
18.6k
      return uv > (threshold - uint64_t(digit > last_digit));
161
18.6k
   }
_ZN3glz23would_overflow_negativeIiEEbu17__remove_volatileIT_Eh
Line
Count
Source
151
10.9k
   {
152
      // For negative: max magnitude is max + 1 (e.g., -2147483648 for int32)
153
10.9k
      using U = std::remove_volatile_t<T>;
154
10.9k
      constexpr auto max_val = static_cast<uint64_t>((std::numeric_limits<U>::max)()) + 1;
155
10.9k
      constexpr auto threshold = max_val / 10;
156
10.9k
      constexpr auto last_digit = max_val % 10;
157
10.9k
      const auto uv = static_cast<uint64_t>(v);
158
10.9k
      const auto digit = static_cast<uint64_t>(next_digit - '0');
159
      // When digit > last_digit, effective threshold is one less
160
10.9k
      return uv > (threshold - uint64_t(digit > last_digit));
161
10.9k
   }
_ZN3glz23would_overflow_negativeIlEEbu17__remove_volatileIT_Eh
Line
Count
Source
151
7.45k
   {
152
      // For negative: max magnitude is max + 1 (e.g., -2147483648 for int32)
153
7.45k
      using U = std::remove_volatile_t<T>;
154
7.45k
      constexpr auto max_val = static_cast<uint64_t>((std::numeric_limits<U>::max)()) + 1;
155
7.45k
      constexpr auto threshold = max_val / 10;
156
7.45k
      constexpr auto last_digit = max_val % 10;
157
7.45k
      const auto uv = static_cast<uint64_t>(v);
158
7.45k
      const auto digit = static_cast<uint64_t>(next_digit - '0');
159
      // When digit > last_digit, effective threshold is one less
160
7.45k
      return uv > (threshold - uint64_t(digit > last_digit));
161
7.45k
   }
_ZN3glz23would_overflow_negativeIsEEbu17__remove_volatileIT_Eh
Line
Count
Source
151
64
   {
152
      // For negative: max magnitude is max + 1 (e.g., -2147483648 for int32)
153
64
      using U = std::remove_volatile_t<T>;
154
64
      constexpr auto max_val = static_cast<uint64_t>((std::numeric_limits<U>::max)()) + 1;
155
64
      constexpr auto threshold = max_val / 10;
156
64
      constexpr auto last_digit = max_val % 10;
157
64
      const auto uv = static_cast<uint64_t>(v);
158
64
      const auto digit = static_cast<uint64_t>(next_digit - '0');
159
      // When digit > last_digit, effective threshold is one less
160
64
      return uv > (threshold - uint64_t(digit > last_digit));
161
64
   }
_ZN3glz23would_overflow_negativeIxEEbu17__remove_volatileIT_Eh
Line
Count
Source
151
166
   {
152
      // For negative: max magnitude is max + 1 (e.g., -2147483648 for int32)
153
166
      using U = std::remove_volatile_t<T>;
154
166
      constexpr auto max_val = static_cast<uint64_t>((std::numeric_limits<U>::max)()) + 1;
155
166
      constexpr auto threshold = max_val / 10;
156
166
      constexpr auto last_digit = max_val % 10;
157
166
      const auto uv = static_cast<uint64_t>(v);
158
166
      const auto digit = static_cast<uint64_t>(next_digit - '0');
159
      // When digit > last_digit, effective threshold is one less
160
166
      return uv > (threshold - uint64_t(digit > last_digit));
161
166
   }
162
163
   struct value128 final
164
   {
165
      uint64_t low;
166
      uint64_t high;
167
   };
168
169
   // slow emulation routine for 32-bit
170
0
   GLZ_ALWAYS_INLINE constexpr uint64_t emulu(uint32_t x, uint32_t y) { return x * (uint64_t)y; }
171
172
   GLZ_ALWAYS_INLINE constexpr uint64_t umul128_generic(uint64_t ab, uint64_t cd, uint64_t* hi)
173
0
   {
174
0
      uint64_t ad = emulu((uint32_t)(ab >> 32), (uint32_t)cd);
175
0
      uint64_t bd = emulu((uint32_t)ab, (uint32_t)cd);
176
0
      uint64_t adbc = ad + emulu((uint32_t)ab, (uint32_t)(cd >> 32));
177
0
      uint64_t adbc_carry = (uint64_t)(adbc < ad);
178
0
      uint64_t lo = bd + (adbc << 32);
179
0
      *hi = emulu((uint32_t)(ab >> 32), (uint32_t)(cd >> 32)) + (adbc >> 32) + (adbc_carry << 32) + (uint64_t)(lo < bd);
180
0
      return lo;
181
0
   }
182
183
   // compute 64-bit a*b
184
   GLZ_ALWAYS_INLINE constexpr value128 full_multiplication(uint64_t a, uint64_t b)
185
0
   {
186
0
      if consteval {
187
0
         value128 answer;
188
0
         answer.low = umul128_generic(a, b, &answer.high);
189
0
         return answer;
190
0
      }
191
0
      value128 answer;
192
0
#if defined(_M_ARM64) && !defined(__MINGW32__)
193
0
      // ARM64 has native support for 64-bit multiplications, no need to emulate
194
0
      // But MinGW on ARM64 doesn't have native support for 64-bit multiplications
195
0
      answer.high = __umulh(a, b);
196
0
      answer.low = a * b;
197
0
#elif defined(GLZ_FASTFLOAT_32BIT) || (defined(_WIN64) && !defined(__clang__) && !defined(__MINGW32__))
198
0
      answer.low = _umul128(a, b, &answer.high); // _umul128 not available on ARM64
199
0
#elif defined(GLZ_FASTFLOAT_64BIT) && defined(__SIZEOF_INT128__)
200
0
      __uint128_t r = ((__uint128_t)a) * b;
201
0
      answer.low = uint64_t(r);
202
0
      answer.high = uint64_t(r >> 64);
203
0
#else
204
0
      answer.low = umul128_generic(a, b, &answer.high);
205
0
#endif
206
0
      return answer;
207
0
   }
208
209
   template <std::integral T>
210
      requires(std::is_unsigned_v<T> && (sizeof(T) <= 8))
211
   GLZ_ALWAYS_INLINE constexpr const uint8_t* parse_int(T& v, const uint8_t* c) noexcept
212
13.1k
   {
213
13.1k
      if (is_digit(*c)) [[likely]] {
214
13.1k
         v = *c - '0';
215
13.1k
         ++c;
216
13.1k
      }
217
42
      else [[unlikely]] {
218
42
         return {};
219
42
      }
220
221
13.1k
      if (is_digit(*c)) {
222
5.74k
         v = v * 10 + (*c - '0');
223
5.74k
         ++c;
224
5.74k
      }
225
7.38k
      else {
226
7.38k
         return c;
227
7.38k
      }
228
229
5.74k
      if (c[-2] == '0') [[unlikely]] {
230
4
         return {};
231
4
      }
232
233
5.73k
      if constexpr (sizeof(T) > 1) {
234
5.73k
         if (is_digit(*c)) {
235
5.03k
            v = v * 10 + (*c - '0');
236
5.03k
            ++c;
237
5.03k
         }
238
705
         else {
239
705
            return c;
240
705
         }
241
242
5.03k
         if (is_digit(*c)) {
243
4.03k
            v = v * 10 + (*c - '0');
244
4.03k
            ++c;
245
4.03k
         }
246
999
         else {
247
999
            return c;
248
999
         }
249
250
4.03k
         if constexpr (sizeof(T) > 2) {
251
2.20k
            if (is_digit(*c)) {
252
2.11k
               v = v * 10 + (*c - '0');
253
2.11k
               ++c;
254
2.11k
            }
255
82
            else {
256
82
               return c;
257
82
            }
258
259
2.11k
            if (is_digit(*c)) {
260
2.04k
               v = v * 10 + (*c - '0');
261
2.04k
               ++c;
262
2.04k
            }
263
78
            else {
264
78
               return c;
265
78
            }
266
267
2.04k
            if (is_digit(*c)) {
268
1.94k
               v = v * 10 + (*c - '0');
269
1.94k
               ++c;
270
1.94k
            }
271
92
            else {
272
92
               return c;
273
92
            }
274
275
1.94k
            if (is_digit(*c)) {
276
1.84k
               v = v * 10 + (*c - '0');
277
1.84k
               ++c;
278
1.84k
            }
279
108
            else {
280
108
               return c;
281
108
            }
282
283
1.84k
            if (is_digit(*c)) {
284
1.68k
               v = v * 10 + (*c - '0');
285
1.68k
               ++c;
286
1.68k
            }
287
158
            else {
288
158
               return c;
289
158
            }
290
291
1.68k
            if constexpr (sizeof(T) > 4) {
292
1.27k
               if (is_digit(*c)) {
293
1.27k
                  v = v * 10 + (*c - '0');
294
1.27k
                  ++c;
295
1.27k
               }
296
6
               else {
297
6
                  return c;
298
6
               }
299
300
1.27k
               if (is_digit(*c)) {
301
1.20k
                  v = v * 10 + (*c - '0');
302
1.20k
                  ++c;
303
1.20k
               }
304
68
               else {
305
68
                  return c;
306
68
               }
307
308
1.20k
               if (is_digit(*c)) {
309
1.18k
                  v = v * 10 + (*c - '0');
310
1.18k
                  ++c;
311
1.18k
               }
312
18
               else {
313
18
                  return c;
314
18
               }
315
316
1.18k
               if (is_digit(*c)) {
317
1.08k
                  v = v * 10 + (*c - '0');
318
1.08k
                  ++c;
319
1.08k
               }
320
102
               else {
321
102
                  return c;
322
102
               }
323
324
1.08k
               if (is_digit(*c)) {
325
1.05k
                  v = v * 10 + (*c - '0');
326
1.05k
                  ++c;
327
1.05k
               }
328
28
               else {
329
28
                  return c;
330
28
               }
331
332
1.05k
               if (is_digit(*c)) {
333
948
                  v = v * 10 + (*c - '0');
334
948
                  ++c;
335
948
               }
336
108
               else {
337
108
                  return c;
338
108
               }
339
340
948
               if (is_digit(*c)) {
341
886
                  v = v * 10 + (*c - '0');
342
886
                  ++c;
343
886
               }
344
62
               else {
345
62
                  return c;
346
62
               }
347
348
886
               if (is_digit(*c)) {
349
736
                  v = v * 10 + (*c - '0');
350
736
                  ++c;
351
736
               }
352
150
               else {
353
150
                  return c;
354
150
               }
355
356
736
               if (is_digit(*c)) {
357
704
                  v = v * 10 + (*c - '0');
358
704
                  ++c;
359
704
               }
360
32
               else {
361
32
                  return c;
362
32
               }
363
364
704
               if (is_digit(*c)) {
365
564
                  v = v * 10 + (*c - '0');
366
564
                  ++c;
367
564
               }
368
140
               else {
369
140
                  return c;
370
140
               }
371
704
            }
372
1.68k
         }
373
4.03k
      }
374
375
5.73k
      if (is_digit(*c)) {
376
         // Test before multiplying. The previous guard multiplied first and then compared the
377
         // already-wrapped value against max/10 - 10, which only caught wraps that happened to land
378
         // below that threshold: "300" wraps to 44 for uint8_t and sailed through, as did most
379
         // out-of-range values. would_overflow_positive is the same branch-free check the signed
380
         // path above already uses, so the two paths now reject on the same rule.
381
1.74k
         if (would_overflow_positive<T>(v, *c)) [[unlikely]] {
382
10
            return {};
383
10
         }
384
1.73k
         v = v * 10 + (*c - '0');
385
1.73k
         ++c;
386
1.73k
         if (is_digit(*c)) [[unlikely]] {
387
4
            return {};
388
4
         }
389
1.73k
      }
390
391
5.72k
      return c;
392
5.73k
   }
Unexecuted instantiation: _ZN3glz9parse_intITkNSt3__18integralEmQaasr3stdE13is_unsigned_vIT_ElestS2_Li8EEEPKhRS2_S4_
_ZN3glz9parse_intITkNSt3__18integralEtQaasr3stdE13is_unsigned_vIT_ElestS2_Li8EEEPKhRS2_S4_
Line
Count
Source
212
10.8k
   {
213
10.8k
      if (is_digit(*c)) [[likely]] {
214
10.8k
         v = *c - '0';
215
10.8k
         ++c;
216
10.8k
      }
217
42
      else [[unlikely]] {
218
42
         return {};
219
42
      }
220
221
10.8k
      if (is_digit(*c)) {
222
3.47k
         v = v * 10 + (*c - '0');
223
3.47k
         ++c;
224
3.47k
      }
225
7.36k
      else {
226
7.36k
         return c;
227
7.36k
      }
228
229
3.47k
      if (c[-2] == '0') [[unlikely]] {
230
4
         return {};
231
4
      }
232
233
3.46k
      if constexpr (sizeof(T) > 1) {
234
3.46k
         if (is_digit(*c)) {
235
2.79k
            v = v * 10 + (*c - '0');
236
2.79k
            ++c;
237
2.79k
         }
238
671
         else {
239
671
            return c;
240
671
         }
241
242
2.79k
         if (is_digit(*c)) {
243
1.83k
            v = v * 10 + (*c - '0');
244
1.83k
            ++c;
245
1.83k
         }
246
961
         else {
247
961
            return c;
248
961
         }
249
250
         if constexpr (sizeof(T) > 2) {
251
            if (is_digit(*c)) {
252
               v = v * 10 + (*c - '0');
253
               ++c;
254
            }
255
            else {
256
               return c;
257
            }
258
259
            if (is_digit(*c)) {
260
               v = v * 10 + (*c - '0');
261
               ++c;
262
            }
263
            else {
264
               return c;
265
            }
266
267
            if (is_digit(*c)) {
268
               v = v * 10 + (*c - '0');
269
               ++c;
270
            }
271
            else {
272
               return c;
273
            }
274
275
            if (is_digit(*c)) {
276
               v = v * 10 + (*c - '0');
277
               ++c;
278
            }
279
            else {
280
               return c;
281
            }
282
283
            if (is_digit(*c)) {
284
               v = v * 10 + (*c - '0');
285
               ++c;
286
            }
287
            else {
288
               return c;
289
            }
290
291
            if constexpr (sizeof(T) > 4) {
292
               if (is_digit(*c)) {
293
                  v = v * 10 + (*c - '0');
294
                  ++c;
295
               }
296
               else {
297
                  return c;
298
               }
299
300
               if (is_digit(*c)) {
301
                  v = v * 10 + (*c - '0');
302
                  ++c;
303
               }
304
               else {
305
                  return c;
306
               }
307
308
               if (is_digit(*c)) {
309
                  v = v * 10 + (*c - '0');
310
                  ++c;
311
               }
312
               else {
313
                  return c;
314
               }
315
316
               if (is_digit(*c)) {
317
                  v = v * 10 + (*c - '0');
318
                  ++c;
319
               }
320
               else {
321
                  return c;
322
               }
323
324
               if (is_digit(*c)) {
325
                  v = v * 10 + (*c - '0');
326
                  ++c;
327
               }
328
               else {
329
                  return c;
330
               }
331
332
               if (is_digit(*c)) {
333
                  v = v * 10 + (*c - '0');
334
                  ++c;
335
               }
336
               else {
337
                  return c;
338
               }
339
340
               if (is_digit(*c)) {
341
                  v = v * 10 + (*c - '0');
342
                  ++c;
343
               }
344
               else {
345
                  return c;
346
               }
347
348
               if (is_digit(*c)) {
349
                  v = v * 10 + (*c - '0');
350
                  ++c;
351
               }
352
               else {
353
                  return c;
354
               }
355
356
               if (is_digit(*c)) {
357
                  v = v * 10 + (*c - '0');
358
                  ++c;
359
               }
360
               else {
361
                  return c;
362
               }
363
364
               if (is_digit(*c)) {
365
                  v = v * 10 + (*c - '0');
366
                  ++c;
367
               }
368
               else {
369
                  return c;
370
               }
371
            }
372
         }
373
1.83k
      }
374
375
3.46k
      if (is_digit(*c)) {
376
         // Test before multiplying. The previous guard multiplied first and then compared the
377
         // already-wrapped value against max/10 - 10, which only caught wraps that happened to land
378
         // below that threshold: "300" wraps to 44 for uint8_t and sailed through, as did most
379
         // out-of-range values. would_overflow_positive is the same branch-free check the signed
380
         // path above already uses, so the two paths now reject on the same rule.
381
1.07k
         if (would_overflow_positive<T>(v, *c)) [[unlikely]] {
382
10
            return {};
383
10
         }
384
1.06k
         v = v * 10 + (*c - '0');
385
1.06k
         ++c;
386
1.06k
         if (is_digit(*c)) [[unlikely]] {
387
4
            return {};
388
4
         }
389
1.06k
      }
390
391
3.45k
      return c;
392
3.46k
   }
_ZN3glz9parse_intITkNSt3__18integralEjQaasr3stdE13is_unsigned_vIT_ElestS2_Li8EEEPKhRS2_S4_
Line
Count
Source
212
718
   {
213
718
      if (is_digit(*c)) [[likely]] {
214
718
         v = *c - '0';
215
718
         ++c;
216
718
      }
217
0
      else [[unlikely]] {
218
0
         return {};
219
0
      }
220
221
718
      if (is_digit(*c)) {
222
706
         v = v * 10 + (*c - '0');
223
706
         ++c;
224
706
      }
225
12
      else {
226
12
         return c;
227
12
      }
228
229
706
      if (c[-2] == '0') [[unlikely]] {
230
0
         return {};
231
0
      }
232
233
706
      if constexpr (sizeof(T) > 1) {
234
706
         if (is_digit(*c)) {
235
686
            v = v * 10 + (*c - '0');
236
686
            ++c;
237
686
         }
238
20
         else {
239
20
            return c;
240
20
         }
241
242
686
         if (is_digit(*c)) {
243
662
            v = v * 10 + (*c - '0');
244
662
            ++c;
245
662
         }
246
24
         else {
247
24
            return c;
248
24
         }
249
250
662
         if constexpr (sizeof(T) > 2) {
251
662
            if (is_digit(*c)) {
252
624
               v = v * 10 + (*c - '0');
253
624
               ++c;
254
624
            }
255
38
            else {
256
38
               return c;
257
38
            }
258
259
624
            if (is_digit(*c)) {
260
586
               v = v * 10 + (*c - '0');
261
586
               ++c;
262
586
            }
263
38
            else {
264
38
               return c;
265
38
            }
266
267
586
            if (is_digit(*c)) {
268
536
               v = v * 10 + (*c - '0');
269
536
               ++c;
270
536
            }
271
50
            else {
272
50
               return c;
273
50
            }
274
275
536
            if (is_digit(*c)) {
276
478
               v = v * 10 + (*c - '0');
277
478
               ++c;
278
478
            }
279
58
            else {
280
58
               return c;
281
58
            }
282
283
478
            if (is_digit(*c)) {
284
404
               v = v * 10 + (*c - '0');
285
404
               ++c;
286
404
            }
287
74
            else {
288
74
               return c;
289
74
            }
290
291
            if constexpr (sizeof(T) > 4) {
292
               if (is_digit(*c)) {
293
                  v = v * 10 + (*c - '0');
294
                  ++c;
295
               }
296
               else {
297
                  return c;
298
               }
299
300
               if (is_digit(*c)) {
301
                  v = v * 10 + (*c - '0');
302
                  ++c;
303
               }
304
               else {
305
                  return c;
306
               }
307
308
               if (is_digit(*c)) {
309
                  v = v * 10 + (*c - '0');
310
                  ++c;
311
               }
312
               else {
313
                  return c;
314
               }
315
316
               if (is_digit(*c)) {
317
                  v = v * 10 + (*c - '0');
318
                  ++c;
319
               }
320
               else {
321
                  return c;
322
               }
323
324
               if (is_digit(*c)) {
325
                  v = v * 10 + (*c - '0');
326
                  ++c;
327
               }
328
               else {
329
                  return c;
330
               }
331
332
               if (is_digit(*c)) {
333
                  v = v * 10 + (*c - '0');
334
                  ++c;
335
               }
336
               else {
337
                  return c;
338
               }
339
340
               if (is_digit(*c)) {
341
                  v = v * 10 + (*c - '0');
342
                  ++c;
343
               }
344
               else {
345
                  return c;
346
               }
347
348
               if (is_digit(*c)) {
349
                  v = v * 10 + (*c - '0');
350
                  ++c;
351
               }
352
               else {
353
                  return c;
354
               }
355
356
               if (is_digit(*c)) {
357
                  v = v * 10 + (*c - '0');
358
                  ++c;
359
               }
360
               else {
361
                  return c;
362
               }
363
364
               if (is_digit(*c)) {
365
                  v = v * 10 + (*c - '0');
366
                  ++c;
367
               }
368
               else {
369
                  return c;
370
               }
371
            }
372
404
         }
373
662
      }
374
375
706
      if (is_digit(*c)) {
376
         // Test before multiplying. The previous guard multiplied first and then compared the
377
         // already-wrapped value against max/10 - 10, which only caught wraps that happened to land
378
         // below that threshold: "300" wraps to 44 for uint8_t and sailed through, as did most
379
         // out-of-range values. would_overflow_positive is the same branch-free check the signed
380
         // path above already uses, so the two paths now reject on the same rule.
381
360
         if (would_overflow_positive<T>(v, *c)) [[unlikely]] {
382
0
            return {};
383
0
         }
384
360
         v = v * 10 + (*c - '0');
385
360
         ++c;
386
360
         if (is_digit(*c)) [[unlikely]] {
387
0
            return {};
388
0
         }
389
360
      }
390
391
706
      return c;
392
706
   }
_ZN3glz9parse_intITkNSt3__18integralEyQaasr3stdE13is_unsigned_vIT_ElestS2_Li8EEEPKhRS2_S4_
Line
Count
Source
212
1.57k
   {
213
1.57k
      if (is_digit(*c)) [[likely]] {
214
1.57k
         v = *c - '0';
215
1.57k
         ++c;
216
1.57k
      }
217
0
      else [[unlikely]] {
218
0
         return {};
219
0
      }
220
221
1.57k
      if (is_digit(*c)) {
222
1.56k
         v = v * 10 + (*c - '0');
223
1.56k
         ++c;
224
1.56k
      }
225
10
      else {
226
10
         return c;
227
10
      }
228
229
1.56k
      if (c[-2] == '0') [[unlikely]] {
230
0
         return {};
231
0
      }
232
233
1.56k
      if constexpr (sizeof(T) > 1) {
234
1.56k
         if (is_digit(*c)) {
235
1.55k
            v = v * 10 + (*c - '0');
236
1.55k
            ++c;
237
1.55k
         }
238
14
         else {
239
14
            return c;
240
14
         }
241
242
1.55k
         if (is_digit(*c)) {
243
1.53k
            v = v * 10 + (*c - '0');
244
1.53k
            ++c;
245
1.53k
         }
246
14
         else {
247
14
            return c;
248
14
         }
249
250
1.53k
         if constexpr (sizeof(T) > 2) {
251
1.53k
            if (is_digit(*c)) {
252
1.49k
               v = v * 10 + (*c - '0');
253
1.49k
               ++c;
254
1.49k
            }
255
44
            else {
256
44
               return c;
257
44
            }
258
259
1.49k
            if (is_digit(*c)) {
260
1.45k
               v = v * 10 + (*c - '0');
261
1.45k
               ++c;
262
1.45k
            }
263
40
            else {
264
40
               return c;
265
40
            }
266
267
1.45k
            if (is_digit(*c)) {
268
1.41k
               v = v * 10 + (*c - '0');
269
1.41k
               ++c;
270
1.41k
            }
271
42
            else {
272
42
               return c;
273
42
            }
274
275
1.41k
            if (is_digit(*c)) {
276
1.36k
               v = v * 10 + (*c - '0');
277
1.36k
               ++c;
278
1.36k
            }
279
50
            else {
280
50
               return c;
281
50
            }
282
283
1.36k
            if (is_digit(*c)) {
284
1.27k
               v = v * 10 + (*c - '0');
285
1.27k
               ++c;
286
1.27k
            }
287
84
            else {
288
84
               return c;
289
84
            }
290
291
1.27k
            if constexpr (sizeof(T) > 4) {
292
1.27k
               if (is_digit(*c)) {
293
1.27k
                  v = v * 10 + (*c - '0');
294
1.27k
                  ++c;
295
1.27k
               }
296
6
               else {
297
6
                  return c;
298
6
               }
299
300
1.27k
               if (is_digit(*c)) {
301
1.20k
                  v = v * 10 + (*c - '0');
302
1.20k
                  ++c;
303
1.20k
               }
304
68
               else {
305
68
                  return c;
306
68
               }
307
308
1.20k
               if (is_digit(*c)) {
309
1.18k
                  v = v * 10 + (*c - '0');
310
1.18k
                  ++c;
311
1.18k
               }
312
18
               else {
313
18
                  return c;
314
18
               }
315
316
1.18k
               if (is_digit(*c)) {
317
1.08k
                  v = v * 10 + (*c - '0');
318
1.08k
                  ++c;
319
1.08k
               }
320
102
               else {
321
102
                  return c;
322
102
               }
323
324
1.08k
               if (is_digit(*c)) {
325
1.05k
                  v = v * 10 + (*c - '0');
326
1.05k
                  ++c;
327
1.05k
               }
328
28
               else {
329
28
                  return c;
330
28
               }
331
332
1.05k
               if (is_digit(*c)) {
333
948
                  v = v * 10 + (*c - '0');
334
948
                  ++c;
335
948
               }
336
108
               else {
337
108
                  return c;
338
108
               }
339
340
948
               if (is_digit(*c)) {
341
886
                  v = v * 10 + (*c - '0');
342
886
                  ++c;
343
886
               }
344
62
               else {
345
62
                  return c;
346
62
               }
347
348
886
               if (is_digit(*c)) {
349
736
                  v = v * 10 + (*c - '0');
350
736
                  ++c;
351
736
               }
352
150
               else {
353
150
                  return c;
354
150
               }
355
356
736
               if (is_digit(*c)) {
357
704
                  v = v * 10 + (*c - '0');
358
704
                  ++c;
359
704
               }
360
32
               else {
361
32
                  return c;
362
32
               }
363
364
704
               if (is_digit(*c)) {
365
564
                  v = v * 10 + (*c - '0');
366
564
                  ++c;
367
564
               }
368
140
               else {
369
140
                  return c;
370
140
               }
371
704
            }
372
1.27k
         }
373
1.53k
      }
374
375
1.56k
      if (is_digit(*c)) {
376
         // Test before multiplying. The previous guard multiplied first and then compared the
377
         // already-wrapped value against max/10 - 10, which only caught wraps that happened to land
378
         // below that threshold: "300" wraps to 44 for uint8_t and sailed through, as did most
379
         // out-of-range values. would_overflow_positive is the same branch-free check the signed
380
         // path above already uses, so the two paths now reject on the same rule.
381
316
         if (would_overflow_positive<T>(v, *c)) [[unlikely]] {
382
0
            return {};
383
0
         }
384
316
         v = v * 10 + (*c - '0');
385
316
         ++c;
386
316
         if (is_digit(*c)) [[unlikely]] {
387
0
            return {};
388
0
         }
389
316
      }
390
391
1.56k
      return c;
392
1.56k
   }
393
394
   template <std::integral T, class Char>
395
      requires(std::is_unsigned_v<T>)
396
   GLZ_ALWAYS_INLINE constexpr bool atoi(T& v, Char*& c) noexcept
397
13.1k
   {
398
13.1k
      if (auto ptr = parse_int(v, reinterpret_cast<const uint8_t*>(c))) [[likely]] {
399
13.1k
         c = reinterpret_cast<const Char*>(ptr);
400
13.1k
         if (*c == 'e' || *c == 'E') {
401
2.96k
            ++c;
402
2.96k
         }
403
10.1k
         else {
404
10.1k
            if (*c == '.') [[unlikely]] {
405
3
               return false;
406
3
            }
407
10.1k
            return true;
408
10.1k
         }
409
410
2.96k
         c += (*c == '+');
411
412
2.96k
         if (not is_digit(*c)) [[unlikely]] {
413
93
            return false;
414
93
         }
415
2.87k
         const uint32_t exp = parse_exponent(c);
416
         // An exponent past the width's limit overflows any non-zero magnitude, but zero stays zero
417
         // however far it is scaled, so "0e19" is in range for every width. Testing the magnitude
418
         // here rather than ahead of the dispatch keeps it off the hot path: it only runs once the
419
         // exponent has already failed the range check.
420
         if constexpr (sizeof(T) == 1) {
421
            if (exp > 2) [[unlikely]] {
422
               return v == 0;
423
            }
424
         }
425
2.87k
         else if constexpr (sizeof(T) == 2) {
426
2.87k
            if (exp > 4) [[unlikely]] {
427
500
               return v == 0;
428
500
            }
429
         }
430
0
         else if constexpr (sizeof(T) == 4) {
431
0
            if (exp > 9) [[unlikely]] {
432
0
               return v == 0;
433
0
            }
434
         }
435
0
         else {
436
0
            if (exp > 19) [[unlikely]] {
437
0
               return v == 0;
438
0
            }
439
0
         }
440
441
         if constexpr (sizeof(T) == 1) {
442
            static constexpr std::array<uint8_t, 3> powers_of_ten{1, 10, 100};
443
            const uint64_t i = v * powers_of_ten[exp];
444
            v = T(i);
445
            return i <= (std::numeric_limits<T>::max)();
446
         }
447
2.87k
         else if constexpr (sizeof(T) == 2) {
448
2.87k
            static constexpr std::array<uint16_t, 5> powers_of_ten{1, 10, 100, 1000, 10000};
449
2.87k
            const uint64_t i = v * powers_of_ten[exp];
450
2.87k
            v = T(i);
451
2.87k
            return i <= (std::numeric_limits<T>::max)();
452
         }
453
0
         else if constexpr (sizeof(T) < 8) {
454
0
            const uint64_t i = v * powers_of_ten_int[exp];
455
0
            v = T(i);
456
0
            return i <= (std::numeric_limits<T>::max)();
457
         }
458
0
         else {
459
0
#if defined(__SIZEOF_INT128__)
460
0
            const __uint128_t res = __uint128_t(v) * powers_of_ten_int[exp];
461
0
            v = T(res);
462
0
            return res <= (std::numeric_limits<T>::max)();
463
#else
464
            const auto res = full_multiplication(v, powers_of_ten_int[exp]);
465
            v = T(res.low);
466
            return res.high == 0;
467
#endif
468
0
         }
469
2.87k
      }
470
2.93k
      return false;
471
13.1k
   }
Unexecuted instantiation: _ZN3glz4atoiITkNSt3__18integralEmKcQsr3stdE13is_unsigned_vIT_EEEbRS3_RPT0_
_ZN3glz4atoiITkNSt3__18integralEtKcQsr3stdE13is_unsigned_vIT_EEEbRS3_RPT0_
Line
Count
Source
397
10.8k
   {
398
10.8k
      if (auto ptr = parse_int(v, reinterpret_cast<const uint8_t*>(c))) [[likely]] {
399
10.8k
         c = reinterpret_cast<const Char*>(ptr);
400
10.8k
         if (*c == 'e' || *c == 'E') {
401
2.96k
            ++c;
402
2.96k
         }
403
7.84k
         else {
404
7.84k
            if (*c == '.') [[unlikely]] {
405
3
               return false;
406
3
            }
407
7.84k
            return true;
408
7.84k
         }
409
410
2.96k
         c += (*c == '+');
411
412
2.96k
         if (not is_digit(*c)) [[unlikely]] {
413
93
            return false;
414
93
         }
415
2.87k
         const uint32_t exp = parse_exponent(c);
416
         // An exponent past the width's limit overflows any non-zero magnitude, but zero stays zero
417
         // however far it is scaled, so "0e19" is in range for every width. Testing the magnitude
418
         // here rather than ahead of the dispatch keeps it off the hot path: it only runs once the
419
         // exponent has already failed the range check.
420
         if constexpr (sizeof(T) == 1) {
421
            if (exp > 2) [[unlikely]] {
422
               return v == 0;
423
            }
424
         }
425
2.87k
         else if constexpr (sizeof(T) == 2) {
426
2.87k
            if (exp > 4) [[unlikely]] {
427
500
               return v == 0;
428
500
            }
429
         }
430
         else if constexpr (sizeof(T) == 4) {
431
            if (exp > 9) [[unlikely]] {
432
               return v == 0;
433
            }
434
         }
435
         else {
436
            if (exp > 19) [[unlikely]] {
437
               return v == 0;
438
            }
439
         }
440
441
         if constexpr (sizeof(T) == 1) {
442
            static constexpr std::array<uint8_t, 3> powers_of_ten{1, 10, 100};
443
            const uint64_t i = v * powers_of_ten[exp];
444
            v = T(i);
445
            return i <= (std::numeric_limits<T>::max)();
446
         }
447
2.87k
         else if constexpr (sizeof(T) == 2) {
448
2.87k
            static constexpr std::array<uint16_t, 5> powers_of_ten{1, 10, 100, 1000, 10000};
449
2.87k
            const uint64_t i = v * powers_of_ten[exp];
450
2.87k
            v = T(i);
451
2.87k
            return i <= (std::numeric_limits<T>::max)();
452
         }
453
         else if constexpr (sizeof(T) < 8) {
454
            const uint64_t i = v * powers_of_ten_int[exp];
455
            v = T(i);
456
            return i <= (std::numeric_limits<T>::max)();
457
         }
458
         else {
459
#if defined(__SIZEOF_INT128__)
460
            const __uint128_t res = __uint128_t(v) * powers_of_ten_int[exp];
461
            v = T(res);
462
            return res <= (std::numeric_limits<T>::max)();
463
#else
464
            const auto res = full_multiplication(v, powers_of_ten_int[exp]);
465
            v = T(res.low);
466
            return res.high == 0;
467
#endif
468
         }
469
2.87k
      }
470
2.93k
      return false;
471
10.8k
   }
_ZN3glz4atoiITkNSt3__18integralEjKcQsr3stdE13is_unsigned_vIT_EEEbRS3_RPT0_
Line
Count
Source
397
718
   {
398
718
      if (auto ptr = parse_int(v, reinterpret_cast<const uint8_t*>(c))) [[likely]] {
399
718
         c = reinterpret_cast<const Char*>(ptr);
400
718
         if (*c == 'e' || *c == 'E') {
401
0
            ++c;
402
0
         }
403
718
         else {
404
718
            if (*c == '.') [[unlikely]] {
405
0
               return false;
406
0
            }
407
718
            return true;
408
718
         }
409
410
0
         c += (*c == '+');
411
412
0
         if (not is_digit(*c)) [[unlikely]] {
413
0
            return false;
414
0
         }
415
0
         const uint32_t exp = parse_exponent(c);
416
         // An exponent past the width's limit overflows any non-zero magnitude, but zero stays zero
417
         // however far it is scaled, so "0e19" is in range for every width. Testing the magnitude
418
         // here rather than ahead of the dispatch keeps it off the hot path: it only runs once the
419
         // exponent has already failed the range check.
420
         if constexpr (sizeof(T) == 1) {
421
            if (exp > 2) [[unlikely]] {
422
               return v == 0;
423
            }
424
         }
425
         else if constexpr (sizeof(T) == 2) {
426
            if (exp > 4) [[unlikely]] {
427
               return v == 0;
428
            }
429
         }
430
0
         else if constexpr (sizeof(T) == 4) {
431
0
            if (exp > 9) [[unlikely]] {
432
0
               return v == 0;
433
0
            }
434
         }
435
         else {
436
            if (exp > 19) [[unlikely]] {
437
               return v == 0;
438
            }
439
         }
440
441
         if constexpr (sizeof(T) == 1) {
442
            static constexpr std::array<uint8_t, 3> powers_of_ten{1, 10, 100};
443
            const uint64_t i = v * powers_of_ten[exp];
444
            v = T(i);
445
            return i <= (std::numeric_limits<T>::max)();
446
         }
447
         else if constexpr (sizeof(T) == 2) {
448
            static constexpr std::array<uint16_t, 5> powers_of_ten{1, 10, 100, 1000, 10000};
449
            const uint64_t i = v * powers_of_ten[exp];
450
            v = T(i);
451
            return i <= (std::numeric_limits<T>::max)();
452
         }
453
0
         else if constexpr (sizeof(T) < 8) {
454
0
            const uint64_t i = v * powers_of_ten_int[exp];
455
0
            v = T(i);
456
0
            return i <= (std::numeric_limits<T>::max)();
457
         }
458
         else {
459
#if defined(__SIZEOF_INT128__)
460
            const __uint128_t res = __uint128_t(v) * powers_of_ten_int[exp];
461
            v = T(res);
462
            return res <= (std::numeric_limits<T>::max)();
463
#else
464
            const auto res = full_multiplication(v, powers_of_ten_int[exp]);
465
            v = T(res.low);
466
            return res.high == 0;
467
#endif
468
         }
469
0
      }
470
0
      return false;
471
718
   }
_ZN3glz4atoiITkNSt3__18integralEyKcQsr3stdE13is_unsigned_vIT_EEEbRS3_RPT0_
Line
Count
Source
397
1.57k
   {
398
1.57k
      if (auto ptr = parse_int(v, reinterpret_cast<const uint8_t*>(c))) [[likely]] {
399
1.57k
         c = reinterpret_cast<const Char*>(ptr);
400
1.57k
         if (*c == 'e' || *c == 'E') {
401
0
            ++c;
402
0
         }
403
1.57k
         else {
404
1.57k
            if (*c == '.') [[unlikely]] {
405
0
               return false;
406
0
            }
407
1.57k
            return true;
408
1.57k
         }
409
410
0
         c += (*c == '+');
411
412
0
         if (not is_digit(*c)) [[unlikely]] {
413
0
            return false;
414
0
         }
415
0
         const uint32_t exp = parse_exponent(c);
416
         // An exponent past the width's limit overflows any non-zero magnitude, but zero stays zero
417
         // however far it is scaled, so "0e19" is in range for every width. Testing the magnitude
418
         // here rather than ahead of the dispatch keeps it off the hot path: it only runs once the
419
         // exponent has already failed the range check.
420
         if constexpr (sizeof(T) == 1) {
421
            if (exp > 2) [[unlikely]] {
422
               return v == 0;
423
            }
424
         }
425
         else if constexpr (sizeof(T) == 2) {
426
            if (exp > 4) [[unlikely]] {
427
               return v == 0;
428
            }
429
         }
430
         else if constexpr (sizeof(T) == 4) {
431
            if (exp > 9) [[unlikely]] {
432
               return v == 0;
433
            }
434
         }
435
0
         else {
436
0
            if (exp > 19) [[unlikely]] {
437
0
               return v == 0;
438
0
            }
439
0
         }
440
441
         if constexpr (sizeof(T) == 1) {
442
            static constexpr std::array<uint8_t, 3> powers_of_ten{1, 10, 100};
443
            const uint64_t i = v * powers_of_ten[exp];
444
            v = T(i);
445
            return i <= (std::numeric_limits<T>::max)();
446
         }
447
         else if constexpr (sizeof(T) == 2) {
448
            static constexpr std::array<uint16_t, 5> powers_of_ten{1, 10, 100, 1000, 10000};
449
            const uint64_t i = v * powers_of_ten[exp];
450
            v = T(i);
451
            return i <= (std::numeric_limits<T>::max)();
452
         }
453
         else if constexpr (sizeof(T) < 8) {
454
            const uint64_t i = v * powers_of_ten_int[exp];
455
            v = T(i);
456
            return i <= (std::numeric_limits<T>::max)();
457
         }
458
0
         else {
459
0
#if defined(__SIZEOF_INT128__)
460
0
            const __uint128_t res = __uint128_t(v) * powers_of_ten_int[exp];
461
0
            v = T(res);
462
0
            return res <= (std::numeric_limits<T>::max)();
463
#else
464
            const auto res = full_multiplication(v, powers_of_ten_int[exp]);
465
            v = T(res.low);
466
            return res.high == 0;
467
#endif
468
0
         }
469
0
      }
470
0
      return false;
471
1.57k
   }
472
473
   template <std::integral T>
474
      requires(std::is_signed_v<T> && (sizeof(T) <= 8))
475
   GLZ_ALWAYS_INLINE constexpr const uint8_t* parse_int(T& v, const uint8_t* c) noexcept
476
1.96M
   {
477
1.96M
      const uint8_t sign = *c == '-';
478
1.96M
      c += sign;
479
480
1.96M
      if (is_digit(*c)) [[likely]] {
481
1.91M
         v = *c - '0';
482
1.91M
         ++c;
483
1.91M
      }
484
55.8k
      else [[unlikely]] {
485
55.8k
         return {};
486
55.8k
      }
487
488
1.91M
      if (is_digit(*c)) {
489
1.32M
         v = v * 10 + (*c - '0');
490
1.32M
         ++c;
491
1.32M
      }
492
593k
      else {
493
593k
         if (sign) {
494
98.8k
            v = -v;
495
98.8k
         }
496
593k
         return c;
497
593k
      }
498
499
1.32M
      if (c[-2] == '0') [[unlikely]] {
500
193
         return {};
501
193
      }
502
503
1.32M
      if constexpr (sizeof(T) > 1) {
504
1.32M
         if (is_digit(*c)) {
505
849k
            v = v * 10 + (*c - '0');
506
849k
            ++c;
507
849k
         }
508
470k
         else {
509
470k
            if (sign) {
510
284k
               v = -v;
511
284k
            }
512
470k
            return c;
513
470k
         }
514
515
849k
         if (is_digit(*c)) {
516
539k
            v = v * 10 + (*c - '0');
517
539k
            ++c;
518
539k
         }
519
310k
         else {
520
310k
            if (sign) {
521
173k
               v = -v;
522
173k
            }
523
310k
            return c;
524
310k
         }
525
526
539k
         if constexpr (sizeof(T) > 2) {
527
539k
            if (is_digit(*c)) {
528
392k
               v = v * 10 + (*c - '0');
529
392k
               ++c;
530
392k
            }
531
146k
            else {
532
146k
               if (sign) {
533
14.8k
                  v = -v;
534
14.8k
               }
535
146k
               return c;
536
146k
            }
537
538
392k
            if (is_digit(*c)) {
539
290k
               v = v * 10 + (*c - '0');
540
290k
               ++c;
541
290k
            }
542
101k
            else {
543
101k
               if (sign) {
544
10.1k
                  v = -v;
545
10.1k
               }
546
101k
               return c;
547
101k
            }
548
549
290k
            if (is_digit(*c)) {
550
172k
               v = v * 10 + (*c - '0');
551
172k
               ++c;
552
172k
            }
553
117k
            else {
554
117k
               if (sign) {
555
22.1k
                  v = -v;
556
22.1k
               }
557
117k
               return c;
558
117k
            }
559
560
172k
            if (is_digit(*c)) {
561
120k
               v = v * 10 + (*c - '0');
562
120k
               ++c;
563
120k
            }
564
52.5k
            else {
565
52.5k
               if (sign) {
566
12.0k
                  v = -v;
567
12.0k
               }
568
52.5k
               return c;
569
52.5k
            }
570
571
120k
            if (is_digit(*c)) {
572
87.4k
               v = v * 10 + (*c - '0');
573
87.4k
               ++c;
574
87.4k
            }
575
32.8k
            else {
576
32.8k
               if (sign) {
577
9.16k
                  v = -v;
578
9.16k
               }
579
32.8k
               return c;
580
32.8k
            }
581
582
87.4k
            if constexpr (sizeof(T) > 4) {
583
1.21k
               if (is_digit(*c)) {
584
1.20k
                  v = v * 10 + (*c - '0');
585
1.20k
                  ++c;
586
1.20k
               }
587
14
               else {
588
14
                  if (sign) {
589
8
                     v = -v;
590
8
                  }
591
14
                  return c;
592
14
               }
593
594
1.20k
               if (is_digit(*c)) {
595
1.12k
                  v = v * 10 + (*c - '0');
596
1.12k
                  ++c;
597
1.12k
               }
598
84
               else {
599
84
                  if (sign) {
600
16
                     v = -v;
601
16
                  }
602
84
                  return c;
603
84
               }
604
605
1.12k
               if (is_digit(*c)) {
606
1.09k
                  v = v * 10 + (*c - '0');
607
1.09k
                  ++c;
608
1.09k
               }
609
26
               else {
610
26
                  if (sign) {
611
8
                     v = -v;
612
8
                  }
613
26
                  return c;
614
26
               }
615
616
1.09k
               if (is_digit(*c)) {
617
972
                  v = v * 10 + (*c - '0');
618
972
                  ++c;
619
972
               }
620
122
               else {
621
122
                  if (sign) {
622
20
                     v = -v;
623
20
                  }
624
122
                  return c;
625
122
               }
626
627
972
               if (is_digit(*c)) {
628
926
                  v = v * 10 + (*c - '0');
629
926
                  ++c;
630
926
               }
631
46
               else {
632
46
                  if (sign) {
633
18
                     v = -v;
634
18
                  }
635
46
                  return c;
636
46
               }
637
638
926
               if (is_digit(*c)) {
639
800
                  v = v * 10 + (*c - '0');
640
800
                  ++c;
641
800
               }
642
126
               else {
643
126
                  if (sign) {
644
18
                     v = -v;
645
18
                  }
646
126
                  return c;
647
126
               }
648
649
800
               if (is_digit(*c)) {
650
732
                  v = v * 10 + (*c - '0');
651
732
                  ++c;
652
732
               }
653
68
               else {
654
68
                  if (sign) {
655
6
                     v = -v;
656
6
                  }
657
68
                  return c;
658
68
               }
659
660
732
               if (is_digit(*c)) {
661
568
                  v = v * 10 + (*c - '0');
662
568
                  ++c;
663
568
               }
664
164
               else {
665
164
                  if (sign) {
666
14
                     v = -v;
667
14
                  }
668
164
                  return c;
669
164
               }
670
671
568
               if (is_digit(*c)) {
672
514
                  v = v * 10 + (*c - '0');
673
514
                  ++c;
674
514
               }
675
54
               else {
676
54
                  if (sign) {
677
22
                     v = -v;
678
22
                  }
679
54
                  return c;
680
54
               }
681
568
            }
682
87.4k
         }
683
539k
      }
684
685
1.32M
      if (is_digit(*c)) {
686
26.3k
         if (sign) {
687
11.2k
            if (would_overflow_negative<T>(v, *c)) [[unlikely]] {
688
375
               return {};
689
375
            }
690
10.8k
            v = -1 * v;
691
10.8k
            v = v * 10 - (*c - '0');
692
10.8k
         }
693
15.1k
         else {
694
15.1k
            if (would_overflow_positive<T>(v, *c)) [[unlikely]] {
695
3.07k
               return {};
696
3.07k
            }
697
12.0k
            v = v * 10 + (*c - '0');
698
12.0k
         }
699
22.8k
         ++c;
700
22.8k
         if (is_digit(*c)) [[unlikely]] {
701
1.75k
            return {};
702
1.75k
         }
703
21.1k
         return c;
704
22.8k
      }
705
706
1.29M
      if (sign) {
707
9.43k
         v = -v;
708
9.43k
      }
709
1.29M
      return c;
710
1.32M
   }
Unexecuted instantiation: _ZN3glz9parse_intITkNSt3__18integralElQaasr3stdE11is_signed_vIT_ElestS2_Li8EEEPKhRS2_S4_
_ZN3glz9parse_intITkNSt3__18integralEiQaasr3stdE11is_signed_vIT_ElestS2_Li8EEEPKhRS2_S4_
Line
Count
Source
476
1.96M
   {
477
1.96M
      const uint8_t sign = *c == '-';
478
1.96M
      c += sign;
479
480
1.96M
      if (is_digit(*c)) [[likely]] {
481
1.91M
         v = *c - '0';
482
1.91M
         ++c;
483
1.91M
      }
484
55.8k
      else [[unlikely]] {
485
55.8k
         return {};
486
55.8k
      }
487
488
1.91M
      if (is_digit(*c)) {
489
1.31M
         v = v * 10 + (*c - '0');
490
1.31M
         ++c;
491
1.31M
      }
492
593k
      else {
493
593k
         if (sign) {
494
98.8k
            v = -v;
495
98.8k
         }
496
593k
         return c;
497
593k
      }
498
499
1.31M
      if (c[-2] == '0') [[unlikely]] {
500
193
         return {};
501
193
      }
502
503
1.31M
      if constexpr (sizeof(T) > 1) {
504
1.31M
         if (is_digit(*c)) {
505
847k
            v = v * 10 + (*c - '0');
506
847k
            ++c;
507
847k
         }
508
470k
         else {
509
470k
            if (sign) {
510
284k
               v = -v;
511
284k
            }
512
470k
            return c;
513
470k
         }
514
515
847k
         if (is_digit(*c)) {
516
537k
            v = v * 10 + (*c - '0');
517
537k
            ++c;
518
537k
         }
519
310k
         else {
520
310k
            if (sign) {
521
173k
               v = -v;
522
173k
            }
523
310k
            return c;
524
310k
         }
525
526
537k
         if constexpr (sizeof(T) > 2) {
527
537k
            if (is_digit(*c)) {
528
390k
               v = v * 10 + (*c - '0');
529
390k
               ++c;
530
390k
            }
531
146k
            else {
532
146k
               if (sign) {
533
14.8k
                  v = -v;
534
14.8k
               }
535
146k
               return c;
536
146k
            }
537
538
390k
            if (is_digit(*c)) {
539
288k
               v = v * 10 + (*c - '0');
540
288k
               ++c;
541
288k
            }
542
101k
            else {
543
101k
               if (sign) {
544
10.1k
                  v = -v;
545
10.1k
               }
546
101k
               return c;
547
101k
            }
548
549
288k
            if (is_digit(*c)) {
550
171k
               v = v * 10 + (*c - '0');
551
171k
               ++c;
552
171k
            }
553
117k
            else {
554
117k
               if (sign) {
555
22.0k
                  v = -v;
556
22.0k
               }
557
117k
               return c;
558
117k
            }
559
560
171k
            if (is_digit(*c)) {
561
119k
               v = v * 10 + (*c - '0');
562
119k
               ++c;
563
119k
            }
564
52.5k
            else {
565
52.5k
               if (sign) {
566
12.0k
                  v = -v;
567
12.0k
               }
568
52.5k
               return c;
569
52.5k
            }
570
571
119k
            if (is_digit(*c)) {
572
86.2k
               v = v * 10 + (*c - '0');
573
86.2k
               ++c;
574
86.2k
            }
575
32.7k
            else {
576
32.7k
               if (sign) {
577
9.15k
                  v = -v;
578
9.15k
               }
579
32.7k
               return c;
580
32.7k
            }
581
582
            if constexpr (sizeof(T) > 4) {
583
               if (is_digit(*c)) {
584
                  v = v * 10 + (*c - '0');
585
                  ++c;
586
               }
587
               else {
588
                  if (sign) {
589
                     v = -v;
590
                  }
591
                  return c;
592
               }
593
594
               if (is_digit(*c)) {
595
                  v = v * 10 + (*c - '0');
596
                  ++c;
597
               }
598
               else {
599
                  if (sign) {
600
                     v = -v;
601
                  }
602
                  return c;
603
               }
604
605
               if (is_digit(*c)) {
606
                  v = v * 10 + (*c - '0');
607
                  ++c;
608
               }
609
               else {
610
                  if (sign) {
611
                     v = -v;
612
                  }
613
                  return c;
614
               }
615
616
               if (is_digit(*c)) {
617
                  v = v * 10 + (*c - '0');
618
                  ++c;
619
               }
620
               else {
621
                  if (sign) {
622
                     v = -v;
623
                  }
624
                  return c;
625
               }
626
627
               if (is_digit(*c)) {
628
                  v = v * 10 + (*c - '0');
629
                  ++c;
630
               }
631
               else {
632
                  if (sign) {
633
                     v = -v;
634
                  }
635
                  return c;
636
               }
637
638
               if (is_digit(*c)) {
639
                  v = v * 10 + (*c - '0');
640
                  ++c;
641
               }
642
               else {
643
                  if (sign) {
644
                     v = -v;
645
                  }
646
                  return c;
647
               }
648
649
               if (is_digit(*c)) {
650
                  v = v * 10 + (*c - '0');
651
                  ++c;
652
               }
653
               else {
654
                  if (sign) {
655
                     v = -v;
656
                  }
657
                  return c;
658
               }
659
660
               if (is_digit(*c)) {
661
                  v = v * 10 + (*c - '0');
662
                  ++c;
663
               }
664
               else {
665
                  if (sign) {
666
                     v = -v;
667
                  }
668
                  return c;
669
               }
670
671
               if (is_digit(*c)) {
672
                  v = v * 10 + (*c - '0');
673
                  ++c;
674
               }
675
               else {
676
                  if (sign) {
677
                     v = -v;
678
                  }
679
                  return c;
680
               }
681
            }
682
86.2k
         }
683
537k
      }
684
685
1.31M
      if (is_digit(*c)) {
686
25.8k
         if (sign) {
687
10.9k
            if (would_overflow_negative<T>(v, *c)) [[unlikely]] {
688
375
               return {};
689
375
            }
690
10.6k
            v = -1 * v;
691
10.6k
            v = v * 10 - (*c - '0');
692
10.6k
         }
693
14.8k
         else {
694
14.8k
            if (would_overflow_positive<T>(v, *c)) [[unlikely]] {
695
3.07k
               return {};
696
3.07k
            }
697
11.7k
            v = v * 10 + (*c - '0');
698
11.7k
         }
699
22.4k
         ++c;
700
22.4k
         if (is_digit(*c)) [[unlikely]] {
701
1.75k
            return {};
702
1.75k
         }
703
20.6k
         return c;
704
22.4k
      }
705
706
1.29M
      if (sign) {
707
9.39k
         v = -v;
708
9.39k
      }
709
1.29M
      return c;
710
1.31M
   }
_ZN3glz9parse_intITkNSt3__18integralEsQaasr3stdE11is_signed_vIT_ElestS2_Li8EEEPKhRS2_S4_
Line
Count
Source
476
264
   {
477
264
      const uint8_t sign = *c == '-';
478
264
      c += sign;
479
480
264
      if (is_digit(*c)) [[likely]] {
481
264
         v = *c - '0';
482
264
         ++c;
483
264
      }
484
0
      else [[unlikely]] {
485
0
         return {};
486
0
      }
487
488
264
      if (is_digit(*c)) {
489
238
         v = v * 10 + (*c - '0');
490
238
         ++c;
491
238
      }
492
26
      else {
493
26
         if (sign) {
494
6
            v = -v;
495
6
         }
496
26
         return c;
497
26
      }
498
499
238
      if (c[-2] == '0') [[unlikely]] {
500
0
         return {};
501
0
      }
502
503
238
      if constexpr (sizeof(T) > 1) {
504
238
         if (is_digit(*c)) {
505
206
            v = v * 10 + (*c - '0');
506
206
            ++c;
507
206
         }
508
32
         else {
509
32
            if (sign) {
510
12
               v = -v;
511
12
            }
512
32
            return c;
513
32
         }
514
515
206
         if (is_digit(*c)) {
516
164
            v = v * 10 + (*c - '0');
517
164
            ++c;
518
164
         }
519
42
         else {
520
42
            if (sign) {
521
10
               v = -v;
522
10
            }
523
42
            return c;
524
42
         }
525
526
         if constexpr (sizeof(T) > 2) {
527
            if (is_digit(*c)) {
528
               v = v * 10 + (*c - '0');
529
               ++c;
530
            }
531
            else {
532
               if (sign) {
533
                  v = -v;
534
               }
535
               return c;
536
            }
537
538
            if (is_digit(*c)) {
539
               v = v * 10 + (*c - '0');
540
               ++c;
541
            }
542
            else {
543
               if (sign) {
544
                  v = -v;
545
               }
546
               return c;
547
            }
548
549
            if (is_digit(*c)) {
550
               v = v * 10 + (*c - '0');
551
               ++c;
552
            }
553
            else {
554
               if (sign) {
555
                  v = -v;
556
               }
557
               return c;
558
            }
559
560
            if (is_digit(*c)) {
561
               v = v * 10 + (*c - '0');
562
               ++c;
563
            }
564
            else {
565
               if (sign) {
566
                  v = -v;
567
               }
568
               return c;
569
            }
570
571
            if (is_digit(*c)) {
572
               v = v * 10 + (*c - '0');
573
               ++c;
574
            }
575
            else {
576
               if (sign) {
577
                  v = -v;
578
               }
579
               return c;
580
            }
581
582
            if constexpr (sizeof(T) > 4) {
583
               if (is_digit(*c)) {
584
                  v = v * 10 + (*c - '0');
585
                  ++c;
586
               }
587
               else {
588
                  if (sign) {
589
                     v = -v;
590
                  }
591
                  return c;
592
               }
593
594
               if (is_digit(*c)) {
595
                  v = v * 10 + (*c - '0');
596
                  ++c;
597
               }
598
               else {
599
                  if (sign) {
600
                     v = -v;
601
                  }
602
                  return c;
603
               }
604
605
               if (is_digit(*c)) {
606
                  v = v * 10 + (*c - '0');
607
                  ++c;
608
               }
609
               else {
610
                  if (sign) {
611
                     v = -v;
612
                  }
613
                  return c;
614
               }
615
616
               if (is_digit(*c)) {
617
                  v = v * 10 + (*c - '0');
618
                  ++c;
619
               }
620
               else {
621
                  if (sign) {
622
                     v = -v;
623
                  }
624
                  return c;
625
               }
626
627
               if (is_digit(*c)) {
628
                  v = v * 10 + (*c - '0');
629
                  ++c;
630
               }
631
               else {
632
                  if (sign) {
633
                     v = -v;
634
                  }
635
                  return c;
636
               }
637
638
               if (is_digit(*c)) {
639
                  v = v * 10 + (*c - '0');
640
                  ++c;
641
               }
642
               else {
643
                  if (sign) {
644
                     v = -v;
645
                  }
646
                  return c;
647
               }
648
649
               if (is_digit(*c)) {
650
                  v = v * 10 + (*c - '0');
651
                  ++c;
652
               }
653
               else {
654
                  if (sign) {
655
                     v = -v;
656
                  }
657
                  return c;
658
               }
659
660
               if (is_digit(*c)) {
661
                  v = v * 10 + (*c - '0');
662
                  ++c;
663
               }
664
               else {
665
                  if (sign) {
666
                     v = -v;
667
                  }
668
                  return c;
669
               }
670
671
               if (is_digit(*c)) {
672
                  v = v * 10 + (*c - '0');
673
                  ++c;
674
               }
675
               else {
676
                  if (sign) {
677
                     v = -v;
678
                  }
679
                  return c;
680
               }
681
            }
682
         }
683
164
      }
684
685
238
      if (is_digit(*c)) {
686
114
         if (sign) {
687
64
            if (would_overflow_negative<T>(v, *c)) [[unlikely]] {
688
0
               return {};
689
0
            }
690
64
            v = -1 * v;
691
64
            v = v * 10 - (*c - '0');
692
64
         }
693
50
         else {
694
50
            if (would_overflow_positive<T>(v, *c)) [[unlikely]] {
695
0
               return {};
696
0
            }
697
50
            v = v * 10 + (*c - '0');
698
50
         }
699
114
         ++c;
700
114
         if (is_digit(*c)) [[unlikely]] {
701
0
            return {};
702
0
         }
703
114
         return c;
704
114
      }
705
706
124
      if (sign) {
707
10
         v = -v;
708
10
      }
709
124
      return c;
710
238
   }
_ZN3glz9parse_intITkNSt3__18integralExQaasr3stdE11is_signed_vIT_ElestS2_Li8EEEPKhRS2_S4_
Line
Count
Source
476
1.57k
   {
477
1.57k
      const uint8_t sign = *c == '-';
478
1.57k
      c += sign;
479
480
1.57k
      if (is_digit(*c)) [[likely]] {
481
1.57k
         v = *c - '0';
482
1.57k
         ++c;
483
1.57k
      }
484
0
      else [[unlikely]] {
485
0
         return {};
486
0
      }
487
488
1.57k
      if (is_digit(*c)) {
489
1.56k
         v = v * 10 + (*c - '0');
490
1.56k
         ++c;
491
1.56k
      }
492
12
      else {
493
12
         if (sign) {
494
2
            v = -v;
495
2
         }
496
12
         return c;
497
12
      }
498
499
1.56k
      if (c[-2] == '0') [[unlikely]] {
500
0
         return {};
501
0
      }
502
503
1.56k
      if constexpr (sizeof(T) > 1) {
504
1.56k
         if (is_digit(*c)) {
505
1.54k
            v = v * 10 + (*c - '0');
506
1.54k
            ++c;
507
1.54k
         }
508
18
         else {
509
18
            if (sign) {
510
4
               v = -v;
511
4
            }
512
18
            return c;
513
18
         }
514
515
1.54k
         if (is_digit(*c)) {
516
1.52k
            v = v * 10 + (*c - '0');
517
1.52k
            ++c;
518
1.52k
         }
519
20
         else {
520
20
            if (sign) {
521
6
               v = -v;
522
6
            }
523
20
            return c;
524
20
         }
525
526
1.52k
         if constexpr (sizeof(T) > 2) {
527
1.52k
            if (is_digit(*c)) {
528
1.47k
               v = v * 10 + (*c - '0');
529
1.47k
               ++c;
530
1.47k
            }
531
48
            else {
532
48
               if (sign) {
533
4
                  v = -v;
534
4
               }
535
48
               return c;
536
48
            }
537
538
1.47k
            if (is_digit(*c)) {
539
1.42k
               v = v * 10 + (*c - '0');
540
1.42k
               ++c;
541
1.42k
            }
542
52
            else {
543
52
               if (sign) {
544
12
                  v = -v;
545
12
               }
546
52
               return c;
547
52
            }
548
549
1.42k
            if (is_digit(*c)) {
550
1.37k
               v = v * 10 + (*c - '0');
551
1.37k
               ++c;
552
1.37k
            }
553
52
            else {
554
52
               if (sign) {
555
10
                  v = -v;
556
10
               }
557
52
               return c;
558
52
            }
559
560
1.37k
            if (is_digit(*c)) {
561
1.31k
               v = v * 10 + (*c - '0');
562
1.31k
               ++c;
563
1.31k
            }
564
62
            else {
565
62
               if (sign) {
566
12
                  v = -v;
567
12
               }
568
62
               return c;
569
62
            }
570
571
1.31k
            if (is_digit(*c)) {
572
1.21k
               v = v * 10 + (*c - '0');
573
1.21k
               ++c;
574
1.21k
            }
575
94
            else {
576
94
               if (sign) {
577
10
                  v = -v;
578
10
               }
579
94
               return c;
580
94
            }
581
582
1.21k
            if constexpr (sizeof(T) > 4) {
583
1.21k
               if (is_digit(*c)) {
584
1.20k
                  v = v * 10 + (*c - '0');
585
1.20k
                  ++c;
586
1.20k
               }
587
14
               else {
588
14
                  if (sign) {
589
8
                     v = -v;
590
8
                  }
591
14
                  return c;
592
14
               }
593
594
1.20k
               if (is_digit(*c)) {
595
1.12k
                  v = v * 10 + (*c - '0');
596
1.12k
                  ++c;
597
1.12k
               }
598
84
               else {
599
84
                  if (sign) {
600
16
                     v = -v;
601
16
                  }
602
84
                  return c;
603
84
               }
604
605
1.12k
               if (is_digit(*c)) {
606
1.09k
                  v = v * 10 + (*c - '0');
607
1.09k
                  ++c;
608
1.09k
               }
609
26
               else {
610
26
                  if (sign) {
611
8
                     v = -v;
612
8
                  }
613
26
                  return c;
614
26
               }
615
616
1.09k
               if (is_digit(*c)) {
617
972
                  v = v * 10 + (*c - '0');
618
972
                  ++c;
619
972
               }
620
122
               else {
621
122
                  if (sign) {
622
20
                     v = -v;
623
20
                  }
624
122
                  return c;
625
122
               }
626
627
972
               if (is_digit(*c)) {
628
926
                  v = v * 10 + (*c - '0');
629
926
                  ++c;
630
926
               }
631
46
               else {
632
46
                  if (sign) {
633
18
                     v = -v;
634
18
                  }
635
46
                  return c;
636
46
               }
637
638
926
               if (is_digit(*c)) {
639
800
                  v = v * 10 + (*c - '0');
640
800
                  ++c;
641
800
               }
642
126
               else {
643
126
                  if (sign) {
644
18
                     v = -v;
645
18
                  }
646
126
                  return c;
647
126
               }
648
649
800
               if (is_digit(*c)) {
650
732
                  v = v * 10 + (*c - '0');
651
732
                  ++c;
652
732
               }
653
68
               else {
654
68
                  if (sign) {
655
6
                     v = -v;
656
6
                  }
657
68
                  return c;
658
68
               }
659
660
732
               if (is_digit(*c)) {
661
568
                  v = v * 10 + (*c - '0');
662
568
                  ++c;
663
568
               }
664
164
               else {
665
164
                  if (sign) {
666
14
                     v = -v;
667
14
                  }
668
164
                  return c;
669
164
               }
670
671
568
               if (is_digit(*c)) {
672
514
                  v = v * 10 + (*c - '0');
673
514
                  ++c;
674
514
               }
675
54
               else {
676
54
                  if (sign) {
677
22
                     v = -v;
678
22
                  }
679
54
                  return c;
680
54
               }
681
568
            }
682
1.21k
         }
683
1.52k
      }
684
685
1.56k
      if (is_digit(*c)) {
686
348
         if (sign) {
687
166
            if (would_overflow_negative<T>(v, *c)) [[unlikely]] {
688
0
               return {};
689
0
            }
690
166
            v = -1 * v;
691
166
            v = v * 10 - (*c - '0');
692
166
         }
693
182
         else {
694
182
            if (would_overflow_positive<T>(v, *c)) [[unlikely]] {
695
0
               return {};
696
0
            }
697
182
            v = v * 10 + (*c - '0');
698
182
         }
699
348
         ++c;
700
348
         if (is_digit(*c)) [[unlikely]] {
701
0
            return {};
702
0
         }
703
348
         return c;
704
348
      }
705
706
1.21k
      if (sign) {
707
26
         v = -v;
708
26
      }
709
1.21k
      return c;
710
1.56k
   }
711
712
   template <std::integral T, class Char>
713
      requires(std::is_signed_v<T>)
714
   GLZ_ALWAYS_INLINE constexpr bool atoi(T& v, Char*& c) noexcept
715
1.96M
   {
716
1.96M
      using X = std::decay_t<T>;
717
1.96M
      using utype = std::make_unsigned_t<X>;
718
719
1.96M
      const uint8_t sign = *c == '-';
720
1.96M
      if (auto ptr = parse_int(v, reinterpret_cast<const uint8_t*>(c))) [[likely]] {
721
1.90M
         c = reinterpret_cast<const Char*>(ptr);
722
1.90M
         if (*c == 'e' || *c == 'E') {
723
129k
            ++c;
724
129k
         }
725
1.77M
         else {
726
1.77M
            if (*c == '.') [[unlikely]] {
727
1.61k
               return false;
728
1.61k
            }
729
1.77M
            return true;
730
1.77M
         }
731
732
129k
         c += (*c == '+');
733
734
129k
         if (not is_digit(*c)) [[unlikely]] {
735
1.92k
            return false;
736
1.92k
         }
737
127k
         const uint32_t exp = parse_exponent(c);
738
         // As in the unsigned overload: only a non-zero magnitude can overflow, so "0e19" and
739
         // "-0e19" are in range for every width. `v` is already the signed mantissa, and negative
740
         // zero compares equal to zero, so both spellings land here with the value they should keep.
741
         if constexpr (sizeof(T) == 1) {
742
            if (exp > 2) [[unlikely]] {
743
               return v == 0;
744
            }
745
         }
746
0
         else if constexpr (sizeof(T) == 2) {
747
0
            if (exp > 4) [[unlikely]] {
748
0
               return v == 0;
749
0
            }
750
         }
751
127k
         else if constexpr (sizeof(T) == 4) {
752
127k
            if (exp > 9) [[unlikely]] {
753
10.0k
               return v == 0;
754
10.0k
            }
755
         }
756
0
         else {
757
0
            if (exp > 18) [[unlikely]] {
758
0
               return v == 0;
759
0
            }
760
0
         }
761
762
117k
         utype i = utype((utype(v) ^ -sign) + sign);
763
127k
         if constexpr (sizeof(T) < 8) {
764
            // Scale in a width the product cannot wrap, then range check before narrowing. Scaling
765
            // inside `utype` truncated first and checked afterwards, so an out-of-range magnitude
766
            // aliased onto an accepted one: "13e2" read as 20 for int8_t and "5e9" as 705032704 for
767
            // int32_t. The widest case here is a 4-byte magnitude scaled by 10^9, which stays well
768
            // inside uint64_t. The unsigned path already widens the same way.
769
127k
            const uint64_t scaled = uint64_t(i) * powers_of_ten_int[exp];
770
127k
            v = T((utype(scaled) ^ -sign) + sign);
771
            // Bound the magnitude directly rather than subtracting the sign from it: a negative
772
            // zero makes `scaled - sign` underflow, and the old narrow expression only survived
773
            // that because it promoted to int. A negative value may reach one past the positive
774
            // limit, which is exactly INT_MIN's magnitude.
775
127k
            return scaled <= uint64_t((std::numeric_limits<T>::max)()) + sign;
776
         }
777
0
         else {
778
            // Scale the sign-stripped magnitude `i`, not the two's-complement bit pattern of `v`:
779
            // for a negative value that pattern is a huge unsigned number, so every negative
780
            // 64-bit integer written with an exponent ("-1e2") overflowed and was rejected. The
781
            // narrower branches above already scale `i`.
782
0
#if defined(__SIZEOF_INT128__)
783
0
            const __uint128_t res = __uint128_t(i) * powers_of_ten_int[exp];
784
0
            v = T((uint64_t(res) ^ -sign) + sign);
785
            // Compare the full 128-bit product. Narrowing it to 64 bits first would let an
786
            // out-of-range magnitude alias onto an accepted one, e.g. 9e36 truncating into range.
787
0
            return res <= __uint128_t(9223372036854775807ull + sign);
788
#else
789
            const auto res = full_multiplication(i, powers_of_ten_int[exp]);
790
            v = T((uint64_t(res.low) ^ -sign) + sign);
791
            return res.high == 0 && (uint64_t(res.low) <= (9223372036854775807ull + sign));
792
#endif
793
0
         }
794
127k
      }
795
188k
      return false;
796
1.96M
   }
Unexecuted instantiation: _ZN3glz4atoiITkNSt3__18integralElKcQsr3stdE11is_signed_vIT_EEEbRS3_RPT0_
_ZN3glz4atoiITkNSt3__18integralEiKcQsr3stdE11is_signed_vIT_EEEbRS3_RPT0_
Line
Count
Source
715
1.96M
   {
716
1.96M
      using X = std::decay_t<T>;
717
1.96M
      using utype = std::make_unsigned_t<X>;
718
719
1.96M
      const uint8_t sign = *c == '-';
720
1.96M
      if (auto ptr = parse_int(v, reinterpret_cast<const uint8_t*>(c))) [[likely]] {
721
1.90M
         c = reinterpret_cast<const Char*>(ptr);
722
1.90M
         if (*c == 'e' || *c == 'E') {
723
129k
            ++c;
724
129k
         }
725
1.77M
         else {
726
1.77M
            if (*c == '.') [[unlikely]] {
727
1.61k
               return false;
728
1.61k
            }
729
1.77M
            return true;
730
1.77M
         }
731
732
129k
         c += (*c == '+');
733
734
129k
         if (not is_digit(*c)) [[unlikely]] {
735
1.92k
            return false;
736
1.92k
         }
737
127k
         const uint32_t exp = parse_exponent(c);
738
         // As in the unsigned overload: only a non-zero magnitude can overflow, so "0e19" and
739
         // "-0e19" are in range for every width. `v` is already the signed mantissa, and negative
740
         // zero compares equal to zero, so both spellings land here with the value they should keep.
741
         if constexpr (sizeof(T) == 1) {
742
            if (exp > 2) [[unlikely]] {
743
               return v == 0;
744
            }
745
         }
746
         else if constexpr (sizeof(T) == 2) {
747
            if (exp > 4) [[unlikely]] {
748
               return v == 0;
749
            }
750
         }
751
127k
         else if constexpr (sizeof(T) == 4) {
752
127k
            if (exp > 9) [[unlikely]] {
753
10.0k
               return v == 0;
754
10.0k
            }
755
         }
756
         else {
757
            if (exp > 18) [[unlikely]] {
758
               return v == 0;
759
            }
760
         }
761
762
117k
         utype i = utype((utype(v) ^ -sign) + sign);
763
127k
         if constexpr (sizeof(T) < 8) {
764
            // Scale in a width the product cannot wrap, then range check before narrowing. Scaling
765
            // inside `utype` truncated first and checked afterwards, so an out-of-range magnitude
766
            // aliased onto an accepted one: "13e2" read as 20 for int8_t and "5e9" as 705032704 for
767
            // int32_t. The widest case here is a 4-byte magnitude scaled by 10^9, which stays well
768
            // inside uint64_t. The unsigned path already widens the same way.
769
127k
            const uint64_t scaled = uint64_t(i) * powers_of_ten_int[exp];
770
127k
            v = T((utype(scaled) ^ -sign) + sign);
771
            // Bound the magnitude directly rather than subtracting the sign from it: a negative
772
            // zero makes `scaled - sign` underflow, and the old narrow expression only survived
773
            // that because it promoted to int. A negative value may reach one past the positive
774
            // limit, which is exactly INT_MIN's magnitude.
775
127k
            return scaled <= uint64_t((std::numeric_limits<T>::max)()) + sign;
776
         }
777
         else {
778
            // Scale the sign-stripped magnitude `i`, not the two's-complement bit pattern of `v`:
779
            // for a negative value that pattern is a huge unsigned number, so every negative
780
            // 64-bit integer written with an exponent ("-1e2") overflowed and was rejected. The
781
            // narrower branches above already scale `i`.
782
#if defined(__SIZEOF_INT128__)
783
            const __uint128_t res = __uint128_t(i) * powers_of_ten_int[exp];
784
            v = T((uint64_t(res) ^ -sign) + sign);
785
            // Compare the full 128-bit product. Narrowing it to 64 bits first would let an
786
            // out-of-range magnitude alias onto an accepted one, e.g. 9e36 truncating into range.
787
            return res <= __uint128_t(9223372036854775807ull + sign);
788
#else
789
            const auto res = full_multiplication(i, powers_of_ten_int[exp]);
790
            v = T((uint64_t(res.low) ^ -sign) + sign);
791
            return res.high == 0 && (uint64_t(res.low) <= (9223372036854775807ull + sign));
792
#endif
793
         }
794
127k
      }
795
188k
      return false;
796
1.96M
   }
_ZN3glz4atoiITkNSt3__18integralEsKcQsr3stdE11is_signed_vIT_EEEbRS3_RPT0_
Line
Count
Source
715
264
   {
716
264
      using X = std::decay_t<T>;
717
264
      using utype = std::make_unsigned_t<X>;
718
719
264
      const uint8_t sign = *c == '-';
720
264
      if (auto ptr = parse_int(v, reinterpret_cast<const uint8_t*>(c))) [[likely]] {
721
264
         c = reinterpret_cast<const Char*>(ptr);
722
264
         if (*c == 'e' || *c == 'E') {
723
0
            ++c;
724
0
         }
725
264
         else {
726
264
            if (*c == '.') [[unlikely]] {
727
0
               return false;
728
0
            }
729
264
            return true;
730
264
         }
731
732
0
         c += (*c == '+');
733
734
0
         if (not is_digit(*c)) [[unlikely]] {
735
0
            return false;
736
0
         }
737
0
         const uint32_t exp = parse_exponent(c);
738
         // As in the unsigned overload: only a non-zero magnitude can overflow, so "0e19" and
739
         // "-0e19" are in range for every width. `v` is already the signed mantissa, and negative
740
         // zero compares equal to zero, so both spellings land here with the value they should keep.
741
         if constexpr (sizeof(T) == 1) {
742
            if (exp > 2) [[unlikely]] {
743
               return v == 0;
744
            }
745
         }
746
0
         else if constexpr (sizeof(T) == 2) {
747
0
            if (exp > 4) [[unlikely]] {
748
0
               return v == 0;
749
0
            }
750
         }
751
         else if constexpr (sizeof(T) == 4) {
752
            if (exp > 9) [[unlikely]] {
753
               return v == 0;
754
            }
755
         }
756
         else {
757
            if (exp > 18) [[unlikely]] {
758
               return v == 0;
759
            }
760
         }
761
762
0
         utype i = utype((utype(v) ^ -sign) + sign);
763
0
         if constexpr (sizeof(T) < 8) {
764
            // Scale in a width the product cannot wrap, then range check before narrowing. Scaling
765
            // inside `utype` truncated first and checked afterwards, so an out-of-range magnitude
766
            // aliased onto an accepted one: "13e2" read as 20 for int8_t and "5e9" as 705032704 for
767
            // int32_t. The widest case here is a 4-byte magnitude scaled by 10^9, which stays well
768
            // inside uint64_t. The unsigned path already widens the same way.
769
0
            const uint64_t scaled = uint64_t(i) * powers_of_ten_int[exp];
770
0
            v = T((utype(scaled) ^ -sign) + sign);
771
            // Bound the magnitude directly rather than subtracting the sign from it: a negative
772
            // zero makes `scaled - sign` underflow, and the old narrow expression only survived
773
            // that because it promoted to int. A negative value may reach one past the positive
774
            // limit, which is exactly INT_MIN's magnitude.
775
0
            return scaled <= uint64_t((std::numeric_limits<T>::max)()) + sign;
776
         }
777
         else {
778
            // Scale the sign-stripped magnitude `i`, not the two's-complement bit pattern of `v`:
779
            // for a negative value that pattern is a huge unsigned number, so every negative
780
            // 64-bit integer written with an exponent ("-1e2") overflowed and was rejected. The
781
            // narrower branches above already scale `i`.
782
#if defined(__SIZEOF_INT128__)
783
            const __uint128_t res = __uint128_t(i) * powers_of_ten_int[exp];
784
            v = T((uint64_t(res) ^ -sign) + sign);
785
            // Compare the full 128-bit product. Narrowing it to 64 bits first would let an
786
            // out-of-range magnitude alias onto an accepted one, e.g. 9e36 truncating into range.
787
            return res <= __uint128_t(9223372036854775807ull + sign);
788
#else
789
            const auto res = full_multiplication(i, powers_of_ten_int[exp]);
790
            v = T((uint64_t(res.low) ^ -sign) + sign);
791
            return res.high == 0 && (uint64_t(res.low) <= (9223372036854775807ull + sign));
792
#endif
793
         }
794
0
      }
795
0
      return false;
796
264
   }
_ZN3glz4atoiITkNSt3__18integralExKcQsr3stdE11is_signed_vIT_EEEbRS3_RPT0_
Line
Count
Source
715
1.57k
   {
716
1.57k
      using X = std::decay_t<T>;
717
1.57k
      using utype = std::make_unsigned_t<X>;
718
719
1.57k
      const uint8_t sign = *c == '-';
720
1.57k
      if (auto ptr = parse_int(v, reinterpret_cast<const uint8_t*>(c))) [[likely]] {
721
1.57k
         c = reinterpret_cast<const Char*>(ptr);
722
1.57k
         if (*c == 'e' || *c == 'E') {
723
0
            ++c;
724
0
         }
725
1.57k
         else {
726
1.57k
            if (*c == '.') [[unlikely]] {
727
0
               return false;
728
0
            }
729
1.57k
            return true;
730
1.57k
         }
731
732
0
         c += (*c == '+');
733
734
0
         if (not is_digit(*c)) [[unlikely]] {
735
0
            return false;
736
0
         }
737
0
         const uint32_t exp = parse_exponent(c);
738
         // As in the unsigned overload: only a non-zero magnitude can overflow, so "0e19" and
739
         // "-0e19" are in range for every width. `v` is already the signed mantissa, and negative
740
         // zero compares equal to zero, so both spellings land here with the value they should keep.
741
         if constexpr (sizeof(T) == 1) {
742
            if (exp > 2) [[unlikely]] {
743
               return v == 0;
744
            }
745
         }
746
         else if constexpr (sizeof(T) == 2) {
747
            if (exp > 4) [[unlikely]] {
748
               return v == 0;
749
            }
750
         }
751
         else if constexpr (sizeof(T) == 4) {
752
            if (exp > 9) [[unlikely]] {
753
               return v == 0;
754
            }
755
         }
756
0
         else {
757
0
            if (exp > 18) [[unlikely]] {
758
0
               return v == 0;
759
0
            }
760
0
         }
761
762
0
         utype i = utype((utype(v) ^ -sign) + sign);
763
         if constexpr (sizeof(T) < 8) {
764
            // Scale in a width the product cannot wrap, then range check before narrowing. Scaling
765
            // inside `utype` truncated first and checked afterwards, so an out-of-range magnitude
766
            // aliased onto an accepted one: "13e2" read as 20 for int8_t and "5e9" as 705032704 for
767
            // int32_t. The widest case here is a 4-byte magnitude scaled by 10^9, which stays well
768
            // inside uint64_t. The unsigned path already widens the same way.
769
            const uint64_t scaled = uint64_t(i) * powers_of_ten_int[exp];
770
            v = T((utype(scaled) ^ -sign) + sign);
771
            // Bound the magnitude directly rather than subtracting the sign from it: a negative
772
            // zero makes `scaled - sign` underflow, and the old narrow expression only survived
773
            // that because it promoted to int. A negative value may reach one past the positive
774
            // limit, which is exactly INT_MIN's magnitude.
775
            return scaled <= uint64_t((std::numeric_limits<T>::max)()) + sign;
776
         }
777
0
         else {
778
            // Scale the sign-stripped magnitude `i`, not the two's-complement bit pattern of `v`:
779
            // for a negative value that pattern is a huge unsigned number, so every negative
780
            // 64-bit integer written with an exponent ("-1e2") overflowed and was rejected. The
781
            // narrower branches above already scale `i`.
782
0
#if defined(__SIZEOF_INT128__)
783
0
            const __uint128_t res = __uint128_t(i) * powers_of_ten_int[exp];
784
0
            v = T((uint64_t(res) ^ -sign) + sign);
785
            // Compare the full 128-bit product. Narrowing it to 64 bits first would let an
786
            // out-of-range magnitude alias onto an accepted one, e.g. 9e36 truncating into range.
787
0
            return res <= __uint128_t(9223372036854775807ull + sign);
788
#else
789
            const auto res = full_multiplication(i, powers_of_ten_int[exp]);
790
            v = T((uint64_t(res.low) ^ -sign) + sign);
791
            return res.high == 0 && (uint64_t(res.low) <= (9223372036854775807ull + sign));
792
#endif
793
0
         }
794
0
      }
795
0
      return false;
796
1.57k
   }
797
798
   // Increase by 8 to support exponentials
799
   inline constexpr std::array<size_t, 4> int_buffer_lengths{16, 16, 24, 32};
800
801
   template <std::integral T, class Char>
802
   GLZ_ALWAYS_INLINE constexpr bool atoi(T& v, const Char*& it, const Char* end) noexcept
803
2.06M
   {
804
      // The number of characters needed at most for each type, rounded to nearest 8 bytes
805
2.06M
      constexpr auto buffer_length = int_buffer_lengths[std::bit_width(sizeof(T)) - 1];
806
      // We copy the rest of the buffer, or buffer_length bytes, into a null terminated buffer. The
807
      // trailing byte is never written by the copy, so the null-terminated atoi below always halts
808
      // inside the array even when the input fills it: the exponent scan stops at a non-digit rather
809
      // than after a fixed digit count, and a value-initialized array alone would not terminate a
810
      // copy that covers every byte.
811
2.06M
      std::array<char, buffer_length + 1> data{};
812
2.06M
      const auto n = size_t(end - it);
813
2.06M
      if (n > 0) [[likely]] {
814
2.06M
         const auto truncated = n > buffer_length;
815
2.06M
         std::memcpy(data.data(), it, truncated ? buffer_length : n);
816
817
2.06M
         const auto start = data.data();
818
2.06M
         const auto* c = start;
819
2.06M
         const auto valid = glz::atoi(v, c);
820
2.06M
         const auto consumed = size_t(c - start);
821
2.06M
         it += consumed;
822
         // Reaching the end of a truncated copy means the number was cut off: parsing halted on the
823
         // terminator this buffer supplies rather than on a character of the input, so what parsed is
824
         // a prefix and its value is not the number's. Only zero padding can stretch a number this
825
         // far -- no in-range integer needs buffer_length characters -- but a caller that ignores
826
         // trailing content would otherwise take the prefix's value as the answer.
827
2.06M
         return valid && not(truncated && consumed == buffer_length);
828
2.06M
      }
829
0
      else [[unlikely]] {
830
0
         return false;
831
0
      }
832
2.06M
   }
_ZN3glz4atoiITkNSt3__18integralEicEEbRT_RPKT0_S6_
Line
Count
Source
803
1.94M
   {
804
      // The number of characters needed at most for each type, rounded to nearest 8 bytes
805
1.94M
      constexpr auto buffer_length = int_buffer_lengths[std::bit_width(sizeof(T)) - 1];
806
      // We copy the rest of the buffer, or buffer_length bytes, into a null terminated buffer. The
807
      // trailing byte is never written by the copy, so the null-terminated atoi below always halts
808
      // inside the array even when the input fills it: the exponent scan stops at a non-digit rather
809
      // than after a fixed digit count, and a value-initialized array alone would not terminate a
810
      // copy that covers every byte.
811
1.94M
      std::array<char, buffer_length + 1> data{};
812
1.94M
      const auto n = size_t(end - it);
813
1.94M
      if (n > 0) [[likely]] {
814
1.94M
         const auto truncated = n > buffer_length;
815
1.94M
         std::memcpy(data.data(), it, truncated ? buffer_length : n);
816
817
1.94M
         const auto start = data.data();
818
1.94M
         const auto* c = start;
819
1.94M
         const auto valid = glz::atoi(v, c);
820
1.94M
         const auto consumed = size_t(c - start);
821
1.94M
         it += consumed;
822
         // Reaching the end of a truncated copy means the number was cut off: parsing halted on the
823
         // terminator this buffer supplies rather than on a character of the input, so what parsed is
824
         // a prefix and its value is not the number's. Only zero padding can stretch a number this
825
         // far -- no in-range integer needs buffer_length characters -- but a caller that ignores
826
         // trailing content would otherwise take the prefix's value as the answer.
827
1.94M
         return valid && not(truncated && consumed == buffer_length);
828
1.94M
      }
829
0
      else [[unlikely]] {
830
0
         return false;
831
0
      }
832
1.94M
   }
_ZN3glz4atoiITkNSt3__18integralEmcEEbRT_RPKT0_S6_
Line
Count
Source
803
41.0k
   {
804
      // The number of characters needed at most for each type, rounded to nearest 8 bytes
805
41.0k
      constexpr auto buffer_length = int_buffer_lengths[std::bit_width(sizeof(T)) - 1];
806
      // We copy the rest of the buffer, or buffer_length bytes, into a null terminated buffer. The
807
      // trailing byte is never written by the copy, so the null-terminated atoi below always halts
808
      // inside the array even when the input fills it: the exponent scan stops at a non-digit rather
809
      // than after a fixed digit count, and a value-initialized array alone would not terminate a
810
      // copy that covers every byte.
811
41.0k
      std::array<char, buffer_length + 1> data{};
812
41.0k
      const auto n = size_t(end - it);
813
41.0k
      if (n > 0) [[likely]] {
814
41.0k
         const auto truncated = n > buffer_length;
815
41.0k
         std::memcpy(data.data(), it, truncated ? buffer_length : n);
816
817
41.0k
         const auto start = data.data();
818
41.0k
         const auto* c = start;
819
41.0k
         const auto valid = glz::atoi(v, c);
820
41.0k
         const auto consumed = size_t(c - start);
821
41.0k
         it += consumed;
822
         // Reaching the end of a truncated copy means the number was cut off: parsing halted on the
823
         // terminator this buffer supplies rather than on a character of the input, so what parsed is
824
         // a prefix and its value is not the number's. Only zero padding can stretch a number this
825
         // far -- no in-range integer needs buffer_length characters -- but a caller that ignores
826
         // trailing content would otherwise take the prefix's value as the answer.
827
41.0k
         return valid && not(truncated && consumed == buffer_length);
828
41.0k
      }
829
0
      else [[unlikely]] {
830
0
         return false;
831
0
      }
832
41.0k
   }
_ZN3glz4atoiITkNSt3__18integralElcEEbRT_RPKT0_S6_
Line
Count
Source
803
72.3k
   {
804
      // The number of characters needed at most for each type, rounded to nearest 8 bytes
805
72.3k
      constexpr auto buffer_length = int_buffer_lengths[std::bit_width(sizeof(T)) - 1];
806
      // We copy the rest of the buffer, or buffer_length bytes, into a null terminated buffer. The
807
      // trailing byte is never written by the copy, so the null-terminated atoi below always halts
808
      // inside the array even when the input fills it: the exponent scan stops at a non-digit rather
809
      // than after a fixed digit count, and a value-initialized array alone would not terminate a
810
      // copy that covers every byte.
811
72.3k
      std::array<char, buffer_length + 1> data{};
812
72.3k
      const auto n = size_t(end - it);
813
72.3k
      if (n > 0) [[likely]] {
814
72.3k
         const auto truncated = n > buffer_length;
815
72.3k
         std::memcpy(data.data(), it, truncated ? buffer_length : n);
816
817
72.3k
         const auto start = data.data();
818
72.3k
         const auto* c = start;
819
72.3k
         const auto valid = glz::atoi(v, c);
820
72.3k
         const auto consumed = size_t(c - start);
821
72.3k
         it += consumed;
822
         // Reaching the end of a truncated copy means the number was cut off: parsing halted on the
823
         // terminator this buffer supplies rather than on a character of the input, so what parsed is
824
         // a prefix and its value is not the number's. Only zero padding can stretch a number this
825
         // far -- no in-range integer needs buffer_length characters -- but a caller that ignores
826
         // trailing content would otherwise take the prefix's value as the answer.
827
72.3k
         return valid && not(truncated && consumed == buffer_length);
828
72.3k
      }
829
0
      else [[unlikely]] {
830
0
         return false;
831
0
      }
832
72.3k
   }
_ZN3glz4atoiITkNSt3__18integralEtcEEbRT_RPKT0_S6_
Line
Count
Source
803
5.22k
   {
804
      // The number of characters needed at most for each type, rounded to nearest 8 bytes
805
5.22k
      constexpr auto buffer_length = int_buffer_lengths[std::bit_width(sizeof(T)) - 1];
806
      // We copy the rest of the buffer, or buffer_length bytes, into a null terminated buffer. The
807
      // trailing byte is never written by the copy, so the null-terminated atoi below always halts
808
      // inside the array even when the input fills it: the exponent scan stops at a non-digit rather
809
      // than after a fixed digit count, and a value-initialized array alone would not terminate a
810
      // copy that covers every byte.
811
5.22k
      std::array<char, buffer_length + 1> data{};
812
5.22k
      const auto n = size_t(end - it);
813
5.22k
      if (n > 0) [[likely]] {
814
5.22k
         const auto truncated = n > buffer_length;
815
5.22k
         std::memcpy(data.data(), it, truncated ? buffer_length : n);
816
817
5.22k
         const auto start = data.data();
818
5.22k
         const auto* c = start;
819
5.22k
         const auto valid = glz::atoi(v, c);
820
5.22k
         const auto consumed = size_t(c - start);
821
5.22k
         it += consumed;
822
         // Reaching the end of a truncated copy means the number was cut off: parsing halted on the
823
         // terminator this buffer supplies rather than on a character of the input, so what parsed is
824
         // a prefix and its value is not the number's. Only zero padding can stretch a number this
825
         // far -- no in-range integer needs buffer_length characters -- but a caller that ignores
826
         // trailing content would otherwise take the prefix's value as the answer.
827
5.22k
         return valid && not(truncated && consumed == buffer_length);
828
5.22k
      }
829
0
      else [[unlikely]] {
830
0
         return false;
831
0
      }
832
5.22k
   }
833
}
834
835
namespace glz::detail
836
{
837
   GLZ_ALWAYS_INLINE constexpr bool is_safe_addition(uint64_t a, uint64_t b) noexcept
838
0
   {
839
0
      return a <= (std::numeric_limits<uint64_t>::max)() - b;
840
0
   }
841
842
   GLZ_ALWAYS_INLINE constexpr bool is_safe_multiplication10(uint64_t a) noexcept
843
0
   {
844
0
      constexpr auto b = (std::numeric_limits<uint64_t>::max)() / 10;
845
0
      return a <= b;
846
0
   }
847
848
   template <class T = uint64_t>
849
   GLZ_ALWAYS_INLINE constexpr bool stoui64(uint64_t& res, const char*& c) noexcept
850
0
   {
851
0
      if (!digit_table[uint8_t(*c)]) [[unlikely]] {
852
0
         return false;
853
0
      }
854
0
855
0
      // maximum number of digits need is: 3, 5, 10, 20, for byte sizes of 1, 2, 4, 8
856
0
      // we need to store one extra space for a digit for sizes of 1, 2, and 4 because we avoid checking for overflow
857
0
      // since we store in a uint64_t
858
0
      constexpr std::array<int64_t, 4> max_digits_from_size = {4, 6, 11, 20};
859
0
      constexpr auto N = max_digits_from_size[std::bit_width(sizeof(T)) - 1];
860
0
861
0
      std::array<uint8_t, N> digits{0};
862
0
      auto next_digit = digits.begin();
863
0
      auto consume_digit = [&c, &next_digit, &digits]() {
864
0
         if (next_digit < digits.cend()) [[likely]] {
865
0
            *next_digit = (*c - '0');
866
0
            ++next_digit;
867
0
         }
868
0
         ++c;
869
0
      };
870
0
871
0
      if (*c == '0') {
872
0
         // digits[i] = 0; already set to zero
873
0
         ++c;
874
0
         ++next_digit;
875
0
876
0
         if (*c == '0') [[unlikely]] {
877
0
            return false;
878
0
         }
879
0
      }
880
0
881
0
      while (digit_table[uint8_t(*c)]) {
882
0
         consume_digit();
883
0
      }
884
0
      auto n = int64_t(std::distance(digits.begin(), next_digit));
885
0
886
0
      if (*c == '.') {
887
0
         ++c;
888
0
         while (digit_table[uint8_t(*c)]) {
889
0
            consume_digit();
890
0
         }
891
0
      }
892
0
893
0
      if (*c == 'e' || *c == 'E') {
894
0
         ++c;
895
0
896
0
         bool negative = false;
897
0
         if (*c == '+' || *c == '-') {
898
0
            negative = (*c == '-');
899
0
            ++c;
900
0
         }
901
0
         // Clamp instead of wrapping: a uint8_t accumulator turns "1e256" into exponent 0, which
902
0
         // aliases an out-of-range magnitude onto an accepted one ("1e256" decoding as 1). The old
903
0
         // `exp < 128` guard could not catch that, since the wrap happened before the test, and it
904
0
         // also left `c` parked mid-number once it did trip.
905
0
         int32_t exp = 0;
906
0
         while (digit_table[uint8_t(*c)]) {
907
0
            if (exp < int32_t(exponent_clamp)) {
908
0
               exp = 10 * exp + (*c - '0');
909
0
            }
910
0
            ++c;
911
0
         }
912
0
         n += negative ? -exp : exp;
913
0
      }
914
0
915
0
      res = 0;
916
0
      if (n < 0) [[unlikely]] {
917
0
         return true;
918
0
      }
919
0
920
0
      if constexpr (std::same_as<T, uint64_t>) {
921
0
         if (n > 20) [[unlikely]] {
922
0
            return false;
923
0
         }
924
0
925
0
         if (n == 20) [[unlikely]] {
926
0
            for (size_t k = 0; k < 19; ++k) {
927
0
               res = 10 * res + digits[k];
928
0
            }
929
0
930
0
            if (is_safe_multiplication10(res)) [[likely]] {
931
0
               res *= 10;
932
0
            }
933
0
            else [[unlikely]] {
934
0
               return false;
935
0
            }
936
0
            if (is_safe_addition(res, digits.back())) [[likely]] {
937
0
               res += digits.back();
938
0
            }
939
0
            else [[unlikely]] {
940
0
               return false;
941
0
            }
942
0
         }
943
0
         else [[likely]] {
944
0
            for (int64_t k = 0; k < n; ++k) {
945
0
               res = 10 * res + digits[k];
946
0
            }
947
0
         }
948
0
      }
949
0
      else {
950
0
         // a value of n == N would result in reading digits[N], which is invalid
951
0
         if (n >= N) [[unlikely]] {
952
0
            return false;
953
0
         }
954
0
         else [[likely]] {
955
0
            for (int64_t k = 0; k < n; ++k) {
956
0
               res = 10 * res + digits[k];
957
0
            }
958
0
         }
959
0
      }
960
0
961
0
      return true;
962
0
   }
963
964
   template <class T = uint64_t>
965
   GLZ_ALWAYS_INLINE constexpr bool stoui64(uint64_t& res, auto& it) noexcept
966
   {
967
      static_assert(sizeof(*it) == sizeof(char));
968
      const char* cur = reinterpret_cast<const char*>(it);
969
      const char* beg = cur;
970
      if (stoui64(res, cur)) {
971
         it += (cur - beg);
972
         return true;
973
      }
974
      return false;
975
   }
976
}
977
978
#if defined(_MSC_VER) && !defined(__clang__)
979
// restore disabled warnings
980
#pragma warning(pop)
981
#endif