| ... | ... | @@ -231,11 +231,10 @@ test "parseCharLiteral" { |
| 231 | 231 | ); |
| 232 | 232 | } |
| 233 | 233 | |
| 234 | | /// Parses `bytes` as a Zig string literal and appends the result to `buf`. |
| 234 | /// Parses `bytes` as a Zig string literal and writes the result to the std.io.Writer type. |
| 235 | 235 | /// Asserts `bytes` has '"' at beginning and end. |
| 236 | | pub fn parseAppend(buf: *std.ArrayList(u8), bytes: []const u8) error{OutOfMemory}!Result { |
| 236 | pub fn parseWrite(writer: anytype, bytes: []const u8) error{OutOfMemory}!Result { |
| 237 | 237 | assert(bytes.len >= 2 and bytes[0] == '"' and bytes[bytes.len - 1] == '"'); |
| 238 | | try buf.ensureUnusedCapacity(bytes.len - 2); |
| 239 | 238 | |
| 240 | 239 | var index: usize = 1; |
| 241 | 240 | while (true) { |
| ... | ... | @@ -248,11 +247,13 @@ pub fn parseAppend(buf: *std.ArrayList(u8), bytes: []const u8) error{OutOfMemory |
| 248 | 247 | switch (result) { |
| 249 | 248 | .success => |codepoint| { |
| 250 | 249 | if (bytes[escape_char_index] == 'u') { |
| 251 | | buf.items.len += utf8Encode(codepoint, buf.unusedCapacitySlice()) catch { |
| 250 | var buf: [4]u8 = undefined; |
| 251 | const len = utf8Encode(codepoint, &buf) catch { |
| 252 | 252 | return Result{ .failure = .{ .invalid_unicode_codepoint = escape_char_index + 1 } }; |
| 253 | 253 | }; |
| 254 | try writer.writeAll(buf[0..len]); |
| 254 | 255 | } else { |
| 255 | | buf.appendAssumeCapacity(@intCast(u8, codepoint)); |
| 256 | try writer.writeByte(@intCast(u8, codepoint)); |
| 256 | 257 | } |
| 257 | 258 | }, |
| 258 | 259 | .failure => |err| return Result{ .failure = err }, |
| ... | ... | @@ -261,7 +262,7 @@ pub fn parseAppend(buf: *std.ArrayList(u8), bytes: []const u8) error{OutOfMemory |
| 261 | 262 | '\n' => return Result{ .failure = .{ .invalid_character = index } }, |
| 262 | 263 | '"' => return Result.success, |
| 263 | 264 | else => { |
| 264 | | try buf.append(b); |
| 265 | try writer.writeByte(b); |
| 265 | 266 | index += 1; |
| 266 | 267 | }, |
| 267 | 268 | } |
| ... | ... | @@ -280,44 +281,6 @@ pub fn parseAlloc(allocator: std.mem.Allocator, bytes: []const u8) ParseError![] |
| 280 | 281 | } |
| 281 | 282 | } |
| 282 | 283 | |
| 283 | | /// Parses `bytes` as a Zig string literal and writes the result to the std.io.Writer type. |
| 284 | | /// Asserts `bytes` has '"' at beginning and end. |
| 285 | | pub fn parseWrite(writer: anytype, bytes: []const u8) error{OutOfMemory}!Result { |
| 286 | | assert(bytes.len >= 2 and bytes[0] == '"' and bytes[bytes.len - 1] == '"'); |
| 287 | | |
| 288 | | var index: usize = 1; |
| 289 | | while (true) { |
| 290 | | const b = bytes[index]; |
| 291 | | |
| 292 | | switch (b) { |
| 293 | | '\\' => { |
| 294 | | const escape_char_index = index + 1; |
| 295 | | const result = parseEscapeSequence(bytes, &index); |
| 296 | | switch (result) { |
| 297 | | .success => |codepoint| { |
| 298 | | if (bytes[escape_char_index] == 'u') { |
| 299 | | var buf: [3]u8 = undefined; |
| 300 | | const len = utf8Encode(codepoint, &buf) catch { |
| 301 | | return Result{ .failure = .{ .invalid_unicode_codepoint = escape_char_index + 1 } }; |
| 302 | | }; |
| 303 | | try writer.writeAll(buf[0..len]); |
| 304 | | } else { |
| 305 | | try writer.writeByte(@intCast(u8, codepoint)); |
| 306 | | } |
| 307 | | }, |
| 308 | | .failure => |err| return Result{ .failure = err }, |
| 309 | | } |
| 310 | | }, |
| 311 | | '\n' => return Result{ .failure = .{ .invalid_character = index } }, |
| 312 | | '"' => return Result.success, |
| 313 | | else => { |
| 314 | | try writer.writeByte(b); |
| 315 | | index += 1; |
| 316 | | }, |
| 317 | | } |
| 318 | | } else unreachable; // TODO should not need else unreachable on while(true) |
| 319 | | } |
| 320 | | |
| 321 | 284 | test "parse" { |
| 322 | 285 | const expect = std.testing.expect; |
| 323 | 286 | const expectError = std.testing.expectError; |