| ... | @@ -1699,7 +1699,7 @@ pub const ParseIntError = error{ | ... | @@ -1699,7 +1699,7 @@ pub const ParseIntError = error{ |
| 1699 | /// The result cannot fit in the type specified | 1699 | /// The result cannot fit in the type specified |
| 1700 | Overflow, | 1700 | Overflow, |
| 1701 | | 1701 | |
| 1702 | /// The input was empty or had a byte that was not a digit | 1702 | /// The input was empty or contained an invalid character |
| 1703 | InvalidCharacter, | 1703 | InvalidCharacter, |
| 1704 | }; | 1704 | }; |
| 1705 | | 1705 | |
| ... | @@ -1905,6 +1905,54 @@ test "parseUnsigned" { | ... | @@ -1905,6 +1905,54 @@ test "parseUnsigned" { |
| 1905 | try std.testing.expectError(error.InvalidCharacter, parseUnsigned(u8, "", 10)); | 1905 | try std.testing.expectError(error.InvalidCharacter, parseUnsigned(u8, "", 10)); |
| 1906 | } | 1906 | } |
| 1907 | | 1907 | |
| | 1908 | /// Parses a number like '2G', '2Gi', or '2GiB'. |
| | 1909 | pub fn parseIntSizeSuffix(buf: []const u8, radix: u8) ParseIntError!usize { |
| | 1910 | var without_B = buf; |
| | 1911 | if (mem.endsWith(u8, buf, "B")) without_B.len -= 1; |
| | 1912 | var without_i = without_B; |
| | 1913 | var base: usize = 1000; |
| | 1914 | if (mem.endsWith(u8, without_B, "i")) { |
| | 1915 | without_i.len -= 1; |
| | 1916 | base = 1024; |
| | 1917 | } |
| | 1918 | if (without_i.len == 0) return error.InvalidCharacter; |
| | 1919 | const orders_of_magnitude: usize = switch (without_i[without_i.len - 1]) { |
| | 1920 | 'k', 'K' => 1, |
| | 1921 | 'M' => 2, |
| | 1922 | 'G' => 3, |
| | 1923 | 'T' => 4, |
| | 1924 | 'P' => 5, |
| | 1925 | 'E' => 6, |
| | 1926 | 'Z' => 7, |
| | 1927 | 'Y' => 8, |
| | 1928 | else => 0, |
| | 1929 | }; |
| | 1930 | var without_suffix = without_i; |
| | 1931 | if (orders_of_magnitude > 0) { |
| | 1932 | without_suffix.len -= 1; |
| | 1933 | } else if (without_i.len != without_B.len) { |
| | 1934 | return error.InvalidCharacter; |
| | 1935 | } |
| | 1936 | const multiplier = math.powi(usize, base, orders_of_magnitude) catch |err| switch (err) { |
| | 1937 | error.Underflow => unreachable, |
| | 1938 | error.Overflow => return error.Overflow, |
| | 1939 | }; |
| | 1940 | const number = try std.fmt.parseInt(usize, without_suffix, radix); |
| | 1941 | return math.mul(usize, number, multiplier); |
| | 1942 | } |
| | 1943 | |
| | 1944 | test "parseIntSizeSuffix" { |
| | 1945 | try std.testing.expect(try parseIntSizeSuffix("2", 10) == 2); |
| | 1946 | try std.testing.expect(try parseIntSizeSuffix("2B", 10) == 2); |
| | 1947 | try std.testing.expect(try parseIntSizeSuffix("2kB", 10) == 2000); |
| | 1948 | try std.testing.expect(try parseIntSizeSuffix("2k", 10) == 2000); |
| | 1949 | try std.testing.expect(try parseIntSizeSuffix("2KiB", 10) == 2048); |
| | 1950 | try std.testing.expect(try parseIntSizeSuffix("2Ki", 10) == 2048); |
| | 1951 | try std.testing.expect(try parseIntSizeSuffix("aKiB", 16) == 10240); |
| | 1952 | try std.testing.expect(parseIntSizeSuffix("", 10) == error.InvalidCharacter); |
| | 1953 | try std.testing.expect(parseIntSizeSuffix("2iB", 10) == error.InvalidCharacter); |
| | 1954 | } |
| | 1955 | |
| 1908 | pub const parseFloat = @import("fmt/parse_float.zig").parseFloat; | 1956 | pub const parseFloat = @import("fmt/parse_float.zig").parseFloat; |
| 1909 | pub const ParseFloatError = @import("fmt/parse_float.zig").ParseFloatError; | 1957 | pub const ParseFloatError = @import("fmt/parse_float.zig").ParseFloatError; |
| 1910 | | 1958 | |