diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2025-07-05 10:43:14 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2025-07-07 22:43:53 -0700 |
| commit | 5378fdb153bc76990105e3640e7725e434e8cdee (patch) | |
| tree | 9791e08538c10c521f5634ed79e3b369fcd004df /lib/std/math | |
| parent | 4ccc6f2b5777afd06f0fddbea4e0e0d0c92b007d (diff) | |
| download | zig-5378fdb153bc76990105e3640e7725e434e8cdee.tar.gz zig-5378fdb153bc76990105e3640e7725e434e8cdee.zip | |
std.fmt: fully remove format string from format methods
Introduces `std.fmt.alt` which is a helper for calling alternate format
methods besides one named "format".
Diffstat (limited to 'lib/std/math')
| -rw-r--r-- | lib/std/math/big/int.zig | 48 | ||||
| -rw-r--r-- | lib/std/math/big/int_test.zig | 14 |
2 files changed, 27 insertions, 35 deletions
diff --git a/lib/std/math/big/int.zig b/lib/std/math/big/int.zig index 3e6d66321f..000b578dc0 100644 --- a/lib/std/math/big/int.zig +++ b/lib/std/math/big/int.zig @@ -2317,46 +2317,40 @@ pub const Const = struct { return .{ normalized_res.reconstruct(if (self.positive) .positive else .negative), exactness }; } - /// To allow `std.fmt.format` to work with this type. /// If the absolute value of integer is greater than or equal to `pow(2, 64 * @sizeOf(usize) * 8)`, /// this function will fail to print the string, printing "(BigInt)" instead of a number. /// This is because the rendering algorithm requires reversing a string, which requires O(N) memory. /// See `toString` and `toStringAlloc` for a way to print big integers without failure. - pub fn format(self: Const, w: *std.io.Writer, comptime fmt: []const u8) std.io.Writer.Error!void { - comptime var base = 10; - comptime var case: std.fmt.Case = .lower; - - if (fmt.len == 0 or comptime mem.eql(u8, fmt, "d")) { - base = 10; - case = .lower; - } else if (comptime mem.eql(u8, fmt, "b")) { - base = 2; - case = .lower; - } else if (comptime mem.eql(u8, fmt, "x")) { - base = 16; - case = .lower; - } else if (comptime mem.eql(u8, fmt, "X")) { - base = 16; - case = .upper; - } else { - std.fmt.invalidFmtError(fmt, self); - } - + pub fn print(self: Const, w: *std.io.Writer, base: u8, case: std.fmt.Case) std.io.Writer.Error!void { const available_len = 64; if (self.limbs.len > available_len) return w.writeAll("(BigInt)"); - var limbs: [calcToStringLimbsBufferLen(available_len, base)]Limb = undefined; + var limbs: [calcToStringLimbsBufferLen(available_len, 10)]Limb = undefined; const biggest: Const = .{ .limbs = &([1]Limb{comptime math.maxInt(Limb)} ** available_len), .positive = false, }; - var buf: [biggest.sizeInBaseUpperBound(base)]u8 = undefined; + var buf: [biggest.sizeInBaseUpperBound(2)]u8 = undefined; const len = self.toString(&buf, base, case, &limbs); return w.writeAll(buf[0..len]); } + const Format = struct { + int: Const, + base: u8, + case: std.fmt.Case, + + pub fn default(f: Format, w: *std.io.Writer) std.io.Writer.Error!void { + return print(f.int, w, f.base, f.case); + } + }; + + pub fn fmt(self: Const, base: u8, case: std.fmt.Case) std.fmt.Formatter(Format, Format.default) { + return .{ .data = .{ .int = self, .base = base, .case = case } }; + } + /// Converts self to a string in the requested base. /// Caller owns returned memory. /// Asserts that `base` is in the range [2, 36]. @@ -2924,12 +2918,16 @@ pub const Managed = struct { } /// To allow `std.fmt.format` to work with `Managed`. + pub fn format(self: Managed, w: *std.io.Writer, comptime f: []const u8) std.io.Writer.Error!void { + return self.toConst().format(w, f); + } + /// If the absolute value of integer is greater than or equal to `pow(2, 64 * @sizeOf(usize) * 8)`, /// this function will fail to print the string, printing "(BigInt)" instead of a number. /// This is because the rendering algorithm requires reversing a string, which requires O(N) memory. /// See `toString` and `toStringAlloc` for a way to print big integers without failure. - pub fn format(self: Managed, w: *std.io.Writer, comptime f: []const u8) std.io.Writer.Error!void { - return self.toConst().format(w, f); + pub fn fmt(self: Managed, base: u8, case: std.fmt.Case) std.fmt.Formatter(Const.Format, Const.Format.default) { + return .{ .data = .{ .int = self.toConst(), .base = base, .case = case } }; } /// Returns math.Order.lt, math.Order.eq, math.Order.gt if |a| < |b|, |a| == diff --git a/lib/std/math/big/int_test.zig b/lib/std/math/big/int_test.zig index 0f688b359d..58f5a01a05 100644 --- a/lib/std/math/big/int_test.zig +++ b/lib/std/math/big/int_test.zig @@ -3813,14 +3813,8 @@ test "(BigInt) positive" { try a.pow(&a, 64 * @sizeOf(Limb) * 8); try b.sub(&a, &c); - const a_fmt = try std.fmt.allocPrintSentinel(testing.allocator, "{fd}", .{a}, 0); - defer testing.allocator.free(a_fmt); - - const b_fmt = try std.fmt.allocPrintSentinel(testing.allocator, "{fd}", .{b}, 0); - defer testing.allocator.free(b_fmt); - - try testing.expect(mem.eql(u8, a_fmt, "(BigInt)")); - try testing.expect(!mem.eql(u8, b_fmt, "(BigInt)")); + try testing.expectFmt("(BigInt)", "{f}", .{a.fmt(10, .lower)}); + try testing.expectFmt("1044388881413152506691752710716624382579964249047383780384233483283953907971557456848826811934997558340890106714439262837987573438185793607263236087851365277945956976543709998340361590134383718314428070011855946226376318839397712745672334684344586617496807908705803704071284048740118609114467977783598029006686938976881787785946905630190260940599579453432823469303026696443059025015972399867714215541693835559885291486318237914434496734087811872639496475100189041349008417061675093668333850551032972088269550769983616369411933015213796825837188091833656751221318492846368125550225998300412344784862595674492194617023806505913245610825731835380087608622102834270197698202313169017678006675195485079921636419370285375124784014907159135459982790513399611551794271106831134090584272884279791554849782954323534517065223269061394905987693002122963395687782878948440616007412945674919823050571642377154816321380631045902916136926708342856440730447899971901781465763473223850267253059899795996090799469201774624817718449867455659250178329070473119433165550807568221846571746373296884912819520317457002440926616910874148385078411929804522981857338977648103126085903001302413467189726673216491511131602920781738033436090243804708340403154190335", "{f}", .{b.fmt(10, .lower)}); } test "(BigInt) negative" { @@ -3838,10 +3832,10 @@ test "(BigInt) negative" { a.negate(); try b.add(&a, &c); - const a_fmt = try std.fmt.allocPrintSentinel(testing.allocator, "{fd}", .{a}, 0); + const a_fmt = try std.fmt.allocPrint(testing.allocator, "{f}", .{a.fmt(10, .lower)}); defer testing.allocator.free(a_fmt); - const b_fmt = try std.fmt.allocPrintSentinel(testing.allocator, "{fd}", .{b}, 0); + const b_fmt = try std.fmt.allocPrint(testing.allocator, "{f}", .{b.fmt(10, .lower)}); defer testing.allocator.free(b_fmt); try testing.expect(mem.eql(u8, a_fmt, "(BigInt)")); |
