| 259 | } // namespace |
| 260 | |
| 261 | u32 ieee754_parse_decimal(const char* s, fl::size len, fl::size* consumed) FL_NOEXCEPT { |
| 262 | fl::size i = 0; |
| 263 | |
| 264 | auto fail = [&]() -> u32 { |
| 265 | if (consumed) *consumed = 0; |
| 266 | return 0; |
| 267 | }; |
| 268 | |
| 269 | // Skip leading whitespace. |
| 270 | while (i < len && (s[i] == ' ' || s[i] == '\t' || s[i] == '\n' || |
| 271 | s[i] == '\r' || s[i] == '\f' || s[i] == '\v')) { |
| 272 | ++i; |
| 273 | } |
| 274 | |
| 275 | // Sign. |
| 276 | u32 sign_bit = 0; |
| 277 | if (i < len && s[i] == '-') { sign_bit = kSignBitMask; ++i; } |
| 278 | else if (i < len && s[i] == '+') { ++i; } |
| 279 | |
| 280 | // Mantissa: integer + optional fractional. Cap at 19 significant decimal |
| 281 | // digits -- that is the max u64 can hold (10**19 < 2**64). Beyond that we |
| 282 | // drop digits but keep tracking the decimal exponent so values like |
| 283 | // "100000000000000000000" (1e20) still round to the right magnitude. |
| 284 | fl::u64 mantissa = 0; |
| 285 | int decimal_exp = 0; |
| 286 | int significant_digits = 0; |
| 287 | bool seen_decimal = false; |
| 288 | bool seen_digit = false; |
| 289 | constexpr int kMaxSignificantDigits = 19; |
| 290 | |
| 291 | while (i < len) { |
| 292 | const char c = s[i]; |
| 293 | if (c >= '0' && c <= '9') { |
| 294 | seen_digit = true; |
| 295 | if (significant_digits < kMaxSignificantDigits) { |
| 296 | // u64 max is ~1.8e19, mantissa * 10 + 9 stays below for 18 digits. |
| 297 | mantissa = mantissa * 10u + static_cast<fl::u64>(c - '0'); |
| 298 | if (significant_digits != 0 || c != '0') { |
| 299 | ++significant_digits; |
| 300 | } |
| 301 | if (seen_decimal) { |
| 302 | --decimal_exp; |
| 303 | } |
| 304 | } else { |
| 305 | // Out of mantissa precision -- track magnitude via decimal_exp only. |
| 306 | if (!seen_decimal) { |
| 307 | ++decimal_exp; |
| 308 | } |
| 309 | } |
| 310 | ++i; |
| 311 | } else if (c == '.' && !seen_decimal) { |
| 312 | seen_decimal = true; |
| 313 | ++i; |
| 314 | } else { |
| 315 | break; |
| 316 | } |
| 317 | } |
| 318 |
no test coverage detected