aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Langley <agl@golang.org>2009-11-11 17:13:14 -0800
committerAdam Langley <agl@golang.org>2009-11-11 17:13:14 -0800
commit3b092fec363252d1ac8522b138ac37d9f1c9de4d (patch)
tree17f9bbb200c3fbb43870bcd351c266f8f6145bd7
parentae3341476d4c7ece87758eccc8d927fa9ee2b5dc (diff)
downloadgo-3b092fec363252d1ac8522b138ac37d9f1c9de4d.tar.gz
go-3b092fec363252d1ac8522b138ac37d9f1c9de4d.zip
json: support \u escaping in strings
Fixes #73. R=rsc CC=golang-dev https://golang.org/cl/154072
-rw-r--r--src/pkg/json/generic_test.go1
-rw-r--r--src/pkg/json/parse.go39
2 files changed, 28 insertions, 12 deletions
diff --git a/src/pkg/json/generic_test.go b/src/pkg/json/generic_test.go
index ce78a39ee4..7fc7bcc55a 100644
--- a/src/pkg/json/generic_test.go
+++ b/src/pkg/json/generic_test.go
@@ -21,6 +21,7 @@ var jsontests = []string{
`[1,2,"abc",null,true,false]`,
`{}`,
`{"a":1}`,
+ `"q\u0302"`,
}
func TestJson(t *testing.T) {
diff --git a/src/pkg/json/parse.go b/src/pkg/json/parse.go
index ac44afca14..d96abd9616 100644
--- a/src/pkg/json/parse.go
+++ b/src/pkg/json/parse.go
@@ -43,6 +43,14 @@ func _UnHex(p string, r, l int) (v int, ok bool) {
return v, true;
}
+func _ToHex(b []byte, rune int) {
+ const hexDigits = "0123456789abcdef";
+ b[0] = hexDigits[rune>>12&0xf];
+ b[1] = hexDigits[rune>>8&0xf];
+ b[2] = hexDigits[rune>>4&0xf];
+ b[3] = hexDigits[rune&0xf];
+}
+
// Unquote unquotes the JSON-quoted string s,
// returning a raw string t. If s is not a valid
// JSON-quoted string, Unquote returns with ok set to false.
@@ -88,7 +96,7 @@ func Unquote(s string) (t string, ok bool) {
w++;
case 'u':
r++;
- rune, ok := _UnHex(s, r, 4);
+ rune, ok := _UnHex(s, r, r+4);
if !ok {
return
}
@@ -122,46 +130,53 @@ func Unquote(s string) (t string, ok bool) {
// Quote quotes the raw string s using JSON syntax,
// so that Unquote(Quote(s)) = s, true.
func Quote(s string) string {
- chr := make([]byte, utf8.UTFMax);
+ chr := make([]byte, 6);
chr0 := chr[0:1];
b := new(bytes.Buffer);
chr[0] = '"';
b.Write(chr0);
- for i := 0; i < len(s); i++ {
+
+ for _, rune := range s {
switch {
- case s[i] == '"' || s[i] == '\\':
+ case rune == '"' || rune == '\\':
chr[0] = '\\';
- chr[1] = s[i];
+ chr[1] = byte(rune);
b.Write(chr[0:2]);
- case s[i] == '\b':
+ case rune == '\b':
chr[0] = '\\';
chr[1] = 'b';
b.Write(chr[0:2]);
- case s[i] == '\f':
+ case rune == '\f':
chr[0] = '\\';
chr[1] = 'f';
b.Write(chr[0:2]);
- case s[i] == '\n':
+ case rune == '\n':
chr[0] = '\\';
chr[1] = 'n';
b.Write(chr[0:2]);
- case s[i] == '\r':
+ case rune == '\r':
chr[0] = '\\';
chr[1] = 'r';
b.Write(chr[0:2]);
- case s[i] == '\t':
+ case rune == '\t':
chr[0] = '\\';
chr[1] = 't';
b.Write(chr[0:2]);
- case 0x20 <= s[i] && s[i] < utf8.RuneSelf:
- chr[0] = s[i];
+ case 0x20 <= rune && rune < utf8.RuneSelf:
+ chr[0] = byte(rune);
b.Write(chr0);
+
+ default:
+ chr[0] = '\\';
+ chr[1] = 'u';
+ _ToHex(chr[2:6], rune);
+ b.Write(chr);
}
}
chr[0] = '"';