| ... | @@ -744,11 +744,8 @@ pub fn printAddress(w: *Writer, value: anytype) Error!void { | ... | @@ -744,11 +744,8 @@ pub fn printAddress(w: *Writer, value: anytype) Error!void { |
| 744 | switch (@typeInfo(T)) { | 744 | switch (@typeInfo(T)) { |
| 745 | .pointer => |info| { | 745 | .pointer => |info| { |
| 746 | try w.writeAll(@typeName(info.child) ++ "@"); | 746 | try w.writeAll(@typeName(info.child) ++ "@"); |
| 747 | if (info.size == .slice) | 747 | const int = if (info.size == .slice) @intFromPtr(value.ptr) else @intFromPtr(value); |
| 748 | try w.printInt(@intFromPtr(value.ptr), 16, .lower, .{}) | 748 | return w.printInt(int, 16, .lower, .{}); |
| 749 | else | | |
| 750 | try w.printInt(@intFromPtr(value), 16, .lower, .{}); | | |
| 751 | return; | | |
| 752 | }, | 749 | }, |
| 753 | .optional => |info| { | 750 | .optional => |info| { |
| 754 | if (@typeInfo(info.child) == .pointer) { | 751 | if (@typeInfo(info.child) == .pointer) { |
| ... | @@ -777,9 +774,9 @@ pub fn printValue( | ... | @@ -777,9 +774,9 @@ pub fn printValue( |
| 777 | '*' => return w.printAddress(value), | 774 | '*' => return w.printAddress(value), |
| 778 | 'f' => return value.format(w), | 775 | 'f' => return value.format(w), |
| 779 | 'd' => switch (@typeInfo(T)) { | 776 | 'd' => switch (@typeInfo(T)) { |
| 780 | .float, .comptime_float => return printFloat(w, value, .decimal, options), | 777 | .float, .comptime_float => return printFloat(w, value, options.toNumber(.decimal, .lower)), |
| 781 | .int, .comptime_int => return printInt(w, value, 10, .lower, options), | 778 | .int, .comptime_int => return printInt(w, value, 10, .lower, options), |
| 782 | .@"struct" => return value.formatInteger(w, 10, .lower), | 779 | .@"struct" => return value.formatNumber(w, options.toNumber(.decimal, .lower)), |
| 783 | .@"enum" => return printInt(w, @intFromEnum(value), 10, .lower, options), | 780 | .@"enum" => return printInt(w, @intFromEnum(value), 10, .lower, options), |
| 784 | .vector => return printVector(w, fmt, options, value, max_depth), | 781 | .vector => return printVector(w, fmt, options, value, max_depth), |
| 785 | else => invalidFmtError(fmt, value), | 782 | else => invalidFmtError(fmt, value), |
| ... | @@ -789,22 +786,22 @@ pub fn printValue( | ... | @@ -789,22 +786,22 @@ pub fn printValue( |
| 789 | 'b' => switch (@typeInfo(T)) { | 786 | 'b' => switch (@typeInfo(T)) { |
| 790 | .int, .comptime_int => return printInt(w, value, 2, .lower, options), | 787 | .int, .comptime_int => return printInt(w, value, 2, .lower, options), |
| 791 | .@"enum" => return printInt(w, @intFromEnum(value), 2, .lower, options), | 788 | .@"enum" => return printInt(w, @intFromEnum(value), 2, .lower, options), |
| 792 | .@"struct" => return value.formatInteger(w, 2, .lower), | 789 | .@"struct" => return value.formatNumber(w, options.toNumber(.binary, .lower)), |
| 793 | .vector => return printVector(w, fmt, options, value, max_depth), | 790 | .vector => return printVector(w, fmt, options, value, max_depth), |
| 794 | else => invalidFmtError(fmt, value), | 791 | else => invalidFmtError(fmt, value), |
| 795 | }, | 792 | }, |
| 796 | 'o' => switch (@typeInfo(T)) { | 793 | 'o' => switch (@typeInfo(T)) { |
| 797 | .int, .comptime_int => return printInt(w, value, 8, .lower, options), | 794 | .int, .comptime_int => return printInt(w, value, 8, .lower, options), |
| 798 | .@"enum" => return printInt(w, @intFromEnum(value), 8, .lower, options), | 795 | .@"enum" => return printInt(w, @intFromEnum(value), 8, .lower, options), |
| 799 | .@"struct" => return value.formatInteger(w, 8, .lower), | 796 | .@"struct" => return value.formatNumber(w, options.toNumber(.octal, .lower)), |
| 800 | .vector => return printVector(w, fmt, options, value, max_depth), | 797 | .vector => return printVector(w, fmt, options, value, max_depth), |
| 801 | else => invalidFmtError(fmt, value), | 798 | else => invalidFmtError(fmt, value), |
| 802 | }, | 799 | }, |
| 803 | 'x' => switch (@typeInfo(T)) { | 800 | 'x' => switch (@typeInfo(T)) { |
| 804 | .float, .comptime_float => return printFloatHexOptions(w, value, .lower, options), | 801 | .float, .comptime_float => return printFloatHexOptions(w, value, options.toNumber(.hex, .lower)), |
| 805 | .int, .comptime_int => return printInt(w, value, 16, .lower, options), | 802 | .int, .comptime_int => return printInt(w, value, 16, .lower, options), |
| 806 | .@"enum" => return printInt(w, @intFromEnum(value), 16, .lower, options), | 803 | .@"enum" => return printInt(w, @intFromEnum(value), 16, .lower, options), |
| 807 | .@"struct" => return value.formatInteger(w, 16, .lower), | 804 | .@"struct" => return value.formatNumber(w, options.toNumber(.hex, .lower)), |
| 808 | .pointer => |info| switch (info.size) { | 805 | .pointer => |info| switch (info.size) { |
| 809 | .one, .slice => { | 806 | .one, .slice => { |
| 810 | const slice: []const u8 = value; | 807 | const slice: []const u8 = value; |
| ... | @@ -823,10 +820,10 @@ pub fn printValue( | ... | @@ -823,10 +820,10 @@ pub fn printValue( |
| 823 | else => invalidFmtError(fmt, value), | 820 | else => invalidFmtError(fmt, value), |
| 824 | }, | 821 | }, |
| 825 | 'X' => switch (@typeInfo(T)) { | 822 | 'X' => switch (@typeInfo(T)) { |
| 826 | .float, .comptime_float => return printFloatHexOptions(w, value, .lower, options), | 823 | .float, .comptime_float => return printFloatHexOptions(w, value, options.toNumber(.hex, .lower)), |
| 827 | .int, .comptime_int => return printInt(w, value, 16, .upper, options), | 824 | .int, .comptime_int => return printInt(w, value, 16, .upper, options), |
| 828 | .@"enum" => return printInt(w, @intFromEnum(value), 16, .upper, options), | 825 | .@"enum" => return printInt(w, @intFromEnum(value), 16, .upper, options), |
| 829 | .@"struct" => return value.formatInteger(w, 16, .upper), | 826 | .@"struct" => return value.formatNumber(w, options.toNumber(.hex, .upper)), |
| 830 | .pointer => |info| switch (info.size) { | 827 | .pointer => |info| switch (info.size) { |
| 831 | .one, .slice => { | 828 | .one, .slice => { |
| 832 | const slice: []const u8 = value; | 829 | const slice: []const u8 = value; |
| ... | @@ -872,8 +869,13 @@ pub fn printValue( | ... | @@ -872,8 +869,13 @@ pub fn printValue( |
| 872 | else => invalidFmtError(fmt, value), | 869 | else => invalidFmtError(fmt, value), |
| 873 | }, | 870 | }, |
| 874 | 'e' => switch (@typeInfo(T)) { | 871 | 'e' => switch (@typeInfo(T)) { |
| 875 | .float, .comptime_float => return printFloat(w, value, .scientific, options), | 872 | .float, .comptime_float => return printFloat(w, value, options.toNumber(.scientific, .lower)), |
| 876 | .@"struct" => return value.formatFloat(w, .scientific), | 873 | .@"struct" => return value.formatNumber(w, options.toNumber(.scientific, .lower)), |
| | 874 | else => invalidFmtError(fmt, value), |
| | 875 | }, |
| | 876 | 'E' => switch (@typeInfo(T)) { |
| | 877 | .float, .comptime_float => return printFloat(w, value, options.toNumber(.scientific, .upper)), |
| | 878 | .@"struct" => return value.formatNumber(w, options.toNumber(.scientific, .upper)), |
| 877 | else => invalidFmtError(fmt, value), | 879 | else => invalidFmtError(fmt, value), |
| 878 | }, | 880 | }, |
| 879 | 't' => switch (@typeInfo(T)) { | 881 | 't' => switch (@typeInfo(T)) { |
| ... | @@ -923,7 +925,7 @@ pub fn printValue( | ... | @@ -923,7 +925,7 @@ pub fn printValue( |
| 923 | switch (@typeInfo(T)) { | 925 | switch (@typeInfo(T)) { |
| 924 | .float, .comptime_float => { | 926 | .float, .comptime_float => { |
| 925 | if (!is_any and fmt.len != 0) invalidFmtError(fmt, value); | 927 | if (!is_any and fmt.len != 0) invalidFmtError(fmt, value); |
| 926 | return printFloat(w, value, .decimal, options); | 928 | return printFloat(w, value, options.toNumber(.decimal, .lower)); |
| 927 | }, | 929 | }, |
| 928 | .int, .comptime_int => { | 930 | .int, .comptime_int => { |
| 929 | if (!is_any and fmt.len != 0) invalidFmtError(fmt, value); | 931 | if (!is_any and fmt.len != 0) invalidFmtError(fmt, value); |
| ... | @@ -1262,12 +1264,13 @@ pub fn printUnicodeCodepoint(w: *Writer, c: u21) Error!void { | ... | @@ -1262,12 +1264,13 @@ pub fn printUnicodeCodepoint(w: *Writer, c: u21) Error!void { |
| 1262 | return w.writeAll(buf[0..len]); | 1264 | return w.writeAll(buf[0..len]); |
| 1263 | } | 1265 | } |
| 1264 | | 1266 | |
| 1265 | pub fn printFloat( | 1267 | /// Uses a larger stack buffer; asserts mode is decimal or scientific. |
| 1266 | w: *Writer, | 1268 | pub fn printFloat(w: *Writer, value: anytype, options: std.fmt.Number) Error!void { |
| 1267 | value: anytype, | 1269 | const mode: std.fmt.float.Mode = switch (options.mode) { |
| 1268 | mode: std.fmt.float.Mode, | 1270 | .decimal => .decimal, |
| 1269 | options: std.fmt.Options, | 1271 | .scientific => .scientific, |
| 1270 | ) Error!void { | 1272 | .binary, .octal, .hex => unreachable, |
| | 1273 | }; |
| 1271 | var buf: [std.fmt.float.bufferSize(.decimal, f64)]u8 = undefined; | 1274 | var buf: [std.fmt.float.bufferSize(.decimal, f64)]u8 = undefined; |
| 1272 | const s = std.fmt.float.render(&buf, value, .{ | 1275 | const s = std.fmt.float.render(&buf, value, .{ |
| 1273 | .mode = mode, | 1276 | .mode = mode, |
| ... | @@ -1275,20 +1278,36 @@ pub fn printFloat( | ... | @@ -1275,20 +1278,36 @@ pub fn printFloat( |
| 1275 | }) catch |err| switch (err) { | 1278 | }) catch |err| switch (err) { |
| 1276 | error.BufferTooSmall => "(float)", | 1279 | error.BufferTooSmall => "(float)", |
| 1277 | }; | 1280 | }; |
| 1278 | return w.alignBufferOptions(s, options); | 1281 | return w.alignBuffer(s, options.width orelse s.len, options.alignment, options.fill); |
| 1279 | } | 1282 | } |
| 1280 | | 1283 | |
| 1281 | pub fn printFloatHexOptions(w: *Writer, value: anytype, case: std.fmt.Case, options: std.fmt.Options) Error!void { | 1284 | /// Uses a smaller stack buffer; asserts mode is not decimal or scientific. |
| | 1285 | pub fn printFloatHexOptions(w: *Writer, value: anytype, options: std.fmt.Number) Error!void { |
| 1282 | var buf: [50]u8 = undefined; // for aligning | 1286 | var buf: [50]u8 = undefined; // for aligning |
| 1283 | var sub_writer: Writer = .fixed(&buf); | 1287 | var sub_writer: Writer = .fixed(&buf); |
| 1284 | printFloatHex(&sub_writer, value, case, options.precision) catch unreachable; // buf is large enough | 1288 | switch (options.mode) { |
| 1285 | return w.alignBufferOptions(sub_writer.buffered(), options); | 1289 | .decimal => unreachable, |
| | 1290 | .scientific => unreachable, |
| | 1291 | .binary => @panic("TODO"), |
| | 1292 | .octal => @panic("TODO"), |
| | 1293 | .hex => {}, |
| | 1294 | } |
| | 1295 | printFloatHex(&sub_writer, value, options.case, options.precision) catch unreachable; // buf is large enough |
| | 1296 | |
| | 1297 | const printed = sub_writer.buffered(); |
| | 1298 | return w.alignBuffer(printed, options.width orelse printed.len, options.alignment, options.fill); |
| 1286 | } | 1299 | } |
| 1287 | | 1300 | |
| 1288 | pub fn printFloatHex(w: *Writer, value: anytype, case: std.fmt.Case, opt_precision: ?usize) Error!void { | 1301 | pub fn printFloatHex(w: *Writer, value: anytype, case: std.fmt.Case, opt_precision: ?usize) Error!void { |
| 1289 | if (std.math.signbit(value)) try w.writeByte('-'); | 1302 | if (std.math.signbit(value)) try w.writeByte('-'); |
| 1290 | if (std.math.isNan(value)) return w.writeAll("nan"); | 1303 | if (std.math.isNan(value)) return w.writeAll(switch (case) { |
| 1291 | if (std.math.isInf(value)) return w.writeAll("inf"); | 1304 | .lower => "nan", |
| | 1305 | .upper => "NAN", |
| | 1306 | }); |
| | 1307 | if (std.math.isInf(value)) return w.writeAll(switch (case) { |
| | 1308 | .lower => "inf", |
| | 1309 | .upper => "INF", |
| | 1310 | }); |
| 1292 | | 1311 | |
| 1293 | const T = @TypeOf(value); | 1312 | const T = @TypeOf(value); |
| 1294 | const TU = std.meta.Int(.unsigned, @bitSizeOf(T)); | 1313 | const TU = std.meta.Int(.unsigned, @bitSizeOf(T)); |
| ... | @@ -1822,7 +1841,7 @@ test printInt { | ... | @@ -1822,7 +1841,7 @@ test printInt { |
| 1822 | test "printFloat with comptime_float" { | 1841 | test "printFloat with comptime_float" { |
| 1823 | var buf: [20]u8 = undefined; | 1842 | var buf: [20]u8 = undefined; |
| 1824 | var w: Writer = .fixed(&buf); | 1843 | var w: Writer = .fixed(&buf); |
| 1825 | try w.printFloat(@as(comptime_float, 1.0), .scientific, .{}); | 1844 | try w.printFloat(@as(comptime_float, 1.0), std.fmt.Options.toNumber(.{}, .scientific, .lower)); |
| 1826 | try std.testing.expectEqualStrings(w.buffered(), "1e0"); | 1845 | try std.testing.expectEqualStrings(w.buffered(), "1e0"); |
| 1827 | try std.testing.expectFmt("1", "{}", .{1.0}); | 1846 | try std.testing.expectFmt("1", "{}", .{1.0}); |
| 1828 | } | 1847 | } |