| ... | @@ -1379,10 +1379,15 @@ pub const Parser = struct { | ... | @@ -1379,10 +1379,15 @@ pub const Parser = struct { |
| 1379 | // TODO: We don't strictly have to copy values which do not contain any escape | 1379 | // TODO: We don't strictly have to copy values which do not contain any escape |
| 1380 | // characters if flagged with the option. | 1380 | // characters if flagged with the option. |
| 1381 | const slice = s.slice(input, i); | 1381 | const slice = s.slice(input, i); |
| 1382 | return switch (s.escapes) { | 1382 | switch (s.escapes) { |
| 1383 | .None => Value{ .String = try mem.dupe(allocator, u8, slice) }, | 1383 | .None => return Value{ .String = try mem.dupe(allocator, u8, slice) }, |
| 1384 | .Some => |some_escapes| Value{ .String = try unescapeStringAlloc(allocator, some_escapes, slice) }, | 1384 | .Some => |some_escapes| { |
| 1385 | }; | 1385 | const output = try allocator.alloc(u8, s.decodedLength()); |
| | 1386 | errdefer allocator.free(output); |
| | 1387 | try unescapeString(output, slice); |
| | 1388 | return Value{ .String = output }; |
| | 1389 | }, |
| | 1390 | } |
| 1386 | } | 1391 | } |
| 1387 | | 1392 | |
| 1388 | fn parseNumber(p: *Parser, n: std.meta.TagPayloadType(Token, Token.Number), input: []const u8, i: usize) !Value { | 1393 | fn parseNumber(p: *Parser, n: std.meta.TagPayloadType(Token, Token.Number), input: []const u8, i: usize) !Value { |
| ... | @@ -1396,12 +1401,7 @@ pub const Parser = struct { | ... | @@ -1396,12 +1401,7 @@ pub const Parser = struct { |
| 1396 | // Unescape a JSON string | 1401 | // Unescape a JSON string |
| 1397 | // Only to be used on strings already validated by the parser | 1402 | // Only to be used on strings already validated by the parser |
| 1398 | // (note the unreachable statements and lack of bounds checking) | 1403 | // (note the unreachable statements and lack of bounds checking) |
| 1399 | fn unescapeStringAlloc(alloc: *Allocator, escapes: std.meta.TagPayloadType(StringEscapes, StringEscapes.Some), input: []const u8) ![]u8 { | 1404 | fn unescapeString(output: []u8, input: []const u8) !void { |
| 1400 | const result_size = input.len +% @bitCast(usize, escapes.size_diff); | | |
| 1401 | | | |
| 1402 | const output = try alloc.alloc(u8, result_size); | | |
| 1403 | errdefer alloc.free(output); | | |
| 1404 | | | |
| 1405 | var inIndex: usize = 0; | 1405 | var inIndex: usize = 0; |
| 1406 | var outIndex: usize = 0; | 1406 | var outIndex: usize = 0; |
| 1407 | | 1407 | |
| ... | @@ -1455,9 +1455,7 @@ fn unescapeStringAlloc(alloc: *Allocator, escapes: std.meta.TagPayloadType(Strin | ... | @@ -1455,9 +1455,7 @@ fn unescapeStringAlloc(alloc: *Allocator, escapes: std.meta.TagPayloadType(Strin |
| 1455 | } | 1455 | } |
| 1456 | } | 1456 | } |
| 1457 | } | 1457 | } |
| 1458 | assert(outIndex == result_size); | 1458 | assert(outIndex == output.len); |
| 1459 | | | |
| 1460 | return output; | | |
| 1461 | } | 1459 | } |
| 1462 | | 1460 | |
| 1463 | test "json.parser.dynamic" { | 1461 | test "json.parser.dynamic" { |