mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
std: replace formatInteger with formatNumber
This commit is contained in:
parent
5bc95a6fa2
commit
51a9a6aab6
3 changed files with 96 additions and 37 deletions
|
|
@ -37,6 +37,45 @@ pub const Options = struct {
|
|||
width: ?usize = null,
|
||||
alignment: Alignment = default_alignment,
|
||||
fill: u8 = default_fill_char,
|
||||
|
||||
pub fn toNumber(o: Options, mode: Number.Mode, case: Case) Number {
|
||||
return .{
|
||||
.mode = mode,
|
||||
.case = case,
|
||||
.precision = o.precision,
|
||||
.width = o.width,
|
||||
.alignment = o.alignment,
|
||||
.fill = o.fill,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
pub const Number = struct {
|
||||
mode: Mode = .decimal,
|
||||
/// Affects hex digits as well as floating point "inf"/"INF".
|
||||
case: Case = .lower,
|
||||
precision: ?usize = null,
|
||||
width: ?usize = null,
|
||||
alignment: Alignment = default_alignment,
|
||||
fill: u8 = default_fill_char,
|
||||
|
||||
pub const Mode = enum {
|
||||
decimal,
|
||||
binary,
|
||||
octal,
|
||||
hex,
|
||||
scientific,
|
||||
|
||||
pub fn base(mode: Mode) ?u8 {
|
||||
return switch (mode) {
|
||||
.decimal => 10,
|
||||
.binary => 2,
|
||||
.octal => 8,
|
||||
.hex => 16,
|
||||
.scientific => null,
|
||||
};
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/// Renders fmt string with args, calling `writer` with slices of bytes.
|
||||
|
|
|
|||
|
|
@ -744,11 +744,8 @@ pub fn printAddress(w: *Writer, value: anytype) Error!void {
|
|||
switch (@typeInfo(T)) {
|
||||
.pointer => |info| {
|
||||
try w.writeAll(@typeName(info.child) ++ "@");
|
||||
if (info.size == .slice)
|
||||
try w.printInt(@intFromPtr(value.ptr), 16, .lower, .{})
|
||||
else
|
||||
try w.printInt(@intFromPtr(value), 16, .lower, .{});
|
||||
return;
|
||||
const int = if (info.size == .slice) @intFromPtr(value.ptr) else @intFromPtr(value);
|
||||
return w.printInt(int, 16, .lower, .{});
|
||||
},
|
||||
.optional => |info| {
|
||||
if (@typeInfo(info.child) == .pointer) {
|
||||
|
|
@ -777,9 +774,9 @@ pub fn printValue(
|
|||
'*' => return w.printAddress(value),
|
||||
'f' => return value.format(w),
|
||||
'd' => switch (@typeInfo(T)) {
|
||||
.float, .comptime_float => return printFloat(w, value, .decimal, options),
|
||||
.float, .comptime_float => return printFloat(w, value, options.toNumber(.decimal, .lower)),
|
||||
.int, .comptime_int => return printInt(w, value, 10, .lower, options),
|
||||
.@"struct" => return value.formatInteger(w, 10, .lower),
|
||||
.@"struct" => return value.formatNumber(w, options.toNumber(.decimal, .lower)),
|
||||
.@"enum" => return printInt(w, @intFromEnum(value), 10, .lower, options),
|
||||
.vector => return printVector(w, fmt, options, value, max_depth),
|
||||
else => invalidFmtError(fmt, value),
|
||||
|
|
@ -789,22 +786,22 @@ pub fn printValue(
|
|||
'b' => switch (@typeInfo(T)) {
|
||||
.int, .comptime_int => return printInt(w, value, 2, .lower, options),
|
||||
.@"enum" => return printInt(w, @intFromEnum(value), 2, .lower, options),
|
||||
.@"struct" => return value.formatInteger(w, 2, .lower),
|
||||
.@"struct" => return value.formatNumber(w, options.toNumber(.binary, .lower)),
|
||||
.vector => return printVector(w, fmt, options, value, max_depth),
|
||||
else => invalidFmtError(fmt, value),
|
||||
},
|
||||
'o' => switch (@typeInfo(T)) {
|
||||
.int, .comptime_int => return printInt(w, value, 8, .lower, options),
|
||||
.@"enum" => return printInt(w, @intFromEnum(value), 8, .lower, options),
|
||||
.@"struct" => return value.formatInteger(w, 8, .lower),
|
||||
.@"struct" => return value.formatNumber(w, options.toNumber(.octal, .lower)),
|
||||
.vector => return printVector(w, fmt, options, value, max_depth),
|
||||
else => invalidFmtError(fmt, value),
|
||||
},
|
||||
'x' => switch (@typeInfo(T)) {
|
||||
.float, .comptime_float => return printFloatHexOptions(w, value, .lower, options),
|
||||
.float, .comptime_float => return printFloatHexOptions(w, value, options.toNumber(.hex, .lower)),
|
||||
.int, .comptime_int => return printInt(w, value, 16, .lower, options),
|
||||
.@"enum" => return printInt(w, @intFromEnum(value), 16, .lower, options),
|
||||
.@"struct" => return value.formatInteger(w, 16, .lower),
|
||||
.@"struct" => return value.formatNumber(w, options.toNumber(.hex, .lower)),
|
||||
.pointer => |info| switch (info.size) {
|
||||
.one, .slice => {
|
||||
const slice: []const u8 = value;
|
||||
|
|
@ -823,10 +820,10 @@ pub fn printValue(
|
|||
else => invalidFmtError(fmt, value),
|
||||
},
|
||||
'X' => switch (@typeInfo(T)) {
|
||||
.float, .comptime_float => return printFloatHexOptions(w, value, .lower, options),
|
||||
.float, .comptime_float => return printFloatHexOptions(w, value, options.toNumber(.hex, .lower)),
|
||||
.int, .comptime_int => return printInt(w, value, 16, .upper, options),
|
||||
.@"enum" => return printInt(w, @intFromEnum(value), 16, .upper, options),
|
||||
.@"struct" => return value.formatInteger(w, 16, .upper),
|
||||
.@"struct" => return value.formatNumber(w, options.toNumber(.hex, .upper)),
|
||||
.pointer => |info| switch (info.size) {
|
||||
.one, .slice => {
|
||||
const slice: []const u8 = value;
|
||||
|
|
@ -872,8 +869,13 @@ pub fn printValue(
|
|||
else => invalidFmtError(fmt, value),
|
||||
},
|
||||
'e' => switch (@typeInfo(T)) {
|
||||
.float, .comptime_float => return printFloat(w, value, .scientific, options),
|
||||
.@"struct" => return value.formatFloat(w, .scientific),
|
||||
.float, .comptime_float => return printFloat(w, value, options.toNumber(.scientific, .lower)),
|
||||
.@"struct" => return value.formatNumber(w, options.toNumber(.scientific, .lower)),
|
||||
else => invalidFmtError(fmt, value),
|
||||
},
|
||||
'E' => switch (@typeInfo(T)) {
|
||||
.float, .comptime_float => return printFloat(w, value, options.toNumber(.scientific, .upper)),
|
||||
.@"struct" => return value.formatNumber(w, options.toNumber(.scientific, .upper)),
|
||||
else => invalidFmtError(fmt, value),
|
||||
},
|
||||
't' => switch (@typeInfo(T)) {
|
||||
|
|
@ -923,7 +925,7 @@ pub fn printValue(
|
|||
switch (@typeInfo(T)) {
|
||||
.float, .comptime_float => {
|
||||
if (!is_any and fmt.len != 0) invalidFmtError(fmt, value);
|
||||
return printFloat(w, value, .decimal, options);
|
||||
return printFloat(w, value, options.toNumber(.decimal, .lower));
|
||||
},
|
||||
.int, .comptime_int => {
|
||||
if (!is_any and fmt.len != 0) invalidFmtError(fmt, value);
|
||||
|
|
@ -1262,12 +1264,13 @@ pub fn printUnicodeCodepoint(w: *Writer, c: u21) Error!void {
|
|||
return w.writeAll(buf[0..len]);
|
||||
}
|
||||
|
||||
pub fn printFloat(
|
||||
w: *Writer,
|
||||
value: anytype,
|
||||
mode: std.fmt.float.Mode,
|
||||
options: std.fmt.Options,
|
||||
) Error!void {
|
||||
/// Uses a larger stack buffer; asserts mode is decimal or scientific.
|
||||
pub fn printFloat(w: *Writer, value: anytype, options: std.fmt.Number) Error!void {
|
||||
const mode: std.fmt.float.Mode = switch (options.mode) {
|
||||
.decimal => .decimal,
|
||||
.scientific => .scientific,
|
||||
.binary, .octal, .hex => unreachable,
|
||||
};
|
||||
var buf: [std.fmt.float.bufferSize(.decimal, f64)]u8 = undefined;
|
||||
const s = std.fmt.float.render(&buf, value, .{
|
||||
.mode = mode,
|
||||
|
|
@ -1275,20 +1278,36 @@ pub fn printFloat(
|
|||
}) catch |err| switch (err) {
|
||||
error.BufferTooSmall => "(float)",
|
||||
};
|
||||
return w.alignBufferOptions(s, options);
|
||||
return w.alignBuffer(s, options.width orelse s.len, options.alignment, options.fill);
|
||||
}
|
||||
|
||||
pub fn printFloatHexOptions(w: *Writer, value: anytype, case: std.fmt.Case, options: std.fmt.Options) Error!void {
|
||||
/// Uses a smaller stack buffer; asserts mode is not decimal or scientific.
|
||||
pub fn printFloatHexOptions(w: *Writer, value: anytype, options: std.fmt.Number) Error!void {
|
||||
var buf: [50]u8 = undefined; // for aligning
|
||||
var sub_writer: Writer = .fixed(&buf);
|
||||
printFloatHex(&sub_writer, value, case, options.precision) catch unreachable; // buf is large enough
|
||||
return w.alignBufferOptions(sub_writer.buffered(), options);
|
||||
switch (options.mode) {
|
||||
.decimal => unreachable,
|
||||
.scientific => unreachable,
|
||||
.binary => @panic("TODO"),
|
||||
.octal => @panic("TODO"),
|
||||
.hex => {},
|
||||
}
|
||||
printFloatHex(&sub_writer, value, options.case, options.precision) catch unreachable; // buf is large enough
|
||||
|
||||
const printed = sub_writer.buffered();
|
||||
return w.alignBuffer(printed, options.width orelse printed.len, options.alignment, options.fill);
|
||||
}
|
||||
|
||||
pub fn printFloatHex(w: *Writer, value: anytype, case: std.fmt.Case, opt_precision: ?usize) Error!void {
|
||||
if (std.math.signbit(value)) try w.writeByte('-');
|
||||
if (std.math.isNan(value)) return w.writeAll("nan");
|
||||
if (std.math.isInf(value)) return w.writeAll("inf");
|
||||
if (std.math.isNan(value)) return w.writeAll(switch (case) {
|
||||
.lower => "nan",
|
||||
.upper => "NAN",
|
||||
});
|
||||
if (std.math.isInf(value)) return w.writeAll(switch (case) {
|
||||
.lower => "inf",
|
||||
.upper => "INF",
|
||||
});
|
||||
|
||||
const T = @TypeOf(value);
|
||||
const TU = std.meta.Int(.unsigned, @bitSizeOf(T));
|
||||
|
|
@ -1822,7 +1841,7 @@ test printInt {
|
|||
test "printFloat with comptime_float" {
|
||||
var buf: [20]u8 = undefined;
|
||||
var w: Writer = .fixed(&buf);
|
||||
try w.printFloat(@as(comptime_float, 1.0), .scientific, .{});
|
||||
try w.printFloat(@as(comptime_float, 1.0), std.fmt.Options.toNumber(.{}, .scientific, .lower));
|
||||
try std.testing.expectEqualStrings(w.buffered(), "1e0");
|
||||
try std.testing.expectFmt("1", "{}", .{1.0});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2030,11 +2030,11 @@ pub const Mutable = struct {
|
|||
}
|
||||
|
||||
pub fn format(self: Mutable, w: *std.io.Writer) std.io.Writer.Error!void {
|
||||
return formatInteger(self, w, 10, .lower);
|
||||
return formatNumber(self, w, .{});
|
||||
}
|
||||
|
||||
pub fn formatInteger(self: Const, w: *std.io.Writer, base: u8, case: std.fmt.Case) std.io.Writer.Error!void {
|
||||
return self.toConst().formatInteger(w, base, case);
|
||||
pub fn formatNumber(self: Const, w: *std.io.Writer, n: std.fmt.Number) std.io.Writer.Error!void {
|
||||
return self.toConst().formatNumber(w, n);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -2329,7 +2329,7 @@ pub const Const = struct {
|
|||
/// 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 formatInteger(self: Const, w: *std.io.Writer, base: u8, case: std.fmt.Case) std.io.Writer.Error!void {
|
||||
pub fn formatNumber(self: Const, w: *std.io.Writer, number: std.fmt.Number) std.io.Writer.Error!void {
|
||||
const available_len = 64;
|
||||
if (self.limbs.len > available_len)
|
||||
return w.writeAll("(BigInt)");
|
||||
|
|
@ -2341,7 +2341,8 @@ pub const Const = struct {
|
|||
.positive = false,
|
||||
};
|
||||
var buf: [biggest.sizeInBaseUpperBound(2)]u8 = undefined;
|
||||
const len = self.toString(&buf, base, case, &limbs);
|
||||
const base: u8 = number.mode.base() orelse @panic("TODO print big int in scientific form");
|
||||
const len = self.toString(&buf, base, number.case, &limbs);
|
||||
return w.writeAll(buf[0..len]);
|
||||
}
|
||||
|
||||
|
|
@ -2913,15 +2914,15 @@ pub const Managed = struct {
|
|||
|
||||
/// To allow `std.fmt.format` to work with `Managed`.
|
||||
pub fn format(self: Managed, w: *std.io.Writer) std.io.Writer.Error!void {
|
||||
return formatInteger(self, w, 10, .lower);
|
||||
return formatNumber(self, w, .{});
|
||||
}
|
||||
|
||||
/// 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 formatInteger(self: Managed, w: *std.io.Writer, base: u8, case: std.fmt.Case) std.io.Writer.Error!void {
|
||||
return self.toConst().formatInteger(w, base, case);
|
||||
pub fn formatNumber(self: Managed, w: *std.io.Writer, n: std.fmt.Number) std.io.Writer.Error!void {
|
||||
return self.toConst().formatNumber(w, n);
|
||||
}
|
||||
|
||||
/// Returns math.Order.lt, math.Order.eq, math.Order.gt if |a| < |b|, |a| ==
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue