|  | // After editing this file, run "go generate" in the parent directory. | 
|  |  | 
|  | // Copyright 2020 The Wuffs Authors. | 
|  | // | 
|  | // Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | // you may not use this file except in compliance with the License. | 
|  | // You may obtain a copy of the License at | 
|  | // | 
|  | //    https://www.apache.org/licenses/LICENSE-2.0 | 
|  | // | 
|  | // Unless required by applicable law or agreed to in writing, software | 
|  | // distributed under the License is distributed on an "AS IS" BASIS, | 
|  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | // See the License for the specific language governing permissions and | 
|  | // limitations under the License. | 
|  |  | 
|  | // ---------------- String Conversions | 
|  |  | 
|  | // wuffs_base__parse_number__foo_digits entries are 0x00 for invalid digits, | 
|  | // and (0x80 | v) for valid digits, where v is the 4 bit value. | 
|  |  | 
|  | static const uint8_t wuffs_base__parse_number__decimal_digits[256] = { | 
|  | // 0     1     2     3     4     5     6     7 | 
|  | // 8     9     A     B     C     D     E     F | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x00 ..= 0x07. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x08 ..= 0x0F. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x10 ..= 0x17. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x18 ..= 0x1F. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x20 ..= 0x27. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x28 ..= 0x2F. | 
|  | 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,  // 0x30 ..= 0x37. '0'-'7'. | 
|  | 0x88, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x38 ..= 0x3F. '8'-'9'. | 
|  |  | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x40 ..= 0x47. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x48 ..= 0x4F. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x50 ..= 0x57. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x58 ..= 0x5F. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x60 ..= 0x67. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x68 ..= 0x6F. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x70 ..= 0x77. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x78 ..= 0x7F. | 
|  |  | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x80 ..= 0x87. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x88 ..= 0x8F. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x90 ..= 0x97. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x98 ..= 0x9F. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0xA0 ..= 0xA7. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0xA8 ..= 0xAF. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0xB0 ..= 0xB7. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0xB8 ..= 0xBF. | 
|  |  | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0xC0 ..= 0xC7. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0xC8 ..= 0xCF. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0xD0 ..= 0xD7. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0xD8 ..= 0xDF. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0xE0 ..= 0xE7. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0xE8 ..= 0xEF. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0xF0 ..= 0xF7. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0xF8 ..= 0xFF. | 
|  | // 0     1     2     3     4     5     6     7 | 
|  | // 8     9     A     B     C     D     E     F | 
|  | }; | 
|  |  | 
|  | static const uint8_t wuffs_base__parse_number__hexadecimal_digits[256] = { | 
|  | // 0     1     2     3     4     5     6     7 | 
|  | // 8     9     A     B     C     D     E     F | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x00 ..= 0x07. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x08 ..= 0x0F. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x10 ..= 0x17. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x18 ..= 0x1F. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x20 ..= 0x27. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x28 ..= 0x2F. | 
|  | 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,  // 0x30 ..= 0x37. '0'-'7'. | 
|  | 0x88, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x38 ..= 0x3F. '8'-'9'. | 
|  |  | 
|  | 0x00, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x00,  // 0x40 ..= 0x47. 'A'-'F'. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x48 ..= 0x4F. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x50 ..= 0x57. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x58 ..= 0x5F. | 
|  | 0x00, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x00,  // 0x60 ..= 0x67. 'a'-'f'. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x68 ..= 0x6F. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x70 ..= 0x77. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x78 ..= 0x7F. | 
|  |  | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x80 ..= 0x87. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x88 ..= 0x8F. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x90 ..= 0x97. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x98 ..= 0x9F. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0xA0 ..= 0xA7. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0xA8 ..= 0xAF. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0xB0 ..= 0xB7. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0xB8 ..= 0xBF. | 
|  |  | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0xC0 ..= 0xC7. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0xC8 ..= 0xCF. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0xD0 ..= 0xD7. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0xD8 ..= 0xDF. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0xE0 ..= 0xE7. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0xE8 ..= 0xEF. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0xF0 ..= 0xF7. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0xF8 ..= 0xFF. | 
|  | // 0     1     2     3     4     5     6     7 | 
|  | // 8     9     A     B     C     D     E     F | 
|  | }; | 
|  |  | 
|  | // -------- | 
|  |  | 
|  | wuffs_base__result_i64  // | 
|  | wuffs_base__parse_number_i64(wuffs_base__slice_u8 s) { | 
|  | uint8_t* p = s.ptr; | 
|  | uint8_t* q = s.ptr + s.len; | 
|  |  | 
|  | for (; (p < q) && (*p == '_'); p++) { | 
|  | } | 
|  |  | 
|  | bool negative = false; | 
|  | if (p >= q) { | 
|  | goto fail_bad_argument; | 
|  | } else if (*p == '-') { | 
|  | p++; | 
|  | negative = true; | 
|  | } else if (*p == '+') { | 
|  | p++; | 
|  | } | 
|  |  | 
|  | do { | 
|  | wuffs_base__result_u64 r = wuffs_base__parse_number_u64( | 
|  | wuffs_base__make_slice_u8(p, (size_t)(q - p))); | 
|  | if (r.status.repr != NULL) { | 
|  | wuffs_base__result_i64 ret; | 
|  | ret.status.repr = r.status.repr; | 
|  | ret.value = 0; | 
|  | return ret; | 
|  | } else if (negative) { | 
|  | if (r.value > 0x8000000000000000) { | 
|  | goto fail_out_of_bounds; | 
|  | } | 
|  | wuffs_base__result_i64 ret; | 
|  | ret.status.repr = NULL; | 
|  | ret.value = -(int64_t)(r.value); | 
|  | return ret; | 
|  | } else if (r.value > 0x7FFFFFFFFFFFFFFF) { | 
|  | goto fail_out_of_bounds; | 
|  | } else { | 
|  | wuffs_base__result_i64 ret; | 
|  | ret.status.repr = NULL; | 
|  | ret.value = +(int64_t)(r.value); | 
|  | return ret; | 
|  | } | 
|  | } while (0); | 
|  |  | 
|  | fail_bad_argument: | 
|  | do { | 
|  | wuffs_base__result_i64 ret; | 
|  | ret.status.repr = wuffs_base__error__bad_argument; | 
|  | ret.value = 0; | 
|  | return ret; | 
|  | } while (0); | 
|  |  | 
|  | fail_out_of_bounds: | 
|  | do { | 
|  | wuffs_base__result_i64 ret; | 
|  | ret.status.repr = wuffs_base__error__out_of_bounds; | 
|  | ret.value = 0; | 
|  | return ret; | 
|  | } while (0); | 
|  | } | 
|  |  | 
|  | wuffs_base__result_u64  // | 
|  | wuffs_base__parse_number_u64(wuffs_base__slice_u8 s) { | 
|  | uint8_t* p = s.ptr; | 
|  | uint8_t* q = s.ptr + s.len; | 
|  |  | 
|  | for (; (p < q) && (*p == '_'); p++) { | 
|  | } | 
|  |  | 
|  | if (p >= q) { | 
|  | goto fail_bad_argument; | 
|  |  | 
|  | } else if (*p == '0') { | 
|  | p++; | 
|  | if (p >= q) { | 
|  | goto ok_zero; | 
|  | } | 
|  | if (*p == '_') { | 
|  | p++; | 
|  | for (; p < q; p++) { | 
|  | if (*p != '_') { | 
|  | goto fail_bad_argument; | 
|  | } | 
|  | } | 
|  | goto ok_zero; | 
|  | } | 
|  |  | 
|  | if ((*p == 'x') || (*p == 'X')) { | 
|  | p++; | 
|  | for (; (p < q) && (*p == '_'); p++) { | 
|  | } | 
|  | if (p < q) { | 
|  | goto hexadecimal; | 
|  | } | 
|  |  | 
|  | } else if ((*p == 'd') || (*p == 'D')) { | 
|  | p++; | 
|  | for (; (p < q) && (*p == '_'); p++) { | 
|  | } | 
|  | if (p < q) { | 
|  | goto decimal; | 
|  | } | 
|  | } | 
|  |  | 
|  | goto fail_bad_argument; | 
|  | } | 
|  |  | 
|  | decimal: | 
|  | do { | 
|  | uint64_t v = wuffs_base__parse_number__decimal_digits[*p++]; | 
|  | if (v == 0) { | 
|  | goto fail_bad_argument; | 
|  | } | 
|  | v &= 0x0F; | 
|  |  | 
|  | // UINT64_MAX is 18446744073709551615, which is ((10 * max10) + max1). | 
|  | const uint64_t max10 = 1844674407370955161; | 
|  | const uint8_t max1 = 5; | 
|  |  | 
|  | for (; p < q; p++) { | 
|  | if (*p == '_') { | 
|  | continue; | 
|  | } | 
|  | uint8_t digit = wuffs_base__parse_number__decimal_digits[*p]; | 
|  | if (digit == 0) { | 
|  | goto fail_bad_argument; | 
|  | } | 
|  | digit &= 0x0F; | 
|  | if ((v > max10) || ((v == max10) && (digit > max1))) { | 
|  | goto fail_out_of_bounds; | 
|  | } | 
|  | v = (10 * v) + ((uint64_t)(digit)); | 
|  | } | 
|  |  | 
|  | wuffs_base__result_u64 ret; | 
|  | ret.status.repr = NULL; | 
|  | ret.value = v; | 
|  | return ret; | 
|  | } while (0); | 
|  |  | 
|  | hexadecimal: | 
|  | do { | 
|  | uint64_t v = wuffs_base__parse_number__hexadecimal_digits[*p++]; | 
|  | if (v == 0) { | 
|  | goto fail_bad_argument; | 
|  | } | 
|  | v &= 0x0F; | 
|  |  | 
|  | for (; p < q; p++) { | 
|  | if (*p == '_') { | 
|  | continue; | 
|  | } | 
|  | uint8_t digit = wuffs_base__parse_number__hexadecimal_digits[*p]; | 
|  | if (digit == 0) { | 
|  | goto fail_bad_argument; | 
|  | } | 
|  | digit &= 0x0F; | 
|  | if ((v >> 60) != 0) { | 
|  | goto fail_out_of_bounds; | 
|  | } | 
|  | v = (v << 4) | ((uint64_t)(digit)); | 
|  | } | 
|  |  | 
|  | wuffs_base__result_u64 ret; | 
|  | ret.status.repr = NULL; | 
|  | ret.value = v; | 
|  | return ret; | 
|  | } while (0); | 
|  |  | 
|  | ok_zero: | 
|  | do { | 
|  | wuffs_base__result_u64 ret; | 
|  | ret.status.repr = NULL; | 
|  | ret.value = 0; | 
|  | return ret; | 
|  | } while (0); | 
|  |  | 
|  | fail_bad_argument: | 
|  | do { | 
|  | wuffs_base__result_u64 ret; | 
|  | ret.status.repr = wuffs_base__error__bad_argument; | 
|  | ret.value = 0; | 
|  | return ret; | 
|  | } while (0); | 
|  |  | 
|  | fail_out_of_bounds: | 
|  | do { | 
|  | wuffs_base__result_u64 ret; | 
|  | ret.status.repr = wuffs_base__error__out_of_bounds; | 
|  | ret.value = 0; | 
|  | return ret; | 
|  | } while (0); | 
|  | } | 
|  |  | 
|  | // ---------------- IEEE 754 Floating Point | 
|  |  | 
|  | #define WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE 1023 | 
|  | #define WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION 500 | 
|  |  | 
|  | // WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL is the largest N | 
|  | // such that ((10 << N) < (1 << 64)). | 
|  | #define WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL 60 | 
|  |  | 
|  | // wuffs_base__private_implementation__high_prec_dec (abbreviated as HPD) is a | 
|  | // fixed precision floating point decimal number, augmented with ±infinity | 
|  | // values, but it cannot represent NaN (Not a Number). | 
|  | // | 
|  | // An HPD isn't for general purpose arithmetic, only for conversions to and | 
|  | // from IEEE 754 double-precision floating point, where the largest and | 
|  | // smallest positive, finite values are approximately 1.8e+308 and 4.9e-324. | 
|  | // HPD exponents above +1023 mean infinity, below -1023 mean zero. The ±1023 | 
|  | // bounds are further away from zero than ±(324 + 500), where 500 and 1023 is | 
|  | // WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION and | 
|  | // WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE. | 
|  | // | 
|  | // digits[.. num_digits] are the number's digits in big-endian order. The | 
|  | // uint8_t values are in the range [0 ..= 9], not ['0' ..= '9'], where e.g. '7' | 
|  | // is the ASCII value 0x37. | 
|  | // | 
|  | // decimal_point is the index (within digits) of the decimal point. It may be | 
|  | // negative or be larger than num_digits, in which case the explicit digits are | 
|  | // padded with implicit zeroes. | 
|  | // | 
|  | // For example, if num_digits is 3 and digits is "\x07\x08\x09": | 
|  | //   - A decimal_point of -2 means ".00789" | 
|  | //   - A decimal_point of -1 means ".0789" | 
|  | //   - A decimal_point of -0 means ".789" | 
|  | //   - A decimal_point of +1 means "7.89" | 
|  | //   - A decimal_point of +2 means "78.9" | 
|  | //   - A decimal_point of +3 means "789." | 
|  | //   - A decimal_point of +4 means "7890." | 
|  | //   - A decimal_point of +5 means "78900." | 
|  | // | 
|  | // As above, a decimal_point higher than +1023 means that the overall value is | 
|  | // infinity, lower than -1023 means zero. | 
|  | // | 
|  | // negative is a sign bit. An HPD can distinguish positive and negative zero. | 
|  | // | 
|  | // truncated is whether there are more than | 
|  | // WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION digits, and at | 
|  | // least one of those extra digits are non-zero. The existence of long-tail | 
|  | // digits can affect rounding. | 
|  | // | 
|  | // The "all fields are zero" value is valid, and represents the number +0. | 
|  | typedef struct { | 
|  | uint32_t num_digits; | 
|  | int32_t decimal_point; | 
|  | bool negative; | 
|  | bool truncated; | 
|  | uint8_t digits[WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION]; | 
|  | } wuffs_base__private_implementation__high_prec_dec; | 
|  |  | 
|  | // wuffs_base__private_implementation__high_prec_dec__trim trims trailing | 
|  | // zeroes from the h->digits[.. h->num_digits] slice. They have no benefit, | 
|  | // since we explicitly track h->decimal_point. | 
|  | // | 
|  | // Preconditions: | 
|  | //  - h is non-NULL. | 
|  | static inline void  // | 
|  | wuffs_base__private_implementation__high_prec_dec__trim( | 
|  | wuffs_base__private_implementation__high_prec_dec* h) { | 
|  | while ((h->num_digits > 0) && (h->digits[h->num_digits - 1] == 0)) { | 
|  | h->num_digits--; | 
|  | } | 
|  | } | 
|  |  | 
|  | static wuffs_base__status  // | 
|  | wuffs_base__private_implementation__high_prec_dec__parse( | 
|  | wuffs_base__private_implementation__high_prec_dec* h, | 
|  | wuffs_base__slice_u8 s) { | 
|  | if (!h) { | 
|  | return wuffs_base__make_status(wuffs_base__error__bad_receiver); | 
|  | } | 
|  | h->num_digits = 0; | 
|  | h->decimal_point = 0; | 
|  | h->negative = false; | 
|  | h->truncated = false; | 
|  |  | 
|  | uint8_t* p = s.ptr; | 
|  | uint8_t* q = s.ptr + s.len; | 
|  |  | 
|  | for (; (p < q) && (*p == '_'); p++) { | 
|  | } | 
|  | if (p >= q) { | 
|  | return wuffs_base__make_status(wuffs_base__error__bad_argument); | 
|  | } | 
|  |  | 
|  | // Parse sign. | 
|  | do { | 
|  | if (*p == '+') { | 
|  | p++; | 
|  | } else if (*p == '-') { | 
|  | h->negative = true; | 
|  | p++; | 
|  | } else { | 
|  | break; | 
|  | } | 
|  | for (; (p < q) && (*p == '_'); p++) { | 
|  | } | 
|  | } while (0); | 
|  |  | 
|  | // Parse digits. | 
|  | uint32_t nd = 0; | 
|  | int32_t dp = 0; | 
|  | bool saw_digits = false; | 
|  | bool saw_non_zero_digits = false; | 
|  | bool saw_dot = false; | 
|  | for (; p < q; p++) { | 
|  | if (*p == '_') { | 
|  | // No-op. | 
|  |  | 
|  | } else if ((*p == '.') || (*p == ',')) { | 
|  | // As per https://en.wikipedia.org/wiki/Decimal_separator, both '.' or | 
|  | // ',' are commonly used. We just parse either, regardless of LOCALE. | 
|  | if (saw_dot) { | 
|  | return wuffs_base__make_status(wuffs_base__error__bad_argument); | 
|  | } | 
|  | saw_dot = true; | 
|  | dp = (int32_t)nd; | 
|  |  | 
|  | } else if ('0' == *p) { | 
|  | if (!saw_dot && !saw_non_zero_digits && saw_digits) { | 
|  | // We don't allow unnecessary leading zeroes: "000123" or "0644". | 
|  | return wuffs_base__make_status(wuffs_base__error__bad_argument); | 
|  | } | 
|  | saw_digits = true; | 
|  | if (nd == 0) { | 
|  | // Track leading zeroes implicitly. | 
|  | dp--; | 
|  | } else if (nd < | 
|  | WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION) { | 
|  | h->digits[nd++] = 0; | 
|  | } else { | 
|  | // Long-tail zeroes are ignored. | 
|  | } | 
|  |  | 
|  | } else if (('0' < *p) && (*p <= '9')) { | 
|  | if (!saw_dot && !saw_non_zero_digits && saw_digits) { | 
|  | // We don't allow unnecessary leading zeroes: "000123" or "0644". | 
|  | return wuffs_base__make_status(wuffs_base__error__bad_argument); | 
|  | } | 
|  | saw_digits = true; | 
|  | saw_non_zero_digits = true; | 
|  | if (nd < WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION) { | 
|  | h->digits[nd++] = (uint8_t)(*p - '0'); | 
|  | } else { | 
|  | // Long-tail non-zeroes set the truncated bit. | 
|  | h->truncated = true; | 
|  | } | 
|  |  | 
|  | } else { | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | if (!saw_digits) { | 
|  | return wuffs_base__make_status(wuffs_base__error__bad_argument); | 
|  | } | 
|  | if (!saw_dot) { | 
|  | dp = (int32_t)nd; | 
|  | } | 
|  |  | 
|  | // Parse exponent. | 
|  | if ((p < q) && ((*p == 'E') || (*p == 'e'))) { | 
|  | p++; | 
|  | for (; (p < q) && (*p == '_'); p++) { | 
|  | } | 
|  | if (p >= q) { | 
|  | return wuffs_base__make_status(wuffs_base__error__bad_argument); | 
|  | } | 
|  |  | 
|  | int32_t exp_sign = +1; | 
|  | if (*p == '+') { | 
|  | p++; | 
|  | } else if (*p == '-') { | 
|  | exp_sign = -1; | 
|  | p++; | 
|  | } | 
|  |  | 
|  | int32_t exp = 0; | 
|  | const int32_t exp_large = | 
|  | WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE + | 
|  | WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION; | 
|  | bool saw_exp_digits = false; | 
|  | for (; p < q; p++) { | 
|  | if (*p == '_') { | 
|  | // No-op. | 
|  | } else if (('0' <= *p) && (*p <= '9')) { | 
|  | saw_exp_digits = true; | 
|  | if (exp < exp_large) { | 
|  | exp = (10 * exp) + ((int32_t)(*p - '0')); | 
|  | } | 
|  | } else { | 
|  | break; | 
|  | } | 
|  | } | 
|  | if (!saw_exp_digits) { | 
|  | return wuffs_base__make_status(wuffs_base__error__bad_argument); | 
|  | } | 
|  | dp += exp_sign * exp; | 
|  | } | 
|  |  | 
|  | // Finish. | 
|  | if (p != q) { | 
|  | return wuffs_base__make_status(wuffs_base__error__bad_argument); | 
|  | } | 
|  | h->num_digits = nd; | 
|  | if (nd == 0) { | 
|  | h->decimal_point = 0; | 
|  | } else if (dp < | 
|  | -WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE) { | 
|  | h->decimal_point = | 
|  | -WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE - 1; | 
|  | } else if (dp > | 
|  | +WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE) { | 
|  | h->decimal_point = | 
|  | +WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE + 1; | 
|  | } else { | 
|  | h->decimal_point = dp; | 
|  | } | 
|  | wuffs_base__private_implementation__high_prec_dec__trim(h); | 
|  | return wuffs_base__make_status(NULL); | 
|  | } | 
|  |  | 
|  | // -------- | 
|  |  | 
|  | // The etc__hpd_left_shift and etc__powers_of_5 tables were printed by | 
|  | // script/print-hpd-left-shift.go. That script has an optional -comments flag, | 
|  | // whose output is not copied here, which prints further detail. | 
|  | // | 
|  | // These tables are used in | 
|  | // wuffs_base__private_implementation__high_prec_dec__lshift_num_new_digits. | 
|  |  | 
|  | // wuffs_base__private_implementation__hpd_left_shift[i] encodes the number of | 
|  | // new digits created after multiplying a positive integer by (1 << i): the | 
|  | // additional length in the decimal representation. For example, shifting "234" | 
|  | // by 3 (equivalent to multiplying by 8) will produce "1872". Going from a | 
|  | // 3-length string to a 4-length string means that 1 new digit was added (and | 
|  | // existing digits may have changed). | 
|  | // | 
|  | // Shifting by i can add either N or N-1 new digits, depending on whether the | 
|  | // original positive integer compares >= or < to the i'th power of 5 (as 10 | 
|  | // equals 2 * 5). Comparison is lexicographic, not numerical. | 
|  | // | 
|  | // For example, shifting by 4 (i.e. multiplying by 16) can add 1 or 2 new | 
|  | // digits, depending on a lexicographic comparison to (5 ** 4), i.e. "625": | 
|  | //  - ("1"      << 4) is "16",       which adds 1 new digit. | 
|  | //  - ("5678"   << 4) is "90848",    which adds 1 new digit. | 
|  | //  - ("624"    << 4) is "9984",     which adds 1 new digit. | 
|  | //  - ("62498"  << 4) is "999968",   which adds 1 new digit. | 
|  | //  - ("625"    << 4) is "10000",    which adds 2 new digits. | 
|  | //  - ("625001" << 4) is "10000016", which adds 2 new digits. | 
|  | //  - ("7008"   << 4) is "112128",   which adds 2 new digits. | 
|  | //  - ("99"     << 4) is "1584",     which adds 2 new digits. | 
|  | // | 
|  | // Thus, when i is 4, N is 2 and (5 ** i) is "625". This etc__hpd_left_shift | 
|  | // array encodes this as: | 
|  | //  - etc__hpd_left_shift[4] is 0x1006 = (2 << 11) | 0x0006. | 
|  | //  - etc__hpd_left_shift[5] is 0x1009 = (? << 11) | 0x0009. | 
|  | // where the ? isn't relevant for i == 4. | 
|  | // | 
|  | // The high 5 bits of etc__hpd_left_shift[i] is N, the higher of the two | 
|  | // possible number of new digits. The low 11 bits are an offset into the | 
|  | // etc__powers_of_5 array (of length 0x051C, so offsets fit in 11 bits). When i | 
|  | // is 4, its offset and the next one is 6 and 9, and etc__powers_of_5[6 .. 9] | 
|  | // is the string "\x06\x02\x05", so the relevant power of 5 is "625". | 
|  | // | 
|  | // Thanks to Ken Thompson for the original idea. | 
|  | static const uint16_t wuffs_base__private_implementation__hpd_left_shift[65] = { | 
|  | 0x0000, 0x0800, 0x0801, 0x0803, 0x1006, 0x1009, 0x100D, 0x1812, 0x1817, | 
|  | 0x181D, 0x2024, 0x202B, 0x2033, 0x203C, 0x2846, 0x2850, 0x285B, 0x3067, | 
|  | 0x3073, 0x3080, 0x388E, 0x389C, 0x38AB, 0x38BB, 0x40CC, 0x40DD, 0x40EF, | 
|  | 0x4902, 0x4915, 0x4929, 0x513E, 0x5153, 0x5169, 0x5180, 0x5998, 0x59B0, | 
|  | 0x59C9, 0x61E3, 0x61FD, 0x6218, 0x6A34, 0x6A50, 0x6A6D, 0x6A8B, 0x72AA, | 
|  | 0x72C9, 0x72E9, 0x7B0A, 0x7B2B, 0x7B4D, 0x8370, 0x8393, 0x83B7, 0x83DC, | 
|  | 0x8C02, 0x8C28, 0x8C4F, 0x9477, 0x949F, 0x94C8, 0x9CF2, 0x051C, 0x051C, | 
|  | 0x051C, 0x051C, | 
|  | }; | 
|  |  | 
|  | // wuffs_base__private_implementation__powers_of_5 contains the powers of 5, | 
|  | // concatenated together: "5", "25", "125", "625", "3125", etc. | 
|  | static const uint8_t wuffs_base__private_implementation__powers_of_5[0x051C] = { | 
|  | 5, 2, 5, 1, 2, 5, 6, 2, 5, 3, 1, 2, 5, 1, 5, 6, 2, 5, 7, 8, 1, 2, 5, 3, 9, | 
|  | 0, 6, 2, 5, 1, 9, 5, 3, 1, 2, 5, 9, 7, 6, 5, 6, 2, 5, 4, 8, 8, 2, 8, 1, 2, | 
|  | 5, 2, 4, 4, 1, 4, 0, 6, 2, 5, 1, 2, 2, 0, 7, 0, 3, 1, 2, 5, 6, 1, 0, 3, 5, | 
|  | 1, 5, 6, 2, 5, 3, 0, 5, 1, 7, 5, 7, 8, 1, 2, 5, 1, 5, 2, 5, 8, 7, 8, 9, 0, | 
|  | 6, 2, 5, 7, 6, 2, 9, 3, 9, 4, 5, 3, 1, 2, 5, 3, 8, 1, 4, 6, 9, 7, 2, 6, 5, | 
|  | 6, 2, 5, 1, 9, 0, 7, 3, 4, 8, 6, 3, 2, 8, 1, 2, 5, 9, 5, 3, 6, 7, 4, 3, 1, | 
|  | 6, 4, 0, 6, 2, 5, 4, 7, 6, 8, 3, 7, 1, 5, 8, 2, 0, 3, 1, 2, 5, 2, 3, 8, 4, | 
|  | 1, 8, 5, 7, 9, 1, 0, 1, 5, 6, 2, 5, 1, 1, 9, 2, 0, 9, 2, 8, 9, 5, 5, 0, 7, | 
|  | 8, 1, 2, 5, 5, 9, 6, 0, 4, 6, 4, 4, 7, 7, 5, 3, 9, 0, 6, 2, 5, 2, 9, 8, 0, | 
|  | 2, 3, 2, 2, 3, 8, 7, 6, 9, 5, 3, 1, 2, 5, 1, 4, 9, 0, 1, 1, 6, 1, 1, 9, 3, | 
|  | 8, 4, 7, 6, 5, 6, 2, 5, 7, 4, 5, 0, 5, 8, 0, 5, 9, 6, 9, 2, 3, 8, 2, 8, 1, | 
|  | 2, 5, 3, 7, 2, 5, 2, 9, 0, 2, 9, 8, 4, 6, 1, 9, 1, 4, 0, 6, 2, 5, 1, 8, 6, | 
|  | 2, 6, 4, 5, 1, 4, 9, 2, 3, 0, 9, 5, 7, 0, 3, 1, 2, 5, 9, 3, 1, 3, 2, 2, 5, | 
|  | 7, 4, 6, 1, 5, 4, 7, 8, 5, 1, 5, 6, 2, 5, 4, 6, 5, 6, 6, 1, 2, 8, 7, 3, 0, | 
|  | 7, 7, 3, 9, 2, 5, 7, 8, 1, 2, 5, 2, 3, 2, 8, 3, 0, 6, 4, 3, 6, 5, 3, 8, 6, | 
|  | 9, 6, 2, 8, 9, 0, 6, 2, 5, 1, 1, 6, 4, 1, 5, 3, 2, 1, 8, 2, 6, 9, 3, 4, 8, | 
|  | 1, 4, 4, 5, 3, 1, 2, 5, 5, 8, 2, 0, 7, 6, 6, 0, 9, 1, 3, 4, 6, 7, 4, 0, 7, | 
|  | 2, 2, 6, 5, 6, 2, 5, 2, 9, 1, 0, 3, 8, 3, 0, 4, 5, 6, 7, 3, 3, 7, 0, 3, 6, | 
|  | 1, 3, 2, 8, 1, 2, 5, 1, 4, 5, 5, 1, 9, 1, 5, 2, 2, 8, 3, 6, 6, 8, 5, 1, 8, | 
|  | 0, 6, 6, 4, 0, 6, 2, 5, 7, 2, 7, 5, 9, 5, 7, 6, 1, 4, 1, 8, 3, 4, 2, 5, 9, | 
|  | 0, 3, 3, 2, 0, 3, 1, 2, 5, 3, 6, 3, 7, 9, 7, 8, 8, 0, 7, 0, 9, 1, 7, 1, 2, | 
|  | 9, 5, 1, 6, 6, 0, 1, 5, 6, 2, 5, 1, 8, 1, 8, 9, 8, 9, 4, 0, 3, 5, 4, 5, 8, | 
|  | 5, 6, 4, 7, 5, 8, 3, 0, 0, 7, 8, 1, 2, 5, 9, 0, 9, 4, 9, 4, 7, 0, 1, 7, 7, | 
|  | 2, 9, 2, 8, 2, 3, 7, 9, 1, 5, 0, 3, 9, 0, 6, 2, 5, 4, 5, 4, 7, 4, 7, 3, 5, | 
|  | 0, 8, 8, 6, 4, 6, 4, 1, 1, 8, 9, 5, 7, 5, 1, 9, 5, 3, 1, 2, 5, 2, 2, 7, 3, | 
|  | 7, 3, 6, 7, 5, 4, 4, 3, 2, 3, 2, 0, 5, 9, 4, 7, 8, 7, 5, 9, 7, 6, 5, 6, 2, | 
|  | 5, 1, 1, 3, 6, 8, 6, 8, 3, 7, 7, 2, 1, 6, 1, 6, 0, 2, 9, 7, 3, 9, 3, 7, 9, | 
|  | 8, 8, 2, 8, 1, 2, 5, 5, 6, 8, 4, 3, 4, 1, 8, 8, 6, 0, 8, 0, 8, 0, 1, 4, 8, | 
|  | 6, 9, 6, 8, 9, 9, 4, 1, 4, 0, 6, 2, 5, 2, 8, 4, 2, 1, 7, 0, 9, 4, 3, 0, 4, | 
|  | 0, 4, 0, 0, 7, 4, 3, 4, 8, 4, 4, 9, 7, 0, 7, 0, 3, 1, 2, 5, 1, 4, 2, 1, 0, | 
|  | 8, 5, 4, 7, 1, 5, 2, 0, 2, 0, 0, 3, 7, 1, 7, 4, 2, 2, 4, 8, 5, 3, 5, 1, 5, | 
|  | 6, 2, 5, 7, 1, 0, 5, 4, 2, 7, 3, 5, 7, 6, 0, 1, 0, 0, 1, 8, 5, 8, 7, 1, 1, | 
|  | 2, 4, 2, 6, 7, 5, 7, 8, 1, 2, 5, 3, 5, 5, 2, 7, 1, 3, 6, 7, 8, 8, 0, 0, 5, | 
|  | 0, 0, 9, 2, 9, 3, 5, 5, 6, 2, 1, 3, 3, 7, 8, 9, 0, 6, 2, 5, 1, 7, 7, 6, 3, | 
|  | 5, 6, 8, 3, 9, 4, 0, 0, 2, 5, 0, 4, 6, 4, 6, 7, 7, 8, 1, 0, 6, 6, 8, 9, 4, | 
|  | 5, 3, 1, 2, 5, 8, 8, 8, 1, 7, 8, 4, 1, 9, 7, 0, 0, 1, 2, 5, 2, 3, 2, 3, 3, | 
|  | 8, 9, 0, 5, 3, 3, 4, 4, 7, 2, 6, 5, 6, 2, 5, 4, 4, 4, 0, 8, 9, 2, 0, 9, 8, | 
|  | 5, 0, 0, 6, 2, 6, 1, 6, 1, 6, 9, 4, 5, 2, 6, 6, 7, 2, 3, 6, 3, 2, 8, 1, 2, | 
|  | 5, 2, 2, 2, 0, 4, 4, 6, 0, 4, 9, 2, 5, 0, 3, 1, 3, 0, 8, 0, 8, 4, 7, 2, 6, | 
|  | 3, 3, 3, 6, 1, 8, 1, 6, 4, 0, 6, 2, 5, 1, 1, 1, 0, 2, 2, 3, 0, 2, 4, 6, 2, | 
|  | 5, 1, 5, 6, 5, 4, 0, 4, 2, 3, 6, 3, 1, 6, 6, 8, 0, 9, 0, 8, 2, 0, 3, 1, 2, | 
|  | 5, 5, 5, 5, 1, 1, 1, 5, 1, 2, 3, 1, 2, 5, 7, 8, 2, 7, 0, 2, 1, 1, 8, 1, 5, | 
|  | 8, 3, 4, 0, 4, 5, 4, 1, 0, 1, 5, 6, 2, 5, 2, 7, 7, 5, 5, 5, 7, 5, 6, 1, 5, | 
|  | 6, 2, 8, 9, 1, 3, 5, 1, 0, 5, 9, 0, 7, 9, 1, 7, 0, 2, 2, 7, 0, 5, 0, 7, 8, | 
|  | 1, 2, 5, 1, 3, 8, 7, 7, 7, 8, 7, 8, 0, 7, 8, 1, 4, 4, 5, 6, 7, 5, 5, 2, 9, | 
|  | 5, 3, 9, 5, 8, 5, 1, 1, 3, 5, 2, 5, 3, 9, 0, 6, 2, 5, 6, 9, 3, 8, 8, 9, 3, | 
|  | 9, 0, 3, 9, 0, 7, 2, 2, 8, 3, 7, 7, 6, 4, 7, 6, 9, 7, 9, 2, 5, 5, 6, 7, 6, | 
|  | 2, 6, 9, 5, 3, 1, 2, 5, 3, 4, 6, 9, 4, 4, 6, 9, 5, 1, 9, 5, 3, 6, 1, 4, 1, | 
|  | 8, 8, 8, 2, 3, 8, 4, 8, 9, 6, 2, 7, 8, 3, 8, 1, 3, 4, 7, 6, 5, 6, 2, 5, 1, | 
|  | 7, 3, 4, 7, 2, 3, 4, 7, 5, 9, 7, 6, 8, 0, 7, 0, 9, 4, 4, 1, 1, 9, 2, 4, 4, | 
|  | 8, 1, 3, 9, 1, 9, 0, 6, 7, 3, 8, 2, 8, 1, 2, 5, 8, 6, 7, 3, 6, 1, 7, 3, 7, | 
|  | 9, 8, 8, 4, 0, 3, 5, 4, 7, 2, 0, 5, 9, 6, 2, 2, 4, 0, 6, 9, 5, 9, 5, 3, 3, | 
|  | 6, 9, 1, 4, 0, 6, 2, 5, | 
|  | }; | 
|  |  | 
|  | // wuffs_base__private_implementation__high_prec_dec__lshift_num_new_digits | 
|  | // returns the number of additional decimal digits when left-shifting by shift. | 
|  | // | 
|  | // See below for preconditions. | 
|  | static uint32_t  // | 
|  | wuffs_base__private_implementation__high_prec_dec__lshift_num_new_digits( | 
|  | wuffs_base__private_implementation__high_prec_dec* h, | 
|  | uint32_t shift) { | 
|  | // Masking with 0x3F should be unnecessary (assuming the preconditions) but | 
|  | // it's cheap and ensures that we don't overflow the | 
|  | // wuffs_base__private_implementation__hpd_left_shift array. | 
|  | shift &= 63; | 
|  |  | 
|  | uint32_t x_a = wuffs_base__private_implementation__hpd_left_shift[shift]; | 
|  | uint32_t x_b = wuffs_base__private_implementation__hpd_left_shift[shift + 1]; | 
|  | uint32_t num_new_digits = x_a >> 11; | 
|  | uint32_t pow5_a = 0x7FF & x_a; | 
|  | uint32_t pow5_b = 0x7FF & x_b; | 
|  |  | 
|  | const uint8_t* pow5 = | 
|  | &wuffs_base__private_implementation__powers_of_5[pow5_a]; | 
|  | uint32_t i = 0; | 
|  | uint32_t n = pow5_b - pow5_a; | 
|  | for (; i < n; i++) { | 
|  | if (i >= h->num_digits) { | 
|  | return num_new_digits - 1; | 
|  | } else if (h->digits[i] == pow5[i]) { | 
|  | continue; | 
|  | } else if (h->digits[i] < pow5[i]) { | 
|  | return num_new_digits - 1; | 
|  | } else { | 
|  | return num_new_digits; | 
|  | } | 
|  | } | 
|  | return num_new_digits; | 
|  | } | 
|  |  | 
|  | // -------- | 
|  |  | 
|  | // wuffs_base__private_implementation__high_prec_dec__rounded_integer returns | 
|  | // the integral (non-fractional) part of h, provided that it is 18 or fewer | 
|  | // decimal digits. For 19 or more digits, it returns UINT64_MAX. Note that: | 
|  | //   - (1 << 53) is    9007199254740992, which has 16 decimal digits. | 
|  | //   - (1 << 56) is   72057594037927936, which has 17 decimal digits. | 
|  | //   - (1 << 59) is  576460752303423488, which has 18 decimal digits. | 
|  | //   - (1 << 63) is 9223372036854775808, which has 19 decimal digits. | 
|  | // and that IEEE 754 double precision has 52 mantissa bits. | 
|  | // | 
|  | // That integral part is rounded-to-even: rounding 7.5 or 8.5 both give 8. | 
|  | // | 
|  | // h's negative bit is ignored: rounding -8.6 returns 9. | 
|  | // | 
|  | // See below for preconditions. | 
|  | static uint64_t  // | 
|  | wuffs_base__private_implementation__high_prec_dec__rounded_integer( | 
|  | wuffs_base__private_implementation__high_prec_dec* h) { | 
|  | if ((h->num_digits == 0) || (h->decimal_point < 0)) { | 
|  | return 0; | 
|  | } else if (h->decimal_point > 18) { | 
|  | return UINT64_MAX; | 
|  | } | 
|  |  | 
|  | uint32_t dp = (uint32_t)(h->decimal_point); | 
|  | uint64_t n = 0; | 
|  | uint32_t i = 0; | 
|  | for (; i < dp; i++) { | 
|  | n = (10 * n) + ((i < h->num_digits) ? h->digits[i] : 0); | 
|  | } | 
|  |  | 
|  | bool round_up = false; | 
|  | if (dp < h->num_digits) { | 
|  | round_up = h->digits[dp] >= 5; | 
|  | if ((h->digits[dp] == 5) && (dp + 1 == h->num_digits)) { | 
|  | // We are exactly halfway. If we're truncated, round up, otherwise round | 
|  | // to even. | 
|  | round_up = h->truncated ||  // | 
|  | ((dp > 0) && (1 & h->digits[dp - 1])); | 
|  | } | 
|  | } | 
|  | if (round_up) { | 
|  | n++; | 
|  | } | 
|  |  | 
|  | return n; | 
|  | } | 
|  |  | 
|  | // wuffs_base__private_implementation__high_prec_dec__small_xshift shifts h's | 
|  | // number (where 'x' is 'l' or 'r' for left or right) by a small shift value. | 
|  | // | 
|  | // Preconditions: | 
|  | //  - h is non-NULL. | 
|  | //  - h->decimal_point is "not extreme". | 
|  | //  - shift is non-zero. | 
|  | //  - shift is "a small shift". | 
|  | // | 
|  | // "Not extreme" means within | 
|  | // ±WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE. | 
|  | // | 
|  | // "A small shift" means not more than | 
|  | // WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL. | 
|  | // | 
|  | // wuffs_base__private_implementation__high_prec_dec__rounded_integer and | 
|  | // wuffs_base__private_implementation__high_prec_dec__lshift_num_new_digits | 
|  | // have the same preconditions. | 
|  |  | 
|  | static void  // | 
|  | wuffs_base__private_implementation__high_prec_dec__small_lshift( | 
|  | wuffs_base__private_implementation__high_prec_dec* h, | 
|  | uint32_t shift) { | 
|  | if (h->num_digits == 0) { | 
|  | return; | 
|  | } | 
|  | uint32_t num_new_digits = | 
|  | wuffs_base__private_implementation__high_prec_dec__lshift_num_new_digits( | 
|  | h, shift); | 
|  | uint32_t rx = h->num_digits - 1;                   // Read  index. | 
|  | uint32_t wx = h->num_digits - 1 + num_new_digits;  // Write index. | 
|  | uint64_t n = 0; | 
|  |  | 
|  | // Repeat: pick up a digit, put down a digit, right to left. | 
|  | while (((int32_t)rx) >= 0) { | 
|  | n += ((uint64_t)(h->digits[rx])) << shift; | 
|  | uint64_t quo = n / 10; | 
|  | uint64_t rem = n - (10 * quo); | 
|  | if (wx < WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION) { | 
|  | h->digits[wx] = (uint8_t)rem; | 
|  | } else if (rem > 0) { | 
|  | h->truncated = true; | 
|  | } | 
|  | n = quo; | 
|  | wx--; | 
|  | rx--; | 
|  | } | 
|  |  | 
|  | // Put down leading digits, right to left. | 
|  | while (n > 0) { | 
|  | uint64_t quo = n / 10; | 
|  | uint64_t rem = n - (10 * quo); | 
|  | if (wx < WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION) { | 
|  | h->digits[wx] = (uint8_t)rem; | 
|  | } else if (rem > 0) { | 
|  | h->truncated = true; | 
|  | } | 
|  | n = quo; | 
|  | wx--; | 
|  | } | 
|  |  | 
|  | // Finish. | 
|  | h->num_digits += num_new_digits; | 
|  | if (h->num_digits > | 
|  | WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION) { | 
|  | h->num_digits = WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION; | 
|  | } | 
|  | h->decimal_point += (int32_t)num_new_digits; | 
|  | wuffs_base__private_implementation__high_prec_dec__trim(h); | 
|  | } | 
|  |  | 
|  | static void  // | 
|  | wuffs_base__private_implementation__high_prec_dec__small_rshift( | 
|  | wuffs_base__private_implementation__high_prec_dec* h, | 
|  | uint32_t shift) { | 
|  | uint32_t rx = 0;  // Read  index. | 
|  | uint32_t wx = 0;  // Write index. | 
|  | uint64_t n = 0; | 
|  |  | 
|  | // Pick up enough leading digits to cover the first shift. | 
|  | while ((n >> shift) == 0) { | 
|  | if (rx < h->num_digits) { | 
|  | // Read a digit. | 
|  | n = (10 * n) + h->digits[rx++]; | 
|  | } else if (n == 0) { | 
|  | // h's number used to be zero and remains zero. | 
|  | return; | 
|  | } else { | 
|  | // Read sufficient implicit trailing zeroes. | 
|  | while ((n >> shift) == 0) { | 
|  | n = 10 * n; | 
|  | rx++; | 
|  | } | 
|  | break; | 
|  | } | 
|  | } | 
|  | h->decimal_point -= ((int32_t)(rx - 1)); | 
|  | if (h->decimal_point < | 
|  | -WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE) { | 
|  | // After the shift, h's number is effectively zero. | 
|  | h->num_digits = 0; | 
|  | h->decimal_point = 0; | 
|  | h->negative = false; | 
|  | h->truncated = false; | 
|  | return; | 
|  | } | 
|  |  | 
|  | // Repeat: pick up a digit, put down a digit, left to right. | 
|  | uint64_t mask = (((uint64_t)(1)) << shift) - 1; | 
|  | while (rx < h->num_digits) { | 
|  | uint8_t new_digit = ((uint8_t)(n >> shift)); | 
|  | n = (10 * (n & mask)) + h->digits[rx++]; | 
|  | h->digits[wx++] = new_digit; | 
|  | } | 
|  |  | 
|  | // Put down trailing digits, left to right. | 
|  | while (n > 0) { | 
|  | uint8_t new_digit = ((uint8_t)(n >> shift)); | 
|  | n = 10 * (n & mask); | 
|  | if (wx < WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION) { | 
|  | h->digits[wx++] = new_digit; | 
|  | } else if (new_digit > 0) { | 
|  | h->truncated = true; | 
|  | } | 
|  | } | 
|  |  | 
|  | // Finish. | 
|  | h->num_digits = wx; | 
|  | wuffs_base__private_implementation__high_prec_dec__trim(h); | 
|  | } | 
|  |  | 
|  | // -------- | 
|  |  | 
|  | wuffs_base__result_f64  // | 
|  | wuffs_base__parse_number_f64_special(wuffs_base__slice_u8 s, | 
|  | const char* fallback_status_repr) { | 
|  | do { | 
|  | uint8_t* p = s.ptr; | 
|  | uint8_t* q = s.ptr + s.len; | 
|  |  | 
|  | for (; (p < q) && (*p == '_'); p++) { | 
|  | } | 
|  | if (p >= q) { | 
|  | goto fallback; | 
|  | } | 
|  |  | 
|  | // Parse sign. | 
|  | bool negative = false; | 
|  | do { | 
|  | if (*p == '+') { | 
|  | p++; | 
|  | } else if (*p == '-') { | 
|  | negative = true; | 
|  | p++; | 
|  | } else { | 
|  | break; | 
|  | } | 
|  | for (; (p < q) && (*p == '_'); p++) { | 
|  | } | 
|  | } while (0); | 
|  | if (p >= q) { | 
|  | goto fallback; | 
|  | } | 
|  |  | 
|  | bool nan = false; | 
|  | switch (p[0]) { | 
|  | case 'I': | 
|  | case 'i': | 
|  | if (((q - p) < 3) ||                     // | 
|  | ((p[1] != 'N') && (p[1] != 'n')) ||  // | 
|  | ((p[2] != 'F') && (p[2] != 'f'))) { | 
|  | goto fallback; | 
|  | } | 
|  | p += 3; | 
|  |  | 
|  | if ((p >= q) || (*p == '_')) { | 
|  | break; | 
|  | } else if (((q - p) < 5) ||                     // | 
|  | ((p[0] != 'I') && (p[0] != 'i')) ||  // | 
|  | ((p[1] != 'N') && (p[1] != 'n')) ||  // | 
|  | ((p[2] != 'I') && (p[2] != 'i')) ||  // | 
|  | ((p[3] != 'T') && (p[3] != 't')) ||  // | 
|  | ((p[4] != 'Y') && (p[4] != 'y'))) { | 
|  | goto fallback; | 
|  | } | 
|  | p += 5; | 
|  |  | 
|  | if ((p >= q) || (*p == '_')) { | 
|  | break; | 
|  | } | 
|  | goto fallback; | 
|  |  | 
|  | case 'N': | 
|  | case 'n': | 
|  | if (((q - p) < 3) ||                     // | 
|  | ((p[1] != 'A') && (p[1] != 'a')) ||  // | 
|  | ((p[2] != 'N') && (p[2] != 'n'))) { | 
|  | goto fallback; | 
|  | } | 
|  | p += 3; | 
|  |  | 
|  | if ((p >= q) || (*p == '_')) { | 
|  | nan = true; | 
|  | break; | 
|  | } | 
|  | goto fallback; | 
|  |  | 
|  | default: | 
|  | goto fallback; | 
|  | } | 
|  |  | 
|  | // Finish. | 
|  | for (; (p < q) && (*p == '_'); p++) { | 
|  | } | 
|  | if (p != q) { | 
|  | goto fallback; | 
|  | } | 
|  | wuffs_base__result_f64 ret; | 
|  | ret.status.repr = NULL; | 
|  | ret.value = wuffs_base__ieee_754_bit_representation__to_f64( | 
|  | (nan ? 0x7FFFFFFFFFFFFFFF : 0x7FF0000000000000) | | 
|  | (negative ? 0x8000000000000000 : 0)); | 
|  | return ret; | 
|  | } while (0); | 
|  |  | 
|  | fallback: | 
|  | do { | 
|  | wuffs_base__result_f64 ret; | 
|  | ret.status.repr = fallback_status_repr; | 
|  | ret.value = 0; | 
|  | return ret; | 
|  | } while (0); | 
|  | } | 
|  |  | 
|  | wuffs_base__result_f64  // | 
|  | wuffs_base__parse_number_f64(wuffs_base__slice_u8 s) { | 
|  | wuffs_base__private_implementation__high_prec_dec h; | 
|  |  | 
|  | do { | 
|  | // powers converts decimal powers of 10 to binary powers of 2. For example, | 
|  | // (10000 >> 13) is 1. It stops before the elements exceed 60, also known | 
|  | // as WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL. | 
|  | static const uint32_t num_powers = 19; | 
|  | static const uint8_t powers[19] = { | 
|  | 0,  3,  6,  9,  13, 16, 19, 23, 26, 29,  // | 
|  | 33, 36, 39, 43, 46, 49, 53, 56, 59,      // | 
|  | }; | 
|  |  | 
|  | wuffs_base__status status = | 
|  | wuffs_base__private_implementation__high_prec_dec__parse(&h, s); | 
|  | if (status.repr) { | 
|  | return wuffs_base__parse_number_f64_special(s, status.repr); | 
|  | } | 
|  |  | 
|  | // Handle zero and obvious extremes. The largest and smallest positive | 
|  | // finite f64 values are approximately 1.8e+308 and 4.9e-324. | 
|  | if ((h.num_digits == 0) || (h.decimal_point < -326)) { | 
|  | goto zero; | 
|  | } else if (h.decimal_point > 310) { | 
|  | goto infinity; | 
|  | } | 
|  |  | 
|  | // Scale by powers of 2 until we're in the range [½ .. 1], which gives us | 
|  | // our exponent (in base-2). First we shift right, possibly a little too | 
|  | // far, ending with a value certainly below 1 and possibly below ½... | 
|  | const int32_t bias = -1023; | 
|  | int32_t exp2 = 0; | 
|  | while (h.decimal_point > 0) { | 
|  | uint32_t n = (uint32_t)(+h.decimal_point); | 
|  | uint32_t shift = | 
|  | (n < num_powers) | 
|  | ? powers[n] | 
|  | : WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL; | 
|  |  | 
|  | wuffs_base__private_implementation__high_prec_dec__small_rshift(&h, | 
|  | shift); | 
|  | if (h.decimal_point < | 
|  | -WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE) { | 
|  | goto zero; | 
|  | } | 
|  | exp2 += (int32_t)shift; | 
|  | } | 
|  | // ...then we shift left, putting us in [½ .. 1]. | 
|  | while (h.decimal_point <= 0) { | 
|  | uint32_t shift; | 
|  | if (h.decimal_point == 0) { | 
|  | if (h.digits[0] >= 5) { | 
|  | break; | 
|  | } | 
|  | shift = (h.digits[0] <= 2) ? 2 : 1; | 
|  | } else { | 
|  | uint32_t n = (uint32_t)(-h.decimal_point); | 
|  | shift = (n < num_powers) | 
|  | ? powers[n] | 
|  | : WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL; | 
|  | } | 
|  |  | 
|  | wuffs_base__private_implementation__high_prec_dec__small_lshift(&h, | 
|  | shift); | 
|  | if (h.decimal_point > | 
|  | +WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE) { | 
|  | goto infinity; | 
|  | } | 
|  | exp2 -= (int32_t)shift; | 
|  | } | 
|  |  | 
|  | // We're in the range [½ .. 1] but f64 uses [1 .. 2]. | 
|  | exp2--; | 
|  |  | 
|  | // The minimum normal exponent is (bias + 1). | 
|  | while ((bias + 1) > exp2) { | 
|  | uint32_t n = (uint32_t)((bias + 1) - exp2); | 
|  | if (n > WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL) { | 
|  | n = WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL; | 
|  | } | 
|  | wuffs_base__private_implementation__high_prec_dec__small_rshift(&h, n); | 
|  | exp2 += (int32_t)n; | 
|  | } | 
|  |  | 
|  | // Check for overflow. | 
|  | if ((exp2 - bias) >= 0x07FF) {  // (1 << 11) - 1. | 
|  | goto infinity; | 
|  | } | 
|  |  | 
|  | // Extract 53 bits for the mantissa (in base-2). | 
|  | wuffs_base__private_implementation__high_prec_dec__small_lshift(&h, 53); | 
|  | uint64_t man2 = | 
|  | wuffs_base__private_implementation__high_prec_dec__rounded_integer(&h); | 
|  |  | 
|  | // Rounding might have added one bit. If so, shift and re-check overflow. | 
|  | if ((man2 >> 53) != 0) { | 
|  | man2 >>= 1; | 
|  | exp2++; | 
|  | if ((exp2 - bias) >= 0x07FF) {  // (1 << 11) - 1. | 
|  | goto infinity; | 
|  | } | 
|  | } | 
|  |  | 
|  | // Handle subnormal numbers. | 
|  | if ((man2 >> 52) == 0) { | 
|  | exp2 = bias; | 
|  | } | 
|  |  | 
|  | // Pack the bits and return. | 
|  | uint64_t exp2_bits = (uint64_t)((exp2 - bias) & 0x07FF);  // (1 << 11) - 1. | 
|  | uint64_t bits = (man2 & 0x000FFFFFFFFFFFFF) |             // (1 << 52) - 1. | 
|  | (exp2_bits << 52) |                       // | 
|  | (h.negative ? 0x8000000000000000 : 0);    // (1 << 63). | 
|  |  | 
|  | wuffs_base__result_f64 ret; | 
|  | ret.status.repr = NULL; | 
|  | ret.value = wuffs_base__ieee_754_bit_representation__to_f64(bits); | 
|  | return ret; | 
|  | } while (0); | 
|  |  | 
|  | zero: | 
|  | do { | 
|  | uint64_t bits = h.negative ? 0x8000000000000000 : 0; | 
|  |  | 
|  | wuffs_base__result_f64 ret; | 
|  | ret.status.repr = NULL; | 
|  | ret.value = wuffs_base__ieee_754_bit_representation__to_f64(bits); | 
|  | return ret; | 
|  | } while (0); | 
|  |  | 
|  | infinity: | 
|  | do { | 
|  | uint64_t bits = h.negative ? 0xFFF0000000000000 : 0x7FF0000000000000; | 
|  |  | 
|  | wuffs_base__result_f64 ret; | 
|  | ret.status.repr = NULL; | 
|  | ret.value = wuffs_base__ieee_754_bit_representation__to_f64(bits); | 
|  | return ret; | 
|  | } while (0); | 
|  | } | 
|  |  | 
|  | // ---------------- Unicode and UTF-8 | 
|  |  | 
|  | size_t  // | 
|  | wuffs_base__utf_8__encode(wuffs_base__slice_u8 dst, uint32_t code_point) { | 
|  | if (code_point <= 0x7F) { | 
|  | if (dst.len >= 1) { | 
|  | dst.ptr[0] = (uint8_t)(code_point); | 
|  | return 1; | 
|  | } | 
|  |  | 
|  | } else if (code_point <= 0x07FF) { | 
|  | if (dst.len >= 2) { | 
|  | dst.ptr[0] = (uint8_t)(0xC0 | ((code_point >> 6))); | 
|  | dst.ptr[1] = (uint8_t)(0x80 | ((code_point >> 0) & 0x3F)); | 
|  | return 2; | 
|  | } | 
|  |  | 
|  | } else if (code_point <= 0xFFFF) { | 
|  | if ((dst.len >= 3) && ((code_point < 0xD800) || (0xDFFF < code_point))) { | 
|  | dst.ptr[0] = (uint8_t)(0xE0 | ((code_point >> 12))); | 
|  | dst.ptr[1] = (uint8_t)(0x80 | ((code_point >> 6) & 0x3F)); | 
|  | dst.ptr[2] = (uint8_t)(0x80 | ((code_point >> 0) & 0x3F)); | 
|  | return 3; | 
|  | } | 
|  |  | 
|  | } else if (code_point <= 0x10FFFF) { | 
|  | if (dst.len >= 4) { | 
|  | dst.ptr[0] = (uint8_t)(0xF0 | ((code_point >> 18))); | 
|  | dst.ptr[1] = (uint8_t)(0x80 | ((code_point >> 12) & 0x3F)); | 
|  | dst.ptr[2] = (uint8_t)(0x80 | ((code_point >> 6) & 0x3F)); | 
|  | dst.ptr[3] = (uint8_t)(0x80 | ((code_point >> 0) & 0x3F)); | 
|  | return 4; | 
|  | } | 
|  | } | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | // wuffs_base__utf_8__byte_length_minus_1 is the byte length (minus 1) of a | 
|  | // UTF-8 encoded code point, based on the encoding's initial byte. | 
|  | //  - 0x00 is 1-byte UTF-8 (ASCII). | 
|  | //  - 0x01 is the start of 2-byte UTF-8. | 
|  | //  - 0x02 is the start of 3-byte UTF-8. | 
|  | //  - 0x03 is the start of 4-byte UTF-8. | 
|  | //  - 0x40 is a UTF-8 tail byte. | 
|  | //  - 0x80 is invalid UTF-8. | 
|  | // | 
|  | // RFC 3629 (UTF-8) gives this grammar for valid UTF-8: | 
|  | //    UTF8-1      = %x00-7F | 
|  | //    UTF8-2      = %xC2-DF UTF8-tail | 
|  | //    UTF8-3      = %xE0 %xA0-BF UTF8-tail / %xE1-EC 2( UTF8-tail ) / | 
|  | //                  %xED %x80-9F UTF8-tail / %xEE-EF 2( UTF8-tail ) | 
|  | //    UTF8-4      = %xF0 %x90-BF 2( UTF8-tail ) / %xF1-F3 3( UTF8-tail ) / | 
|  | //                  %xF4 %x80-8F 2( UTF8-tail ) | 
|  | //    UTF8-tail   = %x80-BF | 
|  | static const uint8_t wuffs_base__utf_8__byte_length_minus_1[256] = { | 
|  | // 0     1     2     3     4     5     6     7 | 
|  | // 8     9     A     B     C     D     E     F | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x00 ..= 0x07. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x08 ..= 0x0F. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x10 ..= 0x17. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x18 ..= 0x1F. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x20 ..= 0x27. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x28 ..= 0x2F. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x30 ..= 0x37. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x38 ..= 0x3F. | 
|  |  | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x40 ..= 0x47. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x48 ..= 0x4F. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x50 ..= 0x57. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x58 ..= 0x5F. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x60 ..= 0x67. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x68 ..= 0x6F. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x70 ..= 0x77. | 
|  | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x78 ..= 0x7F. | 
|  |  | 
|  | 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,  // 0x80 ..= 0x87. | 
|  | 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,  // 0x88 ..= 0x8F. | 
|  | 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,  // 0x90 ..= 0x97. | 
|  | 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,  // 0x98 ..= 0x9F. | 
|  | 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,  // 0xA0 ..= 0xA7. | 
|  | 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,  // 0xA8 ..= 0xAF. | 
|  | 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,  // 0xB0 ..= 0xB7. | 
|  | 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,  // 0xB8 ..= 0xBF. | 
|  |  | 
|  | 0x80, 0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,  // 0xC0 ..= 0xC7. | 
|  | 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,  // 0xC8 ..= 0xCF. | 
|  | 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,  // 0xD0 ..= 0xD7. | 
|  | 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,  // 0xD8 ..= 0xDF. | 
|  | 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,  // 0xE0 ..= 0xE7. | 
|  | 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,  // 0xE8 ..= 0xEF. | 
|  | 0x03, 0x03, 0x03, 0x03, 0x03, 0x80, 0x80, 0x80,  // 0xF0 ..= 0xF7. | 
|  | 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,  // 0xF8 ..= 0xFF. | 
|  | // 0     1     2     3     4     5     6     7 | 
|  | // 8     9     A     B     C     D     E     F | 
|  | }; | 
|  |  | 
|  | wuffs_base__utf_8__next__output  // | 
|  | wuffs_base__utf_8__next(wuffs_base__slice_u8 s) { | 
|  | if (s.len == 0) { | 
|  | return wuffs_base__make_utf_8__next__output(0, 0); | 
|  | } | 
|  | uint32_t c = s.ptr[0]; | 
|  | switch (wuffs_base__utf_8__byte_length_minus_1[c & 0xFF]) { | 
|  | case 0: | 
|  | return wuffs_base__make_utf_8__next__output(c, 1); | 
|  |  | 
|  | case 1: | 
|  | if (s.len < 2) { | 
|  | break; | 
|  | } | 
|  | c = wuffs_base__load_u16le__no_bounds_check(s.ptr); | 
|  | if ((c & 0xC000) != 0x8000) { | 
|  | break; | 
|  | } | 
|  | c = (0x0007C0 & (c << 6)) | (0x00003F & (c >> 8)); | 
|  | return wuffs_base__make_utf_8__next__output(c, 2); | 
|  |  | 
|  | case 2: | 
|  | if (s.len < 3) { | 
|  | break; | 
|  | } | 
|  | c = wuffs_base__load_u24le__no_bounds_check(s.ptr); | 
|  | if ((c & 0xC0C000) != 0x808000) { | 
|  | break; | 
|  | } | 
|  | c = (0x00F000 & (c << 12)) | (0x000FC0 & (c >> 2)) | | 
|  | (0x00003F & (c >> 16)); | 
|  | if ((c <= 0x07FF) || ((0xD800 <= c) && (c <= 0xDFFF))) { | 
|  | break; | 
|  | } | 
|  | return wuffs_base__make_utf_8__next__output(c, 3); | 
|  |  | 
|  | case 3: | 
|  | if (s.len < 4) { | 
|  | break; | 
|  | } | 
|  | c = wuffs_base__load_u32le__no_bounds_check(s.ptr); | 
|  | if ((c & 0xC0C0C000) != 0x80808000) { | 
|  | break; | 
|  | } | 
|  | c = (0x1C0000 & (c << 18)) | (0x03F000 & (c << 4)) | | 
|  | (0x000FC0 & (c >> 10)) | (0x00003F & (c >> 24)); | 
|  | if ((c <= 0xFFFF) || (0x110000 <= c)) { | 
|  | break; | 
|  | } | 
|  | return wuffs_base__make_utf_8__next__output(c, 4); | 
|  | } | 
|  |  | 
|  | return wuffs_base__make_utf_8__next__output( | 
|  | WUFFS_BASE__UNICODE_REPLACEMENT_CHARACTER, 1); | 
|  | } | 
|  |  | 
|  | size_t  // | 
|  | wuffs_base__utf_8__longest_valid_prefix(wuffs_base__slice_u8 s) { | 
|  | // TODO: possibly optimize the all-ASCII case (4 or 8 bytes at a time). | 
|  | // | 
|  | // TODO: possibly optimize this by manually inlining the | 
|  | // wuffs_base__utf_8__next calls. | 
|  | size_t original_len = s.len; | 
|  | while (s.len > 0) { | 
|  | wuffs_base__utf_8__next__output o = wuffs_base__utf_8__next(s); | 
|  | if ((o.code_point > 0x7F) && (o.byte_length == 1)) { | 
|  | break; | 
|  | } | 
|  | s.ptr += o.byte_length; | 
|  | s.len -= o.byte_length; | 
|  | } | 
|  | return original_len - s.len; | 
|  | } | 
|  |  | 
|  | size_t  // | 
|  | wuffs_base__ascii__longest_valid_prefix(wuffs_base__slice_u8 s) { | 
|  | // TODO: possibly optimize this by checking 4 or 8 bytes at a time. | 
|  | uint8_t* original_ptr = s.ptr; | 
|  | uint8_t* p = s.ptr; | 
|  | uint8_t* q = s.ptr + s.len; | 
|  | for (; (p != q) && ((*p & 0x80) == 0); p++) { | 
|  | } | 
|  | return (size_t)(p - original_ptr); | 
|  | } |