parse_number() * * Parse a double. */
| 780 | * Parse a double. |
| 781 | */ |
| 782 | Json parse_number() { |
| 783 | size_t start_pos = i; |
| 784 | |
| 785 | if (str[i] == '-') |
| 786 | i++; |
| 787 | |
| 788 | // Integer part |
| 789 | if (str[i] == '0') { |
| 790 | i++; |
| 791 | if (in_range(str[i], '0', '9')) |
| 792 | return fail("leading 0s not permitted in numbers"); |
| 793 | } else if (in_range(str[i], '1', '9')) { |
| 794 | i++; |
| 795 | while (in_range(str[i], '0', '9')) |
| 796 | i++; |
| 797 | } else { |
| 798 | return fail("invalid " + esc(str[i]) + " in number"); |
| 799 | } |
| 800 | |
| 801 | if (str[i] != '.' && str[i] != 'e' && str[i] != 'E' |
| 802 | && (i - start_pos) <= static_cast<size_t>(std::numeric_limits<int>::digits10)) { |
| 803 | return std::atoi(str.c_str() + start_pos); |
| 804 | } |
| 805 | |
| 806 | // Decimal part |
| 807 | if (str[i] == '.') { |
| 808 | i++; |
| 809 | if (!in_range(str[i], '0', '9')) |
| 810 | return fail("at least one digit required in fractional part"); |
| 811 | |
| 812 | while (in_range(str[i], '0', '9')) |
| 813 | i++; |
| 814 | } |
| 815 | |
| 816 | // Exponent part |
| 817 | if (str[i] == 'e' || str[i] == 'E') { |
| 818 | i++; |
| 819 | |
| 820 | if (str[i] == '+' || str[i] == '-') |
| 821 | i++; |
| 822 | |
| 823 | if (!in_range(str[i], '0', '9')) |
| 824 | return fail("at least one digit required in exponent"); |
| 825 | |
| 826 | while (in_range(str[i], '0', '9')) |
| 827 | i++; |
| 828 | } |
| 829 | |
| 830 | return std::strtod(str.c_str() + start_pos, nullptr); |
| 831 | } |
| 832 | |
| 833 | /* expect(str, res) |
| 834 | * |