[FIX] Cleanup code

This commit is contained in:
Evgeniy Kulikov 2018-02-11 01:11:17 +03:00
parent 46c712f1ce
commit 901bd6381c
No known key found for this signature in database
GPG Key ID: BF6AEE0A2A699BF2
2 changed files with 175 additions and 175 deletions

344
gjson.go
View File

@ -210,34 +210,34 @@ func (t Result) ForEach(iterator func(key, value Result) bool) {
iterator(Result{}, t) iterator(Result{}, t)
return return
} }
json := t.Raw raw := t.Raw
var keys bool var keys bool
var i int var i int
var key, value Result var key, value Result
for ; i < len(json); i++ { for ; i < len(raw); i++ {
if json[i] == '{' { if raw[i] == '{' {
i++ i++
key.Type = String key.Type = String
keys = true keys = true
break break
} else if json[i] == '[' { } else if raw[i] == '[' {
i++ i++
break break
} }
if json[i] > ' ' { if raw[i] > ' ' {
return return
} }
} }
var str string var str string
var vesc bool var vesc bool
var ok bool var ok bool
for ; i < len(json); i++ { for ; i < len(raw); i++ {
if keys { if keys {
if json[i] != '"' { if raw[i] != '"' {
continue continue
} }
s := i s := i
i, str, vesc, ok = parseString(json, i+1) i, str, vesc, ok = parseString(raw, i+1)
if !ok { if !ok {
return return
} }
@ -249,14 +249,14 @@ func (t Result) ForEach(iterator func(key, value Result) bool) {
key.Raw = str key.Raw = str
key.Index = s key.Index = s
} }
for ; i < len(json); i++ { for ; i < len(raw); i++ {
if json[i] <= ' ' || json[i] == ',' || json[i] == ':' { if raw[i] <= ' ' || raw[i] == ',' || raw[i] == ':' {
continue continue
} }
break break
} }
s := i s := i
i, value, ok = parseAny(json, i, true) i, value, ok = parseAny(raw, i, true)
if !ok { if !ok {
return return
} }
@ -291,29 +291,29 @@ type arrayOrMapResult struct {
} }
func (t Result) arrayOrMap(vc byte, valueize bool) (r arrayOrMapResult) { func (t Result) arrayOrMap(vc byte, valueize bool) (r arrayOrMapResult) {
var json = t.Raw var raw = t.Raw
var i int var i int
var value Result var value Result
var count int var count int
var key Result var key Result
if vc == 0 { if vc == 0 {
for ; i < len(json); i++ { for ; i < len(raw); i++ {
if json[i] == '{' || json[i] == '[' { if raw[i] == '{' || raw[i] == '[' {
r.vc = json[i] r.vc = raw[i]
i++ i++
break break
} }
if json[i] > ' ' { if raw[i] > ' ' {
goto end goto end
} }
} }
} else { } else {
for ; i < len(json); i++ { for ; i < len(raw); i++ {
if json[i] == vc { if raw[i] == vc {
i++ i++
break break
} }
if json[i] > ' ' { if raw[i] > ' ' {
goto end goto end
} }
} }
@ -332,37 +332,37 @@ func (t Result) arrayOrMap(vc byte, valueize bool) (r arrayOrMapResult) {
r.a = make([]Result, 0) r.a = make([]Result, 0)
} }
} }
for ; i < len(json); i++ { for ; i < len(raw); i++ {
if json[i] <= ' ' { if raw[i] <= ' ' {
continue continue
} }
// get next value // get next value
if json[i] == ']' || json[i] == '}' { if raw[i] == ']' || raw[i] == '}' {
break break
} }
switch json[i] { switch raw[i] {
default: default:
if (json[i] >= '0' && json[i] <= '9') || json[i] == '-' { if (raw[i] >= '0' && raw[i] <= '9') || raw[i] == '-' {
value.Type = Number value.Type = Number
value.Raw, value.Num = tonum(json[i:]) value.Raw, value.Num = toNum(raw[i:])
} else { } else {
continue continue
} }
case '{', '[': case '{', '[':
value.Type = JSON value.Type = JSON
value.Raw = squash(json[i:]) value.Raw = squash(raw[i:])
case 'n': case 'n':
value.Type = Null value.Type = Null
value.Raw = tolit(json[i:]) value.Raw = toLit(raw[i:])
case 't': case 't':
value.Type = True value.Type = True
value.Raw = tolit(json[i:]) value.Raw = toLit(raw[i:])
case 'f': case 'f':
value.Type = False value.Type = False
value.Raw = tolit(json[i:]) value.Raw = toLit(raw[i:])
case '"': case '"':
value.Type = String value.Type = String
value.Raw, value.Str = tostr(json[i:]) value.Raw, value.Str = toStr(raw[i:])
} }
i += len(value.Raw) - 1 i += len(value.Raw) - 1
@ -405,22 +405,22 @@ func Parse(json string) Result {
default: default:
if (json[i] >= '0' && json[i] <= '9') || json[i] == '-' { if (json[i] >= '0' && json[i] <= '9') || json[i] == '-' {
value.Type = Number value.Type = Number
value.Raw, value.Num = tonum(json[i:]) value.Raw, value.Num = toNum(json[i:])
} else { } else {
return Result{} return Result{}
} }
case 'n': case 'n':
value.Type = Null value.Type = Null
value.Raw = tolit(json[i:]) value.Raw = toLit(json[i:])
case 't': case 't':
value.Type = True value.Type = True
value.Raw = tolit(json[i:]) value.Raw = toLit(json[i:])
case 'f': case 'f':
value.Type = False value.Type = False
value.Raw = tolit(json[i:]) value.Raw = toLit(json[i:])
case '"': case '"':
value.Type = String value.Type = String
value.Raw, value.Str = tostr(json[i:]) value.Raw, value.Str = toStr(json[i:])
} }
break break
} }
@ -433,27 +433,27 @@ func ParseBytes(json []byte) Result {
return Parse(string(json)) return Parse(string(json))
} }
func squash(json string) string { func squash(jsonString string) string {
// expects that the lead character is a '[' or '{' // expects that the lead character is a '[' or '{'
// squash the value, ignoring all nested arrays and objects. // squash the value, ignoring all nested arrays and objects.
// the first '[' or '{' has already been read // the first '[' or '{' has already been read
depth := 1 depth := 1
for i := 1; i < len(json); i++ { for i := 1; i < len(jsonString); i++ {
if json[i] >= '"' && json[i] <= '}' { if jsonString[i] >= '"' && jsonString[i] <= '}' {
switch json[i] { switch jsonString[i] {
case '"': case '"':
i++ i++
s2 := i s2 := i
for ; i < len(json); i++ { for ; i < len(jsonString); i++ {
if json[i] > '\\' { if jsonString[i] > '\\' {
continue continue
} }
if json[i] == '"' { if jsonString[i] == '"' {
// look for an escaped slash // look for an escaped slash
if json[i-1] == '\\' { if jsonString[i-1] == '\\' {
n := 0 n := 0
for j := i - 2; j > s2-1; j-- { for j := i - 2; j > s2-1; j-- {
if json[j] != '\\' { if jsonString[j] != '\\' {
break break
} }
n++ n++
@ -470,75 +470,75 @@ func squash(json string) string {
case '}', ']': case '}', ']':
depth-- depth--
if depth == 0 { if depth == 0 {
return json[:i+1] return jsonString[:i+1]
} }
} }
} }
} }
return json return jsonString
} }
func tonum(json string) (raw string, num float64) { func toNum(jsonString string) (raw string, num float64) {
for i := 1; i < len(json); i++ { for i := 1; i < len(jsonString); i++ {
// less than dash might have valid characters // less than dash might have valid characters
if json[i] <= '-' { if jsonString[i] <= '-' {
if json[i] <= ' ' || json[i] == ',' { if jsonString[i] <= ' ' || jsonString[i] == ',' {
// break on whitespace and comma // break on whitespace and comma
raw = json[:i] raw = jsonString[:i]
num, _ = strconv.ParseFloat(raw, 64) num, _ = strconv.ParseFloat(raw, 64)
return return
} }
// could be a '+' or '-'. let's assume so. // could be a '+' or '-'. let's assume so.
continue continue
} }
if json[i] < ']' { if jsonString[i] < ']' {
// probably a valid number // probably a valid number
continue continue
} }
if json[i] == 'e' || json[i] == 'E' { if jsonString[i] == 'e' || jsonString[i] == 'E' {
// allow for exponential numbers // allow for exponential numbers
continue continue
} }
// likely a ']' or '}' // likely a ']' or '}'
raw = json[:i] raw = jsonString[:i]
num, _ = strconv.ParseFloat(raw, 64) num, _ = strconv.ParseFloat(raw, 64)
return return
} }
raw = json raw = jsonString
num, _ = strconv.ParseFloat(raw, 64) num, _ = strconv.ParseFloat(raw, 64)
return return
} }
func tolit(json string) (raw string) { func toLit(jsonString string) (raw string) {
for i := 1; i < len(json); i++ { for i := 1; i < len(jsonString); i++ {
if json[i] < 'a' || json[i] > 'z' { if jsonString[i] < 'a' || jsonString[i] > 'z' {
return json[:i] return jsonString[:i]
} }
} }
return json return jsonString
} }
func tostr(json string) (raw string, str string) { func toStr(jsonString string) (raw string, str string) {
// expects that the lead character is a '"' // expects that the lead character is a '"'
for i := 1; i < len(json); i++ { for i := 1; i < len(jsonString); i++ {
if json[i] > '\\' { if jsonString[i] > '\\' {
continue continue
} }
if json[i] == '"' { if jsonString[i] == '"' {
return json[:i+1], json[1:i] return jsonString[:i+1], jsonString[1:i]
} }
if json[i] == '\\' { if jsonString[i] == '\\' {
i++ i++
for ; i < len(json); i++ { for ; i < len(jsonString); i++ {
if json[i] > '\\' { if jsonString[i] > '\\' {
continue continue
} }
if json[i] == '"' { if jsonString[i] == '"' {
// look for an escaped slash // look for an escaped slash
if json[i-1] == '\\' { if jsonString[i-1] == '\\' {
n := 0 n := 0
for j := i - 2; j > 0; j-- { for j := i - 2; j > 0; j-- {
if json[j] != '\\' { if jsonString[j] != '\\' {
break break
} }
n++ n++
@ -551,15 +551,15 @@ func tostr(json string) (raw string, str string) {
} }
} }
var ret string var ret string
if i+1 < len(json) { if i+1 < len(jsonString) {
ret = json[:i+1] ret = jsonString[:i+1]
} else { } else {
ret = json[:i] ret = jsonString[:i]
} }
return ret, unescape(json[1:i]) return ret, unescape(jsonString[1:i])
} }
} }
return json, json[1:] return jsonString, jsonString[1:]
} }
// Exists returns true if value exists. // Exists returns true if value exists.
@ -919,7 +919,7 @@ func parseObject(c *parseContext, i int, path string) (int, bool) {
} }
if c.json[i] == '"' { if c.json[i] == '"' {
i, key, kesc, ok = i+1, c.json[s:i], false, true i, key, kesc, ok = i+1, c.json[s:i], false, true
goto parse_key_string_done goto parseKeyStringDone
} }
if c.json[i] == '\\' { if c.json[i] == '\\' {
i++ i++
@ -942,14 +942,14 @@ func parseObject(c *parseContext, i int, path string) (int, bool) {
} }
} }
i, key, kesc, ok = i+1, c.json[s:i], true, true i, key, kesc, ok = i+1, c.json[s:i], true, true
goto parse_key_string_done goto parseKeyStringDone
} }
} }
break break
} }
} }
key, kesc, ok = c.json[s:], false, false key, kesc, ok = c.json[s:], false, false
parse_key_string_done: parseKeyStringDone:
break break
} }
if c.json[i] == '}' { if c.json[i] == '}' {
@ -1426,37 +1426,37 @@ func fromBytesGet(result Result) Result {
// GetBytes searches json for the specified path. // GetBytes searches json for the specified path.
// If working with bytes, this method preferred over Get(string(data), path) // If working with bytes, this method preferred over Get(string(data), path)
func GetBytes(json []byte, path string) Result { func GetBytes(raw []byte, path string) Result {
var result Result var result Result
if json != nil { if raw != nil {
// unsafe cast to string // unsafe cast to string
result = Get(*(*string)(unsafe.Pointer(&json)), path) result = Get(*(*string)(unsafe.Pointer(&raw)), path)
result = fromBytesGet(result) result = fromBytesGet(result)
} }
return result return result
} }
// runeit returns the rune from the the \uXXXX // runeIt returns the rune from the the \uXXXX
func runeit(json string) rune { func runeIt(jsonString string) rune {
n, _ := strconv.ParseUint(json[:4], 16, 64) n, _ := strconv.ParseUint(jsonString[:4], 16, 64)
return rune(n) return rune(n)
} }
// unescape unescapes a string // unescape unescapes a string
func unescape(json string) string { //, error) { func unescape(jsonString string) string { //, error) {
var str = make([]byte, 0, len(json)) var str = make([]byte, 0, len(jsonString))
for i := 0; i < len(json); i++ { for i := 0; i < len(jsonString); i++ {
switch { switch {
default: default:
str = append(str, json[i]) str = append(str, jsonString[i])
case json[i] < ' ': case jsonString[i] < ' ':
return string(str) return string(str)
case json[i] == '\\': case jsonString[i] == '\\':
i++ i++
if i >= len(json) { if i >= len(jsonString) {
return string(str) return string(str)
} }
switch json[i] { switch jsonString[i] {
default: default:
return string(str) return string(str)
case '\\': case '\\':
@ -1476,16 +1476,16 @@ func unescape(json string) string { //, error) {
case '"': case '"':
str = append(str, '"') str = append(str, '"')
case 'u': case 'u':
if i+5 > len(json) { if i+5 > len(jsonString) {
return string(str) return string(str)
} }
r := runeit(json[i+1:]) r := runeIt(jsonString[i+1:])
i += 5 i += 5
if utf16.IsSurrogate(r) { if utf16.IsSurrogate(r) {
// need another code // need another code
if len(json[i:]) >= 6 && json[i] == '\\' && json[i+1] == 'u' { if len(jsonString[i:]) >= 6 && jsonString[i] == '\\' && jsonString[i+1] == 'u' {
// we expect it to be correct so just consume it // we expect it to be correct so just consume it
r = utf16.DecodeRune(r, runeit(json[i+2:])) r = utf16.DecodeRune(r, runeIt(jsonString[i+2:]))
i += 6 i += 6
} }
} }
@ -1565,27 +1565,27 @@ func stringLessInsensitive(a, b string) bool {
// parseAny parses the next value from a json string. // parseAny parses the next value from a json string.
// A Result is returned when the hit param is set. // A Result is returned when the hit param is set.
// The return values are (i int, res Result, ok bool) // The return values are (i int, res Result, ok bool)
func parseAny(json string, i int, hit bool) (int, Result, bool) { func parseAny(jsonString string, i int, hit bool) (int, Result, bool) {
var res Result var res Result
var val string var val string
for ; i < len(json); i++ { for ; i < len(jsonString); i++ {
if json[i] == '{' || json[i] == '[' { if jsonString[i] == '{' || jsonString[i] == '[' {
i, val = parseSquash(json, i) i, val = parseSquash(jsonString, i)
if hit { if hit {
res.Raw = val res.Raw = val
res.Type = JSON res.Type = JSON
} }
return i, res, true return i, res, true
} }
if json[i] <= ' ' { if jsonString[i] <= ' ' {
continue continue
} }
switch json[i] { switch jsonString[i] {
case '"': case '"':
i++ i++
var vesc bool var vesc bool
var ok bool var ok bool
i, val, vesc, ok = parseString(json, i) i, val, vesc, ok = parseString(jsonString, i)
if !ok { if !ok {
return i, res, false return i, res, false
} }
@ -1600,7 +1600,7 @@ func parseAny(json string, i int, hit bool) (int, Result, bool) {
} }
return i, res, true return i, res, true
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
i, val = parseNumber(json, i) i, val = parseNumber(jsonString, i)
if hit { if hit {
res.Raw = val res.Raw = val
res.Type = Number res.Type = Number
@ -1608,8 +1608,8 @@ func parseAny(json string, i int, hit bool) (int, Result, bool) {
} }
return i, res, true return i, res, true
case 't', 'f', 'n': case 't', 'f', 'n':
vc := json[i] vc := jsonString[i]
i, val = parseLiteral(json, i) i, val = parseLiteral(jsonString, i)
if hit { if hit {
res.Raw = val res.Raw = val
switch vc { switch vc {
@ -1633,10 +1633,10 @@ var ( // used for testing
// GetMany searches json for the multiple paths. // GetMany searches json for the multiple paths.
// The return value is a Result array where the number of items // The return value is a Result array where the number of items
// will be equal to the number of input paths. // will be equal to the number of input paths.
func GetMany(json string, path ...string) []Result { func GetMany(jsonString string, path ...string) []Result {
res := make([]Result, len(path)) res := make([]Result, len(path))
for i, path := range path { for i, path := range path {
res[i] = Get(json, path) res[i] = Get(jsonString, path)
} }
return res return res
} }
@ -1651,31 +1651,31 @@ func GetManyBytes(json []byte, path ...string) []Result {
var fieldsmu sync.RWMutex var fieldsmu sync.RWMutex
var fields = make(map[string]map[string]int) var fields = make(map[string]map[string]int)
func assign(jsval Result, goval reflect.Value) { func assign(jsVal Result, goVal reflect.Value) {
if jsval.Type == Null { if jsVal.Type == Null {
return return
} }
switch goval.Kind() { switch goVal.Kind() {
default: default:
case reflect.Ptr: case reflect.Ptr:
if !goval.IsNil() { if !goVal.IsNil() {
newval := reflect.New(goval.Elem().Type()) newval := reflect.New(goVal.Elem().Type())
assign(jsval, newval.Elem()) assign(jsVal, newval.Elem())
goval.Elem().Set(newval.Elem()) goVal.Elem().Set(newval.Elem())
} else { } else {
newval := reflect.New(goval.Type().Elem()) newval := reflect.New(goVal.Type().Elem())
assign(jsval, newval.Elem()) assign(jsVal, newval.Elem())
goval.Set(newval) goVal.Set(newval)
} }
case reflect.Struct: case reflect.Struct:
fieldsmu.RLock() fieldsmu.RLock()
sf := fields[goval.Type().String()] sf := fields[goVal.Type().String()]
fieldsmu.RUnlock() fieldsmu.RUnlock()
if sf == nil { if sf == nil {
fieldsmu.Lock() fieldsmu.Lock()
sf = make(map[string]int) sf = make(map[string]int)
for i := 0; i < goval.Type().NumField(); i++ { for i := 0; i < goVal.Type().NumField(); i++ {
f := goval.Type().Field(i) f := goVal.Type().Field(i)
tag := strings.Split(f.Tag.Get("json"), ",")[0] tag := strings.Split(f.Tag.Get("json"), ",")[0]
if tag != "-" { if tag != "-" {
if tag != "" { if tag != "" {
@ -1686,12 +1686,12 @@ func assign(jsval Result, goval reflect.Value) {
} }
} }
} }
fields[goval.Type().String()] = sf fields[goVal.Type().String()] = sf
fieldsmu.Unlock() fieldsmu.Unlock()
} }
jsval.ForEach(func(key, value Result) bool { jsVal.ForEach(func(key, value Result) bool {
if idx, ok := sf[key.Str]; ok { if idx, ok := sf[key.Str]; ok {
f := goval.Field(idx) f := goVal.Field(idx)
if f.CanSet() { if f.CanSet() {
assign(value, f) assign(value, f)
} }
@ -1699,49 +1699,49 @@ func assign(jsval Result, goval reflect.Value) {
return true return true
}) })
case reflect.Slice: case reflect.Slice:
if goval.Type().Elem().Kind() == reflect.Uint8 && jsval.Type == String { if goVal.Type().Elem().Kind() == reflect.Uint8 && jsVal.Type == String {
data, _ := base64.StdEncoding.DecodeString(jsval.String()) data, _ := base64.StdEncoding.DecodeString(jsVal.String())
goval.Set(reflect.ValueOf(data)) goVal.Set(reflect.ValueOf(data))
} else { } else {
jsvals := jsval.Array() jsvals := jsVal.Array()
slice := reflect.MakeSlice(goval.Type(), len(jsvals), len(jsvals)) slice := reflect.MakeSlice(goVal.Type(), len(jsvals), len(jsvals))
for i := 0; i < len(jsvals); i++ { for i := 0; i < len(jsvals); i++ {
assign(jsvals[i], slice.Index(i)) assign(jsvals[i], slice.Index(i))
} }
goval.Set(slice) goVal.Set(slice)
} }
case reflect.Array: case reflect.Array:
i, n := 0, goval.Len() i, n := 0, goVal.Len()
jsval.ForEach(func(_, value Result) bool { jsVal.ForEach(func(_, value Result) bool {
if i == n { if i == n {
return false return false
} }
assign(value, goval.Index(i)) assign(value, goVal.Index(i))
i++ i++
return true return true
}) })
case reflect.Map: case reflect.Map:
if goval.Type().Key().Kind() == reflect.String && goval.Type().Elem().Kind() == reflect.Interface { if goVal.Type().Key().Kind() == reflect.String && goVal.Type().Elem().Kind() == reflect.Interface {
goval.Set(reflect.ValueOf(jsval.Value())) goVal.Set(reflect.ValueOf(jsVal.Value()))
} }
case reflect.Interface: case reflect.Interface:
goval.Set(reflect.ValueOf(jsval.Value())) goVal.Set(reflect.ValueOf(jsVal.Value()))
case reflect.Bool: case reflect.Bool:
goval.SetBool(jsval.Bool()) goVal.SetBool(jsVal.Bool())
case reflect.Float32, reflect.Float64: case reflect.Float32, reflect.Float64:
goval.SetFloat(jsval.Float()) goVal.SetFloat(jsVal.Float())
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
goval.SetInt(jsval.Int()) goVal.SetInt(jsVal.Int())
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
goval.SetUint(jsval.Uint()) goVal.SetUint(jsVal.Uint())
case reflect.String: case reflect.String:
goval.SetString(jsval.String()) goVal.SetString(jsVal.String())
} }
if len(goval.Type().PkgPath()) > 0 { if len(goVal.Type().PkgPath()) > 0 {
v := goval.Addr() v := goVal.Addr()
if v.Type().NumMethod() > 0 { if v.Type().NumMethod() > 0 {
if u, ok := v.Interface().(json.Unmarshaler); ok { if u, ok := v.Interface().(json.Unmarshaler); ok {
u.UnmarshalJSON([]byte(jsval.Raw)) u.UnmarshalJSON([]byte(jsVal.Raw))
} }
} }
} }
@ -1771,7 +1771,7 @@ func UnmarshalValidationEnabled(enabled bool) {
// Deprecated: Use encoder/json.Unmarshal instead // Deprecated: Use encoder/json.Unmarshal instead
func Unmarshal(data []byte, v interface{}) error { func Unmarshal(data []byte, v interface{}) error {
if atomic.LoadUintptr(&validate) == 1 { if atomic.LoadUintptr(&validate) == 1 {
_, ok := validpayload(data, 0) _, ok := validPayload(data, 0)
if !ok { if !ok {
return errors.New("invalid json") return errors.New("invalid json")
} }
@ -1782,11 +1782,11 @@ func Unmarshal(data []byte, v interface{}) error {
return nil return nil
} }
func validpayload(data []byte, i int) (outi int, ok bool) { func validPayload(data []byte, i int) (outi int, ok bool) {
for ; i < len(data); i++ { for ; i < len(data); i++ {
switch data[i] { switch data[i] {
default: default:
i, ok = validany(data, i) i, ok = validAny(data, i)
if !ok { if !ok {
return i, false return i, false
} }
@ -1805,7 +1805,7 @@ func validpayload(data []byte, i int) (outi int, ok bool) {
} }
return i, false return i, false
} }
func validany(data []byte, i int) (outi int, ok bool) { func validAny(data []byte, i int) (outi int, ok bool) {
for ; i < len(data); i++ { for ; i < len(data); i++ {
switch data[i] { switch data[i] {
default: default:
@ -1813,24 +1813,24 @@ func validany(data []byte, i int) (outi int, ok bool) {
case ' ', '\t', '\n', '\r': case ' ', '\t', '\n', '\r':
continue continue
case '{': case '{':
return validobject(data, i+1) return validObject(data, i+1)
case '[': case '[':
return validarray(data, i+1) return validArray(data, i+1)
case '"': case '"':
return validstring(data, i+1) return validString(data, i+1)
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
return validnumber(data, i+1) return validNumber(data, i+1)
case 't': case 't':
return validtrue(data, i+1) return validTrue(data, i+1)
case 'f': case 'f':
return validfalse(data, i+1) return validFalse(data, i+1)
case 'n': case 'n':
return validnull(data, i+1) return validNull(data, i+1)
} }
} }
return i, false return i, false
} }
func validobject(data []byte, i int) (outi int, ok bool) { func validObject(data []byte, i int) (outi int, ok bool) {
for ; i < len(data); i++ { for ; i < len(data); i++ {
switch data[i] { switch data[i] {
default: default:
@ -1841,16 +1841,16 @@ func validobject(data []byte, i int) (outi int, ok bool) {
return i + 1, true return i + 1, true
case '"': case '"':
key: key:
if i, ok = validstring(data, i+1); !ok { if i, ok = validString(data, i+1); !ok {
return i, false return i, false
} }
if i, ok = validcolon(data, i); !ok { if i, ok = validColon(data, i); !ok {
return i, false return i, false
} }
if i, ok = validany(data, i); !ok { if i, ok = validAny(data, i); !ok {
return i, false return i, false
} }
if i, ok = validcomma(data, i, '}'); !ok { if i, ok = validComma(data, i, '}'); !ok {
return i, false return i, false
} }
if data[i] == '}' { if data[i] == '}' {
@ -1866,7 +1866,7 @@ func validobject(data []byte, i int) (outi int, ok bool) {
} }
return i, false return i, false
} }
func validcolon(data []byte, i int) (outi int, ok bool) { func validColon(data []byte, i int) (outi int, ok bool) {
for ; i < len(data); i++ { for ; i < len(data); i++ {
switch data[i] { switch data[i] {
default: default:
@ -1879,7 +1879,7 @@ func validcolon(data []byte, i int) (outi int, ok bool) {
} }
return i, false return i, false
} }
func validcomma(data []byte, i int, end byte) (outi int, ok bool) { func validComma(data []byte, i int, end byte) (outi int, ok bool) {
for ; i < len(data); i++ { for ; i < len(data); i++ {
switch data[i] { switch data[i] {
default: default:
@ -1894,15 +1894,15 @@ func validcomma(data []byte, i int, end byte) (outi int, ok bool) {
} }
return i, false return i, false
} }
func validarray(data []byte, i int) (outi int, ok bool) { func validArray(data []byte, i int) (outi int, ok bool) {
for ; i < len(data); i++ { for ; i < len(data); i++ {
switch data[i] { switch data[i] {
default: default:
for ; i < len(data); i++ { for ; i < len(data); i++ {
if i, ok = validany(data, i); !ok { if i, ok = validAny(data, i); !ok {
return i, false return i, false
} }
if i, ok = validcomma(data, i, ']'); !ok { if i, ok = validComma(data, i, ']'); !ok {
return i, false return i, false
} }
if data[i] == ']' { if data[i] == ']' {
@ -1917,7 +1917,7 @@ func validarray(data []byte, i int) (outi int, ok bool) {
} }
return i, false return i, false
} }
func validstring(data []byte, i int) (outi int, ok bool) { func validString(data []byte, i int) (outi int, ok bool) {
for ; i < len(data); i++ { for ; i < len(data); i++ {
if data[i] < ' ' { if data[i] < ' ' {
return i, false return i, false
@ -1949,7 +1949,7 @@ func validstring(data []byte, i int) (outi int, ok bool) {
} }
return i, false return i, false
} }
func validnumber(data []byte, i int) (outi int, ok bool) { func validNumber(data []byte, i int) (outi int, ok bool) {
i-- i--
// sign // sign
if data[i] == '-' { if data[i] == '-' {
@ -2018,19 +2018,19 @@ func validnumber(data []byte, i int) (outi int, ok bool) {
return i, true return i, true
} }
func validtrue(data []byte, i int) (outi int, ok bool) { func validTrue(data []byte, i int) (outi int, ok bool) {
if i+3 <= len(data) && data[i] == 'r' && data[i+1] == 'u' && data[i+2] == 'e' { if i+3 <= len(data) && data[i] == 'r' && data[i+1] == 'u' && data[i+2] == 'e' {
return i + 3, true return i + 3, true
} }
return i, false return i, false
} }
func validfalse(data []byte, i int) (outi int, ok bool) { func validFalse(data []byte, i int) (outi int, ok bool) {
if i+4 <= len(data) && data[i] == 'a' && data[i+1] == 'l' && data[i+2] == 's' && data[i+3] == 'e' { if i+4 <= len(data) && data[i] == 'a' && data[i+1] == 'l' && data[i+2] == 's' && data[i+3] == 'e' {
return i + 4, true return i + 4, true
} }
return i, false return i, false
} }
func validnull(data []byte, i int) (outi int, ok bool) { func validNull(data []byte, i int) (outi int, ok bool) {
if i+3 <= len(data) && data[i] == 'u' && data[i+1] == 'l' && data[i+2] == 'l' { if i+3 <= len(data) && data[i] == 'u' && data[i+1] == 'l' && data[i+2] == 'l' {
return i + 3, true return i + 3, true
} }
@ -2039,7 +2039,7 @@ func validnull(data []byte, i int) (outi int, ok bool) {
// Valid returns true if the input is valid json. // Valid returns true if the input is valid json.
func Valid(json string) bool { func Valid(json string) bool {
_, ok := validpayload([]byte(json), 0) _, ok := validPayload([]byte(json), 0)
return ok return ok
} }

View File

@ -971,7 +971,7 @@ func TestUnmarshal(t *testing.T) {
} }
func testvalid(json string, expect bool) { func testvalid(json string, expect bool) {
_, ok := validpayload([]byte(json), 0) _, ok := validPayload([]byte(json), 0)
if ok != expect { if ok != expect {
panic("mismatch") panic("mismatch")
} }
@ -1062,14 +1062,14 @@ func TestValidRandom(t *testing.T) {
for time.Since(start) < time.Second*3 { for time.Since(start) < time.Second*3 {
n := rand.Int() % len(b) n := rand.Int() % len(b)
rand.Read(b[:n]) rand.Read(b[:n])
validpayload(b[:n], 0) validPayload(b[:n], 0)
} }
start = time.Now() start = time.Now()
for time.Since(start) < time.Second*3 { for time.Since(start) < time.Second*3 {
n := rand.Int() % len(b) n := rand.Int() % len(b)
makeRandomJSONChars(b[:n]) makeRandomJSONChars(b[:n])
validpayload(b[:n], 0) validPayload(b[:n], 0)
} }
} }