| author | |
| committer | |
| log | 772636ed0d4a2051955197999c9ddf2906384806 |
| tree | ad6779833aa096513c83f20e846993f745cafa1d |
| parent | a4cffd80bdc9bf879d1048b52aeba5716723803d |
| signature |
This is consistent with `JSON.parse("-0")` in JavaScript, RFC 8259
doesn't specifically mention what to do in this case.
If a negative zero is encoded the intention is likely to preserve the
sign.3 files changed, 26 insertions(+), 1 deletions(-)
lib/std/json/dynamic_test.zig+11| ... | @@ -339,6 +339,17 @@ test "many object keys" { | ... | @@ -339,6 +339,17 @@ test "many object keys" { |
| 339 | try testing.expectEqualStrings("v5", parsed.value.object.get("k5").?.string); | 339 | try testing.expectEqualStrings("v5", parsed.value.object.get("k5").?.string); |
| 340 | } | 340 | } |
| 341 | 341 | ||
| 342 | test "negative zero" { | ||
| 343 | const doc = "-0"; | ||
| 344 | var fbs = std.io.fixedBufferStream(doc); | ||
| 345 | var reader = smallBufferJsonReader(testing.allocator, fbs.reader()); | ||
| 346 | defer reader.deinit(); | ||
| 347 | var parsed = try parseFromTokenSource(Value, testing.allocator, &reader, .{}); | ||
| 348 | defer parsed.deinit(); | ||
| 349 | |||
| 350 | try testing.expect(parsed.value.float == 0 and std.math.signbit(parsed.value.float)); | ||
| 351 | } | ||
| 352 | |||
| 342 | fn smallBufferJsonReader(allocator: Allocator, io_reader: anytype) JsonReader(16, @TypeOf(io_reader)) { | 353 | fn smallBufferJsonReader(allocator: Allocator, io_reader: anytype) JsonReader(16, @TypeOf(io_reader)) { |
| 343 | return JsonReader(16, @TypeOf(io_reader)).init(allocator, io_reader); | 354 | return JsonReader(16, @TypeOf(io_reader)).init(allocator, io_reader); |
| 344 | } | 355 | } |
lib/std/json/scanner.zig+2-1| ... | @@ -1700,11 +1700,12 @@ fn appendSlice(list: *std.ArrayList(u8), buf: []const u8, max_value_len: usize) | ... | @@ -1700,11 +1700,12 @@ fn appendSlice(list: *std.ArrayList(u8), buf: []const u8, max_value_len: usize) |
| 1700 | } | 1700 | } |
| 1701 | 1701 | ||
| 1702 | /// For the slice you get from a `Token.number` or `Token.allocated_number`, | 1702 | /// For the slice you get from a `Token.number` or `Token.allocated_number`, |
| 1703 | /// this function returns true if the number doesn't contain any fraction or exponent components. | 1703 | /// this function returns true if the number doesn't contain any fraction or exponent components, and is not `-0`. |
| 1704 | /// Note, the numeric value encoded by the value may still be an integer, such as `1.0`. | 1704 | /// Note, the numeric value encoded by the value may still be an integer, such as `1.0`. |
| 1705 | /// This function is meant to give a hint about whether integer parsing or float parsing should be used on the value. | 1705 | /// This function is meant to give a hint about whether integer parsing or float parsing should be used on the value. |
| 1706 | /// This function will not give meaningful results on non-numeric input. | 1706 | /// This function will not give meaningful results on non-numeric input. |
| 1707 | pub fn isNumberFormattedLikeAnInteger(value: []const u8) bool { | 1707 | pub fn isNumberFormattedLikeAnInteger(value: []const u8) bool { |
| 1708 | if (std.mem.eql(u8, value, "-0")) return false; | ||
| 1708 | return std.mem.indexOfAny(u8, value, ".eE") == null; | 1709 | return std.mem.indexOfAny(u8, value, ".eE") == null; |
| 1709 | } | 1710 | } |
| 1710 | 1711 |
lib/std/json/scanner_test.zig+13| ... | @@ -7,6 +7,7 @@ const TokenType = @import("./scanner.zig").TokenType; | ... | @@ -7,6 +7,7 @@ const TokenType = @import("./scanner.zig").TokenType; |
| 7 | const Diagnostics = @import("./scanner.zig").Diagnostics; | 7 | const Diagnostics = @import("./scanner.zig").Diagnostics; |
| 8 | const Error = @import("./scanner.zig").Error; | 8 | const Error = @import("./scanner.zig").Error; |
| 9 | const validate = @import("./scanner.zig").validate; | 9 | const validate = @import("./scanner.zig").validate; |
| 10 | const isNumberFormattedLikeAnInteger = @import("./scanner.zig").isNumberFormattedLikeAnInteger; | ||
| 10 | 11 | ||
| 11 | const example_document_str = | 12 | const example_document_str = |
| 12 | \\{ | 13 | \\{ |
| ... | @@ -465,3 +466,15 @@ test "enableDiagnostics" { | ... | @@ -465,3 +466,15 @@ test "enableDiagnostics" { |
| 465 | try testDiagnostics(error.SyntaxError, 1, s.len, s.len - 1, s); | 466 | try testDiagnostics(error.SyntaxError, 1, s.len, s.len - 1, s); |
| 466 | } | 467 | } |
| 467 | } | 468 | } |
| 469 | |||
| 470 | test isNumberFormattedLikeAnInteger { | ||
| 471 | try std.testing.expect(isNumberFormattedLikeAnInteger("0")); | ||
| 472 | try std.testing.expect(isNumberFormattedLikeAnInteger("1")); | ||
| 473 | try std.testing.expect(isNumberFormattedLikeAnInteger("123")); | ||
| 474 | try std.testing.expect(!isNumberFormattedLikeAnInteger("-0")); | ||
| 475 | try std.testing.expect(!isNumberFormattedLikeAnInteger("0.0")); | ||
| 476 | try std.testing.expect(!isNumberFormattedLikeAnInteger("1.0")); | ||
| 477 | try std.testing.expect(!isNumberFormattedLikeAnInteger("1.23")); | ||
| 478 | try std.testing.expect(!isNumberFormattedLikeAnInteger("1e10")); | ||
| 479 | try std.testing.expect(!isNumberFormattedLikeAnInteger("1E10")); | ||
| 480 | } |