You've already forked json-iterator
							
							
				mirror of
				https://github.com/json-iterator/go.git
				synced 2025-10-31 00:07:40 +02:00 
			
		
		
		
	Formated, doced. Also fixed few minor bugs.
This commit is contained in:
		| @@ -1,3 +1,5 @@ | ||||
| [](https://goreportcard.com/report/github.com/json-iterator/go) | ||||
|  | ||||
| jsoniter (json-iterator) is fast and flexible JSON parser available in [Java](https://github.com/json-iterator/java) and [Go](https://github.com/json-iterator/go) | ||||
|  | ||||
| # Why jsoniter? | ||||
| @@ -37,7 +39,7 @@ import "github.com/json-iterator/go" | ||||
| iter := ParseString(`[0, [1, 2], [3, 4], 5]`) | ||||
| count := 0 | ||||
| for iter.ReadArray() { | ||||
|     iter.skip() | ||||
|     iter.Skip() | ||||
|     count++ | ||||
| } | ||||
| fmt.Println(count) // 4 | ||||
|   | ||||
| @@ -1,8 +1,8 @@ | ||||
| package jsoniter | ||||
|  | ||||
| import ( | ||||
| 	"testing" | ||||
| 	"fmt" | ||||
| 	"testing" | ||||
| ) | ||||
|  | ||||
| func Test_get_from_map(t *testing.T) { | ||||
| @@ -36,7 +36,7 @@ func Test_is_null(t *testing.T) { | ||||
| 	any := Any{val: []interface{}{ | ||||
| 		1, 2, 3, | ||||
| 	}} | ||||
| 	if any.IsNull() != false { | ||||
| 	if any.IsNil() != false { | ||||
| 		t.FailNow() | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -2,8 +2,7 @@ package jsoniter | ||||
|  | ||||
| import "io" | ||||
|  | ||||
| // adapt to json/encoding api | ||||
|  | ||||
| // Unmarshal adapts to json/encoding APIs | ||||
| func Unmarshal(data []byte, v interface{}) error { | ||||
| 	iter := ParseBytes(data) | ||||
| 	iter.Read(v) | ||||
|   | ||||
							
								
								
									
										206
									
								
								feature_any.go
									
									
									
									
									
								
							
							
						
						
									
										206
									
								
								feature_any.go
									
									
									
									
									
								
							| @@ -6,104 +6,109 @@ import ( | ||||
| 	"strconv" | ||||
| ) | ||||
|  | ||||
| // Any API is for maximum flexibility | ||||
| type Any struct { | ||||
| 	val   interface{} | ||||
| 	Error error | ||||
| 	val          interface{} | ||||
| 	Error        error | ||||
| 	LastAccessed interface{} | ||||
| } | ||||
|  | ||||
| // MakeAny creates Any instance | ||||
| func MakeAny(val interface{}) *Any { | ||||
| 	return &Any{val, nil, nil} | ||||
| } | ||||
|  | ||||
| // Get extracts a json object from Any | ||||
| func (any *Any) Get(keys ...interface{}) interface{} { | ||||
| 	ret, err := getPath(any.val, keys...) | ||||
| 	any.LastAccessed = ret | ||||
| 	if err != nil { | ||||
| 		any.Error = err | ||||
| 		return ""; | ||||
| 		return "" | ||||
| 	} | ||||
| 	return ret | ||||
| } | ||||
|  | ||||
| // GetValueType gets type of a value | ||||
| func (any *Any) GetValueType(keys ...interface{}) ValueType { | ||||
| 	ret, err := getPath(any.val, keys...) | ||||
| 	any.LastAccessed = ret | ||||
| 	if err != nil { | ||||
| 		any.Error = err | ||||
| 		return Invalid; | ||||
| 		return Invalid | ||||
| 	} | ||||
|  | ||||
| 	switch reflect.TypeOf(ret).Kind() { | ||||
| 	case reflect.Uint8: | ||||
| 		return Number; | ||||
| 		return Number | ||||
| 	case reflect.Int8: | ||||
| 		return Number; | ||||
| 		return Number | ||||
| 	case reflect.Uint16: | ||||
| 		return Number; | ||||
| 		return Number | ||||
| 	case reflect.Int16: | ||||
| 		return Number; | ||||
| 		return Number | ||||
| 	case reflect.Uint32: | ||||
| 		return Number; | ||||
| 		return Number | ||||
| 	case reflect.Int32: | ||||
| 		return Number; | ||||
| 		return Number | ||||
| 	case reflect.Uint64: | ||||
| 		return Number; | ||||
| 		return Number | ||||
| 	case reflect.Int64: | ||||
| 		return Number; | ||||
| 		return Number | ||||
| 	case reflect.Int: | ||||
| 		return Number; | ||||
| 		return Number | ||||
| 	case reflect.Uint: | ||||
| 		return Number; | ||||
| 		return Number | ||||
| 	case reflect.Float32: | ||||
| 		return Number; | ||||
| 		return Number | ||||
| 	case reflect.Float64: | ||||
| 		return Number; | ||||
| 		return Number | ||||
| 	case reflect.String: | ||||
| 		return String; | ||||
| 		return String | ||||
| 	case reflect.Bool: | ||||
| 		return Bool; | ||||
| 		return Bool | ||||
| 	case reflect.Array: | ||||
| 		return Array; | ||||
| 		return Array | ||||
| 	case reflect.Struct: | ||||
| 		return Object; | ||||
| 		return Object | ||||
| 	default: | ||||
| 		return Invalid | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // ToString converts a json object to string | ||||
| func (any *Any) ToString(keys ...interface{}) string { | ||||
| 	ret, err := getPath(any.val, keys...) | ||||
| 	any.LastAccessed = ret | ||||
| 	if err != nil { | ||||
| 		any.Error = err | ||||
| 		return ""; | ||||
| 		return "" | ||||
| 	} | ||||
| 	switch ret := ret.(type) { | ||||
| 	case uint8: | ||||
| 		return strconv.FormatInt(int64(ret), 10); | ||||
| 		return strconv.FormatInt(int64(ret), 10) | ||||
| 	case int8: | ||||
| 		return strconv.FormatInt(int64(ret), 10); | ||||
| 		return strconv.FormatInt(int64(ret), 10) | ||||
| 	case uint16: | ||||
| 		return strconv.FormatInt(int64(ret), 10); | ||||
| 		return strconv.FormatInt(int64(ret), 10) | ||||
| 	case int16: | ||||
| 		return strconv.FormatInt(int64(ret), 10); | ||||
| 		return strconv.FormatInt(int64(ret), 10) | ||||
| 	case uint32: | ||||
| 		return strconv.FormatInt(int64(ret), 10); | ||||
| 		return strconv.FormatInt(int64(ret), 10) | ||||
| 	case int32: | ||||
| 		return strconv.FormatInt(int64(ret), 10); | ||||
| 		return strconv.FormatInt(int64(ret), 10) | ||||
| 	case uint64: | ||||
| 		return strconv.FormatUint(uint64(ret), 10); | ||||
| 		return strconv.FormatUint(uint64(ret), 10) | ||||
| 	case int64: | ||||
| 		return strconv.FormatInt(int64(ret), 10); | ||||
| 		return strconv.FormatInt(int64(ret), 10) | ||||
| 	case int: | ||||
| 		return strconv.FormatInt(int64(ret), 10); | ||||
| 		return strconv.FormatInt(int64(ret), 10) | ||||
| 	case uint: | ||||
| 		return strconv.FormatInt(int64(ret), 10); | ||||
| 		return strconv.FormatInt(int64(ret), 10) | ||||
| 	case float32: | ||||
| 		return strconv.FormatFloat(float64(ret), 'E', -1, 32); | ||||
| 		return strconv.FormatFloat(float64(ret), 'E', -1, 32) | ||||
| 	case float64: | ||||
| 		return strconv.FormatFloat(ret, 'E', -1, 64); | ||||
| 		return strconv.FormatFloat(ret, 'E', -1, 64) | ||||
| 	case string: | ||||
| 		return ret | ||||
| 	default: | ||||
| @@ -111,135 +116,149 @@ func (any *Any) ToString(keys ...interface{}) string { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // ToUint8 converts a json object to Uint8 | ||||
| func (any *Any) ToUint8(keys ...interface{}) uint8 { | ||||
| 	ret, err := getPathAsInt64(any, keys...) | ||||
| 	if err != nil { | ||||
| 		any.Error = err | ||||
| 		return 0; | ||||
| 		return 0 | ||||
| 	} | ||||
| 	return uint8(ret) | ||||
| } | ||||
|  | ||||
| // ToInt8 converts a json object to Int8 | ||||
| func (any *Any) ToInt8(keys ...interface{}) int8 { | ||||
| 	ret, err := getPathAsInt64(any, keys...) | ||||
| 	if err != nil { | ||||
| 		any.Error = err | ||||
| 		return 0; | ||||
| 		return 0 | ||||
| 	} | ||||
| 	return int8(ret) | ||||
| } | ||||
|  | ||||
| // ToUint16 converts a json object to Uint16 | ||||
| func (any *Any) ToUint16(keys ...interface{}) uint16 { | ||||
| 	ret, err := getPathAsInt64(any, keys...) | ||||
| 	if err != nil { | ||||
| 		any.Error = err | ||||
| 		return 0; | ||||
| 		return 0 | ||||
| 	} | ||||
| 	return uint16(ret) | ||||
| } | ||||
|  | ||||
| // ToInt16 converts a json object to Int16 | ||||
| func (any *Any) ToInt16(keys ...interface{}) int16 { | ||||
| 	ret, err := getPathAsInt64(any, keys...) | ||||
| 	if err != nil { | ||||
| 		any.Error = err | ||||
| 		return 0; | ||||
| 		return 0 | ||||
| 	} | ||||
| 	return int16(ret) | ||||
| } | ||||
|  | ||||
| // ToUint32 converts a json object to Uint32 | ||||
| func (any *Any) ToUint32(keys ...interface{}) uint32 { | ||||
| 	ret, err := getPathAsInt64(any, keys...) | ||||
| 	if err != nil { | ||||
| 		any.Error = err | ||||
| 		return 0; | ||||
| 		return 0 | ||||
| 	} | ||||
| 	return uint32(ret) | ||||
| } | ||||
|  | ||||
| // ToInt32 converts a json object to Int32 | ||||
| func (any *Any) ToInt32(keys ...interface{}) int32 { | ||||
| 	ret, err := getPathAsInt64(any, keys...) | ||||
| 	if err != nil { | ||||
| 		any.Error = err | ||||
| 		return 0; | ||||
| 		return 0 | ||||
| 	} | ||||
| 	return int32(ret) | ||||
| } | ||||
|  | ||||
| // ToUint64 converts a json object to Uint64 | ||||
| func (any *Any) ToUint64(keys ...interface{}) uint64 { | ||||
| 	ret, err := getPathAsUint64(any, keys...) | ||||
| 	if err != nil { | ||||
| 		any.Error = err | ||||
| 		return 0; | ||||
| 		return 0 | ||||
| 	} | ||||
| 	return uint64(ret) | ||||
| } | ||||
|  | ||||
| // ToInt64 converts a json object to Int64 | ||||
| func (any *Any) ToInt64(keys ...interface{}) int64 { | ||||
| 	ret, err := getPathAsInt64(any, keys...) | ||||
| 	if err != nil { | ||||
| 		any.Error = err | ||||
| 		return 0; | ||||
| 		return 0 | ||||
| 	} | ||||
| 	return int64(ret) | ||||
| } | ||||
|  | ||||
| // ToInt converts a json object to Int | ||||
| func (any *Any) ToInt(keys ...interface{}) int { | ||||
| 	ret, err := getPathAsInt64(any, keys...) | ||||
| 	if err != nil { | ||||
| 		any.Error = err | ||||
| 		return 0; | ||||
| 		return 0 | ||||
| 	} | ||||
| 	return int(ret) | ||||
| } | ||||
|  | ||||
| // ToUint converts a json object to Uint | ||||
| func (any *Any) ToUint(keys ...interface{}) uint { | ||||
| 	ret, err := getPathAsInt64(any, keys...) | ||||
| 	if err != nil { | ||||
| 		any.Error = err | ||||
| 		return 0; | ||||
| 		return 0 | ||||
| 	} | ||||
| 	return uint(ret) | ||||
| } | ||||
|  | ||||
| // ToFloat32 converts a json object to Float32 | ||||
| func (any *Any) ToFloat32(keys ...interface{}) float32 { | ||||
| 	ret, err := getPathAsFloat64(any, keys...) | ||||
| 	if err != nil { | ||||
| 		any.Error = err | ||||
| 		return 0; | ||||
| 		return 0 | ||||
| 	} | ||||
| 	return float32(ret) | ||||
| } | ||||
|  | ||||
| // ToFloat64 converts a json object to Float64 | ||||
| func (any *Any) ToFloat64(keys ...interface{}) float64 { | ||||
| 	ret, err := getPathAsFloat64(any, keys...) | ||||
| 	if err != nil { | ||||
| 		any.Error = err | ||||
| 		return 0; | ||||
| 		return 0 | ||||
| 	} | ||||
| 	return ret | ||||
| } | ||||
|  | ||||
| // ToBool converts a json object to Bool | ||||
| func (any *Any) ToBool(keys ...interface{}) bool { | ||||
| 	ret, err := getPath(any.val, keys...) | ||||
| 	any.LastAccessed = ret | ||||
| 	if err != nil { | ||||
| 		any.Error = err | ||||
| 		return false; | ||||
| 		return false | ||||
| 	} | ||||
| 	typedRet, ok := ret.(bool) | ||||
| 	if !ok { | ||||
| 		any.Error = fmt.Errorf("%v is not bool", ret) | ||||
| 		return false; | ||||
| 		return false | ||||
| 	} | ||||
| 	return typedRet | ||||
| } | ||||
|  | ||||
| func (any *Any) IsNull(keys ...interface{}) bool { | ||||
| // IsNil judges whether a json object is nil | ||||
| func (any *Any) IsNil(keys ...interface{}) bool { | ||||
| 	ret, err := getPath(any.val, keys...) | ||||
| 	any.LastAccessed = ret | ||||
| 	if err != nil { | ||||
| 		any.Error = err | ||||
| 		return false; | ||||
| 		return false | ||||
| 	} | ||||
| 	return reflect.ValueOf(ret).IsNil() | ||||
| } | ||||
| @@ -253,35 +272,35 @@ func getPathAsInt64(any *Any, keys ...interface{}) (int64, error) { | ||||
| 	} | ||||
| 	switch ret := ret.(type) { | ||||
| 	case uint8: | ||||
| 		return int64(ret), nil; | ||||
| 		return int64(ret), nil | ||||
| 	case int8: | ||||
| 		return int64(ret), nil; | ||||
| 		return int64(ret), nil | ||||
| 	case uint16: | ||||
| 		return int64(ret), nil; | ||||
| 		return int64(ret), nil | ||||
| 	case int16: | ||||
| 		return int64(ret), nil; | ||||
| 		return int64(ret), nil | ||||
| 	case uint32: | ||||
| 		return int64(ret), nil; | ||||
| 		return int64(ret), nil | ||||
| 	case int32: | ||||
| 		return int64(ret), nil; | ||||
| 		return int64(ret), nil | ||||
| 	case uint64: | ||||
| 		return int64(ret), nil; | ||||
| 		return int64(ret), nil | ||||
| 	case int64: | ||||
| 		return int64(ret), nil; | ||||
| 		return int64(ret), nil | ||||
| 	case int: | ||||
| 		return int64(ret), nil; | ||||
| 		return int64(ret), nil | ||||
| 	case uint: | ||||
| 		return int64(ret), nil; | ||||
| 		return int64(ret), nil | ||||
| 	case float32: | ||||
| 		return int64(ret), nil; | ||||
| 		return int64(ret), nil | ||||
| 	case float64: | ||||
| 		return int64(ret), nil; | ||||
| 		return int64(ret), nil | ||||
| 	case string: | ||||
| 		intVal, err := strconv.ParseInt(ret, 10, 64) | ||||
| 		if err != nil { | ||||
| 			return 0, err | ||||
| 		} | ||||
| 		return intVal, nil; | ||||
| 		return intVal, nil | ||||
| 	default: | ||||
| 		return 0, fmt.Errorf("%v is not number", ret) | ||||
| 	} | ||||
| @@ -296,35 +315,35 @@ func getPathAsUint64(any *Any, keys ...interface{}) (uint64, error) { | ||||
| 	} | ||||
| 	switch ret := ret.(type) { | ||||
| 	case uint8: | ||||
| 		return uint64(ret), nil; | ||||
| 		return uint64(ret), nil | ||||
| 	case int8: | ||||
| 		return uint64(ret), nil; | ||||
| 		return uint64(ret), nil | ||||
| 	case uint16: | ||||
| 		return uint64(ret), nil; | ||||
| 		return uint64(ret), nil | ||||
| 	case int16: | ||||
| 		return uint64(ret), nil; | ||||
| 		return uint64(ret), nil | ||||
| 	case uint32: | ||||
| 		return uint64(ret), nil; | ||||
| 		return uint64(ret), nil | ||||
| 	case int32: | ||||
| 		return uint64(ret), nil; | ||||
| 		return uint64(ret), nil | ||||
| 	case uint64: | ||||
| 		return uint64(ret), nil; | ||||
| 		return uint64(ret), nil | ||||
| 	case int64: | ||||
| 		return uint64(ret), nil; | ||||
| 		return uint64(ret), nil | ||||
| 	case int: | ||||
| 		return uint64(ret), nil; | ||||
| 		return uint64(ret), nil | ||||
| 	case uint: | ||||
| 		return uint64(ret), nil; | ||||
| 		return uint64(ret), nil | ||||
| 	case float32: | ||||
| 		return uint64(ret), nil; | ||||
| 		return uint64(ret), nil | ||||
| 	case float64: | ||||
| 		return uint64(ret), nil; | ||||
| 		return uint64(ret), nil | ||||
| 	case string: | ||||
| 		intVal, err := strconv.ParseUint(ret, 10, 64) | ||||
| 		if err != nil { | ||||
| 			return 0, err | ||||
| 		} | ||||
| 		return intVal, nil; | ||||
| 		return intVal, nil | ||||
| 	default: | ||||
| 		return 0, fmt.Errorf("%v is not number", ret) | ||||
| 	} | ||||
| @@ -339,43 +358,43 @@ func getPathAsFloat64(any *Any, keys ...interface{}) (float64, error) { | ||||
| 	} | ||||
| 	switch ret := ret.(type) { | ||||
| 	case uint8: | ||||
| 		return float64(ret), nil; | ||||
| 		return float64(ret), nil | ||||
| 	case int8: | ||||
| 		return float64(ret), nil; | ||||
| 		return float64(ret), nil | ||||
| 	case uint16: | ||||
| 		return float64(ret), nil; | ||||
| 		return float64(ret), nil | ||||
| 	case int16: | ||||
| 		return float64(ret), nil; | ||||
| 		return float64(ret), nil | ||||
| 	case uint32: | ||||
| 		return float64(ret), nil; | ||||
| 		return float64(ret), nil | ||||
| 	case int32: | ||||
| 		return float64(ret), nil; | ||||
| 		return float64(ret), nil | ||||
| 	case uint64: | ||||
| 		return float64(ret), nil; | ||||
| 		return float64(ret), nil | ||||
| 	case int64: | ||||
| 		return float64(ret), nil; | ||||
| 		return float64(ret), nil | ||||
| 	case int: | ||||
| 		return float64(ret), nil; | ||||
| 		return float64(ret), nil | ||||
| 	case uint: | ||||
| 		return float64(ret), nil; | ||||
| 		return float64(ret), nil | ||||
| 	case float32: | ||||
| 		return float64(ret), nil; | ||||
| 		return float64(ret), nil | ||||
| 	case float64: | ||||
| 		return float64(ret), nil; | ||||
| 		return float64(ret), nil | ||||
| 	case string: | ||||
| 		floatVal, err := strconv.ParseFloat(ret, 64) | ||||
| 		if err != nil { | ||||
| 			return 0, err | ||||
| 		} | ||||
| 		return floatVal, nil; | ||||
| 		return floatVal, nil | ||||
| 	default: | ||||
| 		return 0, fmt.Errorf("%v is not number", ret) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func getPath(val interface{}, keys ...interface{}) (interface{}, error) { | ||||
| 	if (len(keys) == 0) { | ||||
| 		return val, nil; | ||||
| 	if len(keys) == 0 { | ||||
| 		return val, nil | ||||
| 	} | ||||
| 	switch key := keys[0].(type) { | ||||
| 	case string: | ||||
| @@ -383,7 +402,7 @@ func getPath(val interface{}, keys ...interface{}) (interface{}, error) { | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		nextKeys := make([]interface{}, len(keys) - 1) | ||||
| 		nextKeys := make([]interface{}, len(keys)-1) | ||||
| 		copy(nextKeys, keys[1:]) | ||||
| 		return getPath(nextVal, nextKeys...) | ||||
| 	case int: | ||||
| @@ -391,13 +410,12 @@ func getPath(val interface{}, keys ...interface{}) (interface{}, error) { | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		nextKeys := make([]interface{}, len(keys) - 1) | ||||
| 		nextKeys := make([]interface{}, len(keys)-1) | ||||
| 		copy(nextKeys, keys[1:]) | ||||
| 		return getPath(nextVal, nextKeys...) | ||||
| 	default: | ||||
| 		return nil, fmt.Errorf("%v is not string or int", keys[0]); | ||||
| 		return nil, fmt.Errorf("%v is not string or int", keys[0]) | ||||
| 	} | ||||
| 	return getPath(val, keys); | ||||
| } | ||||
|  | ||||
| func getFromMap(val interface{}, key string) (interface{}, error) { | ||||
|   | ||||
| @@ -2,20 +2,20 @@ package jsoniter | ||||
|  | ||||
| import "unsafe" | ||||
|  | ||||
| // ReadObject is a implemented iterator for json | ||||
| func (iter *Iterator) ReadObject() (ret string) { | ||||
| 	c := iter.nextToken() | ||||
| 	if iter.Error != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	switch c { | ||||
| 	case 'n': { | ||||
| 	case 'n': | ||||
| 		iter.skipUntilBreak() | ||||
| 		if iter.Error != nil { | ||||
| 			return | ||||
| 		} | ||||
| 		return "" // null | ||||
| 	} | ||||
| 	case '{': { | ||||
| 	case '{': | ||||
| 		c = iter.nextToken() | ||||
| 		if iter.Error != nil { | ||||
| 			return | ||||
| @@ -27,16 +27,15 @@ func (iter *Iterator) ReadObject() (ret string) { | ||||
| 			iter.unreadByte() | ||||
| 			return iter.readObjectField() | ||||
| 		default: | ||||
| 			iter.ReportError("ReadObject", `expect " after {`) | ||||
| 			iter.reportError("ReadObject", `expect " after {`) | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| 	case ',': | ||||
| 		return iter.readObjectField() | ||||
| 	case '}': | ||||
| 		return "" // end of object | ||||
| 	default: | ||||
| 		iter.ReportError("ReadObject", `expect { or , or } or n`) | ||||
| 		iter.reportError("ReadObject", `expect { or , or } or n`) | ||||
| 		return | ||||
| 	} | ||||
| } | ||||
| @@ -51,7 +50,7 @@ func (iter *Iterator) readObjectStart() bool { | ||||
| 		iter.unreadByte() | ||||
| 		return true | ||||
| 	} | ||||
| 	iter.ReportError("readObjectStart", "expect { ") | ||||
| 	iter.reportError("readObjectStart", "expect { ") | ||||
| 	return false | ||||
| } | ||||
|  | ||||
| @@ -59,20 +58,20 @@ func (iter *Iterator) readObjectField() (ret string) { | ||||
| 	str := iter.readStringAsBytes() | ||||
| 	if iter.skipWhitespacesWithoutLoadMore() { | ||||
| 		if ret == "" { | ||||
| 			ret = string(str); | ||||
| 			ret = string(str) | ||||
| 		} | ||||
| 		if !iter.loadMore() { | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| 	if iter.buf[iter.head] != ':' { | ||||
| 		iter.ReportError("ReadObject", "expect : after object field") | ||||
| 		iter.reportError("ReadObject", "expect : after object field") | ||||
| 		return | ||||
| 	} | ||||
| 	iter.head++ | ||||
| 	if iter.skipWhitespacesWithoutLoadMore() { | ||||
| 		if ret == "" { | ||||
| 			ret = string(str); | ||||
| 			ret = string(str) | ||||
| 		} | ||||
| 		if !iter.loadMore() { | ||||
| 			return | ||||
|   | ||||
| @@ -1,14 +1,14 @@ | ||||
| package jsoniter | ||||
|  | ||||
| import ( | ||||
| 	"reflect" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"unsafe" | ||||
| 	"sync/atomic" | ||||
| 	"strings" | ||||
| 	"io" | ||||
| 	"reflect" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| 	"sync/atomic" | ||||
| 	"unsafe" | ||||
| ) | ||||
|  | ||||
| /* | ||||
| @@ -18,8 +18,9 @@ Reflection on value is avoided as we can, as the reflect.Value itself will alloc | ||||
| 2. append to slice, if the existing cap is not enough, allocate will be done using Reflect.New | ||||
| 3. assignment to map, both key and value will be reflect.Value | ||||
| For a simple struct binding, it will be reflect.Value free and allocation free | ||||
|  */ | ||||
| */ | ||||
|  | ||||
| // Decoder works like a father class for sub-type decoders | ||||
| type Decoder interface { | ||||
| 	decode(ptr unsafe.Pointer, iter *Iterator) | ||||
| } | ||||
| @@ -129,7 +130,6 @@ func (decoder *interfaceDecoder) decode(ptr unsafe.Pointer, iter *Iterator) { | ||||
| 	*((*interface{})(ptr)) = iter.ReadAny().Get() | ||||
| } | ||||
|  | ||||
|  | ||||
| type anyDecoder struct { | ||||
| } | ||||
|  | ||||
| @@ -144,7 +144,7 @@ type stringNumberDecoder struct { | ||||
| func (decoder *stringNumberDecoder) decode(ptr unsafe.Pointer, iter *Iterator) { | ||||
| 	c := iter.nextToken() | ||||
| 	if c != '"' { | ||||
| 		iter.ReportError("stringNumberDecoder", `expect "`) | ||||
| 		iter.reportError("stringNumberDecoder", `expect "`) | ||||
| 		return | ||||
| 	} | ||||
| 	decoder.elemDecoder.decode(ptr, iter) | ||||
| @@ -153,7 +153,7 @@ func (decoder *stringNumberDecoder) decode(ptr unsafe.Pointer, iter *Iterator) { | ||||
| 	} | ||||
| 	c = iter.readByte() | ||||
| 	if c != '"' { | ||||
| 		iter.ReportError("stringNumberDecoder", `expect "`) | ||||
| 		iter.reportError("stringNumberDecoder", `expect "`) | ||||
| 		return | ||||
| 	} | ||||
| } | ||||
| @@ -164,7 +164,7 @@ type optionalDecoder struct { | ||||
| } | ||||
|  | ||||
| func (decoder *optionalDecoder) decode(ptr unsafe.Pointer, iter *Iterator) { | ||||
| 	if iter.ReadNull() { | ||||
| 	if iter.ReadNil() { | ||||
| 		*((*unsafe.Pointer)(ptr)) = nil | ||||
| 	} else { | ||||
| 		if *((*unsafe.Pointer)(ptr)) == nil { | ||||
| @@ -180,7 +180,7 @@ func (decoder *optionalDecoder) decode(ptr unsafe.Pointer, iter *Iterator) { | ||||
| } | ||||
|  | ||||
| type generalStructDecoder struct { | ||||
| 	type_  reflect.Type | ||||
| 	typ    reflect.Type | ||||
| 	fields map[string]*structFieldDecoder | ||||
| } | ||||
|  | ||||
| @@ -194,23 +194,23 @@ func (decoder *generalStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator) | ||||
| 		} | ||||
| 	} | ||||
| 	if iter.Error != nil && iter.Error != io.EOF { | ||||
| 		iter.Error = fmt.Errorf("%v: %s", decoder.type_, iter.Error.Error()) | ||||
| 		iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error()) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| type skipDecoder struct { | ||||
| 	type_ reflect.Type | ||||
| 	typ reflect.Type | ||||
| } | ||||
|  | ||||
| func (decoder *skipDecoder) decode(ptr unsafe.Pointer, iter *Iterator) { | ||||
| 	iter.Skip() | ||||
| 	if iter.Error != nil && iter.Error != io.EOF { | ||||
| 		iter.Error = fmt.Errorf("%v: %s", decoder.type_, iter.Error.Error()) | ||||
| 		iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error()) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| type oneFieldStructDecoder struct { | ||||
| 	type_        reflect.Type | ||||
| 	typ          reflect.Type | ||||
| 	fieldName    string | ||||
| 	fieldDecoder *structFieldDecoder | ||||
| } | ||||
| @@ -224,12 +224,12 @@ func (decoder *oneFieldStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator) | ||||
| 		} | ||||
| 	} | ||||
| 	if iter.Error != nil && iter.Error != io.EOF { | ||||
| 		iter.Error = fmt.Errorf("%v: %s", decoder.type_, iter.Error.Error()) | ||||
| 		iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error()) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| type twoFieldsStructDecoder struct { | ||||
| 	type_         reflect.Type | ||||
| 	typ           reflect.Type | ||||
| 	fieldName1    string | ||||
| 	fieldDecoder1 *structFieldDecoder | ||||
| 	fieldName2    string | ||||
| @@ -248,12 +248,12 @@ func (decoder *twoFieldsStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator | ||||
| 		} | ||||
| 	} | ||||
| 	if iter.Error != nil && iter.Error != io.EOF { | ||||
| 		iter.Error = fmt.Errorf("%v: %s", decoder.type_, iter.Error.Error()) | ||||
| 		iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error()) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| type threeFieldsStructDecoder struct { | ||||
| 	type_         reflect.Type | ||||
| 	typ           reflect.Type | ||||
| 	fieldName1    string | ||||
| 	fieldDecoder1 *structFieldDecoder | ||||
| 	fieldName2    string | ||||
| @@ -276,12 +276,12 @@ func (decoder *threeFieldsStructDecoder) decode(ptr unsafe.Pointer, iter *Iterat | ||||
| 		} | ||||
| 	} | ||||
| 	if iter.Error != nil && iter.Error != io.EOF { | ||||
| 		iter.Error = fmt.Errorf("%v: %s", decoder.type_, iter.Error.Error()) | ||||
| 		iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error()) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| type fourFieldsStructDecoder struct { | ||||
| 	type_         reflect.Type | ||||
| 	typ           reflect.Type | ||||
| 	fieldName1    string | ||||
| 	fieldDecoder1 *structFieldDecoder | ||||
| 	fieldName2    string | ||||
| @@ -325,7 +325,7 @@ func (decoder *fourFieldsStructDecoder) decode(ptr unsafe.Pointer, iter *Iterato | ||||
| 		} | ||||
| 	} | ||||
| 	if iter.Error != nil && iter.Error != io.EOF { | ||||
| 		iter.Error = fmt.Errorf("%v: %s", decoder.type_, iter.Error.Error()) | ||||
| 		iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error()) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -343,9 +343,9 @@ func (decoder *structFieldDecoder) decode(ptr unsafe.Pointer, iter *Iterator) { | ||||
| } | ||||
|  | ||||
| type mapDecoder struct { | ||||
| 	mapType  reflect.Type | ||||
| 	elemType  reflect.Type | ||||
| 	elemDecoder Decoder | ||||
| 	mapType      reflect.Type | ||||
| 	elemType     reflect.Type | ||||
| 	elemDecoder  Decoder | ||||
| 	mapInterface emptyInterface | ||||
| } | ||||
|  | ||||
| @@ -391,30 +391,30 @@ func (decoder *sliceDecoder) doDecode(ptr unsafe.Pointer, iter *Iterator) { | ||||
| 		return | ||||
| 	} | ||||
| 	offset := uintptr(0) | ||||
| 	decoder.elemDecoder.decode(unsafe.Pointer(uintptr(slice.Data) + offset), iter) | ||||
| 	decoder.elemDecoder.decode(unsafe.Pointer(uintptr(slice.Data)+offset), iter) | ||||
| 	if !iter.ReadArray() { | ||||
| 		slice.Len = 1 | ||||
| 		return | ||||
| 	} | ||||
| 	offset += decoder.elemType.Size() | ||||
| 	decoder.elemDecoder.decode(unsafe.Pointer(uintptr(slice.Data) + offset), iter) | ||||
| 	decoder.elemDecoder.decode(unsafe.Pointer(uintptr(slice.Data)+offset), iter) | ||||
| 	if !iter.ReadArray() { | ||||
| 		slice.Len = 2 | ||||
| 		return | ||||
| 	} | ||||
| 	offset += decoder.elemType.Size() | ||||
| 	decoder.elemDecoder.decode(unsafe.Pointer(uintptr(slice.Data) + offset), iter) | ||||
| 	decoder.elemDecoder.decode(unsafe.Pointer(uintptr(slice.Data)+offset), iter) | ||||
| 	if !iter.ReadArray() { | ||||
| 		slice.Len = 3 | ||||
| 		return | ||||
| 	} | ||||
| 	offset += decoder.elemType.Size() | ||||
| 	decoder.elemDecoder.decode(unsafe.Pointer(uintptr(slice.Data) + offset), iter) | ||||
| 	decoder.elemDecoder.decode(unsafe.Pointer(uintptr(slice.Data)+offset), iter) | ||||
| 	slice.Len = 4 | ||||
| 	for iter.ReadArray() { | ||||
| 		growOne(slice, decoder.sliceType, decoder.elemType) | ||||
| 		offset += decoder.elemType.Size() | ||||
| 		decoder.elemDecoder.decode(unsafe.Pointer(uintptr(slice.Data) + offset), iter) | ||||
| 		decoder.elemDecoder.decode(unsafe.Pointer(uintptr(slice.Data)+offset), iter) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -494,29 +494,33 @@ func init() { | ||||
| } | ||||
|  | ||||
| type DecoderFunc func(ptr unsafe.Pointer, iter *Iterator) | ||||
| type ExtensionFunc func(type_ reflect.Type, field *reflect.StructField) ([]string, DecoderFunc) | ||||
| type ExtensionFunc func(typ reflect.Type, field *reflect.StructField) ([]string, DecoderFunc) | ||||
|  | ||||
| type funcDecoder struct { | ||||
| 	func_ DecoderFunc | ||||
| 	fun DecoderFunc | ||||
| } | ||||
|  | ||||
| func (decoder *funcDecoder) decode(ptr unsafe.Pointer, iter *Iterator) { | ||||
| 	decoder.func_(ptr, iter) | ||||
| 	decoder.fun(ptr, iter) | ||||
| } | ||||
|  | ||||
| func RegisterTypeDecoder(type_ string, func_ DecoderFunc) { | ||||
| 	typeDecoders[type_] = &funcDecoder{func_} | ||||
| // RegisterTypeDecoder can register a type for json object | ||||
| func RegisterTypeDecoder(typ string, fun DecoderFunc) { | ||||
| 	typeDecoders[typ] = &funcDecoder{fun} | ||||
| } | ||||
|  | ||||
| func RegisterFieldDecoder(type_ string, field string, func_ DecoderFunc) { | ||||
| 	fieldDecoders[fmt.Sprintf("%s/%s", type_, field)] = &funcDecoder{func_} | ||||
| // RegisterFieldDecoder can register a type for json field | ||||
| func RegisterFieldDecoder(typ string, field string, fun DecoderFunc) { | ||||
| 	fieldDecoders[fmt.Sprintf("%s/%s", typ, field)] = &funcDecoder{fun} | ||||
| } | ||||
|  | ||||
| // RegisterExtension can register a custom extension | ||||
| func RegisterExtension(extension ExtensionFunc) { | ||||
| 	extensions = append(extensions, extension) | ||||
| } | ||||
|  | ||||
| func ClearDecoders() { | ||||
| // CleanDecoders cleans decoders registered | ||||
| func CleanDecoders() { | ||||
| 	typeDecoders = map[string]Decoder{} | ||||
| 	fieldDecoders = map[string]Decoder{} | ||||
| } | ||||
| @@ -527,6 +531,7 @@ type emptyInterface struct { | ||||
| 	word unsafe.Pointer | ||||
| } | ||||
|  | ||||
| // ReadAny converts a json object in a Iterator instance to Any | ||||
| func (iter *Iterator) ReadAny() (ret *Any) { | ||||
| 	valueType := iter.WhatIsNext() | ||||
| 	switch valueType { | ||||
| @@ -540,7 +545,7 @@ func (iter *Iterator) ReadAny() (ret *Any) { | ||||
| 		return MakeAny(iter.ReadBool()) | ||||
| 	case Array: | ||||
| 		val := []interface{}{} | ||||
| 		for (iter.ReadArray()) { | ||||
| 		for iter.ReadArray() { | ||||
| 			element := iter.ReadAny() | ||||
| 			if iter.Error != nil { | ||||
| 				return | ||||
| @@ -559,20 +564,18 @@ func (iter *Iterator) ReadAny() (ret *Any) { | ||||
| 		} | ||||
| 		return MakeAny(val) | ||||
| 	default: | ||||
| 		iter.ReportError("ReadAny", fmt.Sprintf("unexpected value type: %v", valueType)) | ||||
| 		iter.reportError("ReadAny", fmt.Sprintf("unexpected value type: %v", valueType)) | ||||
| 		return MakeAny(nil) | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| func (iter *Iterator) readNumber() (ret *Any) { | ||||
| 	strBuf := [8]byte{} | ||||
| 	str := strBuf[0:0] | ||||
| 	hasMore := true | ||||
| 	foundFloat := false | ||||
| 	foundNegative := false | ||||
| 	for(hasMore) { | ||||
| 	for hasMore { | ||||
| 		for i := iter.head; i < iter.tail; i++ { | ||||
| 			c := iter.buf[i] | ||||
| 			switch c { | ||||
| @@ -630,12 +633,13 @@ func (iter *Iterator) readNumber() (ret *Any) { | ||||
| 	return MakeAny(val) | ||||
| } | ||||
|  | ||||
| // Read converts an Iterator instance into go interface, same as json.Unmarshal | ||||
| func (iter *Iterator) Read(obj interface{}) { | ||||
| 	type_ := reflect.TypeOf(obj) | ||||
| 	cacheKey := type_.Elem() | ||||
| 	typ := reflect.TypeOf(obj) | ||||
| 	cacheKey := typ.Elem() | ||||
| 	cachedDecoder := getDecoderFromCache(cacheKey) | ||||
| 	if cachedDecoder == nil { | ||||
| 		decoder, err := decoderOfType(type_) | ||||
| 		decoder, err := decoderOfType(typ) | ||||
| 		if err != nil { | ||||
| 			iter.Error = err | ||||
| 			return | ||||
| @@ -656,17 +660,17 @@ func (p prefix) addTo(decoder Decoder, err error) (Decoder, error) { | ||||
| 	return decoder, err | ||||
| } | ||||
|  | ||||
| func decoderOfType(type_ reflect.Type) (Decoder, error) { | ||||
| 	switch type_.Kind() { | ||||
| func decoderOfType(typ reflect.Type) (Decoder, error) { | ||||
| 	switch typ.Kind() { | ||||
| 	case reflect.Ptr: | ||||
| 		return prefix("ptr").addTo(decoderOfPtr(type_.Elem())) | ||||
| 		return prefix("ptr").addTo(decoderOfPtr(typ.Elem())) | ||||
| 	default: | ||||
| 		return nil, errors.New("expect ptr") | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func decoderOfPtr(type_ reflect.Type) (Decoder, error) { | ||||
| 	typeName := type_.String() | ||||
| func decoderOfPtr(typ reflect.Type) (Decoder, error) { | ||||
| 	typeName := typ.String() | ||||
| 	if typeName == "jsoniter.Any" { | ||||
| 		return &anyDecoder{}, nil | ||||
| 	} | ||||
| @@ -674,7 +678,7 @@ func decoderOfPtr(type_ reflect.Type) (Decoder, error) { | ||||
| 	if typeDecoder != nil { | ||||
| 		return typeDecoder, nil | ||||
| 	} | ||||
| 	switch type_.Kind() { | ||||
| 	switch typ.Kind() { | ||||
| 	case reflect.String: | ||||
| 		return &stringDecoder{}, nil | ||||
| 	case reflect.Int: | ||||
| @@ -706,39 +710,39 @@ func decoderOfPtr(type_ reflect.Type) (Decoder, error) { | ||||
| 	case reflect.Interface: | ||||
| 		return &interfaceDecoder{}, nil | ||||
| 	case reflect.Struct: | ||||
| 		return decoderOfStruct(type_) | ||||
| 		return decoderOfStruct(typ) | ||||
| 	case reflect.Slice: | ||||
| 		return prefix("[slice]").addTo(decoderOfSlice(type_)) | ||||
| 		return prefix("[slice]").addTo(decoderOfSlice(typ)) | ||||
| 	case reflect.Map: | ||||
| 		return prefix("[map]").addTo(decoderOfMap(type_)) | ||||
| 		return prefix("[map]").addTo(decoderOfMap(typ)) | ||||
| 	case reflect.Ptr: | ||||
| 		return prefix("[optional]").addTo(decoderOfOptional(type_.Elem())) | ||||
| 		return prefix("[optional]").addTo(decoderOfOptional(typ.Elem())) | ||||
| 	default: | ||||
| 		return nil, fmt.Errorf("unsupported type: %v", type_) | ||||
| 		return nil, fmt.Errorf("unsupported type: %v", typ) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func decoderOfOptional(type_ reflect.Type) (Decoder, error) { | ||||
| 	decoder, err := decoderOfPtr(type_) | ||||
| func decoderOfOptional(typ reflect.Type) (Decoder, error) { | ||||
| 	decoder, err := decoderOfPtr(typ) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return &optionalDecoder{type_, decoder}, nil | ||||
| 	return &optionalDecoder{typ, decoder}, nil | ||||
| } | ||||
|  | ||||
| func decoderOfStruct(type_ reflect.Type) (Decoder, error) { | ||||
| func decoderOfStruct(typ reflect.Type) (Decoder, error) { | ||||
| 	fields := map[string]*structFieldDecoder{} | ||||
| 	for i := 0; i < type_.NumField(); i++ { | ||||
| 		field := type_.Field(i) | ||||
| 		fieldDecoderKey := fmt.Sprintf("%s/%s", type_.String(), field.Name) | ||||
| 	for i := 0; i < typ.NumField(); i++ { | ||||
| 		field := typ.Field(i) | ||||
| 		fieldDecoderKey := fmt.Sprintf("%s/%s", typ.String(), field.Name) | ||||
| 		var fieldNames []string | ||||
| 		for _, extension := range extensions { | ||||
| 			alternativeFieldNames, func_ := extension(type_, &field) | ||||
| 			alternativeFieldNames, fun := extension(typ, &field) | ||||
| 			if alternativeFieldNames != nil { | ||||
| 				fieldNames = alternativeFieldNames | ||||
| 			} | ||||
| 			if func_ != nil { | ||||
| 				fieldDecoders[fieldDecoderKey] = &funcDecoder{func_} | ||||
| 			if fun != nil { | ||||
| 				fieldDecoders[fieldDecoderKey] = &funcDecoder{fun} | ||||
| 			} | ||||
| 		} | ||||
| 		decoder := fieldDecoders[fieldDecoderKey] | ||||
| @@ -771,10 +775,10 @@ func decoderOfStruct(type_ reflect.Type) (Decoder, error) { | ||||
| 	} | ||||
| 	switch len(fields) { | ||||
| 	case 0: | ||||
| 		return &skipDecoder{type_}, nil | ||||
| 		return &skipDecoder{typ}, nil | ||||
| 	case 1: | ||||
| 		for fieldName, fieldDecoder := range fields { | ||||
| 			return &oneFieldStructDecoder{type_, fieldName, fieldDecoder}, nil | ||||
| 			return &oneFieldStructDecoder{typ, fieldName, fieldDecoder}, nil | ||||
| 		} | ||||
| 	case 2: | ||||
| 		var fieldName1 string | ||||
| @@ -790,7 +794,7 @@ func decoderOfStruct(type_ reflect.Type) (Decoder, error) { | ||||
| 				fieldDecoder2 = fieldDecoder | ||||
| 			} | ||||
| 		} | ||||
| 		return &twoFieldsStructDecoder{type_, fieldName1, fieldDecoder1, fieldName2, fieldDecoder2}, nil | ||||
| 		return &twoFieldsStructDecoder{typ, fieldName1, fieldDecoder1, fieldName2, fieldDecoder2}, nil | ||||
| 	case 3: | ||||
| 		var fieldName1 string | ||||
| 		var fieldName2 string | ||||
| @@ -810,7 +814,7 @@ func decoderOfStruct(type_ reflect.Type) (Decoder, error) { | ||||
| 				fieldDecoder3 = fieldDecoder | ||||
| 			} | ||||
| 		} | ||||
| 		return &threeFieldsStructDecoder{type_, | ||||
| 		return &threeFieldsStructDecoder{typ, | ||||
| 			fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3}, nil | ||||
| 	case 4: | ||||
| 		var fieldName1 string | ||||
| @@ -836,26 +840,26 @@ func decoderOfStruct(type_ reflect.Type) (Decoder, error) { | ||||
| 				fieldDecoder4 = fieldDecoder | ||||
| 			} | ||||
| 		} | ||||
| 		return &fourFieldsStructDecoder{type_, | ||||
| 		return &fourFieldsStructDecoder{typ, | ||||
| 			fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3, | ||||
| 			fieldName4, fieldDecoder4}, nil | ||||
| 	} | ||||
| 	return &generalStructDecoder{type_, fields}, nil | ||||
| 	return &generalStructDecoder{typ, fields}, nil | ||||
| } | ||||
|  | ||||
| func decoderOfSlice(type_ reflect.Type) (Decoder, error) { | ||||
| 	decoder, err := decoderOfPtr(type_.Elem()) | ||||
| func decoderOfSlice(typ reflect.Type) (Decoder, error) { | ||||
| 	decoder, err := decoderOfPtr(typ.Elem()) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return &sliceDecoder{type_, type_.Elem(), decoder}, nil | ||||
| 	return &sliceDecoder{typ, typ.Elem(), decoder}, nil | ||||
| } | ||||
|  | ||||
| func decoderOfMap(type_ reflect.Type) (Decoder, error) { | ||||
| 	decoder, err := decoderOfPtr(type_.Elem()) | ||||
| func decoderOfMap(typ reflect.Type) (Decoder, error) { | ||||
| 	decoder, err := decoderOfPtr(typ.Elem()) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	mapInterface := reflect.New(type_).Interface() | ||||
| 	return &mapDecoder{type_, type_.Elem(), decoder, *((*emptyInterface)(unsafe.Pointer(&mapInterface)))}, nil | ||||
| 	mapInterface := reflect.New(typ).Interface() | ||||
| 	return &mapDecoder{typ, typ.Elem(), decoder, *((*emptyInterface)(unsafe.Pointer(&mapInterface)))}, nil | ||||
| } | ||||
|   | ||||
							
								
								
									
										271
									
								
								jsoniter.go
									
									
									
									
									
								
							
							
						
						
									
										271
									
								
								jsoniter.go
									
									
									
									
									
								
							| @@ -1,12 +1,12 @@ | ||||
| package jsoniter | ||||
|  | ||||
| import ( | ||||
| 	"io" | ||||
| 	"fmt" | ||||
| 	"unicode/utf16" | ||||
| 	"strconv" | ||||
| 	"unsafe" | ||||
| 	"encoding/base64" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"strconv" | ||||
| 	"unicode/utf16" | ||||
| 	"unsafe" | ||||
| ) | ||||
|  | ||||
| type ValueType int | ||||
| @@ -30,37 +30,38 @@ func init() { | ||||
| 		digits[i] = 255 | ||||
| 	} | ||||
| 	for i := '0'; i <= '9'; i++ { | ||||
| 		digits[i] = byte(i - '0'); | ||||
| 		digits[i] = byte(i - '0') | ||||
| 	} | ||||
| 	for i := 'a'; i <= 'f'; i++ { | ||||
| 		digits[i] = byte((i - 'a') + 10); | ||||
| 		digits[i] = byte((i - 'a') + 10) | ||||
| 	} | ||||
| 	for i := 'A'; i <= 'F'; i++ { | ||||
| 		digits[i] = byte((i - 'A') + 10); | ||||
| 		digits[i] = byte((i - 'A') + 10) | ||||
| 	} | ||||
| 	valueTypes = make([]ValueType, 256) | ||||
| 	for i := 0; i < len(valueTypes); i++ { | ||||
| 		valueTypes[i] = Invalid | ||||
| 	} | ||||
| 	valueTypes['"'] = String; | ||||
| 	valueTypes['-'] = Number; | ||||
| 	valueTypes['0'] = Number; | ||||
| 	valueTypes['1'] = Number; | ||||
| 	valueTypes['2'] = Number; | ||||
| 	valueTypes['3'] = Number; | ||||
| 	valueTypes['4'] = Number; | ||||
| 	valueTypes['5'] = Number; | ||||
| 	valueTypes['6'] = Number; | ||||
| 	valueTypes['7'] = Number; | ||||
| 	valueTypes['8'] = Number; | ||||
| 	valueTypes['9'] = Number; | ||||
| 	valueTypes['t'] = Bool; | ||||
| 	valueTypes['f'] = Bool; | ||||
| 	valueTypes['n'] = Null; | ||||
| 	valueTypes['['] = Array; | ||||
| 	valueTypes['{'] = Object; | ||||
| 	valueTypes['"'] = String | ||||
| 	valueTypes['-'] = Number | ||||
| 	valueTypes['0'] = Number | ||||
| 	valueTypes['1'] = Number | ||||
| 	valueTypes['2'] = Number | ||||
| 	valueTypes['3'] = Number | ||||
| 	valueTypes['4'] = Number | ||||
| 	valueTypes['5'] = Number | ||||
| 	valueTypes['6'] = Number | ||||
| 	valueTypes['7'] = Number | ||||
| 	valueTypes['8'] = Number | ||||
| 	valueTypes['9'] = Number | ||||
| 	valueTypes['t'] = Bool | ||||
| 	valueTypes['f'] = Bool | ||||
| 	valueTypes['n'] = Null | ||||
| 	valueTypes['['] = Array | ||||
| 	valueTypes['{'] = Object | ||||
| } | ||||
|  | ||||
| // Iterator is a fast and flexible JSON parser | ||||
| type Iterator struct { | ||||
| 	reader io.Reader | ||||
| 	buf    []byte | ||||
| @@ -69,37 +70,42 @@ type Iterator struct { | ||||
| 	Error  error | ||||
| } | ||||
|  | ||||
| // Create creates an empty Iterator instance | ||||
| func Create() *Iterator { | ||||
| 	return &Iterator{ | ||||
| 		reader: nil, | ||||
| 		buf: nil, | ||||
| 		head: 0, | ||||
| 		tail: 0, | ||||
| 		buf:    nil, | ||||
| 		head:   0, | ||||
| 		tail:   0, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Parse parses a json buffer in io.Reader into an Iterator instance | ||||
| func Parse(reader io.Reader, bufSize int) *Iterator { | ||||
| 	return &Iterator{ | ||||
| 		reader: reader, | ||||
| 		buf: make([]byte, bufSize), | ||||
| 		head: 0, | ||||
| 		tail: 0, | ||||
| 		buf:    make([]byte, bufSize), | ||||
| 		head:   0, | ||||
| 		tail:   0, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // ParseBytes parses a json byte slice into an Iterator instance | ||||
| func ParseBytes(input []byte) *Iterator { | ||||
| 	return &Iterator{ | ||||
| 		reader: nil, | ||||
| 		buf: input, | ||||
| 		head: 0, | ||||
| 		tail: len(input), | ||||
| 		buf:    input, | ||||
| 		head:   0, | ||||
| 		tail:   len(input), | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // ParseString parses a json string into an Iterator instance | ||||
| func ParseString(input string) *Iterator { | ||||
| 	return ParseBytes([]byte(input)) | ||||
| } | ||||
|  | ||||
| // Reset can reset an Iterator instance for another json buffer in io.Reader | ||||
| func (iter *Iterator) Reset(reader io.Reader) *Iterator { | ||||
| 	iter.reader = reader | ||||
| 	iter.head = 0 | ||||
| @@ -107,6 +113,7 @@ func (iter *Iterator) Reset(reader io.Reader) *Iterator { | ||||
| 	return iter | ||||
| } | ||||
|  | ||||
| // ResetBytes can reset an Iterator instance for another json byte slice | ||||
| func (iter *Iterator) ResetBytes(input []byte) *Iterator { | ||||
| 	iter.reader = nil | ||||
| 	iter.Error = nil | ||||
| @@ -116,10 +123,11 @@ func (iter *Iterator) ResetBytes(input []byte) *Iterator { | ||||
| 	return iter | ||||
| } | ||||
|  | ||||
| // WhatIsNext gets ValueType of relatively next json object | ||||
| func (iter *Iterator) WhatIsNext() ValueType { | ||||
| 	valueType := valueTypes[iter.nextToken()]; | ||||
| 	iter.unreadByte(); | ||||
| 	return valueType; | ||||
| 	valueType := valueTypes[iter.nextToken()] | ||||
| 	iter.unreadByte() | ||||
| 	return valueType | ||||
| } | ||||
|  | ||||
| func (iter *Iterator) skipWhitespacesWithoutLoadMore() bool { | ||||
| @@ -144,7 +152,7 @@ func (iter *Iterator) nextToken() byte { | ||||
| 			case ' ', '\n', '\t', '\r': | ||||
| 				continue | ||||
| 			} | ||||
| 			iter.head = i+1 | ||||
| 			iter.head = i + 1 | ||||
| 			return c | ||||
| 		} | ||||
| 		if !iter.loadMore() { | ||||
| @@ -153,7 +161,7 @@ func (iter *Iterator) nextToken() byte { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (iter *Iterator) ReportError(operation string, msg string) { | ||||
| func (iter *Iterator) reportError(operation string, msg string) { | ||||
| 	if iter.Error != nil { | ||||
| 		return | ||||
| 	} | ||||
| @@ -162,16 +170,17 @@ func (iter *Iterator) ReportError(operation string, msg string) { | ||||
| 		peekStart = 0 | ||||
| 	} | ||||
| 	iter.Error = fmt.Errorf("%s: %s, parsing %v ...%s... at %s", operation, msg, iter.head, | ||||
| 		string(iter.buf[peekStart: iter.head]), string(iter.buf[0:iter.tail])) | ||||
| 		string(iter.buf[peekStart:iter.head]), string(iter.buf[0:iter.tail])) | ||||
| } | ||||
|  | ||||
| // CurrentBuffer gets current buffer as string | ||||
| func (iter *Iterator) CurrentBuffer() string { | ||||
| 	peekStart := iter.head - 10 | ||||
| 	if peekStart < 0 { | ||||
| 		peekStart = 0 | ||||
| 	} | ||||
| 	return fmt.Sprintf("parsing %v ...|%s|... at %s", iter.head, | ||||
| 		string(iter.buf[peekStart: iter.head]), string(iter.buf[0:iter.tail])) | ||||
| 		string(iter.buf[peekStart:iter.head]), string(iter.buf[0:iter.tail])) | ||||
| } | ||||
|  | ||||
| func (iter *Iterator) readByte() (ret byte) { | ||||
| @@ -180,9 +189,8 @@ func (iter *Iterator) readByte() (ret byte) { | ||||
| 			ret = iter.buf[iter.head] | ||||
| 			iter.head++ | ||||
| 			return ret | ||||
| 		} else { | ||||
| 			return 0 | ||||
| 		} | ||||
| 		return 0 | ||||
| 	} | ||||
| 	ret = iter.buf[iter.head] | ||||
| 	iter.head++ | ||||
| @@ -200,9 +208,6 @@ func (iter *Iterator) loadMore() bool { | ||||
| 			if err != nil { | ||||
| 				iter.Error = err | ||||
| 				return false | ||||
| 			} else { | ||||
| 				// n == 0, err == nil is not EOF | ||||
| 				continue | ||||
| 			} | ||||
| 		} else { | ||||
| 			iter.head = 0 | ||||
| @@ -214,58 +219,63 @@ func (iter *Iterator) loadMore() bool { | ||||
|  | ||||
| func (iter *Iterator) unreadByte() { | ||||
| 	if iter.head == 0 { | ||||
| 		iter.ReportError("unreadByte", "unread too many bytes") | ||||
| 		iter.reportError("unreadByte", "unread too many bytes") | ||||
| 		return | ||||
| 	} | ||||
| 	iter.head -= 1 | ||||
| 	iter.head-- | ||||
| 	return | ||||
| } | ||||
|  | ||||
| const maxUint64 = (1 << 64 - 1) | ||||
| const cutoffUint64 = maxUint64 / 10 + 1 | ||||
| const maxUint32 = (1 << 32 - 1) | ||||
| const cutoffUint32 = maxUint32 / 10 + 1 | ||||
| const maxUint64 = (1<<64 - 1) | ||||
| const cutoffUint64 = maxUint64/10 + 1 | ||||
| const maxUint32 = (1<<32 - 1) | ||||
| const cutoffUint32 = maxUint32/10 + 1 | ||||
|  | ||||
| // ReadUint reads a json object as Uint | ||||
| func (iter *Iterator) ReadUint() (ret uint) { | ||||
| 	val := iter.ReadUint64() | ||||
| 	converted := uint(val) | ||||
| 	if uint64(converted) != val { | ||||
| 		iter.ReportError("ReadUint", "int overflow") | ||||
| 		iter.reportError("ReadUint", "int overflow") | ||||
| 		return | ||||
| 	} | ||||
| 	return converted | ||||
| } | ||||
|  | ||||
| // ReadUint8 reads a json object as Uint8 | ||||
| func (iter *Iterator) ReadUint8() (ret uint8) { | ||||
| 	val := iter.ReadUint64() | ||||
| 	converted := uint8(val) | ||||
| 	if uint64(converted) != val { | ||||
| 		iter.ReportError("ReadUint8", "int overflow") | ||||
| 		iter.reportError("ReadUint8", "int overflow") | ||||
| 		return | ||||
| 	} | ||||
| 	return converted | ||||
| } | ||||
|  | ||||
| // ReadUint16 reads a json object as Uint16 | ||||
| func (iter *Iterator) ReadUint16() (ret uint16) { | ||||
| 	val := iter.ReadUint64() | ||||
| 	converted := uint16(val) | ||||
| 	if uint64(converted) != val { | ||||
| 		iter.ReportError("ReadUint16", "int overflow") | ||||
| 		iter.reportError("ReadUint16", "int overflow") | ||||
| 		return | ||||
| 	} | ||||
| 	return converted | ||||
| } | ||||
|  | ||||
| // ReadUint32 reads a json object as Uint32 | ||||
| func (iter *Iterator) ReadUint32() (ret uint32) { | ||||
| 	val := iter.ReadUint64() | ||||
| 	converted := uint32(val) | ||||
| 	if uint64(converted) != val { | ||||
| 		iter.ReportError("ReadUint32", "int overflow") | ||||
| 		iter.reportError("ReadUint32", "int overflow") | ||||
| 		return | ||||
| 	} | ||||
| 	return converted | ||||
| } | ||||
|  | ||||
| // ReadUint64 reads a json object as Uint64 | ||||
| func (iter *Iterator) ReadUint64() (ret uint64) { | ||||
| 	c := iter.nextToken() | ||||
| 	v := digits[c] | ||||
| @@ -273,15 +283,15 @@ func (iter *Iterator) ReadUint64() (ret uint64) { | ||||
| 		return 0 // single zero | ||||
| 	} | ||||
| 	if v == 255 { | ||||
| 		iter.ReportError("ReadUint64", "unexpected character") | ||||
| 		iter.reportError("ReadUint64", "unexpected character") | ||||
| 		return | ||||
| 	} | ||||
| 	for { | ||||
| 		if ret >= cutoffUint64 { | ||||
| 			iter.ReportError("ReadUint64", "overflow") | ||||
| 			iter.reportError("ReadUint64", "overflow") | ||||
| 			return | ||||
| 		} | ||||
| 		ret = ret * 10 + uint64(v) | ||||
| 		ret = ret*10 + uint64(v) | ||||
| 		c = iter.readByte() | ||||
| 		v = digits[c] | ||||
| 		if v == 255 { | ||||
| @@ -292,46 +302,51 @@ func (iter *Iterator) ReadUint64() (ret uint64) { | ||||
| 	return ret | ||||
| } | ||||
|  | ||||
| // ReadInt reads a json object as Int | ||||
| func (iter *Iterator) ReadInt() (ret int) { | ||||
| 	val := iter.ReadInt64() | ||||
| 	converted := int(val) | ||||
| 	if int64(converted) != val { | ||||
| 		iter.ReportError("ReadInt", "int overflow") | ||||
| 		iter.reportError("ReadInt", "int overflow") | ||||
| 		return | ||||
| 	} | ||||
| 	return converted | ||||
| } | ||||
|  | ||||
| // ReadInt8 reads a json object as Int8 | ||||
| func (iter *Iterator) ReadInt8() (ret int8) { | ||||
| 	val := iter.ReadInt64() | ||||
| 	converted := int8(val) | ||||
| 	if int64(converted) != val { | ||||
| 		iter.ReportError("ReadInt8", "int overflow") | ||||
| 		iter.reportError("ReadInt8", "int overflow") | ||||
| 		return | ||||
| 	} | ||||
| 	return converted | ||||
| } | ||||
|  | ||||
| // ReadInt16 reads a json object as Int16 | ||||
| func (iter *Iterator) ReadInt16() (ret int16) { | ||||
| 	val := iter.ReadInt64() | ||||
| 	converted := int16(val) | ||||
| 	if int64(converted) != val { | ||||
| 		iter.ReportError("ReadInt16", "int overflow") | ||||
| 		iter.reportError("ReadInt16", "int overflow") | ||||
| 		return | ||||
| 	} | ||||
| 	return converted | ||||
| } | ||||
|  | ||||
| // ReadInt32 reads a json object as Int32 | ||||
| func (iter *Iterator) ReadInt32() (ret int32) { | ||||
| 	val := iter.ReadInt64() | ||||
| 	converted := int32(val) | ||||
| 	if int64(converted) != val { | ||||
| 		iter.ReportError("ReadInt32", "int overflow") | ||||
| 		iter.reportError("ReadInt32", "int overflow") | ||||
| 		return | ||||
| 	} | ||||
| 	return converted | ||||
| } | ||||
|  | ||||
| // ReadInt64 reads a json object as Int64 | ||||
| func (iter *Iterator) ReadInt64() (ret int64) { | ||||
| 	c := iter.nextToken() | ||||
| 	if iter.Error != nil { | ||||
| @@ -342,25 +357,24 @@ func (iter *Iterator) ReadInt64() (ret int64) { | ||||
| 	if c == '-' { | ||||
| 		n := iter.ReadUint64() | ||||
| 		return -int64(n) | ||||
| 	} else { | ||||
| 		iter.unreadByte() | ||||
| 		n := iter.ReadUint64() | ||||
| 		return int64(n) | ||||
| 	} | ||||
| 	iter.unreadByte() | ||||
| 	n := iter.ReadUint64() | ||||
| 	return int64(n) | ||||
| } | ||||
|  | ||||
| // ReadString reads a json object as String | ||||
| func (iter *Iterator) ReadString() (ret string) { | ||||
| 	return string(iter.readStringAsBytes()) | ||||
| } | ||||
|  | ||||
|  | ||||
| func (iter *Iterator) readStringAsBytes() (ret []byte) { | ||||
| 	c := iter.nextToken() | ||||
| 	if c == '"' { | ||||
| 		end := iter.findStringEndWithoutEscape() | ||||
| 		if end != -1 { | ||||
| 			// fast path: reuse the underlying buffer | ||||
| 			ret = iter.buf[iter.head:end-1] | ||||
| 			ret = iter.buf[iter.head : end-1] | ||||
| 			iter.head = end | ||||
| 			return ret | ||||
| 		} | ||||
| @@ -370,7 +384,7 @@ func (iter *Iterator) readStringAsBytes() (ret []byte) { | ||||
| 		iter.skipUntilBreak() | ||||
| 		return | ||||
| 	} | ||||
| 	iter.ReportError("ReadString", `expects " or n`) | ||||
| 	iter.reportError("ReadString", `expects " or n`) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| @@ -399,7 +413,7 @@ func (iter *Iterator) readStringAsBytesSlowPath() (ret []byte) { | ||||
| 						return | ||||
| 					} | ||||
| 					if c != '\\' { | ||||
| 						iter.ReportError("ReadString", | ||||
| 						iter.reportError("ReadString", | ||||
| 							`expects \u after utf16 surrogate, but \ not found`) | ||||
| 						return | ||||
| 					} | ||||
| @@ -408,7 +422,7 @@ func (iter *Iterator) readStringAsBytesSlowPath() (ret []byte) { | ||||
| 						return | ||||
| 					} | ||||
| 					if c != 'u' { | ||||
| 						iter.ReportError("ReadString", | ||||
| 						iter.reportError("ReadString", | ||||
| 							`expects \u after utf16 surrogate, but \u not found`) | ||||
| 						return | ||||
| 					} | ||||
| @@ -438,7 +452,7 @@ func (iter *Iterator) readStringAsBytesSlowPath() (ret []byte) { | ||||
| 			case 't': | ||||
| 				str = append(str, '\t') | ||||
| 			default: | ||||
| 				iter.ReportError("ReadString", | ||||
| 				iter.reportError("ReadString", | ||||
| 					`invalid escape char after \`) | ||||
| 				return | ||||
| 			} | ||||
| @@ -455,20 +469,20 @@ func (iter *Iterator) readU4() (ret rune) { | ||||
| 		if iter.Error != nil { | ||||
| 			return | ||||
| 		} | ||||
| 		if (c >= '0' && c <= '9') { | ||||
| 		if c >= '0' && c <= '9' { | ||||
| 			if ret >= cutoffUint32 { | ||||
| 				iter.ReportError("readU4", "overflow") | ||||
| 				iter.reportError("readU4", "overflow") | ||||
| 				return | ||||
| 			} | ||||
| 			ret = ret * 16 + rune(c - '0') | ||||
| 		} else if ((c >= 'a' && c <= 'f') ) { | ||||
| 			ret = ret*16 + rune(c-'0') | ||||
| 		} else if c >= 'a' && c <= 'f' { | ||||
| 			if ret >= cutoffUint32 { | ||||
| 				iter.ReportError("readU4", "overflow") | ||||
| 				iter.reportError("readU4", "overflow") | ||||
| 				return | ||||
| 			} | ||||
| 			ret = ret * 16 + rune(c - 'a' + 10) | ||||
| 			ret = ret*16 + rune(c-'a'+10) | ||||
| 		} else { | ||||
| 			iter.ReportError("readU4", "expects 0~9 or a~f") | ||||
| 			iter.reportError("readU4", "expects 0~9 or a~f") | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| @@ -488,14 +502,14 @@ const ( | ||||
| 	mask3 = 0x0F // 0000 1111 | ||||
| 	mask4 = 0x07 // 0000 0111 | ||||
|  | ||||
| 	rune1Max = 1 << 7 - 1 | ||||
| 	rune2Max = 1 << 11 - 1 | ||||
| 	rune3Max = 1 << 16 - 1 | ||||
| 	rune1Max = 1<<7 - 1 | ||||
| 	rune2Max = 1<<11 - 1 | ||||
| 	rune3Max = 1<<16 - 1 | ||||
|  | ||||
| 	surrogateMin = 0xD800 | ||||
| 	surrogateMax = 0xDFFF | ||||
|  | ||||
| 	MaxRune = '\U0010FFFF' // Maximum valid Unicode code point. | ||||
| 	MaxRune   = '\U0010FFFF' // Maximum valid Unicode code point. | ||||
| 	RuneError = '\uFFFD'     // the "error" Rune or "Unicode replacement character" | ||||
| ) | ||||
|  | ||||
| @@ -506,62 +520,62 @@ func appendRune(p []byte, r rune) []byte { | ||||
| 		p = append(p, byte(r)) | ||||
| 		return p | ||||
| 	case i <= rune2Max: | ||||
| 		p = append(p, t2 | byte(r >> 6)) | ||||
| 		p = append(p, tx | byte(r) & maskx) | ||||
| 		p = append(p, t2|byte(r>>6)) | ||||
| 		p = append(p, tx|byte(r)&maskx) | ||||
| 		return p | ||||
| 	case i > MaxRune, surrogateMin <= i && i <= surrogateMax: | ||||
| 		r = RuneError | ||||
| 		fallthrough | ||||
| 	case i <= rune3Max: | ||||
| 		p = append(p, t3 | byte(r >> 12)) | ||||
| 		p = append(p, tx | byte(r >> 6) & maskx) | ||||
| 		p = append(p, tx | byte(r) & maskx) | ||||
| 		p = append(p, t3|byte(r>>12)) | ||||
| 		p = append(p, tx|byte(r>>6)&maskx) | ||||
| 		p = append(p, tx|byte(r)&maskx) | ||||
| 		return p | ||||
| 	default: | ||||
| 		p = append(p, t4 | byte(r >> 18)) | ||||
| 		p = append(p, tx | byte(r >> 12) & maskx) | ||||
| 		p = append(p, tx | byte(r >> 6) & maskx) | ||||
| 		p = append(p, tx | byte(r) & maskx) | ||||
| 		p = append(p, t4|byte(r>>18)) | ||||
| 		p = append(p, tx|byte(r>>12)&maskx) | ||||
| 		p = append(p, tx|byte(r>>6)&maskx) | ||||
| 		p = append(p, tx|byte(r)&maskx) | ||||
| 		return p | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // ReadArray reads a json object as Array | ||||
| func (iter *Iterator) ReadArray() (ret bool) { | ||||
| 	c := iter.nextToken() | ||||
| 	if iter.Error != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	switch c { | ||||
| 	case 'n': { | ||||
| 	case 'n': | ||||
| 		iter.skipUntilBreak() | ||||
| 		return false // null | ||||
| 	} | ||||
| 	case '[': { | ||||
| 	case '[': | ||||
| 		c = iter.nextToken() | ||||
| 		if iter.Error != nil { | ||||
| 			return | ||||
| 		} | ||||
| 		if c == ']' { | ||||
| 			return false | ||||
| 		} else { | ||||
| 			iter.unreadByte() | ||||
| 			return true | ||||
| 		} | ||||
| 	} | ||||
| 	case ']': return false | ||||
| 		iter.unreadByte() | ||||
| 		return true | ||||
| 	case ']': | ||||
| 		return false | ||||
| 	case ',': | ||||
| 		return true | ||||
| 	default: | ||||
| 		iter.ReportError("ReadArray", "expect [ or , or ] or n, but found: " + string([]byte{c})) | ||||
| 		iter.reportError("ReadArray", "expect [ or , or ] or n, but found: "+string([]byte{c})) | ||||
| 		return | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // ReadFloat32 reads a json object as Float32 | ||||
| func (iter *Iterator) ReadFloat32() (ret float32) { | ||||
| 	strBuf := [8]byte{} | ||||
| 	str := strBuf[0:0] | ||||
| 	hasMore := true | ||||
| 	for(hasMore) { | ||||
| 	for hasMore { | ||||
| 		for i := iter.head; i < iter.tail; i++ { | ||||
| 			c := iter.buf[i] | ||||
| 			switch c { | ||||
| @@ -590,11 +604,12 @@ func (iter *Iterator) ReadFloat32() (ret float32) { | ||||
| 	return float32(val) | ||||
| } | ||||
|  | ||||
| // ReadFloat64 reads a json object as Float64 | ||||
| func (iter *Iterator) ReadFloat64() (ret float64) { | ||||
| 	strBuf := [8]byte{} | ||||
| 	str := strBuf[0:0] | ||||
| 	hasMore := true | ||||
| 	for(hasMore) { | ||||
| 	for hasMore { | ||||
| 		for i := iter.head; i < iter.tail; i++ { | ||||
| 			c := iter.buf[i] | ||||
| 			switch c { | ||||
| @@ -623,6 +638,7 @@ func (iter *Iterator) ReadFloat64() (ret float64) { | ||||
| 	return val | ||||
| } | ||||
|  | ||||
| // ReadBool reads a json object as Bool | ||||
| func (iter *Iterator) ReadBool() (ret bool) { | ||||
| 	c := iter.nextToken() | ||||
| 	if iter.Error != nil { | ||||
| @@ -636,11 +652,12 @@ func (iter *Iterator) ReadBool() (ret bool) { | ||||
| 		iter.skipUntilBreak() | ||||
| 		return false | ||||
| 	default: | ||||
| 		iter.ReportError("ReadBool", "expect t or f") | ||||
| 		iter.reportError("ReadBool", "expect t or f") | ||||
| 		return | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // ReadBase64 reads a json object as Base64 in byte slice | ||||
| func (iter *Iterator) ReadBase64() (ret []byte) { | ||||
| 	src := iter.readStringAsBytes() | ||||
| 	if iter.Error != nil { | ||||
| @@ -656,7 +673,9 @@ func (iter *Iterator) ReadBase64() (ret []byte) { | ||||
| 	return ret[:n] | ||||
| } | ||||
|  | ||||
| func (iter *Iterator) ReadNull() (ret bool) { | ||||
| // ReadNil reads a json object as nil and | ||||
| // returns whether it's a nil or not | ||||
| func (iter *Iterator) ReadNil() (ret bool) { | ||||
| 	c := iter.nextToken() | ||||
| 	if c == 'n' { | ||||
| 		iter.skipUntilBreak() | ||||
| @@ -666,6 +685,7 @@ func (iter *Iterator) ReadNull() (ret bool) { | ||||
| 	return false | ||||
| } | ||||
|  | ||||
| // Skip skips a json object and positions to relatively the next json object | ||||
| func (iter *Iterator) Skip() { | ||||
| 	c := iter.nextToken() | ||||
| 	switch c { | ||||
| @@ -678,7 +698,7 @@ func (iter *Iterator) Skip() { | ||||
| 	case '{': | ||||
| 		iter.skipObject() | ||||
| 	default: | ||||
| 		iter.ReportError("Skip", fmt.Sprintf("do not know how to skip: %v", c)) | ||||
| 		iter.reportError("Skip", fmt.Sprintf("do not know how to skip: %v", c)) | ||||
| 		return | ||||
| 	} | ||||
| } | ||||
| @@ -700,7 +720,6 @@ func (iter *Iterator) skipString() { | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
| // adapted from: https://github.com/buger/jsonparser/blob/master/parser.go | ||||
| // Tries to find the end of string | ||||
| // Support if string contains escaped quote symbols. | ||||
| @@ -711,22 +730,21 @@ func (iter *Iterator) findStringEnd() (int, bool) { | ||||
| 		if c == '"' { | ||||
| 			if !escaped { | ||||
| 				return i + 1, false | ||||
| 			} else { | ||||
| 				j := i - 1 | ||||
| 				for { | ||||
| 					if j < iter.head || iter.buf[j] != '\\' { | ||||
| 						// even number of backslashes | ||||
| 						// either end of buffer, or " found | ||||
| 						return i + 1, true | ||||
| 					} | ||||
| 					j-- | ||||
| 					if j < iter.head || iter.buf[j] != '\\' { | ||||
| 						// odd number of backslashes | ||||
| 						// it is \" or \\\" | ||||
| 						break | ||||
| 					} | ||||
| 					j-- | ||||
| 			} | ||||
| 			j := i - 1 | ||||
| 			for { | ||||
| 				if j < iter.head || iter.buf[j] != '\\' { | ||||
| 					// even number of backslashes | ||||
| 					// either end of buffer, or " found | ||||
| 					return i + 1, true | ||||
| 				} | ||||
| 				j-- | ||||
| 				if j < iter.head || iter.buf[j] != '\\' { | ||||
| 					// odd number of backslashes | ||||
| 					// it is \" or \\\" | ||||
| 					break | ||||
| 				} | ||||
| 				j-- | ||||
| 			} | ||||
| 		} else if c == '\\' { | ||||
| 			escaped = true | ||||
| @@ -751,7 +769,6 @@ func (iter *Iterator) findStringEnd() (int, bool) { | ||||
| 	return -1, true // end with \ | ||||
| } | ||||
|  | ||||
|  | ||||
| func (iter *Iterator) findStringEndWithoutEscape() int { | ||||
| 	for i := iter.head; i < iter.tail; i++ { | ||||
| 		c := iter.buf[i] | ||||
| @@ -785,7 +802,7 @@ func (iter *Iterator) skipArray() { | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		if (!iter.loadMore()) { | ||||
| 		if !iter.loadMore() { | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| @@ -812,7 +829,7 @@ func (iter *Iterator) skipObject() { | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		if (!iter.loadMore()) { | ||||
| 		if !iter.loadMore() { | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| @@ -829,7 +846,7 @@ func (iter *Iterator) skipUntilBreak() { | ||||
| 				return | ||||
| 			} | ||||
| 		} | ||||
| 		if (!iter.loadMore()) { | ||||
| 		if !iter.loadMore() { | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
|   | ||||
| @@ -1,8 +1,8 @@ | ||||
| package jsoniter | ||||
|  | ||||
| import ( | ||||
| 	"testing" | ||||
| 	"fmt" | ||||
| 	"testing" | ||||
| ) | ||||
|  | ||||
| func Test_read_string_as_any(t *testing.T) { | ||||
|   | ||||
| @@ -1,8 +1,8 @@ | ||||
| package jsoniter | ||||
|  | ||||
| import ( | ||||
| 	"testing" | ||||
| 	"encoding/json" | ||||
| 	"testing" | ||||
| ) | ||||
|  | ||||
| func Test_empty_array(t *testing.T) { | ||||
|   | ||||
| @@ -1,8 +1,8 @@ | ||||
| package jsoniter | ||||
|  | ||||
| import ( | ||||
| 	"testing" | ||||
| 	"bytes" | ||||
| 	"testing" | ||||
| ) | ||||
|  | ||||
| func Test_read_base64(t *testing.T) { | ||||
| @@ -12,7 +12,6 @@ func Test_read_base64(t *testing.T) { | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
| func Test_bad_case(t *testing.T) { | ||||
| 	// field := *(*string)(unsafe.Pointer(&str)) | ||||
| 	// caused this issue | ||||
|   | ||||
| @@ -1,11 +1,11 @@ | ||||
| package jsoniter | ||||
|  | ||||
| import ( | ||||
| 	"reflect" | ||||
| 	"strconv" | ||||
| 	"testing" | ||||
| 	"time" | ||||
| 	"unsafe" | ||||
| 	"strconv" | ||||
| 	"reflect" | ||||
| ) | ||||
|  | ||||
| func Test_customize_type_decoder(t *testing.T) { | ||||
| @@ -17,7 +17,7 @@ func Test_customize_type_decoder(t *testing.T) { | ||||
| 		} | ||||
| 		*((*time.Time)(ptr)) = t | ||||
| 	}) | ||||
| 	defer ClearDecoders() | ||||
| 	defer CleanDecoders() | ||||
| 	val := time.Time{} | ||||
| 	err := Unmarshal([]byte(`"2016-12-05 08:43:28"`), &val) | ||||
| 	if err != nil { | ||||
| @@ -37,7 +37,7 @@ func Test_customize_field_decoder(t *testing.T) { | ||||
| 	RegisterFieldDecoder("jsoniter.Tom", "field1", func(ptr unsafe.Pointer, iter *Iterator) { | ||||
| 		*((*string)(ptr)) = strconv.Itoa(iter.ReadInt()) | ||||
| 	}) | ||||
| 	defer ClearDecoders() | ||||
| 	defer CleanDecoders() | ||||
| 	tom := Tom{} | ||||
| 	err := Unmarshal([]byte(`{"field1": 100}`), &tom) | ||||
| 	if err != nil { | ||||
| @@ -51,7 +51,7 @@ type TestObject1 struct { | ||||
|  | ||||
| func Test_customize_field_by_extension(t *testing.T) { | ||||
| 	RegisterExtension(func(type_ reflect.Type, field *reflect.StructField) ([]string, DecoderFunc) { | ||||
| 		if (type_.String() == "jsoniter.TestObject1" && field.Name == "field1") { | ||||
| 		if type_.String() == "jsoniter.TestObject1" && field.Name == "field1" { | ||||
| 			return []string{"field-1"}, func(ptr unsafe.Pointer, iter *Iterator) { | ||||
| 				*((*string)(ptr)) = strconv.Itoa(iter.ReadInt()) | ||||
| 			} | ||||
|   | ||||
| @@ -1,8 +1,8 @@ | ||||
| package jsoniter | ||||
|  | ||||
| import ( | ||||
| 	"testing" | ||||
| 	"fmt" | ||||
| 	"testing" | ||||
| ) | ||||
|  | ||||
| func Test_bind_api_demo(t *testing.T) { | ||||
| @@ -39,16 +39,16 @@ func Test_deep_nested_any_api(t *testing.T) { | ||||
| } | ||||
|  | ||||
| type User struct { | ||||
| 	userId int | ||||
| 	name string | ||||
| 	tags []string | ||||
| 	userID int | ||||
| 	name   string | ||||
| 	tags   []string | ||||
| } | ||||
|  | ||||
| func Test_iterator_and_bind_api(t *testing.T) { | ||||
| 	iter := ParseString(`[123, {"name": "taowen", "tags": ["crazy", "hacker"]}]`) | ||||
| 	user := User{} | ||||
| 	iter.ReadArray() | ||||
| 	user.userId = iter.ReadInt() | ||||
| 	user.userID = iter.ReadInt() | ||||
| 	iter.ReadArray() | ||||
| 	iter.Read(&user) | ||||
| 	iter.ReadArray() // array end | ||||
|   | ||||
| @@ -1,8 +1,8 @@ | ||||
| package jsoniter | ||||
|  | ||||
| import ( | ||||
| 	"testing" | ||||
| 	"io" | ||||
| 	"testing" | ||||
| ) | ||||
|  | ||||
| func Test_string_end(t *testing.T) { | ||||
|   | ||||
| @@ -1,9 +1,9 @@ | ||||
| package jsoniter | ||||
|  | ||||
| import ( | ||||
| 	"testing" | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"testing" | ||||
| ) | ||||
|  | ||||
| func Test_float64_0(t *testing.T) { | ||||
|   | ||||
| @@ -1,9 +1,9 @@ | ||||
| package jsoniter | ||||
|  | ||||
| import ( | ||||
| 	"testing" | ||||
| 	"bytes" | ||||
| 	"encoding/json" | ||||
| 	"testing" | ||||
| ) | ||||
|  | ||||
| func Test_uint64_0(t *testing.T) { | ||||
|   | ||||
| @@ -1,9 +1,9 @@ | ||||
| package jsoniter | ||||
|  | ||||
| import ( | ||||
| 	"testing" | ||||
| 	"bytes" | ||||
| 	"io" | ||||
| 	"testing" | ||||
| ) | ||||
|  | ||||
| func Test_read_by_one(t *testing.T) { | ||||
|   | ||||
| @@ -1,10 +1,10 @@ | ||||
| package jsoniter | ||||
|  | ||||
| import ( | ||||
| 	"testing" | ||||
| 	"os" | ||||
| 	"encoding/json" | ||||
| 	"io/ioutil" | ||||
| 	"os" | ||||
| 	"testing" | ||||
| ) | ||||
|  | ||||
| //func Test_large_file(t *testing.T) { | ||||
| @@ -23,7 +23,6 @@ import ( | ||||
| //	} | ||||
| //} | ||||
|  | ||||
|  | ||||
| func Benchmark_jsoniter_large_file(b *testing.B) { | ||||
| 	b.ReportAllocs() | ||||
| 	for n := 0; n < b.N; n++ { | ||||
|   | ||||
| @@ -1,16 +1,16 @@ | ||||
| package jsoniter | ||||
|  | ||||
| import ( | ||||
| 	"testing" | ||||
| 	"reflect" | ||||
| 	"fmt" | ||||
| 	"reflect" | ||||
| 	"testing" | ||||
| ) | ||||
|  | ||||
| func Test_read_map(t *testing.T) { | ||||
| 	iter := ParseString(`{"hello": "world"}`) | ||||
| 	m := map[string]string{"1": "2"} | ||||
| 	iter.Read(&m) | ||||
| 	copy(iter.buf, []byte{0,0,0,0,0,0}) | ||||
| 	copy(iter.buf, []byte{0, 0, 0, 0, 0, 0}) | ||||
| 	if !reflect.DeepEqual(map[string]string{"1": "2", "hello": "world"}, m) { | ||||
| 		fmt.Println(iter.Error) | ||||
| 		t.Fatal(m) | ||||
|   | ||||
| @@ -1,9 +1,9 @@ | ||||
| package jsoniter | ||||
|  | ||||
| import ( | ||||
| 	"testing" | ||||
| 	"reflect" | ||||
| 	"encoding/json" | ||||
| 	"reflect" | ||||
| 	"testing" | ||||
| ) | ||||
|  | ||||
| type Level1 struct { | ||||
| @@ -28,14 +28,14 @@ func Test_nested(t *testing.T) { | ||||
| 					case "world": | ||||
| 						l2.World = iter.ReadString() | ||||
| 					default: | ||||
| 						iter.ReportError("bind l2", "unexpected field: " + l2Field) | ||||
| 						iter.reportError("bind l2", "unexpected field: "+l2Field) | ||||
| 					} | ||||
| 				} | ||||
| 				l2Array = append(l2Array, l2) | ||||
| 			} | ||||
| 			l1.Hello = l2Array | ||||
| 		default: | ||||
| 			iter.ReportError("bind l1", "unexpected field: " + l1Field) | ||||
| 			iter.reportError("bind l1", "unexpected field: "+l1Field) | ||||
| 		} | ||||
| 	} | ||||
| 	if !reflect.DeepEqual(l1, Level1{ | ||||
|   | ||||
| @@ -6,7 +6,7 @@ import ( | ||||
|  | ||||
| func Test_null(t *testing.T) { | ||||
| 	iter := ParseString(`null`) | ||||
| 	if iter.ReadNull() != true { | ||||
| 	if iter.ReadNil() != true { | ||||
| 		t.FailNow() | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -1,9 +1,9 @@ | ||||
| package jsoniter | ||||
|  | ||||
| import ( | ||||
| 	"testing" | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"testing" | ||||
| ) | ||||
|  | ||||
| func Test_empty_object(t *testing.T) { | ||||
| @@ -61,7 +61,7 @@ func Test_two_field(t *testing.T) { | ||||
| 		case "field2": | ||||
| 			iter.ReadInt64() | ||||
| 		default: | ||||
| 			iter.ReportError("bind object", "unexpected field") | ||||
| 			iter.reportError("bind object", "unexpected field") | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -82,7 +82,7 @@ func Benchmark_jsoniter_object(b *testing.B) { | ||||
| 			case "field2": | ||||
| 				obj.Field2 = iter.ReadUint64() | ||||
| 			default: | ||||
| 				iter.ReportError("bind object", "unexpected field") | ||||
| 				iter.reportError("bind object", "unexpected field") | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|   | ||||
| @@ -1,9 +1,9 @@ | ||||
| package jsoniter | ||||
|  | ||||
| import ( | ||||
| 	"testing" | ||||
| 	"fmt" | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"testing" | ||||
| 	"unsafe" | ||||
| ) | ||||
|  | ||||
| @@ -162,15 +162,15 @@ type StructOfString struct { | ||||
|  | ||||
| func Test_reflect_struct_string(t *testing.T) { | ||||
| 	iter := ParseString(`{"field1": "hello", "field2": "world"}`) | ||||
| 	struct_ := StructOfString{} | ||||
| 	iter.Read(&struct_) | ||||
| 	if struct_.field1 != "hello" { | ||||
| 	Struct := StructOfString{} | ||||
| 	iter.Read(&Struct) | ||||
| 	if Struct.field1 != "hello" { | ||||
| 		fmt.Println(iter.Error) | ||||
| 		t.Fatal(struct_.field1) | ||||
| 		t.Fatal(Struct.field1) | ||||
| 	} | ||||
| 	if struct_.field2 != "world" { | ||||
| 	if Struct.field2 != "world" { | ||||
| 		fmt.Println(iter.Error) | ||||
| 		t.Fatal(struct_.field1) | ||||
| 		t.Fatal(Struct.field2) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -181,39 +181,39 @@ type StructOfStringPtr struct { | ||||
|  | ||||
| func Test_reflect_struct_string_ptr(t *testing.T) { | ||||
| 	iter := ParseString(`{"field1": null, "field2": "world"}`) | ||||
| 	struct_ := StructOfStringPtr{} | ||||
| 	iter.Read(&struct_) | ||||
| 	if struct_.field1 != nil { | ||||
| 	Struct := StructOfStringPtr{} | ||||
| 	iter.Read(&Struct) | ||||
| 	if Struct.field1 != nil { | ||||
| 		fmt.Println(iter.Error) | ||||
| 		t.Fatal(struct_.field1) | ||||
| 		t.Fatal(Struct.field1) | ||||
| 	} | ||||
| 	if *struct_.field2 != "world" { | ||||
| 	if *Struct.field2 != "world" { | ||||
| 		fmt.Println(iter.Error) | ||||
| 		t.Fatal(struct_.field2) | ||||
| 		t.Fatal(Struct.field2) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| type StructOfTag struct { | ||||
| 	field1 string `json:"field-1"` | ||||
| 	field2 string `json:"-"` | ||||
| 	field3 int `json:",string"` | ||||
| 	Field1 string `json:"field-1"` | ||||
| 	Field2 string `json:"-"` | ||||
| 	Field3 int    `json:",string"` | ||||
| } | ||||
|  | ||||
| func Test_reflect_struct_tag_field(t *testing.T) { | ||||
| 	iter := ParseString(`{"field-1": "hello", "field2": "", "field3": "100"}`) | ||||
| 	struct_ := StructOfTag{field2: "world"} | ||||
| 	iter.Read(&struct_) | ||||
| 	if struct_.field1 != "hello" { | ||||
| 	iter := ParseString(`{"field-1": "hello", "field2": "", "Field3": "100"}`) | ||||
| 	Struct := StructOfTag{Field2: "world"} | ||||
| 	iter.Read(&Struct) | ||||
| 	if Struct.Field1 != "hello" { | ||||
| 		fmt.Println(iter.Error) | ||||
| 		t.Fatal(struct_.field1) | ||||
| 		t.Fatal(Struct.Field1) | ||||
| 	} | ||||
| 	if struct_.field2 != "world" { | ||||
| 	if Struct.Field2 != "world" { | ||||
| 		fmt.Println(iter.Error) | ||||
| 		t.Fatal(struct_.field2) | ||||
| 		t.Fatal(Struct.Field2) | ||||
| 	} | ||||
| 	if struct_.field3 != 100 { | ||||
| 	if Struct.Field3 != 100 { | ||||
| 		fmt.Println(iter.Error) | ||||
| 		t.Fatal(struct_.field3) | ||||
| 		t.Fatal(Struct.Field3) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -249,7 +249,7 @@ func Test_reflect_large_slice(t *testing.T) { | ||||
| 	} | ||||
| 	if slice[8] != 9 { | ||||
| 		fmt.Println(iter.Error) | ||||
| 		t.Fatal(slice[1]) | ||||
| 		t.Fatal(slice[8]) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -271,7 +271,7 @@ func Test_reflect_nested(t *testing.T) { | ||||
| 	} | ||||
| 	if slice[2].field2 != "world" { | ||||
| 		fmt.Println(iter.Error) | ||||
| 		t.Fatal(slice[1]) | ||||
| 		t.Fatal(slice[2]) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -281,7 +281,7 @@ func Test_reflect_base64(t *testing.T) { | ||||
| 	RegisterTypeDecoder("[]uint8", func(ptr unsafe.Pointer, iter *Iterator) { | ||||
| 		*((*[]byte)(ptr)) = iter.ReadBase64() | ||||
| 	}) | ||||
| 	defer ClearDecoders() | ||||
| 	defer CleanDecoders() | ||||
| 	iter.Read(&val) | ||||
| 	if "abc" != string(val) { | ||||
| 		t.Fatal(string(val)) | ||||
| @@ -289,22 +289,22 @@ func Test_reflect_base64(t *testing.T) { | ||||
| } | ||||
|  | ||||
| type StructOfTagOne struct { | ||||
| 	field1 string `json:"field1"` | ||||
| 	field2 string `json:"field2"` | ||||
| 	field3 int `json:"field3,string"` | ||||
| 	field4 int `json:"field4,string"` | ||||
| 	Field1 string `json:"field1"` | ||||
| 	Field2 string `json:"field2"` | ||||
| 	Field3 int    `json:"field3,string"` | ||||
| 	Field4 int    `json:"field4,string"` | ||||
| } | ||||
|  | ||||
| func Benchmark_jsoniter_reflect(b *testing.B) { | ||||
| 	b.ReportAllocs() | ||||
| 	iter := Create() | ||||
| 	struct_ := &StructOfTagOne{} | ||||
| 	//var struct_ *StructOfTagOne | ||||
| 	Struct := &StructOfTagOne{} | ||||
| 	//var Struct *StructOfTagOne | ||||
| 	input := []byte(`{"field3": "100", "field4": "100"}`) | ||||
| 	//input := []byte(`null`) | ||||
| 	for n := 0; n < b.N; n++ { | ||||
| 		iter.ResetBytes(input) | ||||
| 		iter.Read(&struct_) | ||||
| 		iter.Read(&Struct) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -316,9 +316,9 @@ func Benchmark_jsoniter_direct(b *testing.B) { | ||||
| 		//for field := iter.ReadObject(); field != ""; field = iter.ReadObject() { | ||||
| 		//	switch field { | ||||
| 		//	case "field1": | ||||
| 		//		struct_.field1 = iter.ReadString() | ||||
| 		//		struct_.Field1 = iter.ReadString() | ||||
| 		//	case "field2": | ||||
| 		//		struct_.field2 = iter.ReadString() | ||||
| 		//		struct_.Field2 = iter.ReadString() | ||||
| 		//	default: | ||||
| 		//		iter.Skip() | ||||
| 		//	} | ||||
| @@ -334,8 +334,8 @@ func Benchmark_jsoniter_direct(b *testing.B) { | ||||
| func Benchmark_json_reflect(b *testing.B) { | ||||
| 	b.ReportAllocs() | ||||
| 	for n := 0; n < b.N; n++ { | ||||
| 		struct_ := StructOfTagOne{} | ||||
| 		json.Unmarshal([]byte(`{"field3": "100"}`), &struct_) | ||||
| 		Struct := StructOfTagOne{} | ||||
| 		json.Unmarshal([]byte(`{"field3": "100"}`), &Struct) | ||||
| 		//array := make([]string, 0, 2) | ||||
| 		//json.Unmarshal([]byte(`["hello", "world"]`), &array) | ||||
| 	} | ||||
|   | ||||
| @@ -1,11 +1,10 @@ | ||||
| package jsoniter | ||||
|  | ||||
| import ( | ||||
| 	"testing" | ||||
| 	"encoding/json" | ||||
| 	"testing" | ||||
| ) | ||||
|  | ||||
|  | ||||
| func Test_skip_number(t *testing.T) { | ||||
| 	iter := ParseString(`[-0.12, "b"]`) | ||||
| 	iter.ReadArray() | ||||
|   | ||||
| @@ -1,9 +1,9 @@ | ||||
| package jsoniter | ||||
|  | ||||
| import ( | ||||
| 	"testing" | ||||
| 	"bytes" | ||||
| 	"encoding/json" | ||||
| 	"testing" | ||||
| ) | ||||
|  | ||||
| func Test_string_empty(t *testing.T) { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user