11// JsonhCpp (JSON for Humans)
2- // Version: 4.8
2+ // Version: 4.10
33// Link: https://github.com/jsonh-org/JsonhCpp
44// License: MIT
55
@@ -29460,7 +29460,7 @@ class jsonh_number_parser final {
2946029460 else {
2946129461 exponent_index = digits.find_first_of("eE");
2946229462 }
29463- // If no exponent then normalize real
29463+ // If no exponent then parse real
2946429464 if (exponent_index == std::string::npos) {
2946529465 return parse_fractional_number(digits, base_digits);
2946629466 }
@@ -29493,7 +29493,7 @@ class jsonh_number_parser final {
2949329493
2949429494 // Find dot
2949529495 size_t dot_index = digits.find('.');
29496- // If no dot then normalize integer
29496+ // If no dot then parse integer
2949729497 if (dot_index == std::string::npos) {
2949829498 nonstd::expected<long long, std::string> integer = parse_whole_number(digits, base_digits);
2949929499 if (!integer) {
@@ -30677,7 +30677,7 @@ class jsonh_reader : utf8_reader {
3067730677 }
3067830678 bool detect_quoteless_string(std::string& whitespace_builder) {
3067930679 while (true) {
30680- // Read rune
30680+ // Peek rune
3068130681 std::optional<std::string> next = peek();
3068230682 if (!next) {
3068330683 break;
@@ -30703,26 +30703,6 @@ class jsonh_reader : utf8_reader {
3070330703 std::optional<std::string> next_char = peek();
3070430704 return next_char && (next_char.value() == "\\" || !reserved_runes.contains(next_char.value()));
3070530705 }
30706- nonstd::expected<jsonh_token, std::string> read_number_or_quoteless_string() noexcept {
30707- // Read number
30708- std::string number_builder;
30709- nonstd::expected<jsonh_token, std::string> number = read_number(number_builder);
30710- if (number) {
30711- // Try read quoteless string starting with number
30712- std::string whitespace_chars;
30713- if (detect_quoteless_string(whitespace_chars)) {
30714- return read_quoteless_string(number.value().value + whitespace_chars);
30715- }
30716- // Otherwise, accept number
30717- else {
30718- return number;
30719- }
30720- }
30721- // Read quoteless string starting with malformed number
30722- else {
30723- return read_quoteless_string(number_builder);
30724- }
30725- }
3072630706 nonstd::expected<jsonh_token, std::string> read_number(std::string& number_builder) noexcept {
3072730707 // Read sign
3072830708 std::optional<std::string> sign = read_any({ "-", "+" });
@@ -30810,6 +30790,7 @@ class jsonh_reader : utf8_reader {
3081030790 }
3081130791
3081230792 bool is_fraction = false;
30793+ bool is_empty = true;
3081330794
3081430795 while (true) {
3081530796 // Peek rune
@@ -30822,11 +30803,13 @@ class jsonh_reader : utf8_reader {
3082230803 if (base_digits.find(to_ascii_lower(next.value().data())) != std::string::npos) {
3082330804 read();
3082430805 number_builder += next.value();
30806+ is_empty = false;
3082530807 }
3082630808 // Dot
3082730809 else if (next.value() == ".") {
3082830810 read();
3082930811 number_builder += next.value();
30812+ is_empty = false;
3083030813
3083130814 // Duplicate dot
3083230815 if (is_fraction) {
@@ -30838,6 +30821,7 @@ class jsonh_reader : utf8_reader {
3083830821 else if (next.value() == "_") {
3083930822 read();
3084030823 number_builder += next.value();
30824+ is_empty = false;
3084130825 }
3084230826 // Other
3084330827 else {
@@ -30846,7 +30830,7 @@ class jsonh_reader : utf8_reader {
3084630830 }
3084730831
3084830832 // Ensure not empty
30849- if (number_builder.empty() ) {
30833+ if (is_empty ) {
3085030834 return nonstd::unexpected<std::string>("Empty number");
3085130835 }
3085230836
@@ -30863,6 +30847,26 @@ class jsonh_reader : utf8_reader {
3086330847 // End of number
3086430848 return nonstd::expected<void, std::string>(); // Success
3086530849 }
30850+ nonstd::expected<jsonh_token, std::string> read_number_or_quoteless_string() noexcept {
30851+ // Read number
30852+ std::string number_builder;
30853+ nonstd::expected<jsonh_token, std::string> number = read_number(number_builder);
30854+ if (number) {
30855+ // Try read quoteless string starting with number
30856+ std::string whitespace_chars;
30857+ if (detect_quoteless_string(whitespace_chars)) {
30858+ return read_quoteless_string(number.value().value + whitespace_chars);
30859+ }
30860+ // Otherwise, accept number
30861+ else {
30862+ return number;
30863+ }
30864+ }
30865+ // Read quoteless string starting with malformed number
30866+ else {
30867+ return read_quoteless_string(number_builder);
30868+ }
30869+ }
3086630870 nonstd::expected<jsonh_token, std::string> read_primitive_element() noexcept {
3086730871 // Peek rune
3086830872 std::optional<std::string> next = peek();
@@ -30871,7 +30875,7 @@ class jsonh_reader : utf8_reader {
3087130875 }
3087230876
3087330877 // Number
30874- if (( next.value() >= "0" && next.value() <= "9") || (next.value() == "-" || next.value() == "+") || next.value() == ".") {
30878+ if (next && (( next.value() >= "0" && next.value() <= "9") || (next.value() == "-" || next.value() == "+") || next.value() == ".") ) {
3087530879 return read_number_or_quoteless_string();
3087630880 }
3087730881 // String
@@ -31067,6 +31071,8 @@ class jsonh_reader : utf8_reader {
3106731071 }
3106831072 }
3106931073 nonstd::expected<std::string, std::string> read_hex_escape_sequence(size_t length) noexcept {
31074+ // This method is used to combine escaped UTF-16 surrogate pairs (e.g. "\uD83D\uDC7D" -> "👽")
31075+
3107031076 // Read hex digits & convert to uint
3107131077 nonstd::expected<unsigned int, std::string> code_point = read_hex_sequence(length);
3107231078 if (!code_point) {
0 commit comments