| // Copyright 2009 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| // JSON (JavaScript Object Notation) parser. |
| // See http://www.json.org/ |
| |
| // The json package implements a simple parser and |
| // representation for JSON (JavaScript Object Notation), |
| // as defined at http://www.json.org/. |
| package json |
| |
| import ( |
| "bytes" |
| "strconv" |
| "utf8" |
| ) |
| |
| // Strings |
| // |
| // Double quoted with escapes: \" \\ \/ \b \f \n \r \t \uXXXX. |
| // No literal control characters, supposedly. |
| // Have also seen \' and embedded newlines. |
| |
| func _UnHex(p string, r, l int) (v int, ok bool) { |
| v = 0 |
| for i := r; i < l; i++ { |
| if i >= len(p) { |
| return 0, false |
| } |
| v *= 16 |
| switch { |
| case '0' <= p[i] && p[i] <= '9': |
| v += int(p[i] - '0') |
| case 'a' <= p[i] && p[i] <= 'f': |
| v += int(p[i] - 'a' + 10) |
| case 'A' <= p[i] && p[i] <= 'F': |
| v += int(p[i] - 'A' + 10) |
| default: |
| return 0, false |
| } |
| } |
| 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. |
| func Unquote(s string) (t string, ok bool) { |
| if len(s) < 2 || s[0] != '"' || s[len(s)-1] != '"' { |
| return |
| } |
| b := make([]byte, len(s)) |
| w := 0 |
| for r := 1; r < len(s)-1; { |
| switch { |
| case s[r] == '\\': |
| r++ |
| if r >= len(s)-1 { |
| return |
| } |
| switch s[r] { |
| default: |
| return |
| case '"', '\\', '/', '\'': |
| b[w] = s[r] |
| r++ |
| w++ |
| case 'b': |
| b[w] = '\b' |
| r++ |
| w++ |
| case 'f': |
| b[w] = '\f' |
| r++ |
| w++ |
| case 'n': |
| b[w] = '\n' |
| r++ |
| w++ |
| case 'r': |
| b[w] = '\r' |
| r++ |
| w++ |
| case 't': |
| b[w] = '\t' |
| r++ |
| w++ |
| case 'u': |
| r++ |
| rune, ok := _UnHex(s, r, r+4) |
| if !ok { |
| return |
| } |
| r += 4 |
| w += utf8.EncodeRune(rune, b[w:]) |
| } |
| // Control characters are invalid, but we've seen raw \n. |
| case s[r] < ' ' && s[r] != '\n': |
| if s[r] == '\n' { |
| b[w] = '\n' |
| r++ |
| w++ |
| break |
| } |
| return |
| // ASCII |
| case s[r] < utf8.RuneSelf: |
| b[w] = s[r] |
| r++ |
| w++ |
| // Coerce to well-formed UTF-8. |
| default: |
| rune, size := utf8.DecodeRuneInString(s[r:]) |
| r += size |
| w += utf8.EncodeRune(rune, b[w:]) |
| } |
| } |
| return string(b[0:w]), true |
| } |
| |
| // Quote quotes the raw string s using JSON syntax, |
| // so that Unquote(Quote(s)) = s, true. |
| func Quote(s string) string { |
| chr := make([]byte, 6) |
| chr0 := chr[0:1] |
| b := new(bytes.Buffer) |
| chr[0] = '"' |
| b.Write(chr0) |
| |
| for _, rune := range s { |
| switch { |
| case rune == '"' || rune == '\\': |
| chr[0] = '\\' |
| chr[1] = byte(rune) |
| b.Write(chr[0:2]) |
| |
| case rune == '\b': |
| chr[0] = '\\' |
| chr[1] = 'b' |
| b.Write(chr[0:2]) |
| |
| case rune == '\f': |
| chr[0] = '\\' |
| chr[1] = 'f' |
| b.Write(chr[0:2]) |
| |
| case rune == '\n': |
| chr[0] = '\\' |
| chr[1] = 'n' |
| b.Write(chr[0:2]) |
| |
| case rune == '\r': |
| chr[0] = '\\' |
| chr[1] = 'r' |
| b.Write(chr[0:2]) |
| |
| case rune == '\t': |
| chr[0] = '\\' |
| chr[1] = 't' |
| b.Write(chr[0:2]) |
| |
| 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] = '"' |
| b.Write(chr0) |
| return b.String() |
| } |
| |
| |
| // _Lexer |
| |
| type _Lexer struct { |
| s string |
| i int |
| kind int |
| token string |
| } |
| |
| func punct(c byte) bool { |
| return c == '"' || c == '[' || c == ']' || c == ':' || c == '{' || c == '}' || c == ',' |
| } |
| |
| func white(c byte) bool { return c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == '\v' } |
| |
| func skipwhite(p string, i int) int { |
| for i < len(p) && white(p[i]) { |
| i++ |
| } |
| return i |
| } |
| |
| func skiptoken(p string, i int) int { |
| for i < len(p) && !punct(p[i]) && !white(p[i]) { |
| i++ |
| } |
| return i |
| } |
| |
| func skipstring(p string, i int) int { |
| for i++; i < len(p) && p[i] != '"'; i++ { |
| if p[i] == '\\' { |
| i++ |
| } |
| } |
| if i >= len(p) { |
| return i |
| } |
| return i + 1 |
| } |
| |
| func (t *_Lexer) Next() { |
| i, s := t.i, t.s |
| i = skipwhite(s, i) |
| if i >= len(s) { |
| t.kind = 0 |
| t.token = "" |
| t.i = len(s) |
| return |
| } |
| |
| c := s[i] |
| switch { |
| case c == '-' || '0' <= c && c <= '9': |
| j := skiptoken(s, i) |
| t.kind = '1' |
| t.token = s[i:j] |
| i = j |
| |
| case 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z': |
| j := skiptoken(s, i) |
| t.kind = 'a' |
| t.token = s[i:j] |
| i = j |
| |
| case c == '"': |
| j := skipstring(s, i) |
| t.kind = '"' |
| t.token = s[i:j] |
| i = j |
| |
| case c == '[', c == ']', c == ':', c == '{', c == '}', c == ',': |
| t.kind = int(c) |
| t.token = s[i : i+1] |
| i++ |
| |
| default: |
| t.kind = '?' |
| t.token = s[i : i+1] |
| } |
| |
| t.i = i |
| } |
| |
| |
| // Parser |
| // |
| // Implements parsing but not the actions. Those are |
| // carried out by the implementation of the Builder interface. |
| // A Builder represents the object being created. |
| // Calling a method like Int64(i) sets that object to i. |
| // Calling a method like Elem(i) or Key(s) creates a |
| // new builder for a subpiece of the object (logically, |
| // an array element or a map key). |
| // |
| // There are two Builders, in other files. |
| // The JsonBuilder builds a generic Json structure |
| // in which maps are maps. |
| // The StructBuilder copies data into a possibly |
| // nested data structure, using the "map keys" |
| // as struct field names. |
| |
| type _Value interface{} |
| |
| // BUG(rsc): The json Builder interface needs to be |
| // reconciled with the xml Builder interface. |
| |
| // A Builder is an interface implemented by clients and passed |
| // to the JSON parser. It gives clients full control over the |
| // eventual representation returned by the parser. |
| type Builder interface { |
| // Set value |
| Int64(i int64) |
| Uint64(i uint64) |
| Float64(f float64) |
| String(s string) |
| Bool(b bool) |
| Null() |
| Array() |
| Map() |
| |
| // Create sub-Builders |
| Elem(i int) Builder |
| Key(s string) Builder |
| |
| // Flush changes to parent Builder if necessary. |
| Flush() |
| } |
| |
| func parse(lex *_Lexer, build Builder) bool { |
| ok := false |
| Switch: |
| switch lex.kind { |
| case 0: |
| break |
| case '1': |
| // If the number is exactly an integer, use that. |
| if i, err := strconv.Atoi64(lex.token); err == nil { |
| build.Int64(i) |
| ok = true |
| } else if i, err := strconv.Atoui64(lex.token); err == nil { |
| build.Uint64(i) |
| ok = true |
| } else |
| // Fall back to floating point. |
| if f, err := strconv.Atof64(lex.token); err == nil { |
| build.Float64(f) |
| ok = true |
| } |
| |
| case 'a': |
| switch lex.token { |
| case "true": |
| build.Bool(true) |
| ok = true |
| case "false": |
| build.Bool(false) |
| ok = true |
| case "null": |
| build.Null() |
| ok = true |
| } |
| |
| case '"': |
| if str, ok1 := Unquote(lex.token); ok1 { |
| build.String(str) |
| ok = true |
| } |
| |
| case '[': |
| // array |
| build.Array() |
| lex.Next() |
| n := 0 |
| for lex.kind != ']' { |
| if n > 0 { |
| if lex.kind != ',' { |
| break Switch |
| } |
| lex.Next() |
| } |
| if !parse(lex, build.Elem(n)) { |
| break Switch |
| } |
| n++ |
| } |
| ok = true |
| |
| case '{': |
| // map |
| lex.Next() |
| build.Map() |
| n := 0 |
| for lex.kind != '}' { |
| if n > 0 { |
| if lex.kind != ',' { |
| break Switch |
| } |
| lex.Next() |
| } |
| if lex.kind != '"' { |
| break Switch |
| } |
| key, ok := Unquote(lex.token) |
| if !ok { |
| break Switch |
| } |
| lex.Next() |
| if lex.kind != ':' { |
| break Switch |
| } |
| lex.Next() |
| if !parse(lex, build.Key(key)) { |
| break Switch |
| } |
| n++ |
| } |
| ok = true |
| } |
| |
| if ok { |
| lex.Next() |
| } |
| build.Flush() |
| return ok |
| } |
| |
| // Parse parses the JSON syntax string s and makes calls to |
| // the builder to construct a parsed representation. |
| // On success, it returns with ok set to true. |
| // On error, it returns with ok set to false, errindx set |
| // to the byte index in s where a syntax error occurred, |
| // and errtok set to the offending token. |
| func Parse(s string, builder Builder) (ok bool, errindx int, errtok string) { |
| lex := new(_Lexer) |
| lex.s = s |
| lex.Next() |
| if parse(lex, builder) { |
| if lex.kind == 0 { // EOF |
| return true, 0, "" |
| } |
| } |
| return false, lex.i, lex.token |
| } |