Commit 18ad50970f
Changed files (2)
std
std/fmt/parse_float.zig
@@ -84,10 +84,6 @@ const Z96 = struct {
w += u64(d.d2) -% u64(s.d2);
d.d2 = @truncate(u32, w);
}
-
- fn dump(d: Z96) void {
- std.debug.warn("{} {} {}\n", d.d0, d.d1, d.d2);
- }
};
const FloatRepr = struct {
@@ -178,7 +174,6 @@ fn convertRepr(comptime T: type, n: FloatRepr) T {
}
const State = enum {
- SkipLeadingWhitespace,
MaybeSign,
LeadingMantissaZeros,
LeadingFractionalZeros,
@@ -187,7 +182,6 @@ const State = enum {
ExponentSign,
LeadingExponentZeros,
Exponent,
- Stop,
};
const ParseResult = enum {
@@ -206,27 +200,19 @@ inline fn isSpace(c: u8) bool {
return (c >= 0x09 and c <= 0x13) or c == 0x20;
}
-fn parseRepr(s: []const u8, n: *FloatRepr) ParseResult {
+fn parseRepr(s: []const u8, n: *FloatRepr) !ParseResult {
var digit_index: usize = 0;
var negative = false;
var negative_exp = false;
var exponent: i32 = 0;
- var state = State.SkipLeadingWhitespace;
+ var state = State.MaybeSign;
var i: usize = 0;
- loop: while (state != State.Stop and i < s.len) {
+ loop: while (i < s.len) {
const c = s[i];
switch (state) {
- State.SkipLeadingWhitespace => {
- if (isSpace(c)) {
- i += 1;
- } else {
- state = State.MaybeSign;
- }
- },
-
State.MaybeSign => {
state = State.LeadingMantissaZeros;
@@ -238,7 +224,7 @@ fn parseRepr(s: []const u8, n: *FloatRepr) ParseResult {
} else if (isDigit(c) or c == '.') {
// continue
} else {
- state = State.Stop;
+ return error.InvalidCharacter;
}
},
@@ -329,11 +315,9 @@ fn parseRepr(s: []const u8, n: *FloatRepr) ParseResult {
i += 1;
} else {
- state = State.Stop;
+ return error.InvalidCharacter;
}
},
-
- State.Stop => break :loop,
}
}
@@ -371,12 +355,10 @@ fn caseInEql(a: []const u8, b: []const u8) bool {
return true;
}
-pub fn parseFloat(comptime T: type, s: []const u8) T {
- var r = FloatRepr{
- .negative = false,
- .exponent = 0,
- .mantissa = 0,
- };
+pub fn parseFloat(comptime T: type, s: []const u8) !T {
+ if (s.len == 0) {
+ return error.InvalidCharacter;
+ }
if (caseInEql(s, "nan")) {
return std.math.nan(T);
@@ -386,7 +368,13 @@ pub fn parseFloat(comptime T: type, s: []const u8) T {
return -std.math.inf(T);
}
- return switch (parseRepr(s, &r)) {
+ var r = FloatRepr{
+ .negative = false,
+ .exponent = 0,
+ .mantissa = 0,
+ };
+
+ return switch (try parseRepr(s, &r)) {
ParseResult.Ok => convertRepr(T, r),
ParseResult.PlusZero => 0.0,
ParseResult.MinusZero => -T(0.0),
@@ -396,30 +384,37 @@ pub fn parseFloat(comptime T: type, s: []const u8) T {
}
test "fmt.parseFloat" {
- const assert = std.debug.assert;
+ const testing = std.testing;
+ const expect = testing.expect;
+ const expectEqual = testing.expectEqual;
const approxEq = std.math.approxEq;
const epsilon = 1e-7;
- inline for ([]type{ f32, f64, f128 }) |T| {
+ inline for ([]type{ f16, f32, f64, f128 }) |T| {
const Z = @IntType(false, T.bit_count);
- assert(parseFloat(T, "0") == 0.0);
- assert(parseFloat(T, "+0") == 0.0);
- assert(parseFloat(T, "-0") == 0.0);
+ testing.expectError(error.InvalidCharacter, parseFloat(T, ""));
+ testing.expectError(error.InvalidCharacter, parseFloat(T, " 1"));
+ testing.expectError(error.InvalidCharacter, parseFloat(T, "1abc"));
+
+ expectEqual(try parseFloat(T, "0"), 0.0);
+ expectEqual((try parseFloat(T, "0")), 0.0);
+ expectEqual((try parseFloat(T, "+0")), 0.0);
+ expectEqual((try parseFloat(T, "-0")), 0.0);
- assert(approxEq(T, parseFloat(T, "3.141"), 3.141, epsilon));
- assert(approxEq(T, parseFloat(T, "-3.141"), -3.141, epsilon));
+ expect(approxEq(T, try parseFloat(T, "3.141"), 3.141, epsilon));
+ expect(approxEq(T, try parseFloat(T, "-3.141"), -3.141, epsilon));
- assert(parseFloat(T, "1e-700") == 0);
- assert(parseFloat(T, "1e+700") == std.math.inf(T));
+ expectEqual((try parseFloat(T, "1e-700")), 0);
+ expectEqual((try parseFloat(T, "1e+700")), std.math.inf(T));
- assert(@bitCast(Z, parseFloat(T, "nAn")) == @bitCast(Z, std.math.nan(T)));
- assert(parseFloat(T, "inF") == std.math.inf(T));
- assert(parseFloat(T, "-INF") == -std.math.inf(T));
+ expectEqual(@bitCast(Z, try parseFloat(T, "nAn")), @bitCast(Z, std.math.nan(T)));
+ expectEqual((try parseFloat(T, "inF")), std.math.inf(T));
+ expectEqual((try parseFloat(T, "-INF")), -std.math.inf(T));
if (T != f16) {
- assert(approxEq(T, parseFloat(T, "123142.1"), 123142.1, epsilon));
- assert(approxEq(T, parseFloat(T, "-123142.1124"), T(-123142.1124), epsilon));
+ expect(approxEq(T, try parseFloat(T, "123142.1"), 123142.1, epsilon));
+ expect(approxEq(T, try parseFloat(T, "-123142.1124"), T(-123142.1124), epsilon));
}
}
}
std/json.zig
@@ -1345,7 +1345,7 @@ pub const Parser = struct {
return if (token.number_is_integer)
Value{ .Integer = try std.fmt.parseInt(i64, token.slice(input, i), 10) }
else
- Value{ .Float = std.fmt.parseFloat(f64, token.slice(input, i)) };
+ Value{ .Float = try std.fmt.parseFloat(f64, token.slice(input, i)) };
}
};