authorgravatar for 14938807+xackus@users.noreply.github.comxackus <14938807+xackus@users.noreply.github.com> 2020-01-06 19:59:54+01:00
committergravatar for 14938807+xackus@users.noreply.github.comxackus <14938807+xackus@users.noreply.github.com> 2020-01-06 19:59:54+01:00
log6bebf741f92481ae3dbc9aeb8659c2476e4d211b
treecf1cc67c6f96b5811dca12b8d6d67f634357c3f7
parentc30106c90665079f525129e344cc1c13e4db162b

json: implement copy_strings=false


1 files changed, 35 insertions(+), 7 deletions(-)

lib/std/json.zig+35-7
...@@ -1376,11 +1376,9 @@ pub const Parser = struct {...@@ -1376,11 +1376,9 @@ pub const Parser = struct {
1376 }1376 }
13771377
1378 fn parseString(p: *Parser, allocator: *Allocator, s: std.meta.TagPayloadType(Token, Token.String), input: []const u8, i: usize) !Value {1378 fn parseString(p: *Parser, allocator: *Allocator, s: std.meta.TagPayloadType(Token, Token.String), input: []const u8, i: usize) !Value {
1379 // TODO: We don't strictly have to copy values which do not contain any escape
1380 // characters if flagged with the option.
1381 const slice = s.slice(input, i);1379 const slice = s.slice(input, i);
1382 switch (s.escapes) {1380 switch (s.escapes) {
1383 .None => return Value{ .String = try mem.dupe(allocator, u8, slice) },1381 .None => return Value{ .String = if (p.copy_strings) try mem.dupe(allocator, u8, slice) else slice },
1384 .Some => |some_escapes| {1382 .Some => |some_escapes| {
1385 const output = try allocator.alloc(u8, s.decodedLength());1383 const output = try allocator.alloc(u8, s.decodedLength());
1386 errdefer allocator.free(output);1384 errdefer allocator.free(output);
...@@ -1597,10 +1595,7 @@ test "escaped characters" {...@@ -1597,10 +1595,7 @@ test "escaped characters" {
1597 \\}1595 \\}
1598 ;1596 ;
15991597
1600 var p = Parser.init(debug.global_allocator, false);1598 const obj = (try test_parse(input)).Object;
1601 const tree = try p.parse(input);
1602
1603 const obj = tree.root.Object;
16041599
1605 testing.expectEqualSlices(u8, obj.get("backslash").?.value.String, "\\");1600 testing.expectEqualSlices(u8, obj.get("backslash").?.value.String, "\\");
1606 testing.expectEqualSlices(u8, obj.get("forwardslash").?.value.String, "/");1601 testing.expectEqualSlices(u8, obj.get("forwardslash").?.value.String, "/");
...@@ -1613,3 +1608,36 @@ test "escaped characters" {...@@ -1613,3 +1608,36 @@ test "escaped characters" {
1613 testing.expectEqualSlices(u8, obj.get("unicode").?.value.String, "ą");1608 testing.expectEqualSlices(u8, obj.get("unicode").?.value.String, "ą");
1614 testing.expectEqualSlices(u8, obj.get("surrogatepair").?.value.String, "😂");1609 testing.expectEqualSlices(u8, obj.get("surrogatepair").?.value.String, "😂");
1615}1610}
1611
1612test "string copy option" {
1613 const input =
1614 \\{
1615 \\ "noescape": "aąðŸ˜‚",
1616 \\ "simple": "\\\/\n\r\t\f\b\"",
1617 \\ "unicode": "\u0105",
1618 \\ "surrogatepair": "\ud83d\ude02"
1619 \\}
1620 ;
1621
1622 const tree_nocopy = try Parser.init(debug.global_allocator, false).parse(input);
1623 const obj_nocopy = tree_nocopy.root.Object;
1624
1625 const tree_copy = try Parser.init(debug.global_allocator, true).parse(input);
1626 const obj_copy = tree_copy.root.Object;
1627
1628 for ([_][]const u8{ "noescape", "simple", "unicode", "surrogatepair" }) |field_name| {
1629 testing.expectEqualSlices(u8, obj_nocopy.getValue(field_name).?.String, obj_copy.getValue(field_name).?.String);
1630 }
1631
1632 const nocopy_addr = &obj_nocopy.getValue("noescape").?.String[0];
1633 const copy_addr = &obj_copy.getValue("noescape").?.String[0];
1634
1635 var found_nocopy = false;
1636 for (input) |_, index| {
1637 testing.expect(copy_addr != &input[index]);
1638 if (nocopy_addr == &input[index]) {
1639 found_nocopy = true;
1640 }
1641 }
1642 testing.expect(found_nocopy);
1643}