Преглед на файлове

#61 remove internal buffer from arrayAny

Tao Wen преди 8 години
родител
ревизия
a84cdaa694
променени са 4 файла, в които са добавени 43 реда и са изтрити 109 реда
  1. 8 2
      feature_any.go
  2. 20 88
      feature_any_array.go
  3. 9 18
      feature_any_string.go
  4. 6 1
      jsoniter_any_array_test.go

+ 8 - 2
feature_any.go

@@ -71,7 +71,7 @@ func WrapFloat64(val float64) Any {
 }
 
 func WrapString(val string) Any {
-	return &stringAny{baseAny{}, nil, val}
+	return &stringAny{baseAny{}, val}
 }
 
 func Wrap(val interface{}) Any {
@@ -135,7 +135,7 @@ func (iter *Iterator) readAny() Any {
 	switch c {
 	case '"':
 		iter.unreadByte()
-		return &stringAny{baseAny{}, nil, iter.ReadString()}
+		return &stringAny{baseAny{}, iter.ReadString()}
 	case 'n':
 		iter.skipFixedBytes(3) // null
 		return &nilAny{}
@@ -222,6 +222,12 @@ func locatePath(iter *Iterator, path []interface{}) Any {
 		case int:
 			valueBytes := locateArrayElement(iter, pathKey)
 			iter.ResetBytes(valueBytes)
+		case int32:
+			if '*' == pathKey {
+				return iter.readAny().Get(path[i:]...)
+			} else {
+				return newInvalidAny(path)
+			}
 		default:
 			return newInvalidAny(path[i:])
 		}

+ 20 - 88
feature_any_array.go

@@ -1,7 +1,6 @@
 package jsoniter
 
 import (
-	"fmt"
 	"reflect"
 	"unsafe"
 )
@@ -166,25 +165,19 @@ func (any *arrayLazyAny) GetInterface() interface{} {
 
 type arrayAny struct {
 	baseAny
-	err   error
-	cache []Any
 	val   reflect.Value
 }
 
 func wrapArray(val interface{}) *arrayAny {
-	return &arrayAny{baseAny{}, nil, nil, reflect.ValueOf(val)}
+	return &arrayAny{baseAny{}, reflect.ValueOf(val)}
 }
 
 func (any *arrayAny) ValueType() ValueType {
 	return Array
 }
 
-func (any *arrayAny) Parse() *Iterator {
-	return nil
-}
-
 func (any *arrayAny) LastError() error {
-	return any.err
+	return nil
 }
 
 func (any *arrayAny) ToBool() bool {
@@ -248,115 +241,54 @@ func (any *arrayAny) ToFloat64() float64 {
 }
 
 func (any *arrayAny) ToString() string {
-	if len(any.cache) == 0 {
-		// nothing has been parsed yet
-		str, err := MarshalToString(any.val.Interface())
-		any.err = err
-		return str
-	} else {
-		any.fillCache()
-		str, err := MarshalToString(any.cache)
-		any.err = err
-		return str
-	}
-}
-
-func (any *arrayAny) fillCacheUntil(idx int) Any {
-	if idx < len(any.cache) {
-		return any.cache[idx]
-	} else {
-		for i := len(any.cache); i < any.val.Len(); i++ {
-			element := Wrap(any.val.Index(i).Interface())
-			any.cache = append(any.cache, element)
-			if idx == i {
-				return element
-			}
-		}
-		return nil
-	}
-}
-
-func (any *arrayAny) fillCache() {
-	any.cache = make([]Any, any.val.Len())
-	for i := 0; i < any.val.Len(); i++ {
-		any.cache[i] = Wrap(any.val.Index(i).Interface())
-	}
+	str, _ := MarshalToString(any.val.Interface())
+	return str
 }
 
 func (any *arrayAny) Get(path ...interface{}) Any {
 	if len(path) == 0 {
 		return any
 	}
-	var element Any
 	switch firstPath := path[0].(type) {
 	case int:
-		element = any.fillCacheUntil(firstPath)
-		if element == nil {
-			element = &invalidAny{baseAny{}, fmt.Errorf("%v not found in %v", firstPath, any.cache)}
+		if firstPath < 0 || firstPath >= any.val.Len() {
+			return newInvalidAny(path)
 		}
+		return Wrap(any.val.Index(firstPath).Interface())
 	case int32:
 		if '*' == firstPath {
-			any.fillCache()
-			mappedAll := make([]Any, 0, len(any.cache))
-			for _, element := range any.cache {
-				mapped := element.Get(path[1:]...)
+			mappedAll := make([]Any, 0)
+			for i := 0; i < any.val.Len(); i++ {
+				mapped := Wrap(any.val.Index(i).Interface()).Get(path[1:]...)
 				if mapped.ValueType() != Invalid {
 					mappedAll = append(mappedAll, mapped)
 				}
 			}
 			return wrapArray(mappedAll)
 		} else {
-			element = &invalidAny{baseAny{}, fmt.Errorf("%v not found in %v", path[0], any.cache)}
+			return newInvalidAny(path)
 		}
 	default:
-		element = &invalidAny{baseAny{}, fmt.Errorf("%v not found in %v", path[0], any.cache)}
-	}
-	if len(path) == 1 {
-		return element
-	} else {
-		return element.Get(path[1:]...)
+		return newInvalidAny(path)
 	}
 }
 
 func (any *arrayAny) Size() int {
-	any.fillCache()
-	return len(any.cache)
-}
-
-func (any *arrayAny) IterateArray() (func() (Any, bool), bool) {
-	if any.val.Len() == 0 {
-		return nil, false
-	}
-	i := 0
-	return func() (Any, bool) {
-		if i == any.val.Len() {
-			return nil, false
-		}
-		if i == len(any.cache) {
-			any.cache = append(any.cache, Wrap(any.val.Index(i).Interface()))
-		}
-		val := any.cache[i]
-		i++
-		return val, i != any.val.Len()
-	}, true
+	return any.val.Len()
 }
 
 func (any *arrayAny) GetArray() []Any {
-	any.fillCache()
-	return any.cache
+	elements := make([]Any, any.val.Len())
+	for i := 0; i < any.val.Len(); i++ {
+		elements[i] = Wrap(any.val.Index(i).Interface())
+	}
+	return elements
 }
 
 func (any *arrayAny) WriteTo(stream *Stream) {
-	if len(any.cache) == 0 {
-		// nothing has been parsed yet
-		stream.WriteVal(any.val)
-	} else {
-		any.fillCache()
-		stream.WriteVal(any.cache)
-	}
+	stream.WriteVal(any.val)
 }
 
 func (any *arrayAny) GetInterface() interface{} {
-	any.fillCache()
-	return any.cache
+	return any.val.Interface()
 }

+ 9 - 18
feature_any_string.go

@@ -6,7 +6,6 @@ import (
 
 type stringAny struct {
 	baseAny
-	err error
 	val string
 }
 
@@ -19,7 +18,7 @@ func (any *stringAny) ValueType() ValueType {
 }
 
 func (any *stringAny) LastError() error {
-	return any.err
+	return nil
 }
 
 func (any *stringAny) ToBool() bool {
@@ -38,50 +37,42 @@ func (any *stringAny) ToBool() bool {
 }
 
 func (any *stringAny) ToInt() int {
-	parsed, err := strconv.ParseInt(any.val, 10, 64)
-	any.err = err
+	parsed, _ := strconv.ParseInt(any.val, 10, 64)
 	return int(parsed)
 }
 
 func (any *stringAny) ToInt32() int32 {
-	parsed, err := strconv.ParseInt(any.val, 10, 32)
-	any.err = err
+	parsed, _ := strconv.ParseInt(any.val, 10, 32)
 	return int32(parsed)
 }
 
 func (any *stringAny) ToInt64() int64 {
-	parsed, err := strconv.ParseInt(any.val, 10, 64)
-	any.err = err
+	parsed, _ := strconv.ParseInt(any.val, 10, 64)
 	return parsed
 }
 
 func (any *stringAny) ToUint() uint {
-	parsed, err := strconv.ParseUint(any.val, 10, 64)
-	any.err = err
+	parsed, _ := strconv.ParseUint(any.val, 10, 64)
 	return uint(parsed)
 }
 
 func (any *stringAny) ToUint32() uint32 {
-	parsed, err := strconv.ParseUint(any.val, 10, 32)
-	any.err = err
+	parsed, _ := strconv.ParseUint(any.val, 10, 32)
 	return uint32(parsed)
 }
 
 func (any *stringAny) ToUint64() uint64 {
-	parsed, err := strconv.ParseUint(any.val, 10, 64)
-	any.err = err
+	parsed, _ := strconv.ParseUint(any.val, 10, 64)
 	return parsed
 }
 
 func (any *stringAny) ToFloat32() float32 {
-	parsed, err := strconv.ParseFloat(any.val, 32)
-	any.err = err
+	parsed, _ := strconv.ParseFloat(any.val, 32)
 	return float32(parsed)
 }
 
 func (any *stringAny) ToFloat64() float64 {
-	parsed, err := strconv.ParseFloat(any.val, 64)
-	any.err = err
+	parsed, _ := strconv.ParseFloat(any.val, 64)
 	return parsed
 }
 

+ 6 - 1
jsoniter_any_array_test.go

@@ -60,6 +60,8 @@ func Test_array_lazy_any_get_all(t *testing.T) {
 	should := require.New(t)
 	any := Get([]byte("[[1],[2],[3,4]]"))
 	should.Equal("[1,2,3]", any.Get('*', 0).ToString())
+	any = Get([]byte("[[[1],[2],[3,4]]]"), 0, '*', 0)
+	should.Equal("[1,2,3]", any.ToString())
 }
 
 func Test_array_wrapper_any_get_all(t *testing.T) {
@@ -70,6 +72,9 @@ func Test_array_wrapper_any_get_all(t *testing.T) {
 		{5, 6},
 	})
 	should.Equal("[1,3,5]", any.Get('*', 0).ToString())
+	should.Equal(Array, any.ValueType())
+	should.True(any.ToBool())
+	should.Equal(1, any.Get(0, 0).ToInt())
 }
 
 func Test_array_lazy_any_get_invalid(t *testing.T) {
@@ -85,4 +90,4 @@ func Test_invalid_array(t *testing.T) {
 	should := require.New(t)
 	any := Get([]byte("["), 0)
 	should.Equal(Invalid, any.ValueType())
-}
+}