diff options
author | Adam Langley <agl@golang.org> | 2009-11-11 17:13:14 -0800 |
---|---|---|
committer | Adam Langley <agl@golang.org> | 2009-11-11 17:13:14 -0800 |
commit | b7d09f67c6372a39ea7a8aa1e718cd532132f88a (patch) | |
tree | e6a842e8fef1a6d46085328d30dbebbcda601ce2 /src/pkg/json | |
parent | b766706cf7ce986a4aa27515c12f6307f465f030 (diff) | |
download | golang-b7d09f67c6372a39ea7a8aa1e718cd532132f88a.tar.gz |
json: support \u escaping in strings
Fixes issue 73.
R=rsc
CC=golang-dev
http://codereview.appspot.com/154072
Diffstat (limited to 'src/pkg/json')
-rw-r--r-- | src/pkg/json/generic_test.go | 1 | ||||
-rw-r--r-- | src/pkg/json/parse.go | 39 |
2 files changed, 28 insertions, 12 deletions
diff --git a/src/pkg/json/generic_test.go b/src/pkg/json/generic_test.go index ce78a39ee..7fc7bcc55 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 ac44afca1..d96abd961 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] = '"'; |