| ... | ... | @@ -15,12 +15,16 @@ pub const WriteStream = @import("json/write_stream.zig").WriteStream; |
| 15 | 15 | /// Use `token.slice()` on the input at the current position to get the current slice. |
| 16 | 16 | pub const Token = struct { |
| 17 | 17 | id: Id, |
| 18 | |
| 18 | 19 | /// How many bytes do we skip before counting |
| 19 | 20 | offset: u1, |
| 21 | |
| 20 | 22 | /// Whether string contains an escape sequence and cannot be zero-copied |
| 21 | 23 | string_has_escape: bool, |
| 24 | |
| 22 | 25 | /// Whether number is simple and can be represented by an integer (i.e. no `.` or `e`) |
| 23 | 26 | number_is_integer: bool, |
| 27 | |
| 24 | 28 | /// How many bytes from the current position behind the start of this token is. |
| 25 | 29 | count: usize, |
| 26 | 30 | |
| ... | ... | @@ -1299,54 +1303,52 @@ pub const Parser = struct { |
| 1299 | 1303 | fn unescapeStringAlloc(alloc: *Allocator, input: []const u8) ![]u8 { |
| 1300 | 1304 | const output = try alloc.alloc(u8, input.len); |
| 1301 | 1305 | errdefer alloc.free(output); |
| 1302 | | |
| 1306 | |
| 1303 | 1307 | var inIndex: usize = 0; |
| 1304 | 1308 | var outIndex: usize = 0; |
| 1305 | 1309 | |
| 1306 | | while(inIndex < input.len) { |
| 1307 | | if(input[inIndex] != '\\'){ |
| 1310 | while (inIndex < input.len) { |
| 1311 | if (input[inIndex] != '\\') { |
| 1308 | 1312 | // not an escape sequence |
| 1309 | 1313 | output[outIndex] = input[inIndex]; |
| 1310 | 1314 | inIndex += 1; |
| 1311 | 1315 | outIndex += 1; |
| 1312 | | } else if(input[inIndex + 1] != 'u'){ |
| 1316 | } else if (input[inIndex + 1] != 'u') { |
| 1313 | 1317 | // a simple escape sequence |
| 1314 | | output[outIndex] = @as(u8, |
| 1315 | | switch(input[inIndex + 1]){ |
| 1316 | | '\\' => '\\', |
| 1317 | | '/' => '/', |
| 1318 | | 'n' => '\n', |
| 1319 | | 'r' => '\r', |
| 1320 | | 't' => '\t', |
| 1321 | | 'f' => 12, |
| 1322 | | 'b' => 8, |
| 1323 | | '"' => '"', |
| 1324 | | else => unreachable |
| 1325 | | } |
| 1326 | | ); |
| 1318 | output[outIndex] = @as(u8, switch (input[inIndex + 1]) { |
| 1319 | '\\' => '\\', |
| 1320 | '/' => '/', |
| 1321 | 'n' => '\n', |
| 1322 | 'r' => '\r', |
| 1323 | 't' => '\t', |
| 1324 | 'f' => 12, |
| 1325 | 'b' => 8, |
| 1326 | '"' => '"', |
| 1327 | else => unreachable, |
| 1328 | }); |
| 1327 | 1329 | inIndex += 2; |
| 1328 | 1330 | outIndex += 1; |
| 1329 | 1331 | } else { |
| 1330 | 1332 | // a unicode escape sequence |
| 1331 | | const firstCodeUnit = std.fmt.parseInt(u16, input[inIndex+2 .. inIndex+6], 16) catch unreachable; |
| 1333 | const firstCodeUnit = std.fmt.parseInt(u16, input[inIndex + 2 .. inIndex + 6], 16) catch unreachable; |
| 1332 | 1334 | |
| 1333 | 1335 | // guess optimistically that it's not a surrogate pair |
| 1334 | | if(std.unicode.utf8Encode(firstCodeUnit, output[outIndex..])) |byteCount| { |
| 1336 | if (std.unicode.utf8Encode(firstCodeUnit, output[outIndex..])) |byteCount| { |
| 1335 | 1337 | outIndex += byteCount; |
| 1336 | 1338 | inIndex += 6; |
| 1337 | 1339 | } else |err| { |
| 1338 | 1340 | // it might be a surrogate pair |
| 1339 | | if(err != error.Utf8CannotEncodeSurrogateHalf) { |
| 1341 | if (err != error.Utf8CannotEncodeSurrogateHalf) { |
| 1340 | 1342 | return error.InvalidUnicodeHexSymbol; |
| 1341 | 1343 | } |
| 1342 | 1344 | // check if a second code unit is present |
| 1343 | | if(inIndex + 7 >= input.len or input[inIndex + 6] != '\\' or input[inIndex + 7] != 'u'){ |
| 1345 | if (inIndex + 7 >= input.len or input[inIndex + 6] != '\\' or input[inIndex + 7] != 'u') { |
| 1344 | 1346 | return error.InvalidUnicodeHexSymbol; |
| 1345 | 1347 | } |
| 1346 | | |
| 1347 | | const secondCodeUnit = std.fmt.parseInt(u16, input[inIndex+8 .. inIndex+12], 16) catch unreachable; |
| 1348 | | |
| 1349 | | if(std.unicode.utf16leToUtf8(output[outIndex..], &[2]u16{ firstCodeUnit, secondCodeUnit })) |byteCount| { |
| 1348 | |
| 1349 | const secondCodeUnit = std.fmt.parseInt(u16, input[inIndex + 8 .. inIndex + 12], 16) catch unreachable; |
| 1350 | |
| 1351 | if (std.unicode.utf16leToUtf8(output[outIndex..], &[2]u16{ firstCodeUnit, secondCodeUnit })) |byteCount| { |
| 1350 | 1352 | outIndex += byteCount; |
| 1351 | 1353 | inIndex += 12; |
| 1352 | 1354 | } else |_| { |