| ... | @@ -367,6 +367,36 @@ pub fn format( | ... | @@ -367,6 +367,36 @@ pub fn format( |
| 367 | } | 367 | } |
| 368 | } | 368 | } |
| 369 | | 369 | |
| | 370 | pub 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 | |
| 370 | pub fn formatType( | 400 | pub fn formatType( |
| 371 | value: anytype, | 401 | value: anytype, |
| 372 | comptime fmt: []const u8, | 402 | comptime fmt: []const u8, |
| ... | @@ -375,10 +405,7 @@ pub fn formatType( | ... | @@ -375,10 +405,7 @@ pub fn formatType( |
| 375 | max_depth: usize, | 405 | max_depth: usize, |
| 376 | ) @TypeOf(writer).Error!void { | 406 | ) @TypeOf(writer).Error!void { |
| 377 | if (comptime std.mem.eql(u8, fmt, "*")) { | 407 | if (comptime std.mem.eql(u8, fmt, "*")) { |
| 378 | try writer.writeAll(@typeName(std.meta.Child(@TypeOf(value)))); | 408 | return formatAddress(value, options, writer); |
| 379 | try writer.writeAll("@"); | | |
| 380 | try formatInt(@ptrToInt(value), 16, false, FormatOptions{}, writer); | | |
| 381 | return; | | |
| 382 | } | 409 | } |
| 383 | | 410 | |
| 384 | const T = @TypeOf(value); | 411 | const T = @TypeOf(value); |
| ... | @@ -499,25 +526,18 @@ pub fn formatType( | ... | @@ -499,25 +526,18 @@ pub fn formatType( |
| 499 | return format(writer, "{}@{x}", .{ @typeName(@typeInfo(T).Pointer.child), @ptrToInt(value) }); | 526 | return format(writer, "{}@{x}", .{ @typeName(@typeInfo(T).Pointer.child), @ptrToInt(value) }); |
| 500 | }, | 527 | }, |
| 501 | .Slice => { | 528 | .Slice => { |
| 502 | if (fmt.len > 0 and ((fmt[0] == 'x') or (fmt[0] == 'X'))) { | | |
| 503 | return formatText(value, fmt, options, writer); | | |
| 504 | } | | |
| 505 | if (ptr_info.child == u8) { | 529 | if (ptr_info.child == u8) { |
| 506 | return formatText(value, fmt, options, writer); | 530 | return formatText(value, fmt, options, writer); |
| 507 | } else if (fmt.len > 0 and ((fmt[0] == 'v') or (fmt[0] == 'V'))) { | 531 | } |
| 508 | try format(writer, "[", .{}); | 532 | |
| 509 | var i: usize = 0; | 533 | try writer.writeAll("["); |
| 510 | for (value) |one| { | 534 | for (value) |elem, i| { |
| 511 | if (i == value.len - 1) { | 535 | try formatType(elem, fmt, options, writer, max_depth); |
| 512 | try format(writer, "{}", .{one}); | 536 | if (i != value.len - 1) { |
| 513 | } else { | 537 | try writer.writeAll(", "); |
| 514 | try format(writer, "{}, ", .{one}); | | |
| 515 | } | | |
| 516 | i += 1; | | |
| 517 | } | 538 | } |
| 518 | return format(writer, "]", .{}); | | |
| 519 | } | 539 | } |
| 520 | return format(writer, "{}@{x}", .{ @typeName(ptr_info.child), @ptrToInt(value.ptr) }); | 540 | try writer.writeAll("]"); |
| 521 | }, | 541 | }, |
| 522 | }, | 542 | }, |
| 523 | .Array => |info| { | 543 | .Array => |info| { |
| ... | @@ -1553,7 +1573,7 @@ test "slice" { | ... | @@ -1553,7 +1573,7 @@ test "slice" { |
| 1553 | { | 1573 | { |
| 1554 | var runtime_zero: usize = 0; | 1574 | var runtime_zero: usize = 0; |
| 1555 | const value = @intToPtr([*]align(1) const []const u8, 0xdeadbeef)[runtime_zero..runtime_zero]; | 1575 | 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}); |
| 1557 | } | 1577 | } |
| 1558 | { | 1578 | { |
| 1559 | const null_term_slice: [:0]const u8 = "\x00hello\x00"; | 1579 | const null_term_slice: [:0]const u8 = "\x00hello\x00"; |
| ... | @@ -1562,6 +1582,15 @@ test "slice" { | ... | @@ -1562,6 +1582,15 @@ test "slice" { |
| 1562 | | 1582 | |
| 1563 | try testFmt("buf: Test\n", "buf: {s:5}\n", .{"Test"}); | 1583 | try testFmt("buf: Test\n", "buf: {s:5}\n", .{"Test"}); |
| 1564 | try testFmt("buf: Test\n Other text", "buf: {s}\n Other text", .{"Test"}); | 1584 | 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 | } |
| 1565 | } | 1594 | } |
| 1566 | | 1595 | |
| 1567 | test "escape non-printable" { | 1596 | test "escape non-printable" { |