mirror of
https://github.com/golang/go
synced 2024-11-25 05:07:56 -07:00
json: delete obsolete code
R=r CC=golang-dev https://golang.org/cl/943047
This commit is contained in:
parent
dcff89057b
commit
dc644b8f43
@ -8,9 +8,7 @@ TARG=json
|
||||
GOFILES=\
|
||||
decode.go\
|
||||
encode.go\
|
||||
error.go\
|
||||
indent.go\
|
||||
parse.go\
|
||||
scanner.go\
|
||||
stream.go\
|
||||
|
||||
|
@ -1,19 +0,0 @@
|
||||
// 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.
|
||||
|
||||
package json
|
||||
|
||||
import "fmt"
|
||||
|
||||
// ParseError aggregates information about a JSON parse error. It is
|
||||
// compatible with the os.Error interface.
|
||||
type ParseError struct {
|
||||
Index int // A byte index in JSON string where the error occurred
|
||||
Token string // An offending token
|
||||
}
|
||||
|
||||
// Produce a string representation of this ParseError.
|
||||
func (pe *ParseError) String() string {
|
||||
return fmt.Sprintf("Unexpected JSON token at position %d: %q.", pe.Index, pe.Token)
|
||||
}
|
@ -1,431 +0,0 @@
|
||||
// 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
|
||||
}
|
Loading…
Reference in New Issue
Block a user