aboutsummaryrefslogtreecommitdiff
path: root/core/encoding
diff options
context:
space:
mode:
authorLaytan Laats <laytanlaats@hotmail.com>2023-05-22 17:22:33 +0200
committerLaytan Laats <laytanlaats@hotmail.com>2023-05-22 17:22:33 +0200
commit5d54b710e7b90734ed352648c5c099b4e5d0701e (patch)
tree0f4e196b8f5502ac4e619928649529b79c3d0f36 /core/encoding
parent118ab60588832904e6a980c712702f71b4f7ec15 (diff)
fix #2550 json encoding should use surrogate pairs per RFC7159
Diffstat (limited to 'core/encoding')
-rw-r--r--core/encoding/json/marshal.odin6
-rw-r--r--core/encoding/json/parser.odin11
2 files changed, 13 insertions, 4 deletions
diff --git a/core/encoding/json/marshal.odin b/core/encoding/json/marshal.odin
index 4cf9264c5..d25015ac7 100644
--- a/core/encoding/json/marshal.odin
+++ b/core/encoding/json/marshal.odin
@@ -153,7 +153,7 @@ marshal_to_writer :: proc(w: io.Writer, v: any, opt: ^Marshal_Options) -> (err:
case complex128: r, i = f64(real(z)), f64(imag(z))
case: return .Unsupported_Type
}
-
+
io.write_byte(w, '[') or_return
io.write_f64(w, r) or_return
io.write_string(w, ", ") or_return
@@ -165,8 +165,8 @@ marshal_to_writer :: proc(w: io.Writer, v: any, opt: ^Marshal_Options) -> (err:
case runtime.Type_Info_String:
switch s in a {
- case string: io.write_quoted_string(w, s) or_return
- case cstring: io.write_quoted_string(w, string(s)) or_return
+ case string: io.write_quoted_string(w, s, '"', nil, true) or_return
+ case cstring: io.write_quoted_string(w, string(s), '"', nil, true) or_return
}
case runtime.Type_Info_Boolean:
diff --git a/core/encoding/json/parser.odin b/core/encoding/json/parser.odin
index ed36ae33b..d007e16d7 100644
--- a/core/encoding/json/parser.odin
+++ b/core/encoding/json/parser.odin
@@ -2,6 +2,7 @@ package json
import "core:mem"
import "core:unicode/utf8"
+import "core:unicode/utf16"
import "core:strconv"
Parser :: struct {
@@ -403,11 +404,19 @@ unquote_string :: proc(token: Token, spec: Specification, allocator := context.a
}
i += 6
+ // If this is a surrogate pair, decode as such by taking the next rune too.
+ if r >= utf8.SURROGATE_MIN && r <= utf8.SURROGATE_HIGH_MAX && len(s) > i + 2 && s[i:i+2] == "\\u" {
+ r2 := get_u4_rune(s[i:])
+ if r2 >= utf8.SURROGATE_LOW_MIN && r2 <= utf8.SURROGATE_MAX {
+ i += 6
+ r = utf16.decode_surrogate_pair(r, r2)
+ }
+ }
+
buf, buf_width := utf8.encode_rune(r)
copy(b[w:], buf[:buf_width])
w += buf_width
-
case '0':
if spec != .JSON {
b[w] = '\x00'