authorgravatar for vitalijusv.h4qjc@slmail.meVitalijus Valantiejus <vitalijusv.h4qjc@slmail.me> 2023-12-21 22:43:12+00:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2023-12-22 16:35:28+02:00
logfd98fc1c5f83224cf1f128df7ba1cd24e4d40808
tree6e15dbdc84426d886a0ec86cf8cca73dede6c227
parent70b248497ab87471997c62a515bf4bb4109899b9

std.fmt: fix formatting of array pointers

- Clean up array formatting code. Remove buggy formatting of array pointers, deference pointer to reuse existing array formatting logic. - Change default specifier for array pointers to be "{any}", to be consistent with slices. - Allow using "{x}" and "{e}" for arrays and slices for all number types, including u8. Fixes #18185

1 files changed, 32 insertions(+), 48 deletions(-)

lib/std/fmt.zig+32-48
......@@ -435,7 +435,7 @@ pub fn defaultSpec(comptime T: type) [:0]const u8 {
435435 .Array => |_| return ANY,
436436 .Pointer => |ptr_info| switch (ptr_info.size) {
437437 .One => switch (@typeInfo(ptr_info.child)) {
438 .Array => |_| return "*",
438 .Array => |_| return ANY,
439439 else => {},
440440 },
441441 .Many, .C => return "*",
......@@ -599,26 +599,7 @@ pub fn formatType(
599599 },
600600 .Pointer => |ptr_info| switch (ptr_info.size) {
601601 .One => switch (@typeInfo(ptr_info.child)) {
602 .Array => |info| {
603 if (actual_fmt.len == 0)
604 @compileError("cannot format array ref without a specifier (i.e. {s} or {*})");
605 if (info.child == u8) {
606 switch (actual_fmt[0]) {
607 's', 'x', 'X', 'e', 'E' => {
608 comptime checkTextFmt(actual_fmt);
609 return formatBuf(value, options, writer);
610 },
611 else => {},
612 }
613 }
614 for (value, 0..) |item, i| {
615 comptime checkTextFmt(actual_fmt);
616 if (i != 0) try formatBuf(", ", options, writer);
617 try formatBuf(item, options, writer);
618 }
619 return;
620 },
621 .Enum, .Union, .Struct => {
602 .Array, .Enum, .Union, .Struct => {
622603 return formatType(value.*, actual_fmt, options, writer, max_depth);
623604 },
624605 else => return format(writer, "{s}@{x}", .{ @typeName(ptr_info.child), @intFromPtr(value) }),
......@@ -629,14 +610,8 @@ pub fn formatType(
629610 if (ptr_info.sentinel) |_| {
630611 return formatType(mem.span(value), actual_fmt, options, writer, max_depth);
631612 }
632 if (ptr_info.child == u8) {
633 switch (actual_fmt[0]) {
634 's', 'x', 'X', 'e', 'E' => {
635 comptime checkTextFmt(actual_fmt);
636 return formatBuf(mem.span(value), options, writer);
637 },
638 else => {},
639 }
613 if (actual_fmt[0] == 's' and ptr_info.child == u8) {
614 return formatBuf(mem.span(value), options, writer);
640615 }
641616 invalidFmtError(fmt, value);
642617 },
......@@ -646,14 +621,8 @@ pub fn formatType(
646621 if (max_depth == 0) {
647622 return writer.writeAll("{ ... }");
648623 }
649 if (ptr_info.child == u8) {
650 switch (actual_fmt[0]) {
651 's', 'x', 'X', 'e', 'E' => {
652 comptime checkTextFmt(actual_fmt);
653 return formatBuf(value, options, writer);
654 },
655 else => {},
656 }
624 if (actual_fmt[0] == 's' and ptr_info.child == u8) {
625 return formatBuf(value, options, writer);
657626 }
658627 try writer.writeAll("{ ");
659628 for (value, 0..) |elem, i| {
......@@ -671,14 +640,8 @@ pub fn formatType(
671640 if (max_depth == 0) {
672641 return writer.writeAll("{ ... }");
673642 }
674 if (info.child == u8) {
675 switch (actual_fmt[0]) {
676 's', 'x', 'X', 'e', 'E' => {
677 comptime checkTextFmt(actual_fmt);
678 return formatBuf(&value, options, writer);
679 },
680 else => {},
681 }
643 if (actual_fmt[0] == 's' and info.child == u8) {
644 return formatBuf(&value, options, writer);
682645 }
683646 try writer.writeAll("{ ");
684647 for (value, 0..) |elem, i| {
......@@ -2205,12 +2168,22 @@ test "buffer" {
22052168 }
22062169}
22072170
2171// Test formatting of arrays by value, by single-item pointer, and as a slice
2172fn expectArrayFmt(expected: []const u8, comptime template: []const u8, comptime array_value: anytype) !void {
2173 try expectFmt(expected, template, .{array_value});
2174 try expectFmt(expected, template, .{&array_value});
2175 var runtime_zero: usize = 0;
2176 _ = &runtime_zero;
2177 try expectFmt(expected, template, .{array_value[runtime_zero..]});
2178}
2179
22082180test "array" {
22092181 {
22102182 const value: [3]u8 = "abc".*;
2211 try expectFmt("array: abc\n", "array: {s}\n", .{value});
2212 try expectFmt("array: abc\n", "array: {s}\n", .{&value});
2213 try expectFmt("array: { 97, 98, 99 }\n", "array: {d}\n", .{value});
2183 try expectArrayFmt("array: abc\n", "array: {s}\n", value);
2184 try expectArrayFmt("array: { 97, 98, 99 }\n", "array: {d}\n", value);
2185 try expectArrayFmt("array: { 61, 62, 63 }\n", "array: {x}\n", value);
2186 try expectArrayFmt("array: { 97, 98, 99 }\n", "array: {any}\n", value);
22142187
22152188 var buf: [100]u8 = undefined;
22162189 try expectFmt(
......@@ -2219,12 +2192,23 @@ test "array" {
22192192 .{&value},
22202193 );
22212194 }
2195
2196 {
2197 const value = [2][3]u8{ "abc".*, "def".* };
2198
2199 try expectArrayFmt("array: { abc, def }\n", "array: {s}\n", value);
2200 try expectArrayFmt("array: { { 97, 98, 99 }, { 100, 101, 102 } }\n", "array: {d}\n", value);
2201 try expectArrayFmt("array: { { 61, 62, 63 }, { 64, 65, 66 } }\n", "array: {x}\n", value);
2202 }
22222203}
22232204
22242205test "slice" {
22252206 {
22262207 const value: []const u8 = "abc";
22272208 try expectFmt("slice: abc\n", "slice: {s}\n", .{value});
2209 try expectFmt("slice: { 97, 98, 99 }\n", "slice: {d}\n", .{value});
2210 try expectFmt("slice: { 61, 62, 63 }\n", "slice: {x}\n", .{value});
2211 try expectFmt("slice: { 97, 98, 99 }\n", "slice: {any}\n", .{value});
22282212 }
22292213 {
22302214 var runtime_zero: usize = 0;