| ... | ... | @@ -744,11 +744,8 @@ pub fn printAddress(w: *Writer, value: anytype) Error!void { |
| 744 | 744 | switch (@typeInfo(T)) { |
| 745 | 745 | .pointer => |info| { |
| 746 | 746 | try w.writeAll(@typeName(info.child) ++ "@"); |
| 747 | | if (info.size == .slice) |
| 748 | | try w.printInt(@intFromPtr(value.ptr), 16, .lower, .{}) |
| 749 | | else |
| 750 | | try w.printInt(@intFromPtr(value), 16, .lower, .{}); |
| 751 | | return; |
| 747 | const int = if (info.size == .slice) @intFromPtr(value.ptr) else @intFromPtr(value); |
| 748 | return w.printInt(int, 16, .lower, .{}); |
| 752 | 749 | }, |
| 753 | 750 | .optional => |info| { |
| 754 | 751 | if (@typeInfo(info.child) == .pointer) { |
| ... | ... | @@ -777,9 +774,9 @@ pub fn printValue( |
| 777 | 774 | '*' => return w.printAddress(value), |
| 778 | 775 | 'f' => return value.format(w), |
| 779 | 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 | 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 | 780 | .@"enum" => return printInt(w, @intFromEnum(value), 10, .lower, options), |
| 784 | 781 | .vector => return printVector(w, fmt, options, value, max_depth), |
| 785 | 782 | else => invalidFmtError(fmt, value), |
| ... | ... | @@ -789,22 +786,22 @@ pub fn printValue( |
| 789 | 786 | 'b' => switch (@typeInfo(T)) { |
| 790 | 787 | .int, .comptime_int => return printInt(w, value, 2, .lower, options), |
| 791 | 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 | 790 | .vector => return printVector(w, fmt, options, value, max_depth), |
| 794 | 791 | else => invalidFmtError(fmt, value), |
| 795 | 792 | }, |
| 796 | 793 | 'o' => switch (@typeInfo(T)) { |
| 797 | 794 | .int, .comptime_int => return printInt(w, value, 8, .lower, options), |
| 798 | 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 | 797 | .vector => return printVector(w, fmt, options, value, max_depth), |
| 801 | 798 | else => invalidFmtError(fmt, value), |
| 802 | 799 | }, |
| 803 | 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 | 802 | .int, .comptime_int => return printInt(w, value, 16, .lower, options), |
| 806 | 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 | 805 | .pointer => |info| switch (info.size) { |
| 809 | 806 | .one, .slice => { |
| 810 | 807 | const slice: []const u8 = value; |
| ... | ... | @@ -823,10 +820,10 @@ pub fn printValue( |
| 823 | 820 | else => invalidFmtError(fmt, value), |
| 824 | 821 | }, |
| 825 | 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 | 824 | .int, .comptime_int => return printInt(w, value, 16, .upper, options), |
| 828 | 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 | 827 | .pointer => |info| switch (info.size) { |
| 831 | 828 | .one, .slice => { |
| 832 | 829 | const slice: []const u8 = value; |
| ... | ... | @@ -872,8 +869,13 @@ pub fn printValue( |
| 872 | 869 | else => invalidFmtError(fmt, value), |
| 873 | 870 | }, |
| 874 | 871 | 'e' => switch (@typeInfo(T)) { |
| 875 | | .float, .comptime_float => return printFloat(w, value, .scientific, options), |
| 876 | | .@"struct" => return value.formatFloat(w, .scientific), |
| 872 | .float, .comptime_float => return printFloat(w, value, options.toNumber(.scientific, .lower)), |
| 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 | 879 | else => invalidFmtError(fmt, value), |
| 878 | 880 | }, |
| 879 | 881 | 't' => switch (@typeInfo(T)) { |
| ... | ... | @@ -923,7 +925,7 @@ pub fn printValue( |
| 923 | 925 | switch (@typeInfo(T)) { |
| 924 | 926 | .float, .comptime_float => { |
| 925 | 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 | 930 | .int, .comptime_int => { |
| 929 | 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 | 1264 | return w.writeAll(buf[0..len]); |
| 1263 | 1265 | } |
| 1264 | 1266 | |
| 1265 | | pub fn printFloat( |
| 1266 | | w: *Writer, |
| 1267 | | value: anytype, |
| 1268 | | mode: std.fmt.float.Mode, |
| 1269 | | options: std.fmt.Options, |
| 1270 | | ) Error!void { |
| 1267 | /// Uses a larger stack buffer; asserts mode is decimal or scientific. |
| 1268 | pub fn printFloat(w: *Writer, value: anytype, options: std.fmt.Number) Error!void { |
| 1269 | const mode: std.fmt.float.Mode = switch (options.mode) { |
| 1270 | .decimal => .decimal, |
| 1271 | .scientific => .scientific, |
| 1272 | .binary, .octal, .hex => unreachable, |
| 1273 | }; |
| 1271 | 1274 | var buf: [std.fmt.float.bufferSize(.decimal, f64)]u8 = undefined; |
| 1272 | 1275 | const s = std.fmt.float.render(&buf, value, .{ |
| 1273 | 1276 | .mode = mode, |
| ... | ... | @@ -1275,20 +1278,36 @@ pub fn printFloat( |
| 1275 | 1278 | }) catch |err| switch (err) { |
| 1276 | 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 | 1286 | var buf: [50]u8 = undefined; // for aligning |
| 1283 | 1287 | var sub_writer: Writer = .fixed(&buf); |
| 1284 | | printFloatHex(&sub_writer, value, case, options.precision) catch unreachable; // buf is large enough |
| 1285 | | return w.alignBufferOptions(sub_writer.buffered(), options); |
| 1288 | switch (options.mode) { |
| 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 | 1301 | pub fn printFloatHex(w: *Writer, value: anytype, case: std.fmt.Case, opt_precision: ?usize) Error!void { |
| 1289 | 1302 | if (std.math.signbit(value)) try w.writeByte('-'); |
| 1290 | | if (std.math.isNan(value)) return w.writeAll("nan"); |
| 1291 | | if (std.math.isInf(value)) return w.writeAll("inf"); |
| 1303 | if (std.math.isNan(value)) return w.writeAll(switch (case) { |
| 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 | 1312 | const T = @TypeOf(value); |
| 1294 | 1313 | const TU = std.meta.Int(.unsigned, @bitSizeOf(T)); |
| ... | ... | @@ -1822,7 +1841,7 @@ test printInt { |
| 1822 | 1841 | test "printFloat with comptime_float" { |
| 1823 | 1842 | var buf: [20]u8 = undefined; |
| 1824 | 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 | 1845 | try std.testing.expectEqualStrings(w.buffered(), "1e0"); |
| 1827 | 1846 | try std.testing.expectFmt("1", "{}", .{1.0}); |
| 1828 | 1847 | } |