From 91ca0e4b02ff8f67e7e18a21fdcd1168f1f5a675 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 19 Apr 2020 20:33:15 -0400 Subject: [PATCH] implement rendering escaped zig string literals --- lib/std/zig.zig | 3 +- ..._string_literal.zig => string_literal.zig} | 44 ++++++++++++++++--- 2 files changed, 39 insertions(+), 8 deletions(-) rename lib/std/zig/{parse_string_literal.zig => string_literal.zig} (75%) diff --git a/lib/std/zig.zig b/lib/std/zig.zig index 81f34b09c9..dcf7842a3c 100644 --- a/lib/std/zig.zig +++ b/lib/std/zig.zig @@ -2,8 +2,9 @@ const tokenizer = @import("zig/tokenizer.zig"); pub const Token = tokenizer.Token; pub const Tokenizer = tokenizer.Tokenizer; pub const parse = @import("zig/parse.zig").parse; -pub const parseStringLiteral = @import("zig/parse_string_literal.zig").parseStringLiteral; +pub const parseStringLiteral = @import("zig/string_literal.zig").parse; pub const render = @import("zig/render.zig").render; +pub const renderStringLiteral = @import("zig/string_literal.zig").render; pub const ast = @import("zig/ast.zig"); pub const system = @import("zig/system.zig"); pub const CrossTarget = @import("zig/cross_target.zig").CrossTarget; diff --git a/lib/std/zig/parse_string_literal.zig b/lib/std/zig/string_literal.zig similarity index 75% rename from lib/std/zig/parse_string_literal.zig rename to lib/std/zig/string_literal.zig index 949940f550..cc6030ad15 100644 --- a/lib/std/zig/parse_string_literal.zig +++ b/lib/std/zig/string_literal.zig @@ -6,7 +6,7 @@ const State = enum { Backslash, }; -pub const ParseStringLiteralError = error{ +pub const ParseError = error{ OutOfMemory, /// When this is returned, index will be the position of the character. @@ -14,11 +14,11 @@ pub const ParseStringLiteralError = error{ }; /// caller owns returned memory -pub fn parseStringLiteral( +pub fn parse( allocator: *std.mem.Allocator, bytes: []const u8, bad_index: *usize, // populated if error.InvalidCharacter is returned -) ParseStringLiteralError![]u8 { +) ParseError![]u8 { assert(bytes.len >= 2 and bytes[0] == '"' and bytes[bytes.len - 1] == '"'); var list = std.ArrayList(u8).init(allocator); @@ -110,7 +110,7 @@ pub fn parseStringLiteral( unreachable; } -test "parseStringLiteral" { +test "parse" { const expect = std.testing.expect; const eql = std.mem.eql; @@ -119,7 +119,37 @@ test "parseStringLiteral" { var alloc = &fixed_buf_alloc.allocator; var bad_index: usize = undefined; - expect(eql(u8, "foo", try parseStringLiteral(alloc, "\"foo\"", &bad_index))); - expect(eql(u8, "foo", try parseStringLiteral(alloc, "\"f\x6f\x6f\"", &bad_index))); - expect(eql(u8, "f💯", try parseStringLiteral(alloc, "\"f\u{1f4af}\"", &bad_index))); + expect(eql(u8, "foo", try parse(alloc, "\"foo\"", &bad_index))); + expect(eql(u8, "foo", try parse(alloc, "\"f\x6f\x6f\"", &bad_index))); + expect(eql(u8, "f💯", try parse(alloc, "\"f\u{1f4af}\"", &bad_index))); +} + +/// Writes a Zig-syntax escaped string literal to the stream. Includes the double quotes. +pub fn render(utf8: []const u8, out_stream: var) !void { + try out_stream.writeByte('"'); + for (utf8) |byte| switch (byte) { + '\n' => try out_stream.writeAll("\\n"), + '\r' => try out_stream.writeAll("\\r"), + '\t' => try out_stream.writeAll("\\t"), + '\\' => try out_stream.writeAll("\\\\"), + '"' => try out_stream.writeAll("\\\""), + ' ', '!', '#'...'[', ']'...'~' => try out_stream.writeByte(byte), + else => try out_stream.print("\\x{x:0>2}", .{byte}), + }; + try out_stream.writeByte('"'); +} + +test "render" { + const expect = std.testing.expect; + const eql = std.mem.eql; + + var fixed_buf_mem: [32]u8 = undefined; + + { + var fbs = std.io.fixedBufferStream(&fixed_buf_mem); + try render(" \\ hi \x07 \x11 \" derp", fbs.outStream()); + expect(eql(u8, + \\" \\ hi \x07 \x11 \" derp" + , fbs.getWritten())); + } }