From c11d1055b868add74cc58f3bf745e93110ae6071 Mon Sep 17 00:00:00 2001 From: Benjamin Feng Date: Sat, 29 Feb 2020 15:35:18 -0600 Subject: Integrated outstreams with new formatter --- lib/std/math/big/int.zig | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'lib/std/math/big') diff --git a/lib/std/math/big/int.zig b/lib/std/math/big/int.zig index 8fda3f647a..cef2bae98c 100644 --- a/lib/std/math/big/int.zig +++ b/lib/std/math/big/int.zig @@ -518,17 +518,15 @@ pub const Int = struct { pub fn format( self: Int, comptime fmt: []const u8, - options: std.fmt.FormatOptions, - context: var, - comptime FmtError: type, - output: fn (@TypeOf(context), []const u8) FmtError!void, + options: std.fmtstream.FormatOptions, + out_stream: var, ) FmtError!void { self.assertWritable(); // TODO look at fmt and support other bases // TODO support read-only fixed integers const str = self.toString(self.allocator.?, 10) catch @panic("TODO make this non allocating"); defer self.allocator.?.free(str); - return output(context, str); + return out_stream.print(str); } /// Returns -1, 0, 1 if |a| < |b|, |a| == |b| or |a| > |b| respectively. -- cgit v1.2.3 From 4aae55b4ccf44fa3c2c2a81a6a34f3c898dece30 Mon Sep 17 00:00:00 2001 From: Benjamin Feng Date: Fri, 6 Mar 2020 16:59:21 -0600 Subject: Replace fmt with new fmtstream --- lib/std/atomic/queue.zig | 4 +- lib/std/buffer.zig | 4 +- lib/std/builtin.zig | 14 +- lib/std/fmt.zig | 519 ++++----- lib/std/fmtstream.zig | 1685 ---------------------------- lib/std/http/headers.zig | 4 +- lib/std/io/out_stream.zig | 2 +- lib/std/json.zig | 10 +- lib/std/math/big/int.zig | 2 +- lib/std/net.zig | 14 +- lib/std/net/test.zig | 4 +- lib/std/os.zig | 2 +- lib/std/os/uefi.zig | 4 +- lib/std/progress.zig | 6 +- lib/std/special/build_runner.zig | 6 +- lib/std/std.zig | 1 - lib/std/target.zig | 4 +- lib/std/zig/cross_target.zig | 2 +- lib/std/zig/system.zig | 6 +- src-self-hosted/compilation.zig | 6 +- src-self-hosted/dep_tokenizer.zig | 6 +- src-self-hosted/libc_installation.zig | 2 +- src-self-hosted/link.zig | 20 +- src-self-hosted/print_targets.zig | 2 +- src-self-hosted/test.zig | 6 +- src-self-hosted/translate_c.zig | 44 +- src-self-hosted/type.zig | 8 +- test/src/compare_output.zig | 8 +- test/src/run_translated_c.zig | 4 +- test/src/translate_c.zig | 4 +- test/stage1/behavior/enum_with_members.zig | 6 +- test/tests.zig | 10 +- tools/process_headers.zig | 4 +- tools/update_glibc.zig | 4 +- 34 files changed, 336 insertions(+), 2091 deletions(-) delete mode 100644 lib/std/fmtstream.zig (limited to 'lib/std/math/big') diff --git a/lib/std/atomic/queue.zig b/lib/std/atomic/queue.zig index c308fa681f..1a0f39587e 100644 --- a/lib/std/atomic/queue.zig +++ b/lib/std/atomic/queue.zig @@ -348,7 +348,7 @@ test "std.atomic.Queue dump" { fbs.reset(); try queue.dumpToStream(fbs.outStream()); - var expected = try std.fmtstream.bufPrint(expected_buffer[0..], + var expected = try std.fmt.bufPrint(expected_buffer[0..], \\head: 0x{x}=1 \\ (null) \\tail: 0x{x}=1 @@ -368,7 +368,7 @@ test "std.atomic.Queue dump" { fbs.reset(); try queue.dumpToStream(fbs.outStream()); - expected = try std.fmtstream.bufPrint(expected_buffer[0..], + expected = try std.fmt.bufPrint(expected_buffer[0..], \\head: 0x{x}=1 \\ 0x{x}=2 \\ (null) diff --git a/lib/std/buffer.zig b/lib/std/buffer.zig index 6d361bdb4a..cf028f104e 100644 --- a/lib/std/buffer.zig +++ b/lib/std/buffer.zig @@ -65,11 +65,11 @@ pub const Buffer = struct { } pub fn allocPrint(allocator: *Allocator, comptime format: []const u8, args: var) !Buffer { - const size = std.fmtstream.count(format, args) catch |err| switch (err) { + const size = std.fmt.count(format, args) catch |err| switch (err) { error.Overflow => return error.OutOfMemory, }; var self = try Buffer.initSize(allocator, size); - assert((std.fmtstream.bufPrint(self.list.items, format, args) catch unreachable).len == size); + assert((std.fmt.bufPrint(self.list.items, format, args) catch unreachable).len == size); return self; } diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig index 5cac8c9622..c8cd6c05cf 100644 --- a/lib/std/builtin.zig +++ b/lib/std/builtin.zig @@ -426,27 +426,27 @@ pub const Version = struct { pub fn parse(text: []const u8) !Version { var it = std.mem.separate(text, "."); return Version{ - .major = try std.fmtstream.parseInt(u32, it.next() orelse return error.InvalidVersion, 10), - .minor = try std.fmtstream.parseInt(u32, it.next() orelse "0", 10), - .patch = try std.fmtstream.parseInt(u32, it.next() orelse "0", 10), + .major = try std.fmt.parseInt(u32, it.next() orelse return error.InvalidVersion, 10), + .minor = try std.fmt.parseInt(u32, it.next() orelse "0", 10), + .patch = try std.fmt.parseInt(u32, it.next() orelse "0", 10), }; } pub fn format( self: Version, comptime fmt: []const u8, - options: std.fmtstream.FormatOptions, + options: std.fmt.FormatOptions, out_stream: var, ) !void { if (fmt.len == 0) { if (self.patch == 0) { if (self.minor == 0) { - return std.fmtstream.format(out_stream, "{}", .{self.major}); + return std.fmt.format(out_stream, "{}", .{self.major}); } else { - return std.fmtstream.format(out_stream, "{}.{}", .{ self.major, self.minor }); + return std.fmt.format(out_stream, "{}.{}", .{ self.major, self.minor }); } } else { - return std.fmtstream.format(out_stream, "{}.{}.{}", .{ self.major, self.minor, self.patch }); + return std.fmt.format(out_stream, "{}.{}.{}", .{ self.major, self.minor, self.patch }); } } else { @compileError("Unknown format string: '" ++ fmt ++ "'"); diff --git a/lib/std/fmt.zig b/lib/std/fmt.zig index a7525ba795..5173015b38 100644 --- a/lib/std/fmt.zig +++ b/lib/std/fmt.zig @@ -69,19 +69,17 @@ fn peekIsAlign(comptime fmt: []const u8) bool { /// /// If a formatted user type contains a function of the type /// ``` -/// fn format(value: ?, comptime fmt: []const u8, options: std.fmt.FormatOptions, context: var, comptime Errors: type, comptime output: fn (@TypeOf(context), []const u8) Errors!void) Errors!void +/// fn format(value: ?, comptime fmt: []const u8, options: std.fmt.FormatOptions, out_stream: var) !void /// ``` /// with `?` being the type formatted, this function will be called instead of the default implementation. /// This allows user types to be formatted in a logical manner instead of dumping all fields of the type. /// /// A user type may be a `struct`, `vector`, `union` or `enum` type. pub fn format( - context: var, - comptime Errors: type, - comptime output: fn (@TypeOf(context), []const u8) Errors!void, + out_stream: var, comptime fmt: []const u8, args: var, -) Errors!void { +) !void { const ArgSetType = u32; if (@typeInfo(@TypeOf(args)) != .Struct) { @compileError("Expected tuple or struct argument, found " ++ @typeName(@TypeOf(args))); @@ -138,7 +136,7 @@ pub fn format( .Start => switch (c) { '{' => { if (start_index < i) { - try output(context, fmt[start_index..i]); + try out_stream.writeAll(fmt[start_index..i]); } start_index = i; @@ -150,7 +148,7 @@ pub fn format( }, '}' => { if (start_index < i) { - try output(context, fmt[start_index..i]); + try out_stream.writeAll(fmt[start_index..i]); } state = .CloseBrace; }, @@ -185,9 +183,7 @@ pub fn format( args[arg_to_print], fmt[0..0], options, - context, - Errors, - output, + out_stream, default_max_depth, ); @@ -218,9 +214,7 @@ pub fn format( args[arg_to_print], fmt[specifier_start..i], options, - context, - Errors, - output, + out_stream, default_max_depth, ); state = .Start; @@ -265,9 +259,7 @@ pub fn format( args[arg_to_print], fmt[specifier_start..specifier_end], options, - context, - Errors, - output, + out_stream, default_max_depth, ); state = .Start; @@ -293,9 +285,7 @@ pub fn format( args[arg_to_print], fmt[specifier_start..specifier_end], options, - context, - Errors, - output, + out_stream, default_max_depth, ); state = .Start; @@ -316,7 +306,7 @@ pub fn format( } } if (start_index < fmt.len) { - try output(context, fmt[start_index..]); + try out_stream.writeAll(fmt[start_index..]); } } @@ -324,141 +314,131 @@ pub fn formatType( value: var, comptime fmt: []const u8, options: FormatOptions, - context: var, - comptime Errors: type, - comptime output: fn (@TypeOf(context), []const u8) Errors!void, + out_stream: var, max_depth: usize, -) Errors!void { +) @TypeOf(out_stream).Error!void { if (comptime std.mem.eql(u8, fmt, "*")) { - try output(context, @typeName(@TypeOf(value).Child)); - try output(context, "@"); - try formatInt(@ptrToInt(value), 16, false, FormatOptions{}, context, Errors, output); + try out_stream.writeAll(@typeName(@TypeOf(value).Child)); + try out_stream.writeAll("@"); + try formatInt(@ptrToInt(value), 16, false, FormatOptions{}, out_stream); return; } const T = @TypeOf(value); + if (comptime std.meta.trait.hasFn("format")(T)) { + return try value.format(fmt, options, out_stream); + } + switch (@typeInfo(T)) { .ComptimeInt, .Int, .Float => { - return formatValue(value, fmt, options, context, Errors, output); + return formatValue(value, fmt, options, out_stream); }, .Void => { - return output(context, "void"); + return out_stream.writeAll("void"); }, .Bool => { - return output(context, if (value) "true" else "false"); + return out_stream.writeAll(if (value) "true" else "false"); }, .Optional => { if (value) |payload| { - return formatType(payload, fmt, options, context, Errors, output, max_depth); + return formatType(payload, fmt, options, out_stream, max_depth); } else { - return output(context, "null"); + return out_stream.writeAll("null"); } }, .ErrorUnion => { if (value) |payload| { - return formatType(payload, fmt, options, context, Errors, output, max_depth); + return formatType(payload, fmt, options, out_stream, max_depth); } else |err| { - return formatType(err, fmt, options, context, Errors, output, max_depth); + return formatType(err, fmt, options, out_stream, max_depth); } }, .ErrorSet => { - try output(context, "error."); - return output(context, @errorName(value)); + try out_stream.writeAll("error."); + return out_stream.writeAll(@errorName(value)); }, .Enum => |enumInfo| { - if (comptime std.meta.trait.hasFn("format")(T)) { - return value.format(fmt, options, context, Errors, output); - } - - try output(context, @typeName(T)); + try out_stream.writeAll(@typeName(T)); if (enumInfo.is_exhaustive) { - try output(context, "."); - try output(context, @tagName(value)); + try out_stream.writeAll("."); + try out_stream.writeAll(@tagName(value)); } else { // TODO: when @tagName works on exhaustive enums print known enum strings - try output(context, "("); - try formatType(@enumToInt(value), fmt, options, context, Errors, output, max_depth); - try output(context, ")"); + try out_stream.writeAll("("); + try formatType(@enumToInt(value), fmt, options, out_stream, max_depth); + try out_stream.writeAll(")"); } }, .Union => { - if (comptime std.meta.trait.hasFn("format")(T)) { - return value.format(fmt, options, context, Errors, output); - } - - try output(context, @typeName(T)); + try out_stream.writeAll(@typeName(T)); if (max_depth == 0) { - return output(context, "{ ... }"); + return out_stream.writeAll("{ ... }"); } const info = @typeInfo(T).Union; if (info.tag_type) |UnionTagType| { - try output(context, "{ ."); - try output(context, @tagName(@as(UnionTagType, value))); - try output(context, " = "); + try out_stream.writeAll("{ ."); + try out_stream.writeAll(@tagName(@as(UnionTagType, value))); + try out_stream.writeAll(" = "); inline for (info.fields) |u_field| { if (@enumToInt(@as(UnionTagType, value)) == u_field.enum_field.?.value) { - try formatType(@field(value, u_field.name), fmt, options, context, Errors, output, max_depth - 1); + try formatType(@field(value, u_field.name), fmt, options, out_stream, max_depth - 1); } } - try output(context, " }"); + try out_stream.writeAll(" }"); } else { - try format(context, Errors, output, "@{x}", .{@ptrToInt(&value)}); + try format(out_stream, "@{x}", .{@ptrToInt(&value)}); } }, .Struct => |StructT| { - if (comptime std.meta.trait.hasFn("format")(T)) { - return value.format(fmt, options, context, Errors, output); - } - - try output(context, @typeName(T)); + try out_stream.writeAll(@typeName(T)); if (max_depth == 0) { - return output(context, "{ ... }"); + return out_stream.writeAll("{ ... }"); } - try output(context, "{"); + try out_stream.writeAll("{"); inline for (StructT.fields) |f, i| { if (i == 0) { - try output(context, " ."); + try out_stream.writeAll(" ."); } else { - try output(context, ", ."); + try out_stream.writeAll(", ."); } - try output(context, f.name); - try output(context, " = "); - try formatType(@field(value, f.name), fmt, options, context, Errors, output, max_depth - 1); + try out_stream.writeAll(f.name); + try out_stream.writeAll(" = "); + try formatType(@field(value, f.name), fmt, options, out_stream, max_depth - 1); } - try output(context, " }"); + try out_stream.writeAll(" }"); }, .Pointer => |ptr_info| switch (ptr_info.size) { .One => switch (@typeInfo(ptr_info.child)) { .Array => |info| { if (info.child == u8) { - return formatText(value, fmt, options, context, Errors, output); + return formatText(value, fmt, options, out_stream); } - return format(context, Errors, output, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) }); + return format(out_stream, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) }); }, .Enum, .Union, .Struct => { - return formatType(value.*, fmt, options, context, Errors, output, max_depth); + return formatType(value.*, fmt, options, out_stream, max_depth); }, - else => return format(context, Errors, output, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) }), + else => return format(out_stream, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) }), }, .Many, .C => { if (ptr_info.sentinel) |sentinel| { - return formatType(mem.span(value), fmt, options, context, Errors, output, max_depth); + return formatType(mem.span(value), fmt, options, out_stream, max_depth); } if (ptr_info.child == u8) { if (fmt.len > 0 and fmt[0] == 's') { - return formatText(mem.span(value), fmt, options, context, Errors, output); + return formatText(mem.span(value), fmt, options, out_stream); } } - return format(context, Errors, output, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) }); + return format(out_stream, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) }); }, .Slice => { if (fmt.len > 0 and ((fmt[0] == 'x') or (fmt[0] == 'X'))) { - return formatText(value, fmt, options, context, Errors, output); + return formatText(value, fmt, options, out_stream); } if (ptr_info.child == u8) { - return formatText(value, fmt, options, context, Errors, output); + return formatText(value, fmt, options, out_stream); } - return format(context, Errors, output, "{}@{x}", .{ @typeName(ptr_info.child), @ptrToInt(value.ptr) }); + return format(out_stream, "{}@{x}", .{ @typeName(ptr_info.child), @ptrToInt(value.ptr) }); }, }, .Array => |info| { @@ -473,27 +453,27 @@ pub fn formatType( .sentinel = null, }, }); - return formatType(@as(Slice, &value), fmt, options, context, Errors, output, max_depth); + return formatType(@as(Slice, &value), fmt, options, out_stream, max_depth); }, .Vector => { const len = @typeInfo(T).Vector.len; - try output(context, "{ "); + try out_stream.writeAll("{ "); var i: usize = 0; while (i < len) : (i += 1) { - try formatValue(value[i], fmt, options, context, Errors, output); + try formatValue(value[i], fmt, options, out_stream); if (i < len - 1) { - try output(context, ", "); + try out_stream.writeAll(", "); } } - try output(context, " }"); + try out_stream.writeAll(" }"); }, .Fn => { - return format(context, Errors, output, "{}@{x}", .{ @typeName(T), @ptrToInt(value) }); + return format(out_stream, "{}@{x}", .{ @typeName(T), @ptrToInt(value) }); }, - .Type => return output(context, @typeName(T)), + .Type => return out_stream.writeAll(@typeName(T)), .EnumLiteral => { const buffer = [_]u8{'.'} ++ @tagName(value); - return formatType(buffer, fmt, options, context, Errors, output, max_depth); + return formatType(buffer, fmt, options, out_stream, max_depth); }, else => @compileError("Unable to format type '" ++ @typeName(T) ++ "'"), } @@ -503,21 +483,19 @@ fn formatValue( value: var, comptime fmt: []const u8, options: FormatOptions, - context: var, - comptime Errors: type, - comptime output: fn (@TypeOf(context), []const u8) Errors!void, -) Errors!void { + out_stream: var, +) !void { if (comptime std.mem.eql(u8, fmt, "B")) { - return formatBytes(value, options, 1000, context, Errors, output); + return formatBytes(value, options, 1000, out_stream); } else if (comptime std.mem.eql(u8, fmt, "Bi")) { - return formatBytes(value, options, 1024, context, Errors, output); + return formatBytes(value, options, 1024, out_stream); } const T = @TypeOf(value); switch (@typeInfo(T)) { - .Float => return formatFloatValue(value, fmt, options, context, Errors, output), - .Int, .ComptimeInt => return formatIntValue(value, fmt, options, context, Errors, output), - .Bool => return output(context, if (value) "true" else "false"), + .Float => return formatFloatValue(value, fmt, options, out_stream), + .Int, .ComptimeInt => return formatIntValue(value, fmt, options, out_stream), + .Bool => return out_stream.writeAll(if (value) "true" else "false"), else => comptime unreachable, } } @@ -526,10 +504,8 @@ pub fn formatIntValue( value: var, comptime fmt: []const u8, options: FormatOptions, - context: var, - comptime Errors: type, - comptime output: fn (@TypeOf(context), []const u8) Errors!void, -) Errors!void { + out_stream: var, +) !void { comptime var radix = 10; comptime var uppercase = false; @@ -544,7 +520,7 @@ pub fn formatIntValue( uppercase = false; } else if (comptime std.mem.eql(u8, fmt, "c")) { if (@TypeOf(int_value).bit_count <= 8) { - return formatAsciiChar(@as(u8, int_value), options, context, Errors, output); + return formatAsciiChar(@as(u8, int_value), options, out_stream); } else { @compileError("Cannot print integer that is larger than 8 bits as a ascii"); } @@ -561,21 +537,19 @@ pub fn formatIntValue( @compileError("Unknown format string: '" ++ fmt ++ "'"); } - return formatInt(int_value, radix, uppercase, options, context, Errors, output); + return formatInt(int_value, radix, uppercase, options, out_stream); } fn formatFloatValue( value: var, comptime fmt: []const u8, options: FormatOptions, - context: var, - comptime Errors: type, - comptime output: fn (@TypeOf(context), []const u8) Errors!void, -) Errors!void { + out_stream: var, +) !void { if (fmt.len == 0 or comptime std.mem.eql(u8, fmt, "e")) { - return formatFloatScientific(value, options, context, Errors, output); + return formatFloatScientific(value, options, out_stream); } else if (comptime std.mem.eql(u8, fmt, "d")) { - return formatFloatDecimal(value, options, context, Errors, output); + return formatFloatDecimal(value, options, out_stream); } else { @compileError("Unknown format string: '" ++ fmt ++ "'"); } @@ -585,17 +559,15 @@ pub fn formatText( bytes: []const u8, comptime fmt: []const u8, options: FormatOptions, - context: var, - comptime Errors: type, - comptime output: fn (@TypeOf(context), []const u8) Errors!void, -) Errors!void { + out_stream: var, +) !void { if (fmt.len == 0) { - return output(context, bytes); + return out_stream.writeAll(bytes); } else if (comptime std.mem.eql(u8, fmt, "s")) { - return formatBuf(bytes, options, context, Errors, output); + return formatBuf(bytes, options, out_stream); } else if (comptime (std.mem.eql(u8, fmt, "x") or std.mem.eql(u8, fmt, "X"))) { for (bytes) |c| { - try formatInt(c, 16, fmt[0] == 'X', FormatOptions{ .width = 2, .fill = '0' }, context, Errors, output); + try formatInt(c, 16, fmt[0] == 'X', FormatOptions{ .width = 2, .fill = '0' }, out_stream); } return; } else { @@ -606,27 +578,23 @@ pub fn formatText( pub fn formatAsciiChar( c: u8, options: FormatOptions, - context: var, - comptime Errors: type, - comptime output: fn (@TypeOf(context), []const u8) Errors!void, -) Errors!void { - return output(context, @as(*const [1]u8, &c)[0..]); + out_stream: var, +) !void { + return out_stream.writeAll(@as(*const [1]u8, &c)[0..]); } pub fn formatBuf( buf: []const u8, options: FormatOptions, - context: var, - comptime Errors: type, - comptime output: fn (@TypeOf(context), []const u8) Errors!void, -) Errors!void { - try output(context, buf); + out_stream: var, +) !void { + try out_stream.writeAll(buf); const width = options.width orelse 0; var leftover_padding = if (width > buf.len) (width - buf.len) else return; const pad_byte: u8 = options.fill; while (leftover_padding > 0) : (leftover_padding -= 1) { - try output(context, @as(*const [1]u8, &pad_byte)[0..1]); + try out_stream.writeAll(@as(*const [1]u8, &pad_byte)[0..1]); } } @@ -636,40 +604,38 @@ pub fn formatBuf( pub fn formatFloatScientific( value: var, options: FormatOptions, - context: var, - comptime Errors: type, - comptime output: fn (@TypeOf(context), []const u8) Errors!void, -) Errors!void { + out_stream: var, +) !void { var x = @floatCast(f64, value); // Errol doesn't handle these special cases. if (math.signbit(x)) { - try output(context, "-"); + try out_stream.writeAll("-"); x = -x; } if (math.isNan(x)) { - return output(context, "nan"); + return out_stream.writeAll("nan"); } if (math.isPositiveInf(x)) { - return output(context, "inf"); + return out_stream.writeAll("inf"); } if (x == 0.0) { - try output(context, "0"); + try out_stream.writeAll("0"); if (options.precision) |precision| { if (precision != 0) { - try output(context, "."); + try out_stream.writeAll("."); var i: usize = 0; while (i < precision) : (i += 1) { - try output(context, "0"); + try out_stream.writeAll("0"); } } } else { - try output(context, ".0"); + try out_stream.writeAll(".0"); } - try output(context, "e+00"); + try out_stream.writeAll("e+00"); return; } @@ -679,50 +645,50 @@ pub fn formatFloatScientific( if (options.precision) |precision| { errol.roundToPrecision(&float_decimal, precision, errol.RoundMode.Scientific); - try output(context, float_decimal.digits[0..1]); + try out_stream.writeAll(float_decimal.digits[0..1]); // {e0} case prints no `.` if (precision != 0) { - try output(context, "."); + try out_stream.writeAll("."); var printed: usize = 0; if (float_decimal.digits.len > 1) { const num_digits = math.min(float_decimal.digits.len, precision + 1); - try output(context, float_decimal.digits[1..num_digits]); + try out_stream.writeAll(float_decimal.digits[1..num_digits]); printed += num_digits - 1; } while (printed < precision) : (printed += 1) { - try output(context, "0"); + try out_stream.writeAll("0"); } } } else { - try output(context, float_decimal.digits[0..1]); - try output(context, "."); + try out_stream.writeAll(float_decimal.digits[0..1]); + try out_stream.writeAll("."); if (float_decimal.digits.len > 1) { const num_digits = if (@TypeOf(value) == f32) math.min(@as(usize, 9), float_decimal.digits.len) else float_decimal.digits.len; - try output(context, float_decimal.digits[1..num_digits]); + try out_stream.writeAll(float_decimal.digits[1..num_digits]); } else { - try output(context, "0"); + try out_stream.writeAll("0"); } } - try output(context, "e"); + try out_stream.writeAll("e"); const exp = float_decimal.exp - 1; if (exp >= 0) { - try output(context, "+"); + try out_stream.writeAll("+"); if (exp > -10 and exp < 10) { - try output(context, "0"); + try out_stream.writeAll("0"); } - try formatInt(exp, 10, false, FormatOptions{ .width = 0 }, context, Errors, output); + try formatInt(exp, 10, false, FormatOptions{ .width = 0 }, out_stream); } else { - try output(context, "-"); + try out_stream.writeAll("-"); if (exp > -10 and exp < 10) { - try output(context, "0"); + try out_stream.writeAll("0"); } - try formatInt(-exp, 10, false, FormatOptions{ .width = 0 }, context, Errors, output); + try formatInt(-exp, 10, false, FormatOptions{ .width = 0 }, out_stream); } } @@ -731,36 +697,34 @@ pub fn formatFloatScientific( pub fn formatFloatDecimal( value: var, options: FormatOptions, - context: var, - comptime Errors: type, - comptime output: fn (@TypeOf(context), []const u8) Errors!void, -) Errors!void { + out_stream: var, +) !void { var x = @as(f64, value); // Errol doesn't handle these special cases. if (math.signbit(x)) { - try output(context, "-"); + try out_stream.writeAll("-"); x = -x; } if (math.isNan(x)) { - return output(context, "nan"); + return out_stream.writeAll("nan"); } if (math.isPositiveInf(x)) { - return output(context, "inf"); + return out_stream.writeAll("inf"); } if (x == 0.0) { - try output(context, "0"); + try out_stream.writeAll("0"); if (options.precision) |precision| { if (precision != 0) { - try output(context, "."); + try out_stream.writeAll("."); var i: usize = 0; while (i < precision) : (i += 1) { - try output(context, "0"); + try out_stream.writeAll("0"); } } else { - try output(context, ".0"); + try out_stream.writeAll(".0"); } } @@ -782,14 +746,14 @@ pub fn formatFloatDecimal( if (num_digits_whole > 0) { // We may have to zero pad, for instance 1e4 requires zero padding. - try output(context, float_decimal.digits[0..num_digits_whole_no_pad]); + try out_stream.writeAll(float_decimal.digits[0..num_digits_whole_no_pad]); var i = num_digits_whole_no_pad; while (i < num_digits_whole) : (i += 1) { - try output(context, "0"); + try out_stream.writeAll("0"); } } else { - try output(context, "0"); + try out_stream.writeAll("0"); } // {.0} special case doesn't want a trailing '.' @@ -797,7 +761,7 @@ pub fn formatFloatDecimal( return; } - try output(context, "."); + try out_stream.writeAll("."); // Keep track of fractional count printed for case where we pre-pad then post-pad with 0's. var printed: usize = 0; @@ -809,7 +773,7 @@ pub fn formatFloatDecimal( var i: usize = 0; while (i < zeros_to_print) : (i += 1) { - try output(context, "0"); + try out_stream.writeAll("0"); printed += 1; } @@ -821,14 +785,14 @@ pub fn formatFloatDecimal( // Remaining fractional portion, zero-padding if insufficient. assert(precision >= printed); if (num_digits_whole_no_pad + precision - printed < float_decimal.digits.len) { - try output(context, float_decimal.digits[num_digits_whole_no_pad .. num_digits_whole_no_pad + precision - printed]); + try out_stream.writeAll(float_decimal.digits[num_digits_whole_no_pad .. num_digits_whole_no_pad + precision - printed]); return; } else { - try output(context, float_decimal.digits[num_digits_whole_no_pad..]); + try out_stream.writeAll(float_decimal.digits[num_digits_whole_no_pad..]); printed += float_decimal.digits.len - num_digits_whole_no_pad; while (printed < precision) : (printed += 1) { - try output(context, "0"); + try out_stream.writeAll("0"); } } } else { @@ -840,14 +804,14 @@ pub fn formatFloatDecimal( if (num_digits_whole > 0) { // We may have to zero pad, for instance 1e4 requires zero padding. - try output(context, float_decimal.digits[0..num_digits_whole_no_pad]); + try out_stream.writeAll(float_decimal.digits[0..num_digits_whole_no_pad]); var i = num_digits_whole_no_pad; while (i < num_digits_whole) : (i += 1) { - try output(context, "0"); + try out_stream.writeAll("0"); } } else { - try output(context, "0"); + try out_stream.writeAll("0"); } // Omit `.` if no fractional portion @@ -855,7 +819,7 @@ pub fn formatFloatDecimal( return; } - try output(context, "."); + try out_stream.writeAll("."); // Zero-fill until we reach significant digits or run out of precision. if (float_decimal.exp < 0) { @@ -863,11 +827,11 @@ pub fn formatFloatDecimal( var i: usize = 0; while (i < zero_digit_count) : (i += 1) { - try output(context, "0"); + try out_stream.writeAll("0"); } } - try output(context, float_decimal.digits[num_digits_whole_no_pad..]); + try out_stream.writeAll(float_decimal.digits[num_digits_whole_no_pad..]); } } @@ -875,12 +839,10 @@ pub fn formatBytes( value: var, options: FormatOptions, comptime radix: usize, - context: var, - comptime Errors: type, - comptime output: fn (@TypeOf(context), []const u8) Errors!void, -) Errors!void { + out_stream: var, +) !void { if (value == 0) { - return output(context, "0B"); + return out_stream.writeAll("0B"); } const mags_si = " kMGTPEZY"; @@ -897,10 +859,10 @@ pub fn formatBytes( else => unreachable, }; - try formatFloatDecimal(new_value, options, context, Errors, output); + try formatFloatDecimal(new_value, options, out_stream); if (suffix == ' ') { - return output(context, "B"); + return out_stream.writeAll("B"); } const buf = switch (radix) { @@ -908,7 +870,7 @@ pub fn formatBytes( 1024 => &[_]u8{ suffix, 'i', 'B' }, else => unreachable, }; - return output(context, buf); + return out_stream.writeAll(buf); } pub fn formatInt( @@ -916,10 +878,8 @@ pub fn formatInt( base: u8, uppercase: bool, options: FormatOptions, - context: var, - comptime Errors: type, - comptime output: fn (@TypeOf(context), []const u8) Errors!void, -) Errors!void { + out_stream: var, +) !void { const int_value = if (@TypeOf(value) == comptime_int) blk: { const Int = math.IntFittingRange(value, value); break :blk @as(Int, value); @@ -927,9 +887,9 @@ pub fn formatInt( value; if (@TypeOf(int_value).is_signed) { - return formatIntSigned(int_value, base, uppercase, options, context, Errors, output); + return formatIntSigned(int_value, base, uppercase, options, out_stream); } else { - return formatIntUnsigned(int_value, base, uppercase, options, context, Errors, output); + return formatIntUnsigned(int_value, base, uppercase, options, out_stream); } } @@ -938,10 +898,8 @@ fn formatIntSigned( base: u8, uppercase: bool, options: FormatOptions, - context: var, - comptime Errors: type, - comptime output: fn (@TypeOf(context), []const u8) Errors!void, -) Errors!void { + out_stream: var, +) !void { const new_options = FormatOptions{ .width = if (options.width) |w| (if (w == 0) 0 else w - 1) else null, .precision = options.precision, @@ -950,15 +908,15 @@ fn formatIntSigned( const bit_count = @typeInfo(@TypeOf(value)).Int.bits; const Uint = std.meta.IntType(false, bit_count); if (value < 0) { - try output(context, "-"); + try out_stream.writeAll("-"); const new_value = math.absCast(value); - return formatIntUnsigned(new_value, base, uppercase, new_options, context, Errors, output); + return formatIntUnsigned(new_value, base, uppercase, new_options, out_stream); } else if (options.width == null or options.width.? == 0) { - return formatIntUnsigned(@intCast(Uint, value), base, uppercase, options, context, Errors, output); + return formatIntUnsigned(@intCast(Uint, value), base, uppercase, options, out_stream); } else { - try output(context, "+"); + try out_stream.writeAll("+"); const new_value = @intCast(Uint, value); - return formatIntUnsigned(new_value, base, uppercase, new_options, context, Errors, output); + return formatIntUnsigned(new_value, base, uppercase, new_options, out_stream); } } @@ -967,10 +925,8 @@ fn formatIntUnsigned( base: u8, uppercase: bool, options: FormatOptions, - context: var, - comptime Errors: type, - comptime output: fn (@TypeOf(context), []const u8) Errors!void, -) Errors!void { + out_stream: var, +) !void { assert(base >= 2); var buf: [math.max(@TypeOf(value).bit_count, 1)]u8 = undefined; const min_int_bits = comptime math.max(@TypeOf(value).bit_count, @TypeOf(base).bit_count); @@ -994,34 +950,23 @@ fn formatIntUnsigned( const zero_byte: u8 = options.fill; var leftover_padding = padding - index; while (true) { - try output(context, @as(*const [1]u8, &zero_byte)[0..]); + try out_stream.writeAll(@as(*const [1]u8, &zero_byte)[0..]); leftover_padding -= 1; if (leftover_padding == 0) break; } mem.set(u8, buf[0..index], options.fill); - return output(context, &buf); + return out_stream.writeAll(&buf); } else { const padded_buf = buf[index - padding ..]; mem.set(u8, padded_buf[0..padding], options.fill); - return output(context, padded_buf); + return out_stream.writeAll(padded_buf); } } pub fn formatIntBuf(out_buf: []u8, value: var, base: u8, uppercase: bool, options: FormatOptions) usize { - var context = FormatIntBuf{ - .out_buf = out_buf, - .index = 0, - }; - formatInt(value, base, uppercase, options, &context, error{}, formatIntCallback) catch unreachable; - return context.index; -} -const FormatIntBuf = struct { - out_buf: []u8, - index: usize, -}; -fn formatIntCallback(context: *FormatIntBuf, bytes: []const u8) (error{}!void) { - mem.copy(u8, context.out_buf[context.index..], bytes); - context.index += bytes.len; + var fbs = std.io.fixedBufferStream(out_buf); + formatInt(value, base, uppercase, options, fbs.outStream()) catch unreachable; + return fbs.pos; } pub fn parseInt(comptime T: type, buf: []const u8, radix: u8) !T { @@ -1121,44 +1066,40 @@ fn digitToChar(digit: u8, uppercase: bool) u8 { }; } -const BufPrintContext = struct { - remaining: []u8, -}; - -fn bufPrintWrite(context: *BufPrintContext, bytes: []const u8) !void { - if (context.remaining.len < bytes.len) { - mem.copy(u8, context.remaining, bytes[0..context.remaining.len]); - return error.BufferTooSmall; - } - mem.copy(u8, context.remaining, bytes); - context.remaining = context.remaining[bytes.len..]; -} - pub const BufPrintError = error{ /// As much as possible was written to the buffer, but it was too small to fit all the printed bytes. BufferTooSmall, }; pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: var) BufPrintError![]u8 { - var context = BufPrintContext{ .remaining = buf }; - try format(&context, BufPrintError, bufPrintWrite, fmt, args); - return buf[0 .. buf.len - context.remaining.len]; + var fbs = std.io.fixedBufferStream(buf); + format(fbs.outStream(), fmt, args) catch |err| switch (err) { + error.NoSpaceLeft => return error.BufferTooSmall, + }; + //TODO: should we change one of these return signatures? + //return fbs.getWritten(); + return buf[0..fbs.pos]; +} + +// Count the characters needed for format. Useful for preallocating memory +pub fn count(comptime fmt: []const u8, args: var) !usize { + var counting_stream = std.io.countingOutStream(std.io.null_out_stream); + format(counting_stream.outStream(), fmt, args) catch |err| switch (err) {}; + return std.math.cast(usize, counting_stream.bytes_written); } pub const AllocPrintError = error{OutOfMemory}; pub fn allocPrint(allocator: *mem.Allocator, comptime fmt: []const u8, args: var) AllocPrintError![]u8 { - var size: usize = 0; - format(&size, error{}, countSize, fmt, args) catch |err| switch (err) {}; + const size = count(fmt, args) catch |err| switch (err) { + // Output too long. Can't possibly allocate enough memory to display it. + error.Overflow => return error.OutOfMemory, + }; const buf = try allocator.alloc(u8, size); return bufPrint(buf, fmt, args) catch |err| switch (err) { error.BufferTooSmall => unreachable, // we just counted the size above }; } -fn countSize(size: *usize, bytes: []const u8) (error{}!void) { - size.* += bytes.len; -} - pub fn allocPrint0(allocator: *mem.Allocator, comptime fmt: []const u8, args: var) AllocPrintError![:0]u8 { const result = try allocPrint(allocator, fmt ++ "\x00", args); return result[0 .. result.len - 1 :0]; @@ -1251,20 +1192,17 @@ test "int.padded" { test "buffer" { { var buf1: [32]u8 = undefined; - var context = BufPrintContext{ .remaining = buf1[0..] }; - try formatType(1234, "", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth); - var res = buf1[0 .. buf1.len - context.remaining.len]; - std.testing.expect(mem.eql(u8, res, "1234")); - - context = BufPrintContext{ .remaining = buf1[0..] }; - try formatType('a', "c", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth); - res = buf1[0 .. buf1.len - context.remaining.len]; - std.testing.expect(mem.eql(u8, res, "a")); - - context = BufPrintContext{ .remaining = buf1[0..] }; - try formatType(0b1100, "b", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth); - res = buf1[0 .. buf1.len - context.remaining.len]; - std.testing.expect(mem.eql(u8, res, "1100")); + var fbs = std.io.fixedBufferStream(&buf1); + try formatType(1234, "", FormatOptions{}, fbs.outStream(), default_max_depth); + std.testing.expect(mem.eql(u8, fbs.getWritten(), "1234")); + + fbs.reset(); + try formatType('a', "c", FormatOptions{}, fbs.outStream(), default_max_depth); + std.testing.expect(mem.eql(u8, fbs.getWritten(), "a")); + + fbs.reset(); + try formatType(0b1100, "b", FormatOptions{}, fbs.outStream(), default_max_depth); + std.testing.expect(mem.eql(u8, fbs.getWritten(), "1100")); } } @@ -1449,14 +1387,12 @@ test "custom" { self: SelfType, comptime fmt: []const u8, options: FormatOptions, - context: var, - comptime Errors: type, - comptime output: fn (@TypeOf(context), []const u8) Errors!void, - ) Errors!void { + out_stream: var, + ) !void { if (fmt.len == 0 or comptime std.mem.eql(u8, fmt, "p")) { - return std.fmt.format(context, Errors, output, "({d:.3},{d:.3})", .{ self.x, self.y }); + return std.fmt.format(out_stream, "({d:.3},{d:.3})", .{ self.x, self.y }); } else if (comptime std.mem.eql(u8, fmt, "d")) { - return std.fmt.format(context, Errors, output, "{d:.3}x{d:.3}", .{ self.x, self.y }); + return std.fmt.format(out_stream, "{d:.3}x{d:.3}", .{ self.x, self.y }); } else { @compileError("Unknown format character: '" ++ fmt ++ "'"); } @@ -1640,10 +1576,10 @@ test "hexToBytes" { test "formatIntValue with comptime_int" { const value: comptime_int = 123456789123456789; - var buf = std.ArrayList(u8).init(std.testing.allocator); - defer buf.deinit(); - try formatIntValue(value, "", FormatOptions{}, &buf, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice); - std.testing.expect(mem.eql(u8, buf.toSliceConst(), "123456789123456789")); + var buf: [20]u8 = undefined; + var fbs = std.io.fixedBufferStream(&buf); + try formatIntValue(value, "", FormatOptions{}, fbs.outStream()); + std.testing.expect(mem.eql(u8, fbs.getWritten(), "123456789123456789")); } test "formatType max_depth" { @@ -1656,12 +1592,10 @@ test "formatType max_depth" { self: SelfType, comptime fmt: []const u8, options: FormatOptions, - context: var, - comptime Errors: type, - comptime output: fn (@TypeOf(context), []const u8) Errors!void, - ) Errors!void { + out_stream: var, + ) !void { if (fmt.len == 0) { - return std.fmt.format(context, Errors, output, "({d:.3},{d:.3})", .{ self.x, self.y }); + return std.fmt.format(out_stream, "({d:.3},{d:.3})", .{ self.x, self.y }); } else { @compileError("Unknown format string: '" ++ fmt ++ "'"); } @@ -1695,25 +1629,22 @@ test "formatType max_depth" { inst.a = &inst; inst.tu.ptr = &inst.tu; - var buf0 = std.ArrayList(u8).init(std.testing.allocator); - defer buf0.deinit(); - try formatType(inst, "", FormatOptions{}, &buf0, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice, 0); - std.testing.expect(mem.eql(u8, buf0.toSlice(), "S{ ... }")); - - var buf1 = std.ArrayList(u8).init(std.testing.allocator); - defer buf1.deinit(); - try formatType(inst, "", FormatOptions{}, &buf1, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice, 1); - std.testing.expect(mem.eql(u8, buf1.toSlice(), "S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }")); - - var buf2 = std.ArrayList(u8).init(std.testing.allocator); - defer buf2.deinit(); - try formatType(inst, "", FormatOptions{}, &buf2, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice, 2); - std.testing.expect(mem.eql(u8, buf2.toSlice(), "S{ .a = S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ ... } }, .e = E.Two, .vec = (10.200,2.220) }")); - - var buf3 = std.ArrayList(u8).init(std.testing.allocator); - defer buf3.deinit(); - try formatType(inst, "", FormatOptions{}, &buf3, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice, 3); - std.testing.expect(mem.eql(u8, buf3.toSlice(), "S{ .a = S{ .a = S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ ... } }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ .ptr = TU{ ... } } }, .e = E.Two, .vec = (10.200,2.220) }")); + var buf: [1000]u8 = undefined; + var fbs = std.io.fixedBufferStream(&buf); + try formatType(inst, "", FormatOptions{}, fbs.outStream(), 0); + std.testing.expect(mem.eql(u8, fbs.getWritten(), "S{ ... }")); + + fbs.reset(); + try formatType(inst, "", FormatOptions{}, fbs.outStream(), 1); + std.testing.expect(mem.eql(u8, fbs.getWritten(), "S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }")); + + fbs.reset(); + try formatType(inst, "", FormatOptions{}, fbs.outStream(), 2); + std.testing.expect(mem.eql(u8, fbs.getWritten(), "S{ .a = S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ ... } }, .e = E.Two, .vec = (10.200,2.220) }")); + + fbs.reset(); + try formatType(inst, "", FormatOptions{}, fbs.outStream(), 3); + std.testing.expect(mem.eql(u8, fbs.getWritten(), "S{ .a = S{ .a = S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ ... } }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ .ptr = TU{ ... } } }, .e = E.Two, .vec = (10.200,2.220) }")); } test "positional" { diff --git a/lib/std/fmtstream.zig b/lib/std/fmtstream.zig deleted file mode 100644 index 93734d42aa..0000000000 --- a/lib/std/fmtstream.zig +++ /dev/null @@ -1,1685 +0,0 @@ -const std = @import("std.zig"); -const math = std.math; -const assert = std.debug.assert; -const mem = std.mem; -const builtin = @import("builtin"); -const errol = @import("fmt/errol.zig"); -const lossyCast = std.math.lossyCast; - -pub const default_max_depth = 3; - -pub const Alignment = enum { - Left, - Center, - Right, -}; - -pub const FormatOptions = struct { - precision: ?usize = null, - width: ?usize = null, - alignment: ?Alignment = null, - fill: u8 = ' ', -}; - -fn peekIsAlign(comptime fmt: []const u8) bool { - // Should only be called during a state transition to the format segment. - comptime assert(fmt[0] == ':'); - - inline for (([_]u8{ 1, 2 })[0..]) |i| { - if (fmt.len > i and (fmt[i] == '<' or fmt[i] == '^' or fmt[i] == '>')) { - return true; - } - } - return false; -} - -/// Renders fmt string with args, calling output with slices of bytes. -/// If `output` returns an error, the error is returned from `format` and -/// `output` is not called again. -/// -/// The format string must be comptime known and may contain placeholders following -/// this format: -/// `{[position][specifier]:[fill][alignment][width].[precision]}` -/// -/// Each word between `[` and `]` is a parameter you have to replace with something: -/// -/// - *position* is the index of the argument that should be inserted -/// - *specifier* is a type-dependent formatting option that determines how a type should formatted (see below) -/// - *fill* is a single character which is used to pad the formatted text -/// - *alignment* is one of the three characters `<`, `^` or `>`. they define if the text is *left*, *center*, or *right* aligned -/// - *width* is the total width of the field in characters -/// - *precision* specifies how many decimals a formatted number should have -/// -/// Note that most of the parameters are optional and may be omitted. Also you can leave out separators like `:` and `.` when -/// all parameters after the separator are omitted. -/// Only exception is the *fill* parameter. If *fill* is required, one has to specify *alignment* as well, as otherwise -/// the digits after `:` is interpreted as *width*, not *fill*. -/// -/// The *specifier* has several options for types: -/// - `x` and `X`: -/// - format the non-numeric value as a string of bytes in hexadecimal notation ("binary dump") in either lower case or upper case -/// - output numeric value in hexadecimal notation -/// - `s`: print a pointer-to-many as a c-string, use zero-termination -/// - `B` and `Bi`: output a memory size in either metric (1000) or power-of-two (1024) based notation. works for both float and integer values. -/// - `e`: output floating point value in scientific notation -/// - `d`: output numeric value in decimal notation -/// - `b`: output integer value in binary notation -/// - `c`: output integer as an ASCII character. Integer type must have 8 bits at max. -/// - `*`: output the address of the value instead of the value itself. -/// -/// If a formatted user type contains a function of the type -/// ``` -/// fn format(value: ?, comptime fmt: []const u8, options: std.fmtstream.FormatOptions, out_stream: var) !void -/// ``` -/// with `?` being the type formatted, this function will be called instead of the default implementation. -/// This allows user types to be formatted in a logical manner instead of dumping all fields of the type. -/// -/// A user type may be a `struct`, `vector`, `union` or `enum` type. -pub fn format( - out_stream: var, - comptime fmt: []const u8, - args: var, -) !void { - const ArgSetType = u32; - if (@typeInfo(@TypeOf(args)) != .Struct) { - @compileError("Expected tuple or struct argument, found " ++ @typeName(@TypeOf(args))); - } - if (args.len > ArgSetType.bit_count) { - @compileError("32 arguments max are supported per format call"); - } - - const State = enum { - Start, - Positional, - CloseBrace, - Specifier, - FormatFillAndAlign, - FormatWidth, - FormatPrecision, - }; - - comptime var start_index = 0; - comptime var state = State.Start; - comptime var maybe_pos_arg: ?comptime_int = null; - comptime var specifier_start = 0; - comptime var specifier_end = 0; - comptime var options = FormatOptions{}; - comptime var arg_state: struct { - next_arg: usize = 0, - used_args: ArgSetType = 0, - args_len: usize = args.len, - - fn hasUnusedArgs(comptime self: *@This()) bool { - return (@popCount(ArgSetType, self.used_args) != self.args_len); - } - - fn nextArg(comptime self: *@This(), comptime pos_arg: ?comptime_int) comptime_int { - const next_idx = pos_arg orelse blk: { - const arg = self.next_arg; - self.next_arg += 1; - break :blk arg; - }; - - if (next_idx >= self.args_len) { - @compileError("Too few arguments"); - } - - // Mark this argument as used - self.used_args |= 1 << next_idx; - - return next_idx; - } - } = .{}; - - inline for (fmt) |c, i| { - switch (state) { - .Start => switch (c) { - '{' => { - if (start_index < i) { - try out_stream.writeAll(fmt[start_index..i]); - } - - start_index = i; - specifier_start = i + 1; - specifier_end = i + 1; - maybe_pos_arg = null; - state = .Positional; - options = FormatOptions{}; - }, - '}' => { - if (start_index < i) { - try out_stream.writeAll(fmt[start_index..i]); - } - state = .CloseBrace; - }, - else => {}, - }, - .Positional => switch (c) { - '{' => { - state = .Start; - start_index = i; - }, - ':' => { - state = if (comptime peekIsAlign(fmt[i..])) State.FormatFillAndAlign else State.FormatWidth; - specifier_end = i; - }, - '0'...'9' => { - if (maybe_pos_arg == null) { - maybe_pos_arg = 0; - } - - maybe_pos_arg.? *= 10; - maybe_pos_arg.? += c - '0'; - specifier_start = i + 1; - - if (maybe_pos_arg.? >= args.len) { - @compileError("Positional value refers to non-existent argument"); - } - }, - '}' => { - const arg_to_print = comptime arg_state.nextArg(maybe_pos_arg); - - try formatType( - args[arg_to_print], - fmt[0..0], - options, - out_stream, - default_max_depth, - ); - - state = .Start; - start_index = i + 1; - }, - else => { - state = .Specifier; - specifier_start = i; - }, - }, - .CloseBrace => switch (c) { - '}' => { - state = .Start; - start_index = i; - }, - else => @compileError("Single '}' encountered in format string"), - }, - .Specifier => switch (c) { - ':' => { - specifier_end = i; - state = if (comptime peekIsAlign(fmt[i..])) State.FormatFillAndAlign else State.FormatWidth; - }, - '}' => { - const arg_to_print = comptime arg_state.nextArg(maybe_pos_arg); - - try formatType( - args[arg_to_print], - fmt[specifier_start..i], - options, - out_stream, - default_max_depth, - ); - state = .Start; - start_index = i + 1; - }, - else => {}, - }, - // Only entered if the format string contains a fill/align segment. - .FormatFillAndAlign => switch (c) { - '<' => { - options.alignment = Alignment.Left; - state = .FormatWidth; - }, - '^' => { - options.alignment = Alignment.Center; - state = .FormatWidth; - }, - '>' => { - options.alignment = Alignment.Right; - state = .FormatWidth; - }, - else => { - options.fill = c; - }, - }, - .FormatWidth => switch (c) { - '0'...'9' => { - if (options.width == null) { - options.width = 0; - } - - options.width.? *= 10; - options.width.? += c - '0'; - }, - '.' => { - state = .FormatPrecision; - }, - '}' => { - const arg_to_print = comptime arg_state.nextArg(maybe_pos_arg); - - try formatType( - args[arg_to_print], - fmt[specifier_start..specifier_end], - options, - out_stream, - default_max_depth, - ); - state = .Start; - start_index = i + 1; - }, - else => { - @compileError("Unexpected character in width value: " ++ [_]u8{c}); - }, - }, - .FormatPrecision => switch (c) { - '0'...'9' => { - if (options.precision == null) { - options.precision = 0; - } - - options.precision.? *= 10; - options.precision.? += c - '0'; - }, - '}' => { - const arg_to_print = comptime arg_state.nextArg(maybe_pos_arg); - - try formatType( - args[arg_to_print], - fmt[specifier_start..specifier_end], - options, - out_stream, - default_max_depth, - ); - state = .Start; - start_index = i + 1; - }, - else => { - @compileError("Unexpected character in precision value: " ++ [_]u8{c}); - }, - }, - } - } - comptime { - if (comptime arg_state.hasUnusedArgs()) { - @compileError("Unused arguments"); - } - if (state != State.Start) { - @compileError("Incomplete format string: " ++ fmt); - } - } - if (start_index < fmt.len) { - try out_stream.writeAll(fmt[start_index..]); - } -} - -pub fn formatType( - value: var, - comptime fmt: []const u8, - options: FormatOptions, - out_stream: var, - max_depth: usize, -) @TypeOf(out_stream).Error!void { - if (comptime std.mem.eql(u8, fmt, "*")) { - try out_stream.writeAll(@typeName(@TypeOf(value).Child)); - try out_stream.writeAll("@"); - try formatInt(@ptrToInt(value), 16, false, FormatOptions{}, out_stream); - return; - } - - const T = @TypeOf(value); - if (comptime std.meta.trait.hasFn("format")(T)) { - return try value.format(fmt, options, out_stream); - } - - switch (@typeInfo(T)) { - .ComptimeInt, .Int, .Float => { - return formatValue(value, fmt, options, out_stream); - }, - .Void => { - return out_stream.writeAll("void"); - }, - .Bool => { - return out_stream.writeAll(if (value) "true" else "false"); - }, - .Optional => { - if (value) |payload| { - return formatType(payload, fmt, options, out_stream, max_depth); - } else { - return out_stream.writeAll("null"); - } - }, - .ErrorUnion => { - if (value) |payload| { - return formatType(payload, fmt, options, out_stream, max_depth); - } else |err| { - return formatType(err, fmt, options, out_stream, max_depth); - } - }, - .ErrorSet => { - try out_stream.writeAll("error."); - return out_stream.writeAll(@errorName(value)); - }, - .Enum => |enumInfo| { - try out_stream.writeAll(@typeName(T)); - if (enumInfo.is_exhaustive) { - try out_stream.writeAll("."); - try out_stream.writeAll(@tagName(value)); - } else { - // TODO: when @tagName works on exhaustive enums print known enum strings - try out_stream.writeAll("("); - try formatType(@enumToInt(value), fmt, options, out_stream, max_depth); - try out_stream.writeAll(")"); - } - }, - .Union => { - try out_stream.writeAll(@typeName(T)); - if (max_depth == 0) { - return out_stream.writeAll("{ ... }"); - } - const info = @typeInfo(T).Union; - if (info.tag_type) |UnionTagType| { - try out_stream.writeAll("{ ."); - try out_stream.writeAll(@tagName(@as(UnionTagType, value))); - try out_stream.writeAll(" = "); - inline for (info.fields) |u_field| { - if (@enumToInt(@as(UnionTagType, value)) == u_field.enum_field.?.value) { - try formatType(@field(value, u_field.name), fmt, options, out_stream, max_depth - 1); - } - } - try out_stream.writeAll(" }"); - } else { - try format(out_stream, "@{x}", .{@ptrToInt(&value)}); - } - }, - .Struct => |StructT| { - try out_stream.writeAll(@typeName(T)); - if (max_depth == 0) { - return out_stream.writeAll("{ ... }"); - } - try out_stream.writeAll("{"); - inline for (StructT.fields) |f, i| { - if (i == 0) { - try out_stream.writeAll(" ."); - } else { - try out_stream.writeAll(", ."); - } - try out_stream.writeAll(f.name); - try out_stream.writeAll(" = "); - try formatType(@field(value, f.name), fmt, options, out_stream, max_depth - 1); - } - try out_stream.writeAll(" }"); - }, - .Pointer => |ptr_info| switch (ptr_info.size) { - .One => switch (@typeInfo(ptr_info.child)) { - .Array => |info| { - if (info.child == u8) { - return formatText(value, fmt, options, out_stream); - } - return format(out_stream, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) }); - }, - .Enum, .Union, .Struct => { - return formatType(value.*, fmt, options, out_stream, max_depth); - }, - else => return format(out_stream, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) }), - }, - .Many, .C => { - if (ptr_info.sentinel) |sentinel| { - return formatType(mem.span(value), fmt, options, out_stream, max_depth); - } - if (ptr_info.child == u8) { - if (fmt.len > 0 and fmt[0] == 's') { - return formatText(mem.span(value), fmt, options, out_stream); - } - } - return format(out_stream, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) }); - }, - .Slice => { - if (fmt.len > 0 and ((fmt[0] == 'x') or (fmt[0] == 'X'))) { - return formatText(value, fmt, options, out_stream); - } - if (ptr_info.child == u8) { - return formatText(value, fmt, options, out_stream); - } - return format(out_stream, "{}@{x}", .{ @typeName(ptr_info.child), @ptrToInt(value.ptr) }); - }, - }, - .Array => |info| { - const Slice = @Type(builtin.TypeInfo{ - .Pointer = .{ - .size = .Slice, - .is_const = true, - .is_volatile = false, - .is_allowzero = false, - .alignment = @alignOf(info.child), - .child = info.child, - .sentinel = null, - }, - }); - return formatType(@as(Slice, &value), fmt, options, out_stream, max_depth); - }, - .Vector => { - const len = @typeInfo(T).Vector.len; - try out_stream.writeAll("{ "); - var i: usize = 0; - while (i < len) : (i += 1) { - try formatValue(value[i], fmt, options, out_stream); - if (i < len - 1) { - try out_stream.writeAll(", "); - } - } - try out_stream.writeAll(" }"); - }, - .Fn => { - return format(out_stream, "{}@{x}", .{ @typeName(T), @ptrToInt(value) }); - }, - .Type => return out_stream.writeAll(@typeName(T)), - .EnumLiteral => { - const buffer = [_]u8{'.'} ++ @tagName(value); - return formatType(buffer, fmt, options, out_stream, max_depth); - }, - else => @compileError("Unable to format type '" ++ @typeName(T) ++ "'"), - } -} - -fn formatValue( - value: var, - comptime fmt: []const u8, - options: FormatOptions, - out_stream: var, -) !void { - if (comptime std.mem.eql(u8, fmt, "B")) { - return formatBytes(value, options, 1000, out_stream); - } else if (comptime std.mem.eql(u8, fmt, "Bi")) { - return formatBytes(value, options, 1024, out_stream); - } - - const T = @TypeOf(value); - switch (@typeInfo(T)) { - .Float => return formatFloatValue(value, fmt, options, out_stream), - .Int, .ComptimeInt => return formatIntValue(value, fmt, options, out_stream), - .Bool => return out_stream.writeAll(if (value) "true" else "false"), - else => comptime unreachable, - } -} - -pub fn formatIntValue( - value: var, - comptime fmt: []const u8, - options: FormatOptions, - out_stream: var, -) !void { - comptime var radix = 10; - comptime var uppercase = false; - - const int_value = if (@TypeOf(value) == comptime_int) blk: { - const Int = math.IntFittingRange(value, value); - break :blk @as(Int, value); - } else - value; - - if (fmt.len == 0 or comptime std.mem.eql(u8, fmt, "d")) { - radix = 10; - uppercase = false; - } else if (comptime std.mem.eql(u8, fmt, "c")) { - if (@TypeOf(int_value).bit_count <= 8) { - return formatAsciiChar(@as(u8, int_value), options, out_stream); - } else { - @compileError("Cannot print integer that is larger than 8 bits as a ascii"); - } - } else if (comptime std.mem.eql(u8, fmt, "b")) { - radix = 2; - uppercase = false; - } else if (comptime std.mem.eql(u8, fmt, "x")) { - radix = 16; - uppercase = false; - } else if (comptime std.mem.eql(u8, fmt, "X")) { - radix = 16; - uppercase = true; - } else { - @compileError("Unknown format string: '" ++ fmt ++ "'"); - } - - return formatInt(int_value, radix, uppercase, options, out_stream); -} - -fn formatFloatValue( - value: var, - comptime fmt: []const u8, - options: FormatOptions, - out_stream: var, -) !void { - if (fmt.len == 0 or comptime std.mem.eql(u8, fmt, "e")) { - return formatFloatScientific(value, options, out_stream); - } else if (comptime std.mem.eql(u8, fmt, "d")) { - return formatFloatDecimal(value, options, out_stream); - } else { - @compileError("Unknown format string: '" ++ fmt ++ "'"); - } -} - -pub fn formatText( - bytes: []const u8, - comptime fmt: []const u8, - options: FormatOptions, - out_stream: var, -) !void { - if (fmt.len == 0) { - return out_stream.writeAll(bytes); - } else if (comptime std.mem.eql(u8, fmt, "s")) { - return formatBuf(bytes, options, out_stream); - } else if (comptime (std.mem.eql(u8, fmt, "x") or std.mem.eql(u8, fmt, "X"))) { - for (bytes) |c| { - try formatInt(c, 16, fmt[0] == 'X', FormatOptions{ .width = 2, .fill = '0' }, out_stream); - } - return; - } else { - @compileError("Unknown format string: '" ++ fmt ++ "'"); - } -} - -pub fn formatAsciiChar( - c: u8, - options: FormatOptions, - out_stream: var, -) !void { - return out_stream.writeAll(@as(*const [1]u8, &c)[0..]); -} - -pub fn formatBuf( - buf: []const u8, - options: FormatOptions, - out_stream: var, -) !void { - try out_stream.writeAll(buf); - - const width = options.width orelse 0; - var leftover_padding = if (width > buf.len) (width - buf.len) else return; - const pad_byte: u8 = options.fill; - while (leftover_padding > 0) : (leftover_padding -= 1) { - try out_stream.writeAll(@as(*const [1]u8, &pad_byte)[0..1]); - } -} - -// Print a float in scientific notation to the specified precision. Null uses full precision. -// It should be the case that every full precision, printed value can be re-parsed back to the -// same type unambiguously. -pub fn formatFloatScientific( - value: var, - options: FormatOptions, - out_stream: var, -) !void { - var x = @floatCast(f64, value); - - // Errol doesn't handle these special cases. - if (math.signbit(x)) { - try out_stream.writeAll("-"); - x = -x; - } - - if (math.isNan(x)) { - return out_stream.writeAll("nan"); - } - if (math.isPositiveInf(x)) { - return out_stream.writeAll("inf"); - } - if (x == 0.0) { - try out_stream.writeAll("0"); - - if (options.precision) |precision| { - if (precision != 0) { - try out_stream.writeAll("."); - var i: usize = 0; - while (i < precision) : (i += 1) { - try out_stream.writeAll("0"); - } - } - } else { - try out_stream.writeAll(".0"); - } - - try out_stream.writeAll("e+00"); - return; - } - - var buffer: [32]u8 = undefined; - var float_decimal = errol.errol3(x, buffer[0..]); - - if (options.precision) |precision| { - errol.roundToPrecision(&float_decimal, precision, errol.RoundMode.Scientific); - - try out_stream.writeAll(float_decimal.digits[0..1]); - - // {e0} case prints no `.` - if (precision != 0) { - try out_stream.writeAll("."); - - var printed: usize = 0; - if (float_decimal.digits.len > 1) { - const num_digits = math.min(float_decimal.digits.len, precision + 1); - try out_stream.writeAll(float_decimal.digits[1..num_digits]); - printed += num_digits - 1; - } - - while (printed < precision) : (printed += 1) { - try out_stream.writeAll("0"); - } - } - } else { - try out_stream.writeAll(float_decimal.digits[0..1]); - try out_stream.writeAll("."); - if (float_decimal.digits.len > 1) { - const num_digits = if (@TypeOf(value) == f32) math.min(@as(usize, 9), float_decimal.digits.len) else float_decimal.digits.len; - - try out_stream.writeAll(float_decimal.digits[1..num_digits]); - } else { - try out_stream.writeAll("0"); - } - } - - try out_stream.writeAll("e"); - const exp = float_decimal.exp - 1; - - if (exp >= 0) { - try out_stream.writeAll("+"); - if (exp > -10 and exp < 10) { - try out_stream.writeAll("0"); - } - try formatInt(exp, 10, false, FormatOptions{ .width = 0 }, out_stream); - } else { - try out_stream.writeAll("-"); - if (exp > -10 and exp < 10) { - try out_stream.writeAll("0"); - } - try formatInt(-exp, 10, false, FormatOptions{ .width = 0 }, out_stream); - } -} - -// Print a float of the format x.yyyyy where the number of y is specified by the precision argument. -// By default floats are printed at full precision (no rounding). -pub fn formatFloatDecimal( - value: var, - options: FormatOptions, - out_stream: var, -) !void { - var x = @as(f64, value); - - // Errol doesn't handle these special cases. - if (math.signbit(x)) { - try out_stream.writeAll("-"); - x = -x; - } - - if (math.isNan(x)) { - return out_stream.writeAll("nan"); - } - if (math.isPositiveInf(x)) { - return out_stream.writeAll("inf"); - } - if (x == 0.0) { - try out_stream.writeAll("0"); - - if (options.precision) |precision| { - if (precision != 0) { - try out_stream.writeAll("."); - var i: usize = 0; - while (i < precision) : (i += 1) { - try out_stream.writeAll("0"); - } - } else { - try out_stream.writeAll(".0"); - } - } - - return; - } - - // non-special case, use errol3 - var buffer: [32]u8 = undefined; - var float_decimal = errol.errol3(x, buffer[0..]); - - if (options.precision) |precision| { - errol.roundToPrecision(&float_decimal, precision, errol.RoundMode.Decimal); - - // exp < 0 means the leading is always 0 as errol result is normalized. - var num_digits_whole = if (float_decimal.exp > 0) @intCast(usize, float_decimal.exp) else 0; - - // the actual slice into the buffer, we may need to zero-pad between num_digits_whole and this. - var num_digits_whole_no_pad = math.min(num_digits_whole, float_decimal.digits.len); - - if (num_digits_whole > 0) { - // We may have to zero pad, for instance 1e4 requires zero padding. - try out_stream.writeAll(float_decimal.digits[0..num_digits_whole_no_pad]); - - var i = num_digits_whole_no_pad; - while (i < num_digits_whole) : (i += 1) { - try out_stream.writeAll("0"); - } - } else { - try out_stream.writeAll("0"); - } - - // {.0} special case doesn't want a trailing '.' - if (precision == 0) { - return; - } - - try out_stream.writeAll("."); - - // Keep track of fractional count printed for case where we pre-pad then post-pad with 0's. - var printed: usize = 0; - - // Zero-fill until we reach significant digits or run out of precision. - if (float_decimal.exp <= 0) { - const zero_digit_count = @intCast(usize, -float_decimal.exp); - const zeros_to_print = math.min(zero_digit_count, precision); - - var i: usize = 0; - while (i < zeros_to_print) : (i += 1) { - try out_stream.writeAll("0"); - printed += 1; - } - - if (printed >= precision) { - return; - } - } - - // Remaining fractional portion, zero-padding if insufficient. - assert(precision >= printed); - if (num_digits_whole_no_pad + precision - printed < float_decimal.digits.len) { - try out_stream.writeAll(float_decimal.digits[num_digits_whole_no_pad .. num_digits_whole_no_pad + precision - printed]); - return; - } else { - try out_stream.writeAll(float_decimal.digits[num_digits_whole_no_pad..]); - printed += float_decimal.digits.len - num_digits_whole_no_pad; - - while (printed < precision) : (printed += 1) { - try out_stream.writeAll("0"); - } - } - } else { - // exp < 0 means the leading is always 0 as errol result is normalized. - var num_digits_whole = if (float_decimal.exp > 0) @intCast(usize, float_decimal.exp) else 0; - - // the actual slice into the buffer, we may need to zero-pad between num_digits_whole and this. - var num_digits_whole_no_pad = math.min(num_digits_whole, float_decimal.digits.len); - - if (num_digits_whole > 0) { - // We may have to zero pad, for instance 1e4 requires zero padding. - try out_stream.writeAll(float_decimal.digits[0..num_digits_whole_no_pad]); - - var i = num_digits_whole_no_pad; - while (i < num_digits_whole) : (i += 1) { - try out_stream.writeAll("0"); - } - } else { - try out_stream.writeAll("0"); - } - - // Omit `.` if no fractional portion - if (float_decimal.exp >= 0 and num_digits_whole_no_pad == float_decimal.digits.len) { - return; - } - - try out_stream.writeAll("."); - - // Zero-fill until we reach significant digits or run out of precision. - if (float_decimal.exp < 0) { - const zero_digit_count = @intCast(usize, -float_decimal.exp); - - var i: usize = 0; - while (i < zero_digit_count) : (i += 1) { - try out_stream.writeAll("0"); - } - } - - try out_stream.writeAll(float_decimal.digits[num_digits_whole_no_pad..]); - } -} - -pub fn formatBytes( - value: var, - options: FormatOptions, - comptime radix: usize, - out_stream: var, -) !void { - if (value == 0) { - return out_stream.writeAll("0B"); - } - - const mags_si = " kMGTPEZY"; - const mags_iec = " KMGTPEZY"; - const magnitude = switch (radix) { - 1000 => math.min(math.log2(value) / comptime math.log2(1000), mags_si.len - 1), - 1024 => math.min(math.log2(value) / 10, mags_iec.len - 1), - else => unreachable, - }; - const new_value = lossyCast(f64, value) / math.pow(f64, lossyCast(f64, radix), lossyCast(f64, magnitude)); - const suffix = switch (radix) { - 1000 => mags_si[magnitude], - 1024 => mags_iec[magnitude], - else => unreachable, - }; - - try formatFloatDecimal(new_value, options, out_stream); - - if (suffix == ' ') { - return out_stream.writeAll("B"); - } - - const buf = switch (radix) { - 1000 => &[_]u8{ suffix, 'B' }, - 1024 => &[_]u8{ suffix, 'i', 'B' }, - else => unreachable, - }; - return out_stream.writeAll(buf); -} - -pub fn formatInt( - value: var, - base: u8, - uppercase: bool, - options: FormatOptions, - out_stream: var, -) !void { - const int_value = if (@TypeOf(value) == comptime_int) blk: { - const Int = math.IntFittingRange(value, value); - break :blk @as(Int, value); - } else - value; - - if (@TypeOf(int_value).is_signed) { - return formatIntSigned(int_value, base, uppercase, options, out_stream); - } else { - return formatIntUnsigned(int_value, base, uppercase, options, out_stream); - } -} - -fn formatIntSigned( - value: var, - base: u8, - uppercase: bool, - options: FormatOptions, - out_stream: var, -) !void { - const new_options = FormatOptions{ - .width = if (options.width) |w| (if (w == 0) 0 else w - 1) else null, - .precision = options.precision, - .fill = options.fill, - }; - const bit_count = @typeInfo(@TypeOf(value)).Int.bits; - const Uint = std.meta.IntType(false, bit_count); - if (value < 0) { - try out_stream.writeAll("-"); - const new_value = math.absCast(value); - return formatIntUnsigned(new_value, base, uppercase, new_options, out_stream); - } else if (options.width == null or options.width.? == 0) { - return formatIntUnsigned(@intCast(Uint, value), base, uppercase, options, out_stream); - } else { - try out_stream.writeAll("+"); - const new_value = @intCast(Uint, value); - return formatIntUnsigned(new_value, base, uppercase, new_options, out_stream); - } -} - -fn formatIntUnsigned( - value: var, - base: u8, - uppercase: bool, - options: FormatOptions, - out_stream: var, -) !void { - assert(base >= 2); - var buf: [math.max(@TypeOf(value).bit_count, 1)]u8 = undefined; - const min_int_bits = comptime math.max(@TypeOf(value).bit_count, @TypeOf(base).bit_count); - const MinInt = std.meta.IntType(@TypeOf(value).is_signed, min_int_bits); - var a: MinInt = value; - var index: usize = buf.len; - - while (true) { - const digit = a % base; - index -= 1; - buf[index] = digitToChar(@intCast(u8, digit), uppercase); - a /= base; - if (a == 0) break; - } - - const digits_buf = buf[index..]; - const width = options.width orelse 0; - const padding = if (width > digits_buf.len) (width - digits_buf.len) else 0; - - if (padding > index) { - const zero_byte: u8 = options.fill; - var leftover_padding = padding - index; - while (true) { - try out_stream.writeAll(@as(*const [1]u8, &zero_byte)[0..]); - leftover_padding -= 1; - if (leftover_padding == 0) break; - } - mem.set(u8, buf[0..index], options.fill); - return out_stream.writeAll(&buf); - } else { - const padded_buf = buf[index - padding ..]; - mem.set(u8, padded_buf[0..padding], options.fill); - return out_stream.writeAll(padded_buf); - } -} - -pub fn formatIntBuf(out_buf: []u8, value: var, base: u8, uppercase: bool, options: FormatOptions) usize { - var fbs = std.io.fixedBufferStream(out_buf); - formatInt(value, base, uppercase, options, fbs.outStream()) catch unreachable; - return fbs.pos; -} - -pub fn parseInt(comptime T: type, buf: []const u8, radix: u8) !T { - if (!T.is_signed) return parseUnsigned(T, buf, radix); - if (buf.len == 0) return @as(T, 0); - if (buf[0] == '-') { - return math.negate(try parseUnsigned(T, buf[1..], radix)); - } else if (buf[0] == '+') { - return parseUnsigned(T, buf[1..], radix); - } else { - return parseUnsigned(T, buf, radix); - } -} - -test "parseInt" { - std.testing.expect((parseInt(i32, "-10", 10) catch unreachable) == -10); - std.testing.expect((parseInt(i32, "+10", 10) catch unreachable) == 10); - std.testing.expect(if (parseInt(i32, " 10", 10)) |_| false else |err| err == error.InvalidCharacter); - std.testing.expect(if (parseInt(i32, "10 ", 10)) |_| false else |err| err == error.InvalidCharacter); - std.testing.expect(if (parseInt(u32, "-10", 10)) |_| false else |err| err == error.InvalidCharacter); - std.testing.expect((parseInt(u8, "255", 10) catch unreachable) == 255); - std.testing.expect(if (parseInt(u8, "256", 10)) |_| false else |err| err == error.Overflow); -} - -pub const ParseUnsignedError = error{ - /// The result cannot fit in the type specified - Overflow, - - /// The input had a byte that was not a digit - InvalidCharacter, -}; - -pub fn parseUnsigned(comptime T: type, buf: []const u8, radix: u8) ParseUnsignedError!T { - var x: T = 0; - - for (buf) |c| { - const digit = try charToDigit(c, radix); - - if (x != 0) x = try math.mul(T, x, try math.cast(T, radix)); - x = try math.add(T, x, try math.cast(T, digit)); - } - - return x; -} - -test "parseUnsigned" { - std.testing.expect((try parseUnsigned(u16, "050124", 10)) == 50124); - std.testing.expect((try parseUnsigned(u16, "65535", 10)) == 65535); - std.testing.expectError(error.Overflow, parseUnsigned(u16, "65536", 10)); - - std.testing.expect((try parseUnsigned(u64, "0ffffffffffffffff", 16)) == 0xffffffffffffffff); - std.testing.expectError(error.Overflow, parseUnsigned(u64, "10000000000000000", 16)); - - std.testing.expect((try parseUnsigned(u32, "DeadBeef", 16)) == 0xDEADBEEF); - - std.testing.expect((try parseUnsigned(u7, "1", 10)) == 1); - std.testing.expect((try parseUnsigned(u7, "1000", 2)) == 8); - - std.testing.expectError(error.InvalidCharacter, parseUnsigned(u32, "f", 10)); - std.testing.expectError(error.InvalidCharacter, parseUnsigned(u8, "109", 8)); - - std.testing.expect((try parseUnsigned(u32, "NUMBER", 36)) == 1442151747); - - // these numbers should fit even though the radix itself doesn't fit in the destination type - std.testing.expect((try parseUnsigned(u1, "0", 10)) == 0); - std.testing.expect((try parseUnsigned(u1, "1", 10)) == 1); - std.testing.expectError(error.Overflow, parseUnsigned(u1, "2", 10)); - std.testing.expect((try parseUnsigned(u1, "001", 16)) == 1); - std.testing.expect((try parseUnsigned(u2, "3", 16)) == 3); - std.testing.expectError(error.Overflow, parseUnsigned(u2, "4", 16)); -} - -pub const parseFloat = @import("fmt/parse_float.zig").parseFloat; - -test "parseFloat" { - _ = @import("fmt/parse_float.zig"); -} - -pub fn charToDigit(c: u8, radix: u8) (error{InvalidCharacter}!u8) { - const value = switch (c) { - '0'...'9' => c - '0', - 'A'...'Z' => c - 'A' + 10, - 'a'...'z' => c - 'a' + 10, - else => return error.InvalidCharacter, - }; - - if (value >= radix) return error.InvalidCharacter; - - return value; -} - -fn digitToChar(digit: u8, uppercase: bool) u8 { - return switch (digit) { - 0...9 => digit + '0', - 10...35 => digit + ((if (uppercase) @as(u8, 'A') else @as(u8, 'a')) - 10), - else => unreachable, - }; -} - -pub const BufPrintError = error{ - /// As much as possible was written to the buffer, but it was too small to fit all the printed bytes. - BufferTooSmall, -}; -pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: var) BufPrintError![]u8 { - var fbs = std.io.fixedBufferStream(buf); - format(fbs.outStream(), fmt, args) catch |err| switch (err) { - error.NoSpaceLeft => return error.BufferTooSmall, - }; - //TODO: should we change one of these return signatures? - //return fbs.getWritten(); - return buf[0..fbs.pos]; -} - -// Count the characters needed for format. Useful for preallocating memory -pub fn count(comptime fmt: []const u8, args: var) !usize { - var counting_stream = std.io.countingOutStream(std.io.null_out_stream); - format(counting_stream.outStream(), fmt, args) catch |err| switch (err) {}; - return std.math.cast(usize, counting_stream.bytes_written); -} - -pub const AllocPrintError = error{OutOfMemory}; - -pub fn allocPrint(allocator: *mem.Allocator, comptime fmt: []const u8, args: var) AllocPrintError![]u8 { - const size = count(fmt, args) catch |err| switch (err) { - // Output too long. Can't possibly allocate enough memory to display it. - error.Overflow => return error.OutOfMemory, - }; - const buf = try allocator.alloc(u8, size); - return bufPrint(buf, fmt, args) catch |err| switch (err) { - error.BufferTooSmall => unreachable, // we just counted the size above - }; -} - -pub fn allocPrint0(allocator: *mem.Allocator, comptime fmt: []const u8, args: var) AllocPrintError![:0]u8 { - const result = try allocPrint(allocator, fmt ++ "\x00", args); - return result[0 .. result.len - 1 :0]; -} - -test "bufPrintInt" { - var buffer: [100]u8 = undefined; - const buf = buffer[0..]; - - std.testing.expectEqualSlices(u8, "-1", bufPrintIntToSlice(buf, @as(i1, -1), 10, false, FormatOptions{})); - - std.testing.expectEqualSlices(u8, "-101111000110000101001110", bufPrintIntToSlice(buf, @as(i32, -12345678), 2, false, FormatOptions{})); - std.testing.expectEqualSlices(u8, "-12345678", bufPrintIntToSlice(buf, @as(i32, -12345678), 10, false, FormatOptions{})); - std.testing.expectEqualSlices(u8, "-bc614e", bufPrintIntToSlice(buf, @as(i32, -12345678), 16, false, FormatOptions{})); - std.testing.expectEqualSlices(u8, "-BC614E", bufPrintIntToSlice(buf, @as(i32, -12345678), 16, true, FormatOptions{})); - - std.testing.expectEqualSlices(u8, "12345678", bufPrintIntToSlice(buf, @as(u32, 12345678), 10, true, FormatOptions{})); - - std.testing.expectEqualSlices(u8, " 666", bufPrintIntToSlice(buf, @as(u32, 666), 10, false, FormatOptions{ .width = 6 })); - std.testing.expectEqualSlices(u8, " 1234", bufPrintIntToSlice(buf, @as(u32, 0x1234), 16, false, FormatOptions{ .width = 6 })); - std.testing.expectEqualSlices(u8, "1234", bufPrintIntToSlice(buf, @as(u32, 0x1234), 16, false, FormatOptions{ .width = 1 })); - - std.testing.expectEqualSlices(u8, "+42", bufPrintIntToSlice(buf, @as(i32, 42), 10, false, FormatOptions{ .width = 3 })); - std.testing.expectEqualSlices(u8, "-42", bufPrintIntToSlice(buf, @as(i32, -42), 10, false, FormatOptions{ .width = 3 })); -} - -fn bufPrintIntToSlice(buf: []u8, value: var, base: u8, uppercase: bool, options: FormatOptions) []u8 { - return buf[0..formatIntBuf(buf, value, base, uppercase, options)]; -} - -test "parse u64 digit too big" { - _ = parseUnsigned(u64, "123a", 10) catch |err| { - if (err == error.InvalidCharacter) return; - unreachable; - }; - unreachable; -} - -test "parse unsigned comptime" { - comptime { - std.testing.expect((try parseUnsigned(usize, "2", 10)) == 2); - } -} - -test "optional" { - { - const value: ?i32 = 1234; - try testFmt("optional: 1234\n", "optional: {}\n", .{value}); - } - { - const value: ?i32 = null; - try testFmt("optional: null\n", "optional: {}\n", .{value}); - } -} - -test "error" { - { - const value: anyerror!i32 = 1234; - try testFmt("error union: 1234\n", "error union: {}\n", .{value}); - } - { - const value: anyerror!i32 = error.InvalidChar; - try testFmt("error union: error.InvalidChar\n", "error union: {}\n", .{value}); - } -} - -test "int.small" { - { - const value: u3 = 0b101; - try testFmt("u3: 5\n", "u3: {}\n", .{value}); - } -} - -test "int.specifier" { - { - const value: u8 = 'a'; - try testFmt("u8: a\n", "u8: {c}\n", .{value}); - } - { - const value: u8 = 0b1100; - try testFmt("u8: 0b1100\n", "u8: 0b{b}\n", .{value}); - } -} - -test "int.padded" { - try testFmt("u8: ' 1'", "u8: '{:4}'", .{@as(u8, 1)}); - try testFmt("u8: 'xxx1'", "u8: '{:x<4}'", .{@as(u8, 1)}); -} - -test "buffer" { - { - var buf1: [32]u8 = undefined; - var fbs = std.io.fixedBufferStream(&buf1); - try formatType(1234, "", FormatOptions{}, fbs.outStream(), default_max_depth); - std.testing.expect(mem.eql(u8, fbs.getWritten(), "1234")); - - fbs.reset(); - try formatType('a', "c", FormatOptions{}, fbs.outStream(), default_max_depth); - std.testing.expect(mem.eql(u8, fbs.getWritten(), "a")); - - fbs.reset(); - try formatType(0b1100, "b", FormatOptions{}, fbs.outStream(), default_max_depth); - std.testing.expect(mem.eql(u8, fbs.getWritten(), "1100")); - } -} - -test "array" { - { - const value: [3]u8 = "abc".*; - try testFmt("array: abc\n", "array: {}\n", .{value}); - try testFmt("array: abc\n", "array: {}\n", .{&value}); - - var buf: [100]u8 = undefined; - try testFmt( - try bufPrint(buf[0..], "array: [3]u8@{x}\n", .{@ptrToInt(&value)}), - "array: {*}\n", - .{&value}, - ); - } -} - -test "slice" { - { - const value: []const u8 = "abc"; - try testFmt("slice: abc\n", "slice: {}\n", .{value}); - } - { - const value = @intToPtr([*]align(1) const []const u8, 0xdeadbeef)[0..0]; - try testFmt("slice: []const u8@deadbeef\n", "slice: {}\n", .{value}); - } - - try testFmt("buf: Test \n", "buf: {s:5}\n", .{"Test"}); - try testFmt("buf: Test\n Other text", "buf: {s}\n Other text", .{"Test"}); -} - -test "pointer" { - { - const value = @intToPtr(*align(1) i32, 0xdeadbeef); - try testFmt("pointer: i32@deadbeef\n", "pointer: {}\n", .{value}); - try testFmt("pointer: i32@deadbeef\n", "pointer: {*}\n", .{value}); - } - { - const value = @intToPtr(fn () void, 0xdeadbeef); - try testFmt("pointer: fn() void@deadbeef\n", "pointer: {}\n", .{value}); - } - { - const value = @intToPtr(fn () void, 0xdeadbeef); - try testFmt("pointer: fn() void@deadbeef\n", "pointer: {}\n", .{value}); - } -} - -test "cstr" { - try testFmt( - "cstr: Test C\n", - "cstr: {s}\n", - .{@ptrCast([*c]const u8, "Test C")}, - ); - try testFmt( - "cstr: Test C \n", - "cstr: {s:10}\n", - .{@ptrCast([*c]const u8, "Test C")}, - ); -} - -test "filesize" { - try testFmt("file size: 63MiB\n", "file size: {Bi}\n", .{@as(usize, 63 * 1024 * 1024)}); - try testFmt("file size: 66.06MB\n", "file size: {B:.2}\n", .{@as(usize, 63 * 1024 * 1024)}); -} - -test "struct" { - { - const Struct = struct { - field: u8, - }; - const value = Struct{ .field = 42 }; - try testFmt("struct: Struct{ .field = 42 }\n", "struct: {}\n", .{value}); - try testFmt("struct: Struct{ .field = 42 }\n", "struct: {}\n", .{&value}); - } - { - const Struct = struct { - a: u0, - b: u1, - }; - const value = Struct{ .a = 0, .b = 1 }; - try testFmt("struct: Struct{ .a = 0, .b = 1 }\n", "struct: {}\n", .{value}); - } -} - -test "enum" { - const Enum = enum { - One, - Two, - }; - const value = Enum.Two; - try testFmt("enum: Enum.Two\n", "enum: {}\n", .{value}); - try testFmt("enum: Enum.Two\n", "enum: {}\n", .{&value}); -} - -test "non-exhaustive enum" { - const Enum = enum(u16) { - One = 0x000f, - Two = 0xbeef, - _, - }; - try testFmt("enum: Enum(15)\n", "enum: {}\n", .{Enum.One}); - try testFmt("enum: Enum(48879)\n", "enum: {}\n", .{Enum.Two}); - try testFmt("enum: Enum(4660)\n", "enum: {}\n", .{@intToEnum(Enum, 0x1234)}); - try testFmt("enum: Enum(f)\n", "enum: {x}\n", .{Enum.One}); - try testFmt("enum: Enum(beef)\n", "enum: {x}\n", .{Enum.Two}); - try testFmt("enum: Enum(1234)\n", "enum: {x}\n", .{@intToEnum(Enum, 0x1234)}); -} - -test "float.scientific" { - try testFmt("f32: 1.34000003e+00", "f32: {e}", .{@as(f32, 1.34)}); - try testFmt("f32: 1.23400001e+01", "f32: {e}", .{@as(f32, 12.34)}); - try testFmt("f64: -1.234e+11", "f64: {e}", .{@as(f64, -12.34e10)}); - try testFmt("f64: 9.99996e-40", "f64: {e}", .{@as(f64, 9.999960e-40)}); -} - -test "float.scientific.precision" { - try testFmt("f64: 1.40971e-42", "f64: {e:.5}", .{@as(f64, 1.409706e-42)}); - try testFmt("f64: 1.00000e-09", "f64: {e:.5}", .{@as(f64, @bitCast(f32, @as(u32, 814313563)))}); - try testFmt("f64: 7.81250e-03", "f64: {e:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1006632960)))}); - // libc rounds 1.000005e+05 to 1.00000e+05 but zig does 1.00001e+05. - // In fact, libc doesn't round a lot of 5 cases up when one past the precision point. - try testFmt("f64: 1.00001e+05", "f64: {e:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1203982400)))}); -} - -test "float.special" { - try testFmt("f64: nan", "f64: {}", .{math.nan_f64}); - // negative nan is not defined by IEE 754, - // and ARM thus normalizes it to positive nan - if (builtin.arch != builtin.Arch.arm) { - try testFmt("f64: -nan", "f64: {}", .{-math.nan_f64}); - } - try testFmt("f64: inf", "f64: {}", .{math.inf_f64}); - try testFmt("f64: -inf", "f64: {}", .{-math.inf_f64}); -} - -test "float.decimal" { - try testFmt("f64: 152314000000000000000000000000", "f64: {d}", .{@as(f64, 1.52314e+29)}); - try testFmt("f32: 0", "f32: {d}", .{@as(f32, 0.0)}); - try testFmt("f32: 1.1", "f32: {d:.1}", .{@as(f32, 1.1234)}); - try testFmt("f32: 1234.57", "f32: {d:.2}", .{@as(f32, 1234.567)}); - // -11.1234 is converted to f64 -11.12339... internally (errol3() function takes f64). - // -11.12339... is rounded back up to -11.1234 - try testFmt("f32: -11.1234", "f32: {d:.4}", .{@as(f32, -11.1234)}); - try testFmt("f32: 91.12345", "f32: {d:.5}", .{@as(f32, 91.12345)}); - try testFmt("f64: 91.1234567890", "f64: {d:.10}", .{@as(f64, 91.12345678901235)}); - try testFmt("f64: 0.00000", "f64: {d:.5}", .{@as(f64, 0.0)}); - try testFmt("f64: 6", "f64: {d:.0}", .{@as(f64, 5.700)}); - try testFmt("f64: 10.0", "f64: {d:.1}", .{@as(f64, 9.999)}); - try testFmt("f64: 1.000", "f64: {d:.3}", .{@as(f64, 1.0)}); - try testFmt("f64: 0.00030000", "f64: {d:.8}", .{@as(f64, 0.0003)}); - try testFmt("f64: 0.00000", "f64: {d:.5}", .{@as(f64, 1.40130e-45)}); - try testFmt("f64: 0.00000", "f64: {d:.5}", .{@as(f64, 9.999960e-40)}); -} - -test "float.libc.sanity" { - try testFmt("f64: 0.00001", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 916964781)))}); - try testFmt("f64: 0.00001", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 925353389)))}); - try testFmt("f64: 0.10000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1036831278)))}); - try testFmt("f64: 1.00000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1065353133)))}); - try testFmt("f64: 10.00000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1092616192)))}); - - // libc differences - // - // This is 0.015625 exactly according to gdb. We thus round down, - // however glibc rounds up for some reason. This occurs for all - // floats of the form x.yyyy25 on a precision point. - try testFmt("f64: 0.01563", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1015021568)))}); - // errol3 rounds to ... 630 but libc rounds to ...632. Grisu3 - // also rounds to 630 so I'm inclined to believe libc is not - // optimal here. - try testFmt("f64: 18014400656965630.00000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1518338049)))}); -} - -test "custom" { - const Vec2 = struct { - const SelfType = @This(); - x: f32, - y: f32, - - pub fn format( - self: SelfType, - comptime fmt: []const u8, - options: FormatOptions, - out_stream: var, - ) !void { - if (fmt.len == 0 or comptime std.mem.eql(u8, fmt, "p")) { - return std.fmtstream.format(out_stream, "({d:.3},{d:.3})", .{ self.x, self.y }); - } else if (comptime std.mem.eql(u8, fmt, "d")) { - return std.fmtstream.format(out_stream, "{d:.3}x{d:.3}", .{ self.x, self.y }); - } else { - @compileError("Unknown format character: '" ++ fmt ++ "'"); - } - } - }; - - var buf1: [32]u8 = undefined; - var value = Vec2{ - .x = 10.2, - .y = 2.22, - }; - try testFmt("point: (10.200,2.220)\n", "point: {}\n", .{&value}); - try testFmt("dim: 10.200x2.220\n", "dim: {d}\n", .{&value}); - - // same thing but not passing a pointer - try testFmt("point: (10.200,2.220)\n", "point: {}\n", .{value}); - try testFmt("dim: 10.200x2.220\n", "dim: {d}\n", .{value}); -} - -test "struct" { - const S = struct { - a: u32, - b: anyerror, - }; - - const inst = S{ - .a = 456, - .b = error.Unused, - }; - - try testFmt("S{ .a = 456, .b = error.Unused }", "{}", .{inst}); -} - -test "union" { - const TU = union(enum) { - float: f32, - int: u32, - }; - - const UU = union { - float: f32, - int: u32, - }; - - const EU = extern union { - float: f32, - int: u32, - }; - - const tu_inst = TU{ .int = 123 }; - const uu_inst = UU{ .int = 456 }; - const eu_inst = EU{ .float = 321.123 }; - - try testFmt("TU{ .int = 123 }", "{}", .{tu_inst}); - - var buf: [100]u8 = undefined; - const uu_result = try bufPrint(buf[0..], "{}", .{uu_inst}); - std.testing.expect(mem.eql(u8, uu_result[0..3], "UU@")); - - const eu_result = try bufPrint(buf[0..], "{}", .{eu_inst}); - std.testing.expect(mem.eql(u8, uu_result[0..3], "EU@")); -} - -test "enum" { - const E = enum { - One, - Two, - Three, - }; - - const inst = E.Two; - - try testFmt("E.Two", "{}", .{inst}); -} - -test "struct.self-referential" { - const S = struct { - const SelfType = @This(); - a: ?*SelfType, - }; - - var inst = S{ - .a = null, - }; - inst.a = &inst; - - try testFmt("S{ .a = S{ .a = S{ .a = S{ ... } } } }", "{}", .{inst}); -} - -test "struct.zero-size" { - const A = struct { - fn foo() void {} - }; - const B = struct { - a: A, - c: i32, - }; - - const a = A{}; - const b = B{ .a = a, .c = 0 }; - - try testFmt("B{ .a = A{ }, .c = 0 }", "{}", .{b}); -} - -test "bytes.hex" { - const some_bytes = "\xCA\xFE\xBA\xBE"; - try testFmt("lowercase: cafebabe\n", "lowercase: {x}\n", .{some_bytes}); - try testFmt("uppercase: CAFEBABE\n", "uppercase: {X}\n", .{some_bytes}); - //Test Slices - try testFmt("uppercase: CAFE\n", "uppercase: {X}\n", .{some_bytes[0..2]}); - try testFmt("lowercase: babe\n", "lowercase: {x}\n", .{some_bytes[2..]}); - const bytes_with_zeros = "\x00\x0E\xBA\xBE"; - try testFmt("lowercase: 000ebabe\n", "lowercase: {x}\n", .{bytes_with_zeros}); -} - -fn testFmt(expected: []const u8, comptime template: []const u8, args: var) !void { - var buf: [100]u8 = undefined; - const result = try bufPrint(buf[0..], template, args); - if (mem.eql(u8, result, expected)) return; - - std.debug.warn("\n====== expected this output: =========\n", .{}); - std.debug.warn("{}", .{expected}); - std.debug.warn("\n======== instead found this: =========\n", .{}); - std.debug.warn("{}", .{result}); - std.debug.warn("\n======================================\n", .{}); - return error.TestFailed; -} - -pub fn trim(buf: []const u8) []const u8 { - var start: usize = 0; - while (start < buf.len and isWhiteSpace(buf[start])) : (start += 1) {} - - var end: usize = buf.len; - while (true) { - if (end > start) { - const new_end = end - 1; - if (isWhiteSpace(buf[new_end])) { - end = new_end; - continue; - } - } - break; - } - return buf[start..end]; -} - -test "trim" { - std.testing.expect(mem.eql(u8, "abc", trim("\n abc \t"))); - std.testing.expect(mem.eql(u8, "", trim(" "))); - std.testing.expect(mem.eql(u8, "", trim(""))); - std.testing.expect(mem.eql(u8, "abc", trim(" abc"))); - std.testing.expect(mem.eql(u8, "abc", trim("abc "))); -} - -pub fn isWhiteSpace(byte: u8) bool { - return switch (byte) { - ' ', '\t', '\n', '\r' => true, - else => false, - }; -} - -pub fn hexToBytes(out: []u8, input: []const u8) !void { - if (out.len * 2 < input.len) - return error.InvalidLength; - - var in_i: usize = 0; - while (in_i != input.len) : (in_i += 2) { - const hi = try charToDigit(input[in_i], 16); - const lo = try charToDigit(input[in_i + 1], 16); - out[in_i / 2] = (hi << 4) | lo; - } -} - -test "hexToBytes" { - const test_hex_str = "909A312BB12ED1F819B3521AC4C1E896F2160507FFC1C8381E3B07BB16BD1706"; - var pb: [32]u8 = undefined; - try hexToBytes(pb[0..], test_hex_str); - try testFmt(test_hex_str, "{X}", .{pb}); -} - -test "formatIntValue with comptime_int" { - const value: comptime_int = 123456789123456789; - - var buf: [20]u8 = undefined; - var fbs = std.io.fixedBufferStream(&buf); - try formatIntValue(value, "", FormatOptions{}, fbs.outStream()); - std.testing.expect(mem.eql(u8, fbs.getWritten(), "123456789123456789")); -} - -test "formatType max_depth" { - const Vec2 = struct { - const SelfType = @This(); - x: f32, - y: f32, - - pub fn format( - self: SelfType, - comptime fmt: []const u8, - options: FormatOptions, - out_stream: var, - ) !void { - if (fmt.len == 0) { - return std.fmtstream.format(out_stream, "({d:.3},{d:.3})", .{ self.x, self.y }); - } else { - @compileError("Unknown format string: '" ++ fmt ++ "'"); - } - } - }; - const E = enum { - One, - Two, - Three, - }; - const TU = union(enum) { - const SelfType = @This(); - float: f32, - int: u32, - ptr: ?*SelfType, - }; - const S = struct { - const SelfType = @This(); - a: ?*SelfType, - tu: TU, - e: E, - vec: Vec2, - }; - - var inst = S{ - .a = null, - .tu = TU{ .ptr = null }, - .e = E.Two, - .vec = Vec2{ .x = 10.2, .y = 2.22 }, - }; - inst.a = &inst; - inst.tu.ptr = &inst.tu; - - var buf: [1000]u8 = undefined; - var fbs = std.io.fixedBufferStream(&buf); - try formatType(inst, "", FormatOptions{}, fbs.outStream(), 0); - std.testing.expect(mem.eql(u8, fbs.getWritten(), "S{ ... }")); - - fbs.reset(); - try formatType(inst, "", FormatOptions{}, fbs.outStream(), 1); - std.testing.expect(mem.eql(u8, fbs.getWritten(), "S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }")); - - fbs.reset(); - try formatType(inst, "", FormatOptions{}, fbs.outStream(), 2); - std.testing.expect(mem.eql(u8, fbs.getWritten(), "S{ .a = S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ ... } }, .e = E.Two, .vec = (10.200,2.220) }")); - - fbs.reset(); - try formatType(inst, "", FormatOptions{}, fbs.outStream(), 3); - std.testing.expect(mem.eql(u8, fbs.getWritten(), "S{ .a = S{ .a = S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ ... } }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ .ptr = TU{ ... } } }, .e = E.Two, .vec = (10.200,2.220) }")); -} - -test "positional" { - try testFmt("2 1 0", "{2} {1} {0}", .{ @as(usize, 0), @as(usize, 1), @as(usize, 2) }); - try testFmt("2 1 0", "{2} {1} {}", .{ @as(usize, 0), @as(usize, 1), @as(usize, 2) }); - try testFmt("0 0", "{0} {0}", .{@as(usize, 0)}); - try testFmt("0 1", "{} {1}", .{ @as(usize, 0), @as(usize, 1) }); - try testFmt("1 0 0 1", "{1} {} {0} {}", .{ @as(usize, 0), @as(usize, 1) }); -} - -test "positional with specifier" { - try testFmt("10.0", "{0d:.1}", .{@as(f64, 9.999)}); -} - -test "positional/alignment/width/precision" { - try testFmt("10.0", "{0d: >3.1}", .{@as(f64, 9.999)}); -} - -test "vector" { - // https://github.com/ziglang/zig/issues/3317 - if (builtin.arch == .mipsel) return error.SkipZigTest; - - const vbool: @Vector(4, bool) = [_]bool{ true, false, true, false }; - const vi64: @Vector(4, i64) = [_]i64{ -2, -1, 0, 1 }; - const vu64: @Vector(4, u64) = [_]u64{ 1000, 2000, 3000, 4000 }; - - try testFmt("{ true, false, true, false }", "{}", .{vbool}); - try testFmt("{ -2, -1, 0, 1 }", "{}", .{vi64}); - try testFmt("{ - 2, - 1, + 0, + 1 }", "{d:5}", .{vi64}); - try testFmt("{ 1000, 2000, 3000, 4000 }", "{}", .{vu64}); - try testFmt("{ 3e8, 7d0, bb8, fa0 }", "{x}", .{vu64}); - try testFmt("{ 1kB, 2kB, 3kB, 4kB }", "{B}", .{vu64}); - try testFmt("{ 1000B, 1.953125KiB, 2.9296875KiB, 3.90625KiB }", "{Bi}", .{vu64}); -} - -test "enum-literal" { - try testFmt(".hello_world", "{}", .{.hello_world}); -} diff --git a/lib/std/http/headers.zig b/lib/std/http/headers.zig index cb232a3e3e..1e1e71e3eb 100644 --- a/lib/std/http/headers.zig +++ b/lib/std/http/headers.zig @@ -349,7 +349,7 @@ pub const Headers = struct { pub fn format( self: Self, comptime fmt: []const u8, - options: std.fmtstream.FormatOptions, + options: std.fmt.FormatOptions, out_stream: var, ) !void { for (self.toSlice()) |entry| { @@ -591,5 +591,5 @@ test "Headers.format" { \\foo: bar \\cookie: somevalue \\ - , try std.fmtstream.bufPrint(buf[0..], "{}", .{h})); + , try std.fmt.bufPrint(buf[0..], "{}", .{h})); } diff --git a/lib/std/io/out_stream.zig b/lib/std/io/out_stream.zig index 876a3b4701..bf3ae791a1 100644 --- a/lib/std/io/out_stream.zig +++ b/lib/std/io/out_stream.zig @@ -25,7 +25,7 @@ pub fn OutStream( } pub fn print(self: Self, comptime format: []const u8, args: var) Error!void { - return std.fmtstream.format(self, format, args); + return std.fmt.format(self, format, args); } pub fn writeByte(self: Self, byte: u8) Error!void { diff --git a/lib/std/json.zig b/lib/std/json.zig index f3a0811078..f5a72d86da 100644 --- a/lib/std/json.zig +++ b/lib/std/json.zig @@ -2257,10 +2257,10 @@ pub fn stringify( const T = @TypeOf(value); switch (@typeInfo(T)) { .Float, .ComptimeFloat => { - return std.fmtstream.formatFloatScientific(value, std.fmtstream.FormatOptions{}, out_stream); + return std.fmt.formatFloatScientific(value, std.fmt.FormatOptions{}, out_stream); }, .Int, .ComptimeInt => { - return std.fmtstream.formatIntValue(value, "", std.fmtstream.FormatOptions{}, out_stream); + return std.fmt.formatIntValue(value, "", std.fmt.FormatOptions{}, out_stream); }, .Bool => { return out_stream.writeAll(if (value) "true" else "false"); @@ -2350,16 +2350,16 @@ pub fn stringify( // then it may be represented as a six-character sequence: a reverse solidus, followed // by the lowercase letter u, followed by four hexadecimal digits that encode the character's code point. try out_stream.writeAll("\\u"); - try std.fmtstream.formatIntValue(codepoint, "x", std.fmtstream.FormatOptions{ .width = 4, .fill = '0' }, out_stream); + try std.fmt.formatIntValue(codepoint, "x", std.fmt.FormatOptions{ .width = 4, .fill = '0' }, out_stream); } else { // To escape an extended character that is not in the Basic Multilingual Plane, // the character is represented as a 12-character sequence, encoding the UTF-16 surrogate pair. const high = @intCast(u16, (codepoint - 0x10000) >> 10) + 0xD800; const low = @intCast(u16, codepoint & 0x3FF) + 0xDC00; try out_stream.writeAll("\\u"); - try std.fmtstream.formatIntValue(high, "x", std.fmtstream.FormatOptions{ .width = 4, .fill = '0' }, out_stream); + try std.fmt.formatIntValue(high, "x", std.fmt.FormatOptions{ .width = 4, .fill = '0' }, out_stream); try out_stream.writeAll("\\u"); - try std.fmtstream.formatIntValue(low, "x", std.fmtstream.FormatOptions{ .width = 4, .fill = '0' }, out_stream); + try std.fmt.formatIntValue(low, "x", std.fmt.FormatOptions{ .width = 4, .fill = '0' }, out_stream); } i += ulen - 1; }, diff --git a/lib/std/math/big/int.zig b/lib/std/math/big/int.zig index cef2bae98c..95d0764f68 100644 --- a/lib/std/math/big/int.zig +++ b/lib/std/math/big/int.zig @@ -518,7 +518,7 @@ pub const Int = struct { pub fn format( self: Int, comptime fmt: []const u8, - options: std.fmtstream.FormatOptions, + options: std.fmt.FormatOptions, out_stream: var, ) FmtError!void { self.assertWritable(); diff --git a/lib/std/net.zig b/lib/std/net.zig index a1225654f0..c2328b9bd0 100644 --- a/lib/std/net.zig +++ b/lib/std/net.zig @@ -268,14 +268,14 @@ pub const Address = extern union { pub fn format( self: Address, comptime fmt: []const u8, - options: std.fmtstream.FormatOptions, + options: std.fmt.FormatOptions, out_stream: var, ) !void { switch (self.any.family) { os.AF_INET => { const port = mem.bigToNative(u16, self.in.port); const bytes = @ptrCast(*const [4]u8, &self.in.addr); - try std.fmtstream.format(out_stream, "{}.{}.{}.{}:{}", .{ + try std.fmt.format(out_stream, "{}.{}.{}.{}:{}", .{ bytes[0], bytes[1], bytes[2], @@ -286,7 +286,7 @@ pub const Address = extern union { os.AF_INET6 => { const port = mem.bigToNative(u16, self.in6.port); if (mem.eql(u8, self.in6.addr[0..12], &[_]u8{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff })) { - try std.fmtstream.format(out_stream, "[::ffff:{}.{}.{}.{}]:{}", .{ + try std.fmt.format(out_stream, "[::ffff:{}.{}.{}.{}]:{}", .{ self.in6.addr[12], self.in6.addr[13], self.in6.addr[14], @@ -317,19 +317,19 @@ pub const Address = extern union { } continue; } - try std.fmtstream.format(out_stream, "{x}", .{native_endian_parts[i]}); + try std.fmt.format(out_stream, "{x}", .{native_endian_parts[i]}); if (i != native_endian_parts.len - 1) { try out_stream.writeAll(":"); } } - try std.fmtstream.format(out_stream, "]:{}", .{port}); + try std.fmt.format(out_stream, "]:{}", .{port}); }, os.AF_UNIX => { if (!has_unix_sockets) { unreachable; } - try std.fmtstream.format(out_stream, "{}", .{&self.un.path}); + try std.fmt.format(out_stream, "{}", .{&self.un.path}); }, else => unreachable, } @@ -438,7 +438,7 @@ pub fn getAddressList(allocator: *mem.Allocator, name: []const u8, port: u16) !* const name_c = try std.cstr.addNullByte(allocator, name); defer allocator.free(name_c); - const port_c = try std.fmtstream.allocPrint(allocator, "{}\x00", .{port}); + const port_c = try std.fmt.allocPrint(allocator, "{}\x00", .{port}); defer allocator.free(port_c); const hints = os.addrinfo{ diff --git a/lib/std/net/test.zig b/lib/std/net/test.zig index 0dc3b3020d..087f965c4e 100644 --- a/lib/std/net/test.zig +++ b/lib/std/net/test.zig @@ -29,7 +29,7 @@ test "parse and render IPv6 addresses" { }; for (ips) |ip, i| { var addr = net.Address.parseIp6(ip, 0) catch unreachable; - var newIp = std.fmtstream.bufPrint(buffer[0..], "{}", .{addr}) catch unreachable; + var newIp = std.fmt.bufPrint(buffer[0..], "{}", .{addr}) catch unreachable; std.testing.expect(std.mem.eql(u8, printed[i], newIp[1 .. newIp.len - 3])); } @@ -51,7 +51,7 @@ test "parse and render IPv4 addresses" { "127.0.0.1", }) |ip| { var addr = net.Address.parseIp4(ip, 0) catch unreachable; - var newIp = std.fmtstream.bufPrint(buffer[0..], "{}", .{addr}) catch unreachable; + var newIp = std.fmt.bufPrint(buffer[0..], "{}", .{addr}) catch unreachable; std.testing.expect(std.mem.eql(u8, ip, newIp[0 .. newIp.len - 2])); } diff --git a/lib/std/os.zig b/lib/std/os.zig index baea4cecc5..76a5dc2be5 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -3049,7 +3049,7 @@ pub fn realpathC(pathname: [*:0]const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealP defer close(fd); var procfs_buf: ["/proc/self/fd/-2147483648".len:0]u8 = undefined; - const proc_path = std.fmtstream.bufPrint(procfs_buf[0..], "/proc/self/fd/{}\x00", .{fd}) catch unreachable; + const proc_path = std.fmt.bufPrint(procfs_buf[0..], "/proc/self/fd/{}\x00", .{fd}) catch unreachable; return readlinkC(@ptrCast([*:0]const u8, proc_path.ptr), out_buffer); } diff --git a/lib/std/os/uefi.zig b/lib/std/os/uefi.zig index 5d9a678ce8..5c16483ecf 100644 --- a/lib/std/os/uefi.zig +++ b/lib/std/os/uefi.zig @@ -27,11 +27,11 @@ pub const Guid = extern struct { pub fn format( self: @This(), comptime f: []const u8, - options: std.fmtstream.FormatOptions, + options: std.fmt.FormatOptions, out_stream: var, ) Errors!void { if (f.len == 0) { - return std.fmtstream.format(out_stream, "{x:0>8}-{x:0>4}-{x:0>4}-{x:0>2}{x:0>2}-{x:0>12}", .{ + return std.fmt.format(out_stream, "{x:0>8}-{x:0>4}-{x:0>4}-{x:0>2}{x:0>2}-{x:0>12}", .{ self.time_low, self.time_mid, self.time_high_and_version, diff --git a/lib/std/progress.zig b/lib/std/progress.zig index ebb983cdc6..0264d99c91 100644 --- a/lib/std/progress.zig +++ b/lib/std/progress.zig @@ -130,11 +130,11 @@ pub const Progress = struct { var end: usize = 0; if (self.columns_written > 0) { // restore cursor position - end += (std.fmtstream.bufPrint(self.output_buffer[end..], "\x1b[{}D", .{self.columns_written}) catch unreachable).len; + end += (std.fmt.bufPrint(self.output_buffer[end..], "\x1b[{}D", .{self.columns_written}) catch unreachable).len; self.columns_written = 0; // clear rest of line - end += (std.fmtstream.bufPrint(self.output_buffer[end..], "\x1b[0K", .{}) catch unreachable).len; + end += (std.fmt.bufPrint(self.output_buffer[end..], "\x1b[0K", .{}) catch unreachable).len; } if (!self.done) { @@ -185,7 +185,7 @@ pub const Progress = struct { } fn bufWrite(self: *Progress, end: *usize, comptime format: []const u8, args: var) void { - if (std.fmtstream.bufPrint(self.output_buffer[end.*..], format, args)) |written| { + if (std.fmt.bufPrint(self.output_buffer[end.*..], format, args)) |written| { const amt = written.len; end.* += amt; self.columns_written += amt; diff --git a/lib/std/special/build_runner.zig b/lib/std/special/build_runner.zig index c5a96df667..974247e2a1 100644 --- a/lib/std/special/build_runner.zig +++ b/lib/std/special/build_runner.zig @@ -2,7 +2,7 @@ const root = @import("@build"); const std = @import("std"); const builtin = @import("builtin"); const io = std.io; -const fmtstream = std.fmtstream; +const fmt = std.fmt; const Builder = std.build.Builder; const mem = std.mem; const process = std.process; @@ -153,7 +153,7 @@ fn usage(builder: *Builder, already_ran_build: bool, out_stream: var) !void { const allocator = builder.allocator; for (builder.top_level_steps.toSliceConst()) |top_level_step| { const name = if (&top_level_step.step == builder.default_step) - try fmtstream.allocPrint(allocator, "{} (default)", .{top_level_step.step.name}) + try fmt.allocPrint(allocator, "{} (default)", .{top_level_step.step.name}) else top_level_step.step.name; try out_stream.print(" {s:22} {}\n", .{ name, top_level_step.description }); @@ -175,7 +175,7 @@ fn usage(builder: *Builder, already_ran_build: bool, out_stream: var) !void { try out_stream.print(" (none)\n", .{}); } else { for (builder.available_options_list.toSliceConst()) |option| { - const name = try fmtstream.allocPrint(allocator, " -D{}=[{}]", .{ + const name = try fmt.allocPrint(allocator, " -D{}=[{}]", .{ option.name, Builder.typeIdName(option.type_id), }); diff --git a/lib/std/std.zig b/lib/std/std.zig index b7fe709c7c..9277370ca6 100644 --- a/lib/std/std.zig +++ b/lib/std/std.zig @@ -38,7 +38,6 @@ pub const elf = @import("elf.zig"); pub const event = @import("event.zig"); pub const fifo = @import("fifo.zig"); pub const fmt = @import("fmt.zig"); -pub const fmtstream = @import("fmtstream.zig"); pub const fs = @import("fs.zig"); pub const hash = @import("hash.zig"); pub const hash_map = @import("hash_map.zig"); diff --git a/lib/std/target.zig b/lib/std/target.zig index c117f60cc0..8beb7c3011 100644 --- a/lib/std/target.zig +++ b/lib/std/target.zig @@ -972,7 +972,7 @@ pub const Target = struct { } pub fn linuxTripleSimple(allocator: *mem.Allocator, cpu_arch: Cpu.Arch, os_tag: Os.Tag, abi: Abi) ![:0]u8 { - return std.fmtstream.allocPrint0(allocator, "{}-{}-{}", .{ @tagName(cpu_arch), @tagName(os_tag), @tagName(abi) }); + return std.fmt.allocPrint0(allocator, "{}-{}-{}", .{ @tagName(cpu_arch), @tagName(os_tag), @tagName(abi) }); } pub fn linuxTriple(self: Target, allocator: *mem.Allocator) ![:0]u8 { @@ -1158,7 +1158,7 @@ pub const Target = struct { var result: DynamicLinker = .{}; const S = struct { fn print(r: *DynamicLinker, comptime fmt: []const u8, args: var) DynamicLinker { - r.max_byte = @intCast(u8, (std.fmtstream.bufPrint(&r.buffer, fmt, args) catch unreachable).len - 1); + r.max_byte = @intCast(u8, (std.fmt.bufPrint(&r.buffer, fmt, args) catch unreachable).len - 1); return r.*; } fn copy(r: *DynamicLinker, s: []const u8) DynamicLinker { diff --git a/lib/std/zig/cross_target.zig b/lib/std/zig/cross_target.zig index a60833f93c..cec3ea05e5 100644 --- a/lib/std/zig/cross_target.zig +++ b/lib/std/zig/cross_target.zig @@ -573,7 +573,7 @@ pub const CrossTarget = struct { .Dynamic => "", }; - return std.fmtstream.allocPrint0(allocator, "{}-{}{}", .{ arch, os, static_suffix }); + return std.fmt.allocPrint0(allocator, "{}-{}{}", .{ arch, os, static_suffix }); } pub const Executor = union(enum) { diff --git a/lib/std/zig/system.zig b/lib/std/zig/system.zig index 875ecd424c..558b50b5b3 100644 --- a/lib/std/zig/system.zig +++ b/lib/std/zig/system.zig @@ -130,7 +130,7 @@ pub const NativePaths = struct { } pub fn addIncludeDirFmt(self: *NativePaths, comptime fmt: []const u8, args: var) !void { - const item = try std.fmtstream.allocPrint0(self.include_dirs.allocator, fmt, args); + const item = try std.fmt.allocPrint0(self.include_dirs.allocator, fmt, args); errdefer self.include_dirs.allocator.free(item); try self.include_dirs.append(item); } @@ -140,7 +140,7 @@ pub const NativePaths = struct { } pub fn addLibDirFmt(self: *NativePaths, comptime fmt: []const u8, args: var) !void { - const item = try std.fmtstream.allocPrint0(self.lib_dirs.allocator, fmt, args); + const item = try std.fmt.allocPrint0(self.lib_dirs.allocator, fmt, args); errdefer self.lib_dirs.allocator.free(item); try self.lib_dirs.append(item); } @@ -150,7 +150,7 @@ pub const NativePaths = struct { } pub fn addWarningFmt(self: *NativePaths, comptime fmt: []const u8, args: var) !void { - const item = try std.fmtstream.allocPrint0(self.warnings.allocator, fmt, args); + const item = try std.fmt.allocPrint0(self.warnings.allocator, fmt, args); errdefer self.warnings.allocator.free(item); try self.warnings.append(item); } diff --git a/src-self-hosted/compilation.zig b/src-self-hosted/compilation.zig index fdaee7d12f..7a45bb3c37 100644 --- a/src-self-hosted/compilation.zig +++ b/src-self-hosted/compilation.zig @@ -1051,7 +1051,7 @@ pub const Compilation = struct { } fn addCompileError(self: *Compilation, tree_scope: *Scope.AstTree, span: Span, comptime fmt: []const u8, args: var) !void { - const text = try std.fmtstream.allocPrint(self.gpa(), fmt, args); + const text = try std.fmt.allocPrint(self.gpa(), fmt, args); errdefer self.gpa().free(text); const msg = try Msg.createFromScope(self, tree_scope, span, text); @@ -1061,7 +1061,7 @@ pub const Compilation = struct { } fn addCompileErrorCli(self: *Compilation, realpath: []const u8, comptime fmt: []const u8, args: var) !void { - const text = try std.fmtstream.allocPrint(self.gpa(), fmt, args); + const text = try std.fmt.allocPrint(self.gpa(), fmt, args); errdefer self.gpa().free(text); const msg = try Msg.createFromCli(self, realpath, text); @@ -1154,7 +1154,7 @@ pub const Compilation = struct { const tmp_dir = try self.getTmpDir(); const file_prefix = self.getRandomFileName(); - const file_name = try std.fmtstream.allocPrint(self.gpa(), "{}{}", .{ file_prefix[0..], suffix }); + const file_name = try std.fmt.allocPrint(self.gpa(), "{}{}", .{ file_prefix[0..], suffix }); defer self.gpa().free(file_name); const full_path = try fs.path.join(self.gpa(), &[_][]const u8{ tmp_dir, file_name[0..] }); diff --git a/src-self-hosted/dep_tokenizer.zig b/src-self-hosted/dep_tokenizer.zig index 233b678171..c73719ebea 100644 --- a/src-self-hosted/dep_tokenizer.zig +++ b/src-self-hosted/dep_tokenizer.zig @@ -893,7 +893,7 @@ fn printSection(out: var, label: []const u8, bytes: []const u8) !void { fn printLabel(out: var, label: []const u8, bytes: []const u8) !void { var buf: [80]u8 = undefined; - var text = try std.fmtstream.bufPrint(buf[0..], "{} {} bytes ", .{ label, bytes.len }); + var text = try std.fmt.bufPrint(buf[0..], "{} {} bytes ", .{ label, bytes.len }); try out.write(text); var i: usize = text.len; const end = 79; @@ -979,13 +979,13 @@ fn hexDump16(out: var, offset: usize, bytes: []const u8) !void { fn printDecValue(out: var, value: u64, width: u8) !void { var buffer: [20]u8 = undefined; - const len = std.fmtstream.formatIntBuf(buffer[0..], value, 10, false, width); + const len = std.fmt.formatIntBuf(buffer[0..], value, 10, false, width); try out.write(buffer[0..len]); } fn printHexValue(out: var, value: u64, width: u8) !void { var buffer: [16]u8 = undefined; - const len = std.fmtstream.formatIntBuf(buffer[0..], value, 16, false, width); + const len = std.fmt.formatIntBuf(buffer[0..], value, 16, false, width); try out.write(buffer[0..len]); } diff --git a/src-self-hosted/libc_installation.zig b/src-self-hosted/libc_installation.zig index 3b65fb172b..0f9736456a 100644 --- a/src-self-hosted/libc_installation.zig +++ b/src-self-hosted/libc_installation.zig @@ -543,7 +543,7 @@ fn ccPrintFileName(args: CCPrintFileNameOptions) ![:0]u8 { const allocator = args.allocator; const cc_exe = std.os.getenvZ("CC") orelse default_cc_exe; - const arg1 = try std.fmtstream.allocPrint(allocator, "-print-file-name={}", .{args.search_basename}); + const arg1 = try std.fmt.allocPrint(allocator, "-print-file-name={}", .{args.search_basename}); defer allocator.free(arg1); const argv = [_][]const u8{ cc_exe, arg1 }; diff --git a/src-self-hosted/link.zig b/src-self-hosted/link.zig index b63e6c24f4..1efa15574a 100644 --- a/src-self-hosted/link.zig +++ b/src-self-hosted/link.zig @@ -296,13 +296,13 @@ fn constructLinkerArgsCoff(ctx: *Context) !void { const is_library = ctx.comp.kind == .Lib; - const out_arg = try std.fmtstream.allocPrint(&ctx.arena.allocator, "-OUT:{}\x00", .{ctx.out_file_path.toSliceConst()}); + const out_arg = try std.fmt.allocPrint(&ctx.arena.allocator, "-OUT:{}\x00", .{ctx.out_file_path.toSliceConst()}); try ctx.args.append(@ptrCast([*:0]const u8, out_arg.ptr)); if (ctx.comp.haveLibC()) { - try ctx.args.append(@ptrCast([*:0]const u8, (try std.fmtstream.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", .{ctx.libc.msvc_lib_dir.?})).ptr)); - try ctx.args.append(@ptrCast([*:0]const u8, (try std.fmtstream.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", .{ctx.libc.kernel32_lib_dir.?})).ptr)); - try ctx.args.append(@ptrCast([*:0]const u8, (try std.fmtstream.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", .{ctx.libc.lib_dir.?})).ptr)); + try ctx.args.append(@ptrCast([*:0]const u8, (try std.fmt.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", .{ctx.libc.msvc_lib_dir.?})).ptr)); + try ctx.args.append(@ptrCast([*:0]const u8, (try std.fmt.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", .{ctx.libc.kernel32_lib_dir.?})).ptr)); + try ctx.args.append(@ptrCast([*:0]const u8, (try std.fmt.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", .{ctx.libc.lib_dir.?})).ptr)); } if (ctx.link_in_crt) { @@ -310,20 +310,20 @@ fn constructLinkerArgsCoff(ctx: *Context) !void { const d_str = if (ctx.comp.build_mode == .Debug) "d" else ""; if (ctx.comp.is_static) { - const cmt_lib_name = try std.fmtstream.allocPrint(&ctx.arena.allocator, "libcmt{}.lib\x00", .{d_str}); + const cmt_lib_name = try std.fmt.allocPrint(&ctx.arena.allocator, "libcmt{}.lib\x00", .{d_str}); try ctx.args.append(@ptrCast([*:0]const u8, cmt_lib_name.ptr)); } else { - const msvcrt_lib_name = try std.fmtstream.allocPrint(&ctx.arena.allocator, "msvcrt{}.lib\x00", .{d_str}); + const msvcrt_lib_name = try std.fmt.allocPrint(&ctx.arena.allocator, "msvcrt{}.lib\x00", .{d_str}); try ctx.args.append(@ptrCast([*:0]const u8, msvcrt_lib_name.ptr)); } - const vcruntime_lib_name = try std.fmtstream.allocPrint(&ctx.arena.allocator, "{}vcruntime{}.lib\x00", .{ + const vcruntime_lib_name = try std.fmt.allocPrint(&ctx.arena.allocator, "{}vcruntime{}.lib\x00", .{ lib_str, d_str, }); try ctx.args.append(@ptrCast([*:0]const u8, vcruntime_lib_name.ptr)); - const crt_lib_name = try std.fmtstream.allocPrint(&ctx.arena.allocator, "{}ucrt{}.lib\x00", .{ lib_str, d_str }); + const crt_lib_name = try std.fmt.allocPrint(&ctx.arena.allocator, "{}ucrt{}.lib\x00", .{ lib_str, d_str }); try ctx.args.append(@ptrCast([*:0]const u8, crt_lib_name.ptr)); // Visual C++ 2015 Conformance Changes @@ -383,7 +383,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void { .IPhoneOS => try ctx.args.append("-iphoneos_version_min"), .IPhoneOSSimulator => try ctx.args.append("-ios_simulator_version_min"), } - const ver_str = try std.fmtstream.allocPrint(&ctx.arena.allocator, "{}.{}.{}\x00", .{ + const ver_str = try std.fmt.allocPrint(&ctx.arena.allocator, "{}.{}.{}\x00", .{ platform.major, platform.minor, platform.micro, @@ -445,7 +445,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void { try ctx.args.append("-lSystem"); } else { if (mem.indexOfScalar(u8, lib.name, '/') == null) { - const arg = try std.fmtstream.allocPrint(&ctx.arena.allocator, "-l{}\x00", .{lib.name}); + const arg = try std.fmt.allocPrint(&ctx.arena.allocator, "-l{}\x00", .{lib.name}); try ctx.args.append(@ptrCast([*:0]const u8, arg.ptr)); } else { const arg = try std.cstr.addNullByte(&ctx.arena.allocator, lib.name); diff --git a/src-self-hosted/print_targets.zig b/src-self-hosted/print_targets.zig index 408c39fe7b..ad506425d2 100644 --- a/src-self-hosted/print_targets.zig +++ b/src-self-hosted/print_targets.zig @@ -138,7 +138,7 @@ pub fn cmdTargets( for (available_glibcs) |glibc| { try jws.arrayElem(); - const tmp = try std.fmtstream.allocPrint(allocator, "{}", .{glibc}); + const tmp = try std.fmt.allocPrint(allocator, "{}", .{glibc}); defer allocator.free(tmp); try jws.emitString(tmp); } diff --git a/src-self-hosted/test.zig b/src-self-hosted/test.zig index 98e9fb06df..e87164c9fb 100644 --- a/src-self-hosted/test.zig +++ b/src-self-hosted/test.zig @@ -81,7 +81,7 @@ pub const TestContext = struct { msg: []const u8, ) !void { var file_index_buf: [20]u8 = undefined; - const file_index = try std.fmtstream.bufPrint(file_index_buf[0..], "{}", .{self.file_index.incr()}); + const file_index = try std.fmt.bufPrint(file_index_buf[0..], "{}", .{self.file_index.incr()}); const file1_path = try std.fs.path.join(allocator, [_][]const u8{ tmp_dir_name, file_index, file1 }); if (std.fs.path.dirname(file1_path)) |dirname| { @@ -114,10 +114,10 @@ pub const TestContext = struct { expected_output: []const u8, ) !void { var file_index_buf: [20]u8 = undefined; - const file_index = try std.fmtstream.bufPrint(file_index_buf[0..], "{}", .{self.file_index.incr()}); + const file_index = try std.fmt.bufPrint(file_index_buf[0..], "{}", .{self.file_index.incr()}); const file1_path = try std.fs.path.join(allocator, [_][]const u8{ tmp_dir_name, file_index, file1 }); - const output_file = try std.fmtstream.allocPrint(allocator, "{}-out{}", .{ file1_path, (Target{ .Native = {} }).exeFileExt() }); + const output_file = try std.fmt.allocPrint(allocator, "{}-out{}", .{ file1_path, (Target{ .Native = {} }).exeFileExt() }); if (std.fs.path.dirname(file1_path)) |dirname| { try std.fs.cwd().makePath(dirname); } diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig index 7b05a76cb7..89d6f94d7b 100644 --- a/src-self-hosted/translate_c.zig +++ b/src-self-hosted/translate_c.zig @@ -89,7 +89,7 @@ const Scope = struct { var proposed_name = name; while (scope.contains(proposed_name)) { scope.mangle_count += 1; - proposed_name = try std.fmtstream.allocPrint(c.a(), "{}_{}", .{ name, scope.mangle_count }); + proposed_name = try std.fmt.allocPrint(c.a(), "{}_{}", .{ name, scope.mangle_count }); } try scope.variables.push(.{ .name = name, .alias = proposed_name }); return proposed_name; @@ -246,7 +246,7 @@ pub const Context = struct { const line = ZigClangSourceManager_getSpellingLineNumber(c.source_manager, spelling_loc); const column = ZigClangSourceManager_getSpellingColumnNumber(c.source_manager, spelling_loc); - return std.fmtstream.allocPrint(c.a(), "{}:{}:{}", .{ filename, line, column }); + return std.fmt.allocPrint(c.a(), "{}:{}:{}", .{ filename, line, column }); } }; @@ -516,7 +516,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void { const arg_name = blk: { const param_prefix = if (is_const) "" else "arg_"; - const bare_arg_name = try std.fmtstream.allocPrint(c.a(), "{}{}", .{ param_prefix, mangled_param_name }); + const bare_arg_name = try std.fmt.allocPrint(c.a(), "{}{}", .{ param_prefix, mangled_param_name }); break :blk try block_scope.makeMangledName(c, bare_arg_name); }; @@ -560,7 +560,7 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void { // TODO https://github.com/ziglang/zig/issues/3756 // TODO https://github.com/ziglang/zig/issues/1802 - const checked_name = if (isZigPrimitiveType(var_name)) try std.fmtstream.allocPrint(c.a(), "{}_{}", .{var_name, c.getMangle()}) else var_name; + const checked_name = if (isZigPrimitiveType(var_name)) try std.fmt.allocPrint(c.a(), "{}_{}", .{ var_name, c.getMangle() }) else var_name; const var_decl_loc = ZigClangVarDecl_getLocation(var_decl); const qual_type = ZigClangVarDecl_getTypeSourceInfo_getType(var_decl); @@ -620,7 +620,7 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void { _ = try appendToken(rp.c, .LParen, "("); const expr = try transCreateNodeStringLiteral( rp.c, - try std.fmtstream.allocPrint(rp.c.a(), "\"{}\"", .{str_ptr[0..str_len]}), + try std.fmt.allocPrint(rp.c.a(), "\"{}\"", .{str_ptr[0..str_len]}), ); _ = try appendToken(rp.c, .RParen, ")"); @@ -677,7 +677,7 @@ fn transTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl, top_l // TODO https://github.com/ziglang/zig/issues/3756 // TODO https://github.com/ziglang/zig/issues/1802 - const checked_name = if (isZigPrimitiveType(typedef_name)) try std.fmtstream.allocPrint(c.a(), "{}_{}", .{typedef_name, c.getMangle()}) else typedef_name; + const checked_name = if (isZigPrimitiveType(typedef_name)) try std.fmt.allocPrint(c.a(), "{}_{}", .{ typedef_name, c.getMangle() }) else typedef_name; if (mem.eql(u8, checked_name, "uint8_t")) return transTypeDefAsBuiltin(c, typedef_decl, "u8") @@ -738,7 +738,7 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?* // Record declarations such as `struct {...} x` have no name but they're not // anonymous hence here isAnonymousStructOrUnion is not needed if (bare_name.len == 0) { - bare_name = try std.fmtstream.allocPrint(c.a(), "unnamed_{}", .{c.getMangle()}); + bare_name = try std.fmt.allocPrint(c.a(), "unnamed_{}", .{c.getMangle()}); is_unnamed = true; } @@ -755,7 +755,7 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?* return null; } - const name = try std.fmtstream.allocPrint(c.a(), "{}_{}", .{ container_kind_name, bare_name }); + const name = try std.fmt.allocPrint(c.a(), "{}_{}", .{ container_kind_name, bare_name }); _ = try c.decl_table.put(@ptrToInt(ZigClangRecordDecl_getCanonicalDecl(record_decl)), name); const node = try transCreateNodeVarDecl(c, !is_unnamed, true, name); @@ -812,7 +812,7 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?* var is_anon = false; var raw_name = try c.str(ZigClangNamedDecl_getName_bytes_begin(@ptrCast(*const ZigClangNamedDecl, field_decl))); if (ZigClangFieldDecl_isAnonymousStructOrUnion(field_decl)) { - raw_name = try std.fmtstream.allocPrint(c.a(), "unnamed_{}", .{c.getMangle()}); + raw_name = try std.fmt.allocPrint(c.a(), "unnamed_{}", .{c.getMangle()}); is_anon = true; } const field_name = try appendIdentifier(c, raw_name); @@ -882,11 +882,11 @@ fn transEnumDecl(c: *Context, enum_decl: *const ZigClangEnumDecl) Error!?*ast.No var bare_name = try c.str(ZigClangNamedDecl_getName_bytes_begin(@ptrCast(*const ZigClangNamedDecl, enum_decl))); var is_unnamed = false; if (bare_name.len == 0) { - bare_name = try std.fmtstream.allocPrint(c.a(), "unnamed_{}", .{c.getMangle()}); + bare_name = try std.fmt.allocPrint(c.a(), "unnamed_{}", .{c.getMangle()}); is_unnamed = true; } - const name = try std.fmtstream.allocPrint(c.a(), "enum_{}", .{bare_name}); + const name = try std.fmt.allocPrint(c.a(), "enum_{}", .{bare_name}); _ = try c.decl_table.put(@ptrToInt(ZigClangEnumDecl_getCanonicalDecl(enum_decl)), name); const node = try transCreateNodeVarDecl(c, !is_unnamed, true, name); node.eq_token = try appendToken(c, .Equal, "="); @@ -1754,9 +1754,9 @@ fn escapeChar(c: u8, char_buf: *[4]u8) []const u8 { // Handle the remaining escapes Zig doesn't support by turning them // into their respective hex representation if (std.ascii.isCntrl(c)) - return std.fmtstream.bufPrint(char_buf[0..], "\\x{x:0<2}", .{c}) catch unreachable + return std.fmt.bufPrint(char_buf[0..], "\\x{x:0<2}", .{c}) catch unreachable else - return std.fmtstream.bufPrint(char_buf[0..], "{c}", .{c}) catch unreachable; + return std.fmt.bufPrint(char_buf[0..], "{c}", .{c}) catch unreachable; }, }; } @@ -2436,7 +2436,7 @@ fn transCase( ) TransError!*ast.Node { const block_scope = scope.findBlockScope(rp.c) catch unreachable; const switch_scope = scope.getSwitch(); - const label = try std.fmtstream.allocPrint(rp.c.a(), "__case_{}", .{switch_scope.cases.len - @boolToInt(switch_scope.has_default)}); + const label = try std.fmt.allocPrint(rp.c.a(), "__case_{}", .{switch_scope.cases.len - @boolToInt(switch_scope.has_default)}); _ = try appendToken(rp.c, .Semicolon, ";"); const expr = if (ZigClangCaseStmt_getRHS(stmt)) |rhs| blk: { @@ -4607,7 +4607,7 @@ fn finishTransFnProto( _ = try appendToken(rp.c, .LParen, "("); const expr = try transCreateNodeStringLiteral( rp.c, - try std.fmtstream.allocPrint(rp.c.a(), "\"{}\"", .{str_ptr[0..str_len]}), + try std.fmt.allocPrint(rp.c.a(), "\"{}\"", .{str_ptr[0..str_len]}), ); _ = try appendToken(rp.c, .RParen, ")"); @@ -4866,7 +4866,7 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void { const name = try c.str(raw_name); // TODO https://github.com/ziglang/zig/issues/3756 // TODO https://github.com/ziglang/zig/issues/1802 - const mangled_name = if (isZigPrimitiveType(name)) try std.fmtstream.allocPrint(c.a(), "{}_{}", .{name, c.getMangle()}) else name; + const mangled_name = if (isZigPrimitiveType(name)) try std.fmt.allocPrint(c.a(), "{}_{}", .{ name, c.getMangle() }) else name; if (scope.containsNow(mangled_name)) { continue; } @@ -5151,11 +5151,11 @@ fn parseCNumLit(c: *Context, tok: *CToken, source: []const u8, source_loc: ZigCl switch (lit_bytes[1]) { '0'...'7' => { // Octal - lit_bytes = try std.fmtstream.allocPrint(c.a(), "0o{}", .{lit_bytes}); + lit_bytes = try std.fmt.allocPrint(c.a(), "0o{}", .{lit_bytes}); }, 'X' => { // Hexadecimal with capital X, valid in C but not in Zig - lit_bytes = try std.fmtstream.allocPrint(c.a(), "0x{}", .{lit_bytes[2..]}); + lit_bytes = try std.fmt.allocPrint(c.a(), "0x{}", .{lit_bytes[2..]}); }, else => {}, } @@ -5186,7 +5186,7 @@ fn parseCNumLit(c: *Context, tok: *CToken, source: []const u8, source_loc: ZigCl return &cast_node.base; } else if (tok.id == .FloatLiteral) { if (lit_bytes[0] == '.') - lit_bytes = try std.fmtstream.allocPrint(c.a(), "0{}", .{lit_bytes}); + lit_bytes = try std.fmt.allocPrint(c.a(), "0{}", .{lit_bytes}); if (tok.id.FloatLiteral == .None) { return transCreateNodeFloat(c, lit_bytes); } @@ -5319,7 +5319,7 @@ fn zigifyEscapeSequences(ctx: *Context, source_bytes: []const u8, name: []const num += c - 'A' + 10; }, else => { - i += std.fmtstream.formatIntBuf(bytes[i..], num, 16, false, std.fmtstream.FormatOptions{ .fill = '0', .width = 2 }); + i += std.fmt.formatIntBuf(bytes[i..], num, 16, false, std.fmt.FormatOptions{ .fill = '0', .width = 2 }); num = 0; if (c == '\\') state = .Escape @@ -5345,7 +5345,7 @@ fn zigifyEscapeSequences(ctx: *Context, source_bytes: []const u8, name: []const }; num += c - '0'; } else { - i += std.fmtstream.formatIntBuf(bytes[i..], num, 16, false, std.fmtstream.FormatOptions{ .fill = '0', .width = 2 }); + i += std.fmt.formatIntBuf(bytes[i..], num, 16, false, std.fmt.FormatOptions{ .fill = '0', .width = 2 }); num = 0; count = 0; if (c == '\\') @@ -5359,7 +5359,7 @@ fn zigifyEscapeSequences(ctx: *Context, source_bytes: []const u8, name: []const } } if (state == .Hex or state == .Octal) - i += std.fmtstream.formatIntBuf(bytes[i..], num, 16, false, std.fmtstream.FormatOptions{ .fill = '0', .width = 2 }); + i += std.fmt.formatIntBuf(bytes[i..], num, 16, false, std.fmt.FormatOptions{ .fill = '0', .width = 2 }); return bytes[0..i]; } diff --git a/src-self-hosted/type.zig b/src-self-hosted/type.zig index c2b406823d..70ed754cea 100644 --- a/src-self-hosted/type.zig +++ b/src-self-hosted/type.zig @@ -581,7 +581,7 @@ pub const Type = struct { errdefer comp.gpa().destroy(self); const u_or_i = "ui"[@boolToInt(key.is_signed)]; - const name = try std.fmtstream.allocPrint(comp.gpa(), "{c}{}", .{ u_or_i, key.bit_count }); + const name = try std.fmt.allocPrint(comp.gpa(), "{c}{}", .{ u_or_i, key.bit_count }); errdefer comp.gpa().free(name); self.base.init(comp, .Int, name); @@ -764,13 +764,13 @@ pub const Type = struct { .Non => "", }; const name = switch (self.key.alignment) { - .Abi => try std.fmtstream.allocPrint(comp.gpa(), "{}{}{}{}", .{ + .Abi => try std.fmt.allocPrint(comp.gpa(), "{}{}{}{}", .{ size_str, mut_str, vol_str, self.key.child_type.name, }), - .Override => |alignment| try std.fmtstream.allocPrint(comp.gpa(), "{}align<{}> {}{}{}", .{ + .Override => |alignment| try std.fmt.allocPrint(comp.gpa(), "{}align<{}> {}{}{}", .{ size_str, alignment, mut_str, @@ -845,7 +845,7 @@ pub const Type = struct { }; errdefer comp.gpa().destroy(self); - const name = try std.fmtstream.allocPrint(comp.gpa(), "[{}]{}", .{ key.len, key.elem_type.name }); + const name = try std.fmt.allocPrint(comp.gpa(), "[{}]{}", .{ key.len, key.elem_type.name }); errdefer comp.gpa().free(name); self.base.init(comp, .Array, name); diff --git a/test/src/compare_output.zig b/test/src/compare_output.zig index c68eb1eebf..ae994a0697 100644 --- a/test/src/compare_output.zig +++ b/test/src/compare_output.zig @@ -4,7 +4,7 @@ const std = @import("std"); const builtin = std.builtin; const build = std.build; const ArrayList = std.ArrayList; -const fmtstream = std.fmtstream; +const fmt = std.fmt; const mem = std.mem; const fs = std.fs; const warn = std.debug.warn; @@ -97,7 +97,7 @@ pub const CompareOutputContext = struct { switch (case.special) { Special.Asm => { - const annotated_case_name = fmtstream.allocPrint(self.b.allocator, "assemble-and-link {}", .{ + const annotated_case_name = fmt.allocPrint(self.b.allocator, "assemble-and-link {}", .{ case.name, }) catch unreachable; if (self.test_filter) |filter| { @@ -116,7 +116,7 @@ pub const CompareOutputContext = struct { }, Special.None => { for (self.modes) |mode| { - const annotated_case_name = fmtstream.allocPrint(self.b.allocator, "{} {} ({})", .{ + const annotated_case_name = fmt.allocPrint(self.b.allocator, "{} {} ({})", .{ "compare-output", case.name, @tagName(mode), @@ -141,7 +141,7 @@ pub const CompareOutputContext = struct { } }, Special.RuntimeSafety => { - const annotated_case_name = fmtstream.allocPrint(self.b.allocator, "safety {}", .{case.name}) catch unreachable; + const annotated_case_name = fmt.allocPrint(self.b.allocator, "safety {}", .{case.name}) catch unreachable; if (self.test_filter) |filter| { if (mem.indexOf(u8, annotated_case_name, filter) == null) return; } diff --git a/test/src/run_translated_c.zig b/test/src/run_translated_c.zig index 6304137e4a..14b0ce593c 100644 --- a/test/src/run_translated_c.zig +++ b/test/src/run_translated_c.zig @@ -3,7 +3,7 @@ const std = @import("std"); const build = std.build; const ArrayList = std.ArrayList; -const fmtstream = std.fmtstream; +const fmt = std.fmt; const mem = std.mem; const fs = std.fs; const warn = std.debug.warn; @@ -76,7 +76,7 @@ pub const RunTranslatedCContext = struct { pub fn addCase(self: *RunTranslatedCContext, case: *const TestCase) void { const b = self.b; - const annotated_case_name = fmtstream.allocPrint(self.b.allocator, "run-translated-c {}", .{case.name}) catch unreachable; + const annotated_case_name = fmt.allocPrint(self.b.allocator, "run-translated-c {}", .{case.name}) catch unreachable; if (self.test_filter) |filter| { if (mem.indexOf(u8, annotated_case_name, filter) == null) return; } diff --git a/test/src/translate_c.zig b/test/src/translate_c.zig index 250ec6175e..9a6bd0d323 100644 --- a/test/src/translate_c.zig +++ b/test/src/translate_c.zig @@ -3,7 +3,7 @@ const std = @import("std"); const build = std.build; const ArrayList = std.ArrayList; -const fmtstream = std.fmtstream; +const fmt = std.fmt; const mem = std.mem; const fs = std.fs; const warn = std.debug.warn; @@ -99,7 +99,7 @@ pub const TranslateCContext = struct { const b = self.b; const translate_c_cmd = "translate-c"; - const annotated_case_name = fmtstream.allocPrint(self.b.allocator, "{} {}", .{ translate_c_cmd, case.name }) catch unreachable; + const annotated_case_name = fmt.allocPrint(self.b.allocator, "{} {}", .{ translate_c_cmd, case.name }) catch unreachable; if (self.test_filter) |filter| { if (mem.indexOf(u8, annotated_case_name, filter) == null) return; } diff --git a/test/stage1/behavior/enum_with_members.zig b/test/stage1/behavior/enum_with_members.zig index b299301ced..08b195494b 100644 --- a/test/stage1/behavior/enum_with_members.zig +++ b/test/stage1/behavior/enum_with_members.zig @@ -1,6 +1,6 @@ const expect = @import("std").testing.expect; const mem = @import("std").mem; -const fmtstream = @import("std").fmtstream; +const fmt = @import("std").fmt; const ET = union(enum) { SINT: i32, @@ -8,8 +8,8 @@ const ET = union(enum) { pub fn print(a: *const ET, buf: []u8) anyerror!usize { return switch (a.*) { - ET.SINT => |x| fmtstream.formatIntBuf(buf, x, 10, false, fmtstream.FormatOptions{}), - ET.UINT => |x| fmtstream.formatIntBuf(buf, x, 10, false, fmtstream.FormatOptions{}), + ET.SINT => |x| fmt.formatIntBuf(buf, x, 10, false, fmt.FormatOptions{}), + ET.UINT => |x| fmt.formatIntBuf(buf, x, 10, false, fmt.FormatOptions{}), }; } }; diff --git a/test/tests.zig b/test/tests.zig index 61f694bedb..22dad10e3e 100644 --- a/test/tests.zig +++ b/test/tests.zig @@ -8,7 +8,7 @@ const Buffer = std.Buffer; const io = std.io; const fs = std.fs; const mem = std.mem; -const fmtstream = std.fmtstream; +const fmt = std.fmt; const ArrayList = std.ArrayList; const Mode = builtin.Mode; const LibExeObjStep = build.LibExeObjStep; @@ -484,7 +484,7 @@ pub const StackTracesContext = struct { const expect_for_mode = expect[@enumToInt(mode)]; if (expect_for_mode.len == 0) continue; - const annotated_case_name = fmtstream.allocPrint(self.b.allocator, "{} {} ({})", .{ + const annotated_case_name = fmt.allocPrint(self.b.allocator, "{} {} ({})", .{ "stack-trace", name, @tagName(mode), @@ -943,7 +943,7 @@ pub const CompileErrorContext = struct { pub fn addCase(self: *CompileErrorContext, case: *const TestCase) void { const b = self.b; - const annotated_case_name = fmtstream.allocPrint(self.b.allocator, "compile-error {}", .{ + const annotated_case_name = fmt.allocPrint(self.b.allocator, "compile-error {}", .{ case.name, }) catch unreachable; if (self.test_filter) |filter| { @@ -1009,7 +1009,7 @@ pub const StandaloneContext = struct { const b = self.b; for (self.modes) |mode| { - const annotated_case_name = fmtstream.allocPrint(self.b.allocator, "build {} ({})", .{ + const annotated_case_name = fmt.allocPrint(self.b.allocator, "build {} ({})", .{ root_src, @tagName(mode), }) catch unreachable; @@ -1152,7 +1152,7 @@ pub const GenHContext = struct { const b = self.b; const mode = builtin.Mode.Debug; - const annotated_case_name = fmtstream.allocPrint(self.b.allocator, "gen-h {} ({})", .{ case.name, @tagName(mode) }) catch unreachable; + const annotated_case_name = fmt.allocPrint(self.b.allocator, "gen-h {} ({})", .{ case.name, @tagName(mode) }) catch unreachable; if (self.test_filter) |filter| { if (mem.indexOf(u8, annotated_case_name, filter) == null) return; } diff --git a/tools/process_headers.zig b/tools/process_headers.zig index 43950750e9..abdc9fabf9 100644 --- a/tools/process_headers.zig +++ b/tools/process_headers.zig @@ -299,7 +299,7 @@ pub fn main() !void { std.debug.warn("unrecognized C ABI: {}\n", .{abi_name}); usageAndExit(args[0]); }; - const generic_name = try std.fmtstream.allocPrint(allocator, "generic-{}", .{abi_name}); + const generic_name = try std.fmt.allocPrint(allocator, "generic-{}", .{abi_name}); // TODO compiler crashed when I wrote this the canonical way var libc_targets: []const LibCTarget = undefined; @@ -440,7 +440,7 @@ pub fn main() !void { .specific => |a| @tagName(a), else => @tagName(dest_target.arch), }; - const out_subpath = try std.fmtstream.allocPrint(allocator, "{}-{}-{}", .{ + const out_subpath = try std.fmt.allocPrint(allocator, "{}-{}-{}", .{ arch_name, @tagName(dest_target.os), @tagName(dest_target.abi), diff --git a/tools/update_glibc.zig b/tools/update_glibc.zig index 35351e4d2a..84522aabe4 100644 --- a/tools/update_glibc.zig +++ b/tools/update_glibc.zig @@ -1,6 +1,6 @@ const std = @import("std"); const fs = std.fs; -const fmtstream = std.fmtstream; +const fmt = std.fmt; const assert = std.debug.assert; // Example abilist path: @@ -154,7 +154,7 @@ pub fn main() !void { const fn_set = &target_funcs_gop.kv.value.list; for (lib_names) |lib_name, lib_name_index| { - const basename = try fmtstream.allocPrint(allocator, "lib{}.abilist", .{lib_name}); + const basename = try fmt.allocPrint(allocator, "lib{}.abilist", .{lib_name}); const abi_list_filename = blk: { if (abi_list.targets[0].abi == .gnuabi64 and std.mem.eql(u8, lib_name, "c")) { break :blk try fs.path.join(allocator, &[_][]const u8{ prefix, abi_list.path, "n64", basename }); -- cgit v1.2.3