authorgravatar for yujiri@disroot.orgEvin Yulo <yujiri@disroot.org> 2023-03-17 00:36:26-04:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2023-05-10 16:31:51+03:00
log6d7bb255a45ab89e08ab1981b48898ae7e6bef88
tree7cfb681a259a5759102718ea904f784b6424554d
parentc4dbfd5ae17ac7ca4dc267bf769134febe55e77e

Add std.fmt.parseIntSizeSuffix and use for --maxrss

Fixes #14955

2 files changed, 50 insertions(+), 3 deletions(-)

lib/build_runner.zig+1-2
...@@ -151,8 +151,7 @@ pub fn main() !void {...@@ -151,8 +151,7 @@ pub fn main() !void {
151 std.debug.print("Expected argument after {s}\n\n", .{arg});151 std.debug.print("Expected argument after {s}\n\n", .{arg});
152 usageAndErr(builder, false, stderr_stream);152 usageAndErr(builder, false, stderr_stream);
153 };153 };
154 // TODO: support shorthand such as "2GiB", "2GB", or "2G"154 max_rss = std.fmt.parseIntSizeSuffix(max_rss_text, 10) catch |err| {
155 max_rss = std.fmt.parseInt(usize, max_rss_text, 10) catch |err| {
156 std.debug.print("invalid byte size: '{s}': {s}\n", .{155 std.debug.print("invalid byte size: '{s}': {s}\n", .{
157 max_rss_text, @errorName(err),156 max_rss_text, @errorName(err),
158 });157 });
lib/std/fmt.zig+49-1
...@@ -1699,7 +1699,7 @@ pub const ParseIntError = error{...@@ -1699,7 +1699,7 @@ pub const ParseIntError = error{
1699 /// The result cannot fit in the type specified1699 /// The result cannot fit in the type specified
1700 Overflow,1700 Overflow,
17011701
1702 /// The input was empty or had a byte that was not a digit1702 /// The input was empty or contained an invalid character
1703 InvalidCharacter,1703 InvalidCharacter,
1704};1704};
17051705
...@@ -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}
19071907
1908/// Parses a number like '2G', '2Gi', or '2GiB'.
1909pub 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
1944test "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
1908pub const parseFloat = @import("fmt/parse_float.zig").parseFloat;1956pub const parseFloat = @import("fmt/parse_float.zig").parseFloat;
1909pub const ParseFloatError = @import("fmt/parse_float.zig").ParseFloatError;1957pub const ParseFloatError = @import("fmt/parse_float.zig").ParseFloatError;
19101958