| 818 | } |
| 819 | |
| 820 | bool ParseDecimalComponents(const char* s, size_t size, DecimalComponents* out) { |
| 821 | size_t pos = 0; |
| 822 | |
| 823 | if (size == 0) { |
| 824 | return false; |
| 825 | } |
| 826 | // Sign of the number |
| 827 | if (IsSign(s[pos])) { |
| 828 | out->sign = *(s + pos); |
| 829 | ++pos; |
| 830 | } |
| 831 | // First run of digits |
| 832 | pos = ParseDigitsRun(s, pos, size, &out->whole_digits); |
| 833 | if (pos == size) { |
| 834 | return !out->whole_digits.empty(); |
| 835 | } |
| 836 | // Optional dot (if given in fractional form) |
| 837 | bool has_dot = IsDot(s[pos]); |
| 838 | if (has_dot) { |
| 839 | // Second run of digits |
| 840 | ++pos; |
| 841 | pos = ParseDigitsRun(s, pos, size, &out->fractional_digits); |
| 842 | } |
| 843 | if (out->whole_digits.empty() && out->fractional_digits.empty()) { |
| 844 | // Need at least some digits (whole or fractional) |
| 845 | return false; |
| 846 | } |
| 847 | if (pos == size) { |
| 848 | return true; |
| 849 | } |
| 850 | // Optional exponent |
| 851 | if (StartsExponent(s[pos])) { |
| 852 | ++pos; |
| 853 | if (pos != size && s[pos] == '+') { |
| 854 | ++pos; |
| 855 | } |
| 856 | out->has_exponent = true; |
| 857 | return internal::ParseValue<Int32Type>(s + pos, size - pos, &(out->exponent)); |
| 858 | } |
| 859 | return pos == size; |
| 860 | } |
| 861 | |
| 862 | template <typename Decimal> |
| 863 | Status DecimalFromString(const char* type_name, std::string_view s, Decimal* out, |
no test coverage detected