| ... | ... | @@ -66,6 +66,7 @@ fn peekIsAlign(comptime fmt: []const u8) bool { |
| 66 | 66 | /// - output numeric value in hexadecimal notation |
| 67 | 67 | /// - `s`: print a pointer-to-many as a c-string, use zero-termination |
| 68 | 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 | 70 | /// - `e`: output floating point value in scientific notation |
| 70 | 71 | /// - `d`: output numeric value in decimal notation |
| 71 | 72 | /// - `b`: output integer value in binary notation |
| ... | ... | @@ -599,6 +600,16 @@ pub fn formatText( |
| 599 | 600 | try formatInt(c, 16, fmt[0] == 'X', FormatOptions{ .width = 2, .fill = '0' }, writer); |
| 600 | 601 | } |
| 601 | 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 | 613 | } else { |
| 603 | 614 | @compileError("Unknown format string: '" ++ fmt ++ "'"); |
| 604 | 615 | } |
| ... | ... | @@ -1319,6 +1330,12 @@ test "slice" { |
| 1319 | 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 | 1339 | test "pointer" { |
| 1323 | 1340 | { |
| 1324 | 1341 | const value = @intToPtr(*align(1) i32, 0xdeadbeef); |