| ... | @@ -66,6 +66,7 @@ fn peekIsAlign(comptime fmt: []const u8) bool { | ... | @@ -66,6 +66,7 @@ fn peekIsAlign(comptime fmt: []const u8) bool { |
| 66 | /// - output numeric value in hexadecimal notation | 66 | /// - output numeric value in hexadecimal notation |
| 67 | /// - `s`: print a pointer-to-many as a c-string, use zero-termination | 67 | /// - `s`: print a pointer-to-many as a c-string, use zero-termination |
| 68 | /// - `B` and `Bi`: output a memory size in either metric (1000) or power-of-two (1024) based notation. works for both float and integer values. | 68 | /// - `B` and `Bi`: output a memory size in either metric (1000) or power-of-two (1024) based notation. works for both float and integer values. |
| | 69 | /// - `e` and `E`: if printing a string, escape non-printable characters |
| 69 | /// - `e`: output floating point value in scientific notation | 70 | /// - `e`: output floating point value in scientific notation |
| 70 | /// - `d`: output numeric value in decimal notation | 71 | /// - `d`: output numeric value in decimal notation |
| 71 | /// - `b`: output integer value in binary notation | 72 | /// - `b`: output integer value in binary notation |
| ... | @@ -599,6 +600,16 @@ pub fn formatText( | ... | @@ -599,6 +600,16 @@ pub fn formatText( |
| 599 | try formatInt(c, 16, fmt[0] == 'X', FormatOptions{ .width = 2, .fill = '0' }, writer); | 600 | try formatInt(c, 16, fmt[0] == 'X', FormatOptions{ .width = 2, .fill = '0' }, writer); |
| 600 | } | 601 | } |
| 601 | return; | 602 | return; |
| | 603 | } else if (comptime (std.mem.eql(u8, fmt, "e") or std.mem.eql(u8, fmt, "E"))) { |
| | 604 | for (bytes) |c| { |
| | 605 | if (std.ascii.isPrint(c)) { |
| | 606 | try writer.writeByte(c); |
| | 607 | } else { |
| | 608 | try writer.writeAll("\\x"); |
| | 609 | try formatInt(c, 16, fmt[0] == 'E', FormatOptions{ .width = 2, .fill = '0' }, writer); |
| | 610 | } |
| | 611 | } |
| | 612 | return; |
| 602 | } else { | 613 | } else { |
| 603 | @compileError("Unknown format string: '" ++ fmt ++ "'"); | 614 | @compileError("Unknown format string: '" ++ fmt ++ "'"); |
| 604 | } | 615 | } |
| ... | @@ -1319,6 +1330,12 @@ test "slice" { | ... | @@ -1319,6 +1330,12 @@ test "slice" { |
| 1319 | try testFmt("buf: Test\n Other text", "buf: {s}\n Other text", .{"Test"}); | 1330 | try testFmt("buf: Test\n Other text", "buf: {s}\n Other text", .{"Test"}); |
| 1320 | } | 1331 | } |
| 1321 | | 1332 | |
| | 1333 | test "escape non-printable" { |
| | 1334 | try testFmt("abc", "{e}", .{"abc"}); |
| | 1335 | try testFmt("ab\\xffc", "{e}", .{"ab\xffc"}); |
| | 1336 | try testFmt("ab\\xFFc", "{E}", .{"ab\xffc"}); |
| | 1337 | } |
| | 1338 | |
| 1322 | test "pointer" { | 1339 | test "pointer" { |
| 1323 | { | 1340 | { |
| 1324 | const value = @intToPtr(*align(1) i32, 0xdeadbeef); | 1341 | const value = @intToPtr(*align(1) i32, 0xdeadbeef); |