Coverage Report

Created: 2026-11-12 06:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/abseil-cpp/absl/strings/internal/charconv_parse.cc
Line
Count
Source
1
// Copyright 2018 The Abseil Authors.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//      https://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
#include "absl/strings/internal/charconv_parse.h"
16
#include "absl/strings/charconv.h"
17
18
#include <cassert>
19
#include <cstdint>
20
#include <limits>
21
22
#include "absl/strings/internal/memutil.h"
23
24
namespace absl {
25
ABSL_NAMESPACE_BEGIN
26
namespace {
27
28
// ParseFloat<10> will read the first 19 significant digits of the mantissa.
29
// This number was chosen for multiple reasons.
30
//
31
// (a) First, for whatever integer type we choose to represent the mantissa, we
32
// want to choose the largest possible number of decimal digits for that integer
33
// type.  We are using uint64_t, which can express any 19-digit unsigned
34
// integer.
35
//
36
// (b) Second, we need to parse enough digits that the binary value of any
37
// mantissa we capture has more bits of resolution than the mantissa
38
// representation in the target float.  Our algorithm requires at least 3 bits
39
// of headway, but 19 decimal digits give a little more than that.
40
//
41
// The following static assertions verify the above comments:
42
constexpr int kDecimalMantissaDigitsMax = 19;
43
44
static_assert(std::numeric_limits<uint64_t>::digits10 ==
45
                  kDecimalMantissaDigitsMax,
46
              "(a) above");
47
48
// IEEE doubles, which we assume in Abseil, have 53 binary bits of mantissa.
49
static_assert(std::numeric_limits<double>::is_iec559, "IEEE double assumed");
50
static_assert(std::numeric_limits<double>::radix == 2, "IEEE double fact");
51
static_assert(std::numeric_limits<double>::digits == 53, "IEEE double fact");
52
53
// The lowest valued 19-digit decimal mantissa we can read still contains
54
// sufficient information to reconstruct a binary mantissa.
55
static_assert(1000000000000000000u > (uint64_t{1} << (53 + 3)), "(b) above");
56
57
// ParseFloat<16> will read the first 15 significant digits of the mantissa.
58
//
59
// Because a base-16-to-base-2 conversion can be done exactly, we do not need
60
// to maximize the number of scanned hex digits to improve our conversion.  What
61
// is required is to scan two more bits than the mantissa can represent, so that
62
// we always round correctly.
63
//
64
// (One extra bit does not suffice to perform correct rounding, since a number
65
// exactly halfway between two representable floats has unique rounding rules,
66
// so we need to differentiate between a "halfway between" number and a "closer
67
// to the larger value" number.)
68
constexpr int kHexadecimalMantissaDigitsMax = 15;
69
70
// The minimum number of significant bits that will be read from
71
// kHexadecimalMantissaDigitsMax hex digits.  We must subtract by three, since
72
// the most significant digit can be a "1", which only contributes a single
73
// significant bit.
74
constexpr int kGuaranteedHexadecimalMantissaBitPrecision =
75
    4 * kHexadecimalMantissaDigitsMax - 3;
76
77
static_assert(kGuaranteedHexadecimalMantissaBitPrecision >
78
                  std::numeric_limits<double>::digits + 2,
79
              "kHexadecimalMantissaDigitsMax too small");
80
81
// We also impose a limit on the number of significant digits we will read from
82
// an exponent, to avoid having to deal with integer overflow.  We use 9 for
83
// this purpose.
84
//
85
// If we read a 9 digit exponent, the end result of the conversion will
86
// necessarily be infinity or zero, depending on the sign of the exponent.
87
// Therefore we can just drop extra digits on the floor without any extra
88
// logic.
89
constexpr int kDecimalExponentDigitsMax = 9;
90
static_assert(std::numeric_limits<int>::digits10 >= kDecimalExponentDigitsMax,
91
              "int type too small");
92
93
// To avoid incredibly large inputs causing integer overflow for our exponent,
94
// we impose an arbitrary but very large limit on the number of significant
95
// digits we will accept.  The implementation refuses to match a string with
96
// more consecutive significant mantissa digits than this.
97
constexpr int kDecimalDigitLimit = 50000000;
98
99
// Corresponding limit for hexadecimal digit inputs.  This is one fourth the
100
// amount of kDecimalDigitLimit, since each dropped hexadecimal digit requires
101
// a binary exponent adjustment of 4.
102
constexpr int kHexadecimalDigitLimit = kDecimalDigitLimit / 4;
103
104
// The largest exponent we can read is 999999999 (per
105
// kDecimalExponentDigitsMax), and the largest exponent adjustment we can get
106
// from dropped mantissa digits is 2 * kDecimalDigitLimit, and the sum of these
107
// comfortably fits in an integer.
108
//
109
// We count kDecimalDigitLimit twice because there are independent limits for
110
// numbers before and after the decimal point.  (In the case where there are no
111
// significant digits before the decimal point, there are independent limits for
112
// post-decimal-point leading zeroes and for significant digits.)
113
static_assert(999999999 + 2 * kDecimalDigitLimit <
114
                  std::numeric_limits<int>::max(),
115
              "int type too small");
116
static_assert(999999999 + 2 * (4 * kHexadecimalDigitLimit) <
117
                  std::numeric_limits<int>::max(),
118
              "int type too small");
119
120
// Returns true if the provided bitfield allows parsing an exponent value
121
// (e.g., "1.5e100").
122
14.0M
bool AllowExponent(chars_format flags) {
123
14.0M
  bool fixed = (flags & chars_format::fixed) == chars_format::fixed;
124
14.0M
  bool scientific =
125
14.0M
      (flags & chars_format::scientific) == chars_format::scientific;
126
14.0M
  return scientific || !fixed;
127
14.0M
}
128
129
// Returns true if the provided bitfield requires an exponent value be present.
130
14.0M
bool RequireExponent(chars_format flags) {
131
14.0M
  bool fixed = (flags & chars_format::fixed) == chars_format::fixed;
132
14.0M
  bool scientific =
133
14.0M
      (flags & chars_format::scientific) == chars_format::scientific;
134
14.0M
  return scientific && !fixed;
135
14.0M
}
136
137
const int8_t kAsciiToInt[256] = {
138
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
139
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
140
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0,  1,  2,  3,  4,  5,  6,  7,  8,
141
    9,  -1, -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1,
142
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
143
    -1, -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
144
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
145
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
146
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
147
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
148
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
149
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
150
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
151
    -1, -1, -1, -1, -1, -1, -1, -1, -1};
152
153
// Returns true if `ch` is a digit in the given base
154
template <int base>
155
bool IsDigit(char ch);
156
157
// Converts a valid `ch` to its digit value in the given base.
158
template <int base>
159
unsigned ToDigit(char ch);
160
161
// Returns true if `ch` is the exponent delimiter for the given base.
162
template <int base>
163
bool IsExponentCharacter(char ch);
164
165
// Returns the maximum number of significant digits we will read for a float
166
// in the given base.
167
template <int base>
168
constexpr int MantissaDigitsMax();
169
170
// Returns the largest consecutive run of digits we will accept when parsing a
171
// number in the given base.
172
template <int base>
173
constexpr int DigitLimit();
174
175
// Returns the amount the exponent must be adjusted by for each dropped digit.
176
// (For decimal this is 1, since the digits are in base 10 and the exponent base
177
// is also 10, but for hexadecimal this is 4, since the digits are base 16 but
178
// the exponent base is 2.)
179
template <int base>
180
constexpr int DigitMagnitude();
181
182
template <>
183
31.6M
bool IsDigit<10>(char ch) {
184
31.6M
  return ch >= '0' && ch <= '9';
185
31.6M
}
186
template <>
187
8.60M
bool IsDigit<16>(char ch) {
188
8.60M
  return kAsciiToInt[static_cast<unsigned char>(ch)] >= 0;
189
8.60M
}
190
191
template <>
192
13.4M
unsigned ToDigit<10>(char ch) {
193
13.4M
  return static_cast<unsigned>(ch - '0');
194
13.4M
}
195
template <>
196
22.7k
unsigned ToDigit<16>(char ch) {
197
22.7k
  return static_cast<unsigned>(kAsciiToInt[static_cast<unsigned char>(ch)]);
198
22.7k
}
199
200
template <>
201
10.0k
bool IsExponentCharacter<10>(char ch) {
202
10.0k
  return ch == 'e' || ch == 'E';
203
10.0k
}
204
205
template <>
206
2.67k
bool IsExponentCharacter<16>(char ch) {
207
2.67k
  return ch == 'p' || ch == 'P';
208
2.67k
}
209
210
template <>
211
42.2M
constexpr int MantissaDigitsMax<10>() {
212
42.2M
  return kDecimalMantissaDigitsMax;
213
42.2M
}
214
template <>
215
15.6k
constexpr int MantissaDigitsMax<16>() {
216
15.6k
  return kHexadecimalMantissaDigitsMax;
217
15.6k
}
218
219
template <>
220
14.1M
constexpr int DigitLimit<10>() {
221
14.1M
  return kDecimalDigitLimit;
222
14.1M
}
223
template <>
224
7.89k
constexpr int DigitLimit<16>() {
225
7.89k
  return kHexadecimalDigitLimit;
226
7.89k
}
227
228
template <>
229
12.7M
constexpr int DigitMagnitude<10>() {
230
12.7M
  return 1;
231
12.7M
}
232
template <>
233
4.00k
constexpr int DigitMagnitude<16>() {
234
4.00k
  return 4;
235
4.00k
}
236
237
// Reads decimal digits from [begin, end) into *out.  Returns the number of
238
// digits consumed.
239
//
240
// After max_digits has been read, keeps consuming characters, but no longer
241
// adjusts *out.  If a nonzero digit is dropped this way, *dropped_nonzero_digit
242
// is set; otherwise, it is left unmodified.
243
//
244
// If no digits are matched, returns 0 and leaves *out unchanged.
245
//
246
// ConsumeDigits does not protect against overflow on *out; max_digits must
247
// be chosen with respect to type T to avoid the possibility of overflow.
248
template <int base, typename T>
249
int ConsumeDigits(const char* begin, const char* end, int max_digits, T* out,
250
14.1M
                  bool* dropped_nonzero_digit) {
251
14.1M
  if (base == 10) {
252
14.1M
    assert(max_digits <= std::numeric_limits<T>::digits10);
253
14.1M
  } else if (base == 16) {
254
7.01k
    assert(max_digits * 4 <= std::numeric_limits<T>::digits);
255
7.01k
  }
256
14.1M
  const char* const original_begin = begin;
257
258
  // Skip leading zeros, but only if *out is zero.
259
  // They don't cause an overflow so we don't have to count them for
260
  // `max_digits`.
261
14.2M
  while (!*out && end != begin && *begin == '0') ++begin;
262
263
14.1M
  T accumulator = *out;
264
14.1M
  const char* significant_digits_end =
265
14.1M
      (end - begin > max_digits) ? begin + max_digits : end;
266
27.6M
  while (begin < significant_digits_end && IsDigit<base>(*begin)) {
267
    // Do not guard against *out overflow; max_digits was chosen to avoid this.
268
    // Do assert against it, to detect problems in debug builds.
269
13.4M
    auto digit = static_cast<T>(ToDigit<base>(*begin));
270
13.4M
    assert(accumulator * base >= accumulator);
271
13.4M
    accumulator *= base;
272
13.4M
    assert(accumulator + digit >= accumulator);
273
13.4M
    accumulator += digit;
274
13.4M
    ++begin;
275
13.4M
  }
276
14.1M
  bool dropped_nonzero = false;
277
40.8M
  while (begin < end && IsDigit<base>(*begin)) {
278
26.6M
    dropped_nonzero = dropped_nonzero || (*begin != '0');
279
26.6M
    ++begin;
280
26.6M
  }
281
14.1M
  if (dropped_nonzero && dropped_nonzero_digit != nullptr) {
282
24.2k
    *dropped_nonzero_digit = true;
283
24.2k
  }
284
14.1M
  *out = accumulator;
285
14.1M
  return static_cast<int>(begin - original_begin);
286
14.1M
}
charconv_parse.cc:int absl::lts_20260526::(anonymous namespace)::ConsumeDigits<10, unsigned long>(char const*, char const*, int, unsigned long*, bool*)
Line
Count
Source
250
14.1M
                  bool* dropped_nonzero_digit) {
251
14.1M
  if (base == 10) {
252
14.1M
    assert(max_digits <= std::numeric_limits<T>::digits10);
253
14.1M
  } else if (base == 16) {
254
0
    assert(max_digits * 4 <= std::numeric_limits<T>::digits);
255
0
  }
256
14.1M
  const char* const original_begin = begin;
257
258
  // Skip leading zeros, but only if *out is zero.
259
  // They don't cause an overflow so we don't have to count them for
260
  // `max_digits`.
261
14.1M
  while (!*out && end != begin && *begin == '0') ++begin;
262
263
14.1M
  T accumulator = *out;
264
14.1M
  const char* significant_digits_end =
265
14.1M
      (end - begin > max_digits) ? begin + max_digits : end;
266
27.5M
  while (begin < significant_digits_end && IsDigit<base>(*begin)) {
267
    // Do not guard against *out overflow; max_digits was chosen to avoid this.
268
    // Do assert against it, to detect problems in debug builds.
269
13.4M
    auto digit = static_cast<T>(ToDigit<base>(*begin));
270
13.4M
    assert(accumulator * base >= accumulator);
271
13.4M
    accumulator *= base;
272
13.4M
    assert(accumulator + digit >= accumulator);
273
13.4M
    accumulator += digit;
274
13.4M
    ++begin;
275
13.4M
  }
276
14.1M
  bool dropped_nonzero = false;
277
28.1M
  while (begin < end && IsDigit<base>(*begin)) {
278
14.0M
    dropped_nonzero = dropped_nonzero || (*begin != '0');
279
14.0M
    ++begin;
280
14.0M
  }
281
14.1M
  if (dropped_nonzero && dropped_nonzero_digit != nullptr) {
282
23.2k
    *dropped_nonzero_digit = true;
283
23.2k
  }
284
14.1M
  *out = accumulator;
285
14.1M
  return static_cast<int>(begin - original_begin);
286
14.1M
}
charconv_parse.cc:int absl::lts_20260526::(anonymous namespace)::ConsumeDigits<10, int>(char const*, char const*, int, int*, bool*)
Line
Count
Source
250
12.4k
                  bool* dropped_nonzero_digit) {
251
12.4k
  if (base == 10) {
252
12.4k
    assert(max_digits <= std::numeric_limits<T>::digits10);
253
12.4k
  } else if (base == 16) {
254
0
    assert(max_digits * 4 <= std::numeric_limits<T>::digits);
255
0
  }
256
12.4k
  const char* const original_begin = begin;
257
258
  // Skip leading zeros, but only if *out is zero.
259
  // They don't cause an overflow so we don't have to count them for
260
  // `max_digits`.
261
166k
  while (!*out && end != begin && *begin == '0') ++begin;
262
263
12.4k
  T accumulator = *out;
264
12.4k
  const char* significant_digits_end =
265
12.4k
      (end - begin > max_digits) ? begin + max_digits : end;
266
50.0k
  while (begin < significant_digits_end && IsDigit<base>(*begin)) {
267
    // Do not guard against *out overflow; max_digits was chosen to avoid this.
268
    // Do assert against it, to detect problems in debug builds.
269
37.6k
    auto digit = static_cast<T>(ToDigit<base>(*begin));
270
37.6k
    assert(accumulator * base >= accumulator);
271
37.6k
    accumulator *= base;
272
37.6k
    assert(accumulator + digit >= accumulator);
273
37.6k
    accumulator += digit;
274
37.6k
    ++begin;
275
37.6k
  }
276
12.4k
  bool dropped_nonzero = false;
277
4.10M
  while (begin < end && IsDigit<base>(*begin)) {
278
4.09M
    dropped_nonzero = dropped_nonzero || (*begin != '0');
279
4.09M
    ++begin;
280
4.09M
  }
281
12.4k
  if (dropped_nonzero && dropped_nonzero_digit != nullptr) {
282
0
    *dropped_nonzero_digit = true;
283
0
  }
284
12.4k
  *out = accumulator;
285
12.4k
  return static_cast<int>(begin - original_begin);
286
12.4k
}
charconv_parse.cc:int absl::lts_20260526::(anonymous namespace)::ConsumeDigits<16, unsigned long>(char const*, char const*, int, unsigned long*, bool*)
Line
Count
Source
250
7.01k
                  bool* dropped_nonzero_digit) {
251
7.01k
  if (base == 10) {
252
0
    assert(max_digits <= std::numeric_limits<T>::digits10);
253
7.01k
  } else if (base == 16) {
254
7.01k
    assert(max_digits * 4 <= std::numeric_limits<T>::digits);
255
7.01k
  }
256
7.01k
  const char* const original_begin = begin;
257
258
  // Skip leading zeros, but only if *out is zero.
259
  // They don't cause an overflow so we don't have to count them for
260
  // `max_digits`.
261
7.01k
  while (!*out && end != begin && *begin == '0') ++begin;
262
263
7.01k
  T accumulator = *out;
264
7.01k
  const char* significant_digits_end =
265
7.01k
      (end - begin > max_digits) ? begin + max_digits : end;
266
29.7k
  while (begin < significant_digits_end && IsDigit<base>(*begin)) {
267
    // Do not guard against *out overflow; max_digits was chosen to avoid this.
268
    // Do assert against it, to detect problems in debug builds.
269
22.7k
    auto digit = static_cast<T>(ToDigit<base>(*begin));
270
22.7k
    assert(accumulator * base >= accumulator);
271
22.7k
    accumulator *= base;
272
22.7k
    assert(accumulator + digit >= accumulator);
273
22.7k
    accumulator += digit;
274
22.7k
    ++begin;
275
22.7k
  }
276
7.01k
  bool dropped_nonzero = false;
277
8.57M
  while (begin < end && IsDigit<base>(*begin)) {
278
8.56M
    dropped_nonzero = dropped_nonzero || (*begin != '0');
279
8.56M
    ++begin;
280
8.56M
  }
281
7.01k
  if (dropped_nonzero && dropped_nonzero_digit != nullptr) {
282
1.02k
    *dropped_nonzero_digit = true;
283
1.02k
  }
284
7.01k
  *out = accumulator;
285
7.01k
  return static_cast<int>(begin - original_begin);
286
7.01k
}
287
288
// Returns true if `v` is one of the chars allowed inside parentheses following
289
// a NaN.
290
4.00M
bool IsNanChar(char v) {
291
4.00M
  return (v == '_') || (v >= '0' && v <= '9') || (v >= 'a' && v <= 'z') ||
292
917
         (v >= 'A' && v <= 'Z');
293
4.00M
}
294
295
// Checks the range [begin, end) for a strtod()-formatted infinity or NaN.  If
296
// one is found, sets `out` appropriately and returns true.
297
bool ParseInfinityOrNan(const char* begin, const char* end,
298
14.0M
                        strings_internal::ParsedFloat* out) {
299
14.0M
  if (end - begin < 3) {
300
14.0M
    return false;
301
14.0M
  }
302
38.4k
  switch (*begin) {
303
41
    case 'i':
304
64
    case 'I': {
305
      // An infinity string consists of the characters "inf" or "infinity",
306
      // case insensitive.
307
64
      if (strings_internal::memcasecmp(begin + 1, "nf", 2) != 0) {
308
21
        return false;
309
21
      }
310
43
      out->type = strings_internal::FloatType::kInfinity;
311
43
      if (end - begin >= 8 &&
312
36
          strings_internal::memcasecmp(begin + 3, "inity", 5) == 0) {
313
7
        out->end = begin + 8;
314
36
      } else {
315
36
        out->end = begin + 3;
316
36
      }
317
43
      return true;
318
64
    }
319
128
    case 'n':
320
165
    case 'N': {
321
      // A NaN consists of the characters "nan", case insensitive, optionally
322
      // followed by a parenthesized sequence of zero or more alphanumeric
323
      // characters and/or underscores.
324
165
      if (strings_internal::memcasecmp(begin + 1, "an", 2) != 0) {
325
29
        return false;
326
29
      }
327
136
      out->type = strings_internal::FloatType::kNan;
328
136
      out->end = begin + 3;
329
      // NaN is allowed to be followed by a parenthesized string, consisting of
330
      // only the characters [a-zA-Z0-9_].  Match that if it's present.
331
136
      begin += 3;
332
136
      if (begin < end && *begin == '(') {
333
115
        const char* nan_begin = begin + 1;
334
4.00M
        while (nan_begin < end && IsNanChar(*nan_begin)) {
335
4.00M
          ++nan_begin;
336
4.00M
        }
337
115
        if (nan_begin < end && *nan_begin == ')') {
338
          // We found an extra NaN specifier range
339
33
          out->subrange_begin = begin + 1;
340
33
          out->subrange_end = nan_begin;
341
33
          out->end = nan_begin + 1;
342
33
        }
343
115
      }
344
136
      return true;
345
165
    }
346
38.1k
    default:
347
38.1k
      return false;
348
38.4k
  }
349
38.4k
}
350
}  // namespace
351
352
namespace strings_internal {
353
354
template <int base>
355
strings_internal::ParsedFloat ParseFloat(const char* begin, const char* end,
356
14.0M
                                         chars_format format_flags) {
357
14.0M
  strings_internal::ParsedFloat result;
358
359
  // Exit early if we're given an empty range.
360
14.0M
  if (begin == end) return result;
361
362
  // Handle the infinity and NaN cases.
363
14.0M
  if (ParseInfinityOrNan(begin, end, &result)) {
364
179
    return result;
365
179
  }
366
367
14.0M
  const char* const mantissa_begin = begin;
368
15.6M
  while (begin < end && *begin == '0') {
369
1.61M
    ++begin;  // skip leading zeros
370
1.61M
  }
371
14.0M
  uint64_t mantissa = 0;
372
373
14.0M
  int exponent_adjustment = 0;
374
14.0M
  bool mantissa_is_inexact = false;
375
14.0M
  int pre_decimal_digits = ConsumeDigits<base>(
376
14.0M
      begin, end, MantissaDigitsMax<base>(), &mantissa, &mantissa_is_inexact);
377
14.0M
  begin += pre_decimal_digits;
378
14.0M
  int digits_left;
379
14.0M
  if (pre_decimal_digits >= DigitLimit<base>()) {
380
    // refuse to parse pathological inputs
381
0
    return result;
382
14.0M
  } else if (pre_decimal_digits > MantissaDigitsMax<base>()) {
383
    // We dropped some non-fraction digits on the floor.  Adjust our exponent
384
    // to compensate.
385
2.34k
    exponent_adjustment =
386
2.34k
        static_cast<int>(pre_decimal_digits - MantissaDigitsMax<base>());
387
2.34k
    digits_left = 0;
388
14.0M
  } else {
389
14.0M
    digits_left =
390
14.0M
        static_cast<int>(MantissaDigitsMax<base>() - pre_decimal_digits);
391
14.0M
  }
392
14.0M
  if (begin < end && *begin == '.') {
393
33.5k
    ++begin;
394
33.5k
    if (mantissa == 0) {
395
      // If we haven't seen any nonzero digits yet, keep skipping zeros.  We
396
      // have to adjust the exponent to reflect the changed place value.
397
26.7k
      const char* begin_zeros = begin;
398
4.41M
      while (begin < end && *begin == '0') {
399
4.38M
        ++begin;
400
4.38M
      }
401
26.7k
      int zeros_skipped = static_cast<int>(begin - begin_zeros);
402
26.7k
      if (zeros_skipped >= DigitLimit<base>()) {
403
        // refuse to parse pathological inputs
404
0
        return result;
405
0
      }
406
26.7k
      exponent_adjustment -= static_cast<int>(zeros_skipped);
407
26.7k
    }
408
33.5k
    int post_decimal_digits = ConsumeDigits<base>(
409
33.5k
        begin, end, digits_left, &mantissa, &mantissa_is_inexact);
410
33.5k
    begin += post_decimal_digits;
411
412
    // Since `mantissa` is an integer, each significant digit we read after
413
    // the decimal point requires an adjustment to the exponent. "1.23e0" will
414
    // be stored as `mantissa` == 123 and `exponent` == -2 (that is,
415
    // "123e-2").
416
33.5k
    if (post_decimal_digits >= DigitLimit<base>()) {
417
      // refuse to parse pathological inputs
418
0
      return result;
419
33.5k
    } else if (post_decimal_digits > digits_left) {
420
22.0k
      exponent_adjustment -= digits_left;
421
22.0k
    } else {
422
11.4k
      exponent_adjustment -= post_decimal_digits;
423
11.4k
    }
424
33.5k
  }
425
  // If we've found no mantissa whatsoever, this isn't a number.
426
14.0M
  if (mantissa_begin == begin) {
427
157
    return result;
428
157
  }
429
  // A bare "." doesn't count as a mantissa either.
430
14.0M
  if (begin - mantissa_begin == 1 && *mantissa_begin == '.') {
431
33
    return result;
432
33
  }
433
434
14.0M
  if (mantissa_is_inexact) {
435
    // We dropped significant digits on the floor.  Handle this appropriately.
436
23.6k
    if (base == 10) {
437
      // If we truncated significant decimal digits, store the full range of the
438
      // mantissa for future big integer math for exact rounding.
439
22.7k
      result.subrange_begin = mantissa_begin;
440
22.7k
      result.subrange_end = begin;
441
22.7k
    } else if (base == 16) {
442
      // If we truncated hex digits, reflect this fact by setting the low
443
      // ("sticky") bit.  This allows for correct rounding in all cases.
444
928
      mantissa |= 1;
445
928
    }
446
23.6k
  }
447
14.0M
  result.mantissa = mantissa;
448
449
14.0M
  const char* const exponent_begin = begin;
450
14.0M
  result.literal_exponent = 0;
451
14.0M
  bool found_exponent = false;
452
14.0M
  if (AllowExponent(format_flags) && begin < end &&
453
12.7k
      IsExponentCharacter<base>(*begin)) {
454
12.4k
    bool negative_exponent = false;
455
12.4k
    ++begin;
456
12.4k
    if (begin < end && *begin == '-') {
457
8.23k
      negative_exponent = true;
458
8.23k
      ++begin;
459
8.23k
    } else if (begin < end && *begin == '+') {
460
419
      ++begin;
461
419
    }
462
12.4k
    const char* const exponent_digits_begin = begin;
463
    // Exponent is always expressed in decimal, even for hexadecimal floats.
464
12.4k
    begin += ConsumeDigits<10>(begin, end, kDecimalExponentDigitsMax,
465
12.4k
                               &result.literal_exponent, nullptr);
466
12.4k
    if (begin == exponent_digits_begin) {
467
      // there were no digits where we expected an exponent.  We failed to read
468
      // an exponent and should not consume the 'e' after all.  Rewind 'begin'.
469
64
      found_exponent = false;
470
64
      begin = exponent_begin;
471
12.3k
    } else {
472
12.3k
      found_exponent = true;
473
12.3k
      if (negative_exponent) {
474
8.22k
        result.literal_exponent = -result.literal_exponent;
475
8.22k
      }
476
12.3k
    }
477
12.4k
  }
478
479
14.0M
  if (!found_exponent && RequireExponent(format_flags)) {
480
    // Provided flags required an exponent, but none was found.  This results
481
    // in a failure to scan.
482
0
    return result;
483
0
  }
484
485
  // Success!
486
14.0M
  result.type = strings_internal::FloatType::kNumber;
487
14.0M
  if (result.mantissa > 0) {
488
12.7M
    result.exponent = result.literal_exponent +
489
12.7M
                      (DigitMagnitude<base>() * exponent_adjustment);
490
12.7M
  } else {
491
1.34M
    result.exponent = 0;
492
1.34M
  }
493
14.0M
  result.end = begin;
494
14.0M
  return result;
495
14.0M
}
absl::lts_20260526::strings_internal::ParsedFloat absl::lts_20260526::strings_internal::ParseFloat<10>(char const*, char const*, absl::lts_20260526::chars_format)
Line
Count
Source
356
14.0M
                                         chars_format format_flags) {
357
14.0M
  strings_internal::ParsedFloat result;
358
359
  // Exit early if we're given an empty range.
360
14.0M
  if (begin == end) return result;
361
362
  // Handle the infinity and NaN cases.
363
14.0M
  if (ParseInfinityOrNan(begin, end, &result)) {
364
178
    return result;
365
178
  }
366
367
14.0M
  const char* const mantissa_begin = begin;
368
15.6M
  while (begin < end && *begin == '0') {
369
1.60M
    ++begin;  // skip leading zeros
370
1.60M
  }
371
14.0M
  uint64_t mantissa = 0;
372
373
14.0M
  int exponent_adjustment = 0;
374
14.0M
  bool mantissa_is_inexact = false;
375
14.0M
  int pre_decimal_digits = ConsumeDigits<base>(
376
14.0M
      begin, end, MantissaDigitsMax<base>(), &mantissa, &mantissa_is_inexact);
377
14.0M
  begin += pre_decimal_digits;
378
14.0M
  int digits_left;
379
14.0M
  if (pre_decimal_digits >= DigitLimit<base>()) {
380
    // refuse to parse pathological inputs
381
0
    return result;
382
14.0M
  } else if (pre_decimal_digits > MantissaDigitsMax<base>()) {
383
    // We dropped some non-fraction digits on the floor.  Adjust our exponent
384
    // to compensate.
385
1.93k
    exponent_adjustment =
386
1.93k
        static_cast<int>(pre_decimal_digits - MantissaDigitsMax<base>());
387
1.93k
    digits_left = 0;
388
14.0M
  } else {
389
14.0M
    digits_left =
390
14.0M
        static_cast<int>(MantissaDigitsMax<base>() - pre_decimal_digits);
391
14.0M
  }
392
14.0M
  if (begin < end && *begin == '.') {
393
31.7k
    ++begin;
394
31.7k
    if (mantissa == 0) {
395
      // If we haven't seen any nonzero digits yet, keep skipping zeros.  We
396
      // have to adjust the exponent to reflect the changed place value.
397
25.8k
      const char* begin_zeros = begin;
398
4.30M
      while (begin < end && *begin == '0') {
399
4.28M
        ++begin;
400
4.28M
      }
401
25.8k
      int zeros_skipped = static_cast<int>(begin - begin_zeros);
402
25.8k
      if (zeros_skipped >= DigitLimit<base>()) {
403
        // refuse to parse pathological inputs
404
0
        return result;
405
0
      }
406
25.8k
      exponent_adjustment -= static_cast<int>(zeros_skipped);
407
25.8k
    }
408
31.7k
    int post_decimal_digits = ConsumeDigits<base>(
409
31.7k
        begin, end, digits_left, &mantissa, &mantissa_is_inexact);
410
31.7k
    begin += post_decimal_digits;
411
412
    // Since `mantissa` is an integer, each significant digit we read after
413
    // the decimal point requires an adjustment to the exponent. "1.23e0" will
414
    // be stored as `mantissa` == 123 and `exponent` == -2 (that is,
415
    // "123e-2").
416
31.7k
    if (post_decimal_digits >= DigitLimit<base>()) {
417
      // refuse to parse pathological inputs
418
0
      return result;
419
31.7k
    } else if (post_decimal_digits > digits_left) {
420
21.4k
      exponent_adjustment -= digits_left;
421
21.4k
    } else {
422
10.3k
      exponent_adjustment -= post_decimal_digits;
423
10.3k
    }
424
31.7k
  }
425
  // If we've found no mantissa whatsoever, this isn't a number.
426
14.0M
  if (mantissa_begin == begin) {
427
136
    return result;
428
136
  }
429
  // A bare "." doesn't count as a mantissa either.
430
14.0M
  if (begin - mantissa_begin == 1 && *mantissa_begin == '.') {
431
17
    return result;
432
17
  }
433
434
14.0M
  if (mantissa_is_inexact) {
435
    // We dropped significant digits on the floor.  Handle this appropriately.
436
22.7k
    if (base == 10) {
437
      // If we truncated significant decimal digits, store the full range of the
438
      // mantissa for future big integer math for exact rounding.
439
22.7k
      result.subrange_begin = mantissa_begin;
440
22.7k
      result.subrange_end = begin;
441
22.7k
    } else if (base == 16) {
442
      // If we truncated hex digits, reflect this fact by setting the low
443
      // ("sticky") bit.  This allows for correct rounding in all cases.
444
0
      mantissa |= 1;
445
0
    }
446
22.7k
  }
447
14.0M
  result.mantissa = mantissa;
448
449
14.0M
  const char* const exponent_begin = begin;
450
14.0M
  result.literal_exponent = 0;
451
14.0M
  bool found_exponent = false;
452
14.0M
  if (AllowExponent(format_flags) && begin < end &&
453
10.0k
      IsExponentCharacter<base>(*begin)) {
454
9.83k
    bool negative_exponent = false;
455
9.83k
    ++begin;
456
9.83k
    if (begin < end && *begin == '-') {
457
6.33k
      negative_exponent = true;
458
6.33k
      ++begin;
459
6.33k
    } else if (begin < end && *begin == '+') {
460
194
      ++begin;
461
194
    }
462
9.83k
    const char* const exponent_digits_begin = begin;
463
    // Exponent is always expressed in decimal, even for hexadecimal floats.
464
9.83k
    begin += ConsumeDigits<10>(begin, end, kDecimalExponentDigitsMax,
465
9.83k
                               &result.literal_exponent, nullptr);
466
9.83k
    if (begin == exponent_digits_begin) {
467
      // there were no digits where we expected an exponent.  We failed to read
468
      // an exponent and should not consume the 'e' after all.  Rewind 'begin'.
469
43
      found_exponent = false;
470
43
      begin = exponent_begin;
471
9.79k
    } else {
472
9.79k
      found_exponent = true;
473
9.79k
      if (negative_exponent) {
474
6.32k
        result.literal_exponent = -result.literal_exponent;
475
6.32k
      }
476
9.79k
    }
477
9.83k
  }
478
479
14.0M
  if (!found_exponent && RequireExponent(format_flags)) {
480
    // Provided flags required an exponent, but none was found.  This results
481
    // in a failure to scan.
482
0
    return result;
483
0
  }
484
485
  // Success!
486
14.0M
  result.type = strings_internal::FloatType::kNumber;
487
14.0M
  if (result.mantissa > 0) {
488
12.7M
    result.exponent = result.literal_exponent +
489
12.7M
                      (DigitMagnitude<base>() * exponent_adjustment);
490
12.7M
  } else {
491
1.33M
    result.exponent = 0;
492
1.33M
  }
493
14.0M
  result.end = begin;
494
14.0M
  return result;
495
14.0M
}
absl::lts_20260526::strings_internal::ParsedFloat absl::lts_20260526::strings_internal::ParseFloat<16>(char const*, char const*, absl::lts_20260526::chars_format)
Line
Count
Source
356
5.22k
                                         chars_format format_flags) {
357
5.22k
  strings_internal::ParsedFloat result;
358
359
  // Exit early if we're given an empty range.
360
5.22k
  if (begin == end) return result;
361
362
  // Handle the infinity and NaN cases.
363
5.21k
  if (ParseInfinityOrNan(begin, end, &result)) {
364
1
    return result;
365
1
  }
366
367
5.21k
  const char* const mantissa_begin = begin;
368
8.45k
  while (begin < end && *begin == '0') {
369
3.24k
    ++begin;  // skip leading zeros
370
3.24k
  }
371
5.21k
  uint64_t mantissa = 0;
372
373
5.21k
  int exponent_adjustment = 0;
374
5.21k
  bool mantissa_is_inexact = false;
375
5.21k
  int pre_decimal_digits = ConsumeDigits<base>(
376
5.21k
      begin, end, MantissaDigitsMax<base>(), &mantissa, &mantissa_is_inexact);
377
5.21k
  begin += pre_decimal_digits;
378
5.21k
  int digits_left;
379
5.21k
  if (pre_decimal_digits >= DigitLimit<base>()) {
380
    // refuse to parse pathological inputs
381
0
    return result;
382
5.21k
  } else if (pre_decimal_digits > MantissaDigitsMax<base>()) {
383
    // We dropped some non-fraction digits on the floor.  Adjust our exponent
384
    // to compensate.
385
403
    exponent_adjustment =
386
403
        static_cast<int>(pre_decimal_digits - MantissaDigitsMax<base>());
387
403
    digits_left = 0;
388
4.81k
  } else {
389
4.81k
    digits_left =
390
4.81k
        static_cast<int>(MantissaDigitsMax<base>() - pre_decimal_digits);
391
4.81k
  }
392
5.21k
  if (begin < end && *begin == '.') {
393
1.79k
    ++begin;
394
1.79k
    if (mantissa == 0) {
395
      // If we haven't seen any nonzero digits yet, keep skipping zeros.  We
396
      // have to adjust the exponent to reflect the changed place value.
397
879
      const char* begin_zeros = begin;
398
105k
      while (begin < end && *begin == '0') {
399
104k
        ++begin;
400
104k
      }
401
879
      int zeros_skipped = static_cast<int>(begin - begin_zeros);
402
879
      if (zeros_skipped >= DigitLimit<base>()) {
403
        // refuse to parse pathological inputs
404
0
        return result;
405
0
      }
406
879
      exponent_adjustment -= static_cast<int>(zeros_skipped);
407
879
    }
408
1.79k
    int post_decimal_digits = ConsumeDigits<base>(
409
1.79k
        begin, end, digits_left, &mantissa, &mantissa_is_inexact);
410
1.79k
    begin += post_decimal_digits;
411
412
    // Since `mantissa` is an integer, each significant digit we read after
413
    // the decimal point requires an adjustment to the exponent. "1.23e0" will
414
    // be stored as `mantissa` == 123 and `exponent` == -2 (that is,
415
    // "123e-2").
416
1.79k
    if (post_decimal_digits >= DigitLimit<base>()) {
417
      // refuse to parse pathological inputs
418
0
      return result;
419
1.79k
    } else if (post_decimal_digits > digits_left) {
420
662
      exponent_adjustment -= digits_left;
421
1.13k
    } else {
422
1.13k
      exponent_adjustment -= post_decimal_digits;
423
1.13k
    }
424
1.79k
  }
425
  // If we've found no mantissa whatsoever, this isn't a number.
426
5.21k
  if (mantissa_begin == begin) {
427
21
    return result;
428
21
  }
429
  // A bare "." doesn't count as a mantissa either.
430
5.19k
  if (begin - mantissa_begin == 1 && *mantissa_begin == '.') {
431
16
    return result;
432
16
  }
433
434
5.17k
  if (mantissa_is_inexact) {
435
    // We dropped significant digits on the floor.  Handle this appropriately.
436
928
    if (base == 10) {
437
      // If we truncated significant decimal digits, store the full range of the
438
      // mantissa for future big integer math for exact rounding.
439
0
      result.subrange_begin = mantissa_begin;
440
0
      result.subrange_end = begin;
441
928
    } else if (base == 16) {
442
      // If we truncated hex digits, reflect this fact by setting the low
443
      // ("sticky") bit.  This allows for correct rounding in all cases.
444
928
      mantissa |= 1;
445
928
    }
446
928
  }
447
5.17k
  result.mantissa = mantissa;
448
449
5.17k
  const char* const exponent_begin = begin;
450
5.17k
  result.literal_exponent = 0;
451
5.17k
  bool found_exponent = false;
452
5.17k
  if (AllowExponent(format_flags) && begin < end &&
453
2.67k
      IsExponentCharacter<base>(*begin)) {
454
2.60k
    bool negative_exponent = false;
455
2.60k
    ++begin;
456
2.60k
    if (begin < end && *begin == '-') {
457
1.89k
      negative_exponent = true;
458
1.89k
      ++begin;
459
1.89k
    } else if (begin < end && *begin == '+') {
460
225
      ++begin;
461
225
    }
462
2.60k
    const char* const exponent_digits_begin = begin;
463
    // Exponent is always expressed in decimal, even for hexadecimal floats.
464
2.60k
    begin += ConsumeDigits<10>(begin, end, kDecimalExponentDigitsMax,
465
2.60k
                               &result.literal_exponent, nullptr);
466
2.60k
    if (begin == exponent_digits_begin) {
467
      // there were no digits where we expected an exponent.  We failed to read
468
      // an exponent and should not consume the 'e' after all.  Rewind 'begin'.
469
21
      found_exponent = false;
470
21
      begin = exponent_begin;
471
2.57k
    } else {
472
2.57k
      found_exponent = true;
473
2.57k
      if (negative_exponent) {
474
1.89k
        result.literal_exponent = -result.literal_exponent;
475
1.89k
      }
476
2.57k
    }
477
2.60k
  }
478
479
5.17k
  if (!found_exponent && RequireExponent(format_flags)) {
480
    // Provided flags required an exponent, but none was found.  This results
481
    // in a failure to scan.
482
0
    return result;
483
0
  }
484
485
  // Success!
486
5.17k
  result.type = strings_internal::FloatType::kNumber;
487
5.17k
  if (result.mantissa > 0) {
488
4.00k
    result.exponent = result.literal_exponent +
489
4.00k
                      (DigitMagnitude<base>() * exponent_adjustment);
490
4.00k
  } else {
491
1.17k
    result.exponent = 0;
492
1.17k
  }
493
5.17k
  result.end = begin;
494
5.17k
  return result;
495
5.17k
}
496
497
template ParsedFloat ParseFloat<10>(const char* begin, const char* end,
498
                                    chars_format format_flags);
499
template ParsedFloat ParseFloat<16>(const char* begin, const char* end,
500
                                    chars_format format_flags);
501
502
}  // namespace strings_internal
503
ABSL_NAMESPACE_END
504
}  // namespace absl