authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2020-10-29 22:22:25+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-01-02 17:12:57-07:00
log6f53653db17933fe2c8502d5bfc60857097b8bff
treecfb5be60b1361bab1a5a25c36edbc09e0a7c87f6
parent5275280ede72fbc3eb702ff7f01fac07b306ca46

std: Refactor the slice formatting code

Also fix the `*` specifier for more types, print an error message if we can't show the value address.

1 files changed, 49 insertions(+), 20 deletions(-)

lib/std/fmt.zig+49-20
......@@ -367,6 +367,36 @@ pub fn format(
367367 }
368368}
369369
370pub fn formatAddress(value: anytype, options: FormatOptions, writer: anytype) @TypeOf(writer).Error!void {
371 const T = @TypeOf(value);
372
373 switch (@typeInfo(T)) {
374 .Pointer => |info| {
375 try writer.writeAll(@typeName(info.child) ++ "@");
376 if (info.size == .Slice)
377 try formatInt(@ptrToInt(value.ptr), 16, false, FormatOptions{}, writer)
378 else
379 try formatInt(@ptrToInt(value), 16, false, FormatOptions{}, writer);
380 return;
381 },
382 .Optional => |info| {
383 if (@typeInfo(info.child) == .Pointer) {
384 try writer.writeAll(@typeName(info.child) ++ "@");
385 try formatInt(@ptrToInt(value), 16, false, FormatOptions{}, writer);
386 return;
387 }
388 },
389 .Array => |info| {
390 try writer.writeAll(@typeName(info.child) ++ "@");
391 try formatInt(@ptrToInt(value), 16, false, FormatOptions{}, writer);
392 return;
393 },
394 else => {},
395 }
396
397 @compileError("Cannot format non-pointer type " ++ @typeName(T) ++ " with * specifier");
398}
399
370400pub fn formatType(
371401 value: anytype,
372402 comptime fmt: []const u8,
......@@ -375,10 +405,7 @@ pub fn formatType(
375405 max_depth: usize,
376406) @TypeOf(writer).Error!void {
377407 if (comptime std.mem.eql(u8, fmt, "*")) {
378 try writer.writeAll(@typeName(std.meta.Child(@TypeOf(value))));
379 try writer.writeAll("@");
380 try formatInt(@ptrToInt(value), 16, false, FormatOptions{}, writer);
381 return;
408 return formatAddress(value, options, writer);
382409 }
383410
384411 const T = @TypeOf(value);
......@@ -499,25 +526,18 @@ pub fn formatType(
499526 return format(writer, "{}@{x}", .{ @typeName(@typeInfo(T).Pointer.child), @ptrToInt(value) });
500527 },
501528 .Slice => {
502 if (fmt.len > 0 and ((fmt[0] == 'x') or (fmt[0] == 'X'))) {
503 return formatText(value, fmt, options, writer);
504 }
505529 if (ptr_info.child == u8) {
506530 return formatText(value, fmt, options, writer);
507 } else if (fmt.len > 0 and ((fmt[0] == 'v') or (fmt[0] == 'V'))) {
508 try format(writer, "[", .{});
509 var i: usize = 0;
510 for (value) |one| {
511 if (i == value.len - 1) {
512 try format(writer, "{}", .{one});
513 } else {
514 try format(writer, "{}, ", .{one});
515 }
516 i += 1;
531 }
532
533 try writer.writeAll("[");
534 for (value) |elem, i| {
535 try formatType(elem, fmt, options, writer, max_depth);
536 if (i != value.len - 1) {
537 try writer.writeAll(", ");
517538 }
518 return format(writer, "]", .{});
519539 }
520 return format(writer, "{}@{x}", .{ @typeName(ptr_info.child), @ptrToInt(value.ptr) });
540 try writer.writeAll("]");
521541 },
522542 },
523543 .Array => |info| {
......@@ -1553,7 +1573,7 @@ test "slice" {
15531573 {
15541574 var runtime_zero: usize = 0;
15551575 const value = @intToPtr([*]align(1) const []const u8, 0xdeadbeef)[runtime_zero..runtime_zero];
1556 try testFmt("slice: []const u8@deadbeef\n", "slice: {}\n", .{value});
1576 try testFmt("slice: []const u8@deadbeef\n", "slice: {*}\n", .{value});
15571577 }
15581578 {
15591579 const null_term_slice: [:0]const u8 = "\x00hello\x00";
......@@ -1562,6 +1582,15 @@ test "slice" {
15621582
15631583 try testFmt("buf: Test\n", "buf: {s:5}\n", .{"Test"});
15641584 try testFmt("buf: Test\n Other text", "buf: {s}\n Other text", .{"Test"});
1585
1586 {
1587 var int_slice = [_]u32{ 1, 4096, 391891, 1111111111 };
1588 var runtime_zero: usize = 0;
1589 try testFmt("int: [1, 4096, 391891, 1111111111]", "int: {}", .{int_slice[runtime_zero..]});
1590 try testFmt("int: [1, 4096, 391891, 1111111111]", "int: {d}", .{int_slice[runtime_zero..]});
1591 try testFmt("int: [1, 1000, 5fad3, 423a35c7]", "int: {x}", .{int_slice[runtime_zero..]});
1592 try testFmt("int: [00001, 01000, 5fad3, 423a35c7]", "int: {x:0>5}", .{int_slice[runtime_zero..]});
1593 }
15651594}
15661595
15671596test "escape non-printable" {