diff options
| -rw-r--r-- | std/fmt/index.zig | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/std/fmt/index.zig b/std/fmt/index.zig index 43e758038f..e26b2f6c8b 100644 --- a/std/fmt/index.zig +++ b/std/fmt/index.zig @@ -27,6 +27,8 @@ pub fn format(context: var, comptime Errors: type, output: fn(@typeOf(context), Character, Buf, BufWidth, + Bytes, + BytesWidth, }; comptime var start_index = 0; @@ -95,6 +97,10 @@ pub fn format(context: var, comptime Errors: type, output: fn(@typeOf(context), '.' => { state = State.Float; }, + 'B' => { + width = 0; + state = State.Bytes; + }, else => @compileError("Unknown format character: " ++ []u8{c}), }, State.Buf => switch (c) { @@ -206,6 +212,30 @@ pub fn format(context: var, comptime Errors: type, output: fn(@typeOf(context), }, else => @compileError("Unexpected character in format string: " ++ []u8{c}), }, + State.Bytes => switch (c) { + '}' => { + try formatBytes(args[next_arg], 0, context, Errors, output); + next_arg += 1; + state = State.Start; + start_index = i + 1; + }, + '0' ... '9' => { + width_start = i; + state = State.BytesWidth; + }, + else => @compileError("Unexpected character in format string: " ++ []u8{c}), + }, + State.BytesWidth => switch (c) { + '}' => { + width = comptime (parseUnsigned(usize, fmt[width_start..i], 10) catch unreachable); + try formatBytes(args[next_arg], width, context, Errors, output); + next_arg += 1; + state = State.Start; + start_index = i + 1; + }, + '0' ... '9' => {}, + else => @compileError("Unexpected character in format string: " ++ []u8{c}), + }, } } comptime { @@ -520,6 +550,25 @@ pub fn formatFloatDecimal(value: var, maybe_precision: ?usize, context: var, com } } +pub fn formatBytes(value: var, width: ?usize, + context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8)Errors!void) Errors!void +{ + if (value == 0) { + return output(context, "0B"); + } + + const mags = " KMGTPEZY"; + const magnitude = math.min(math.log2(value) / 10, mags.len - 1); + const new_value = f64(value) / math.pow(f64, 1024, f64(magnitude)); + const suffix = mags[magnitude]; + + try formatFloatDecimal(new_value, width, context, Errors, output); + + if (suffix != ' ') { + try output(context, (&suffix)[0..1]); + } + return output(context, "B"); +} pub fn formatInt(value: var, base: u8, uppercase: bool, width: usize, context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8)Errors!void) Errors!void @@ -768,6 +817,12 @@ test "fmt.format" { assert(mem.eql(u8, result, "u3: 5\n")); } { + var buf1: [32]u8 = undefined; + const value: usize = 63 * 1024 * 1024; + const result = try bufPrint(buf1[0..], "file size: {B}\n", value); + assert(mem.eql(u8, result, "file size: 63MB\n")); + } + { // Dummy field because of https://github.com/zig-lang/zig/issues/557. const Struct = struct { unused: u8, |
