From 3ffa5af7ec3b1af048c8dd9a96534f91a647ae05 Mon Sep 17 00:00:00 2001 From: Tao Wen Date: Sun, 18 Jun 2017 23:18:32 +0800 Subject: [PATCH] #61 remove internal buffer from mapAny --- feature_any_object.go | 157 ++++++++---------------------------------- 1 file changed, 28 insertions(+), 129 deletions(-) diff --git a/feature_any_object.go b/feature_any_object.go index 8fbb6f9..ba4b37c 100644 --- a/feature_any_object.go +++ b/feature_any_object.go @@ -1,7 +1,6 @@ package jsoniter import ( - "fmt" "reflect" "unsafe" ) @@ -193,51 +192,6 @@ func (any *objectAny) ValueType() ValueType { func (any *objectAny) Parse() *Iterator { return nil } -// -//func (any *objectAny) fillCacheUntil(target string) Any { -// if any.cache == nil { -// any.cache = map[string]Any{} -// } -// element, found := any.cache[target] -// if found { -// return element -// } -// for i := len(any.cache); i < any.val.NumField(); i++ { -// field := any.val.Field(i) -// fieldName := any.val.Type().Field(i).Name -// var element Any -// if field.CanInterface() { -// element = Wrap(field.Interface()) -// } else { -// element = &invalidAny{baseAny{}, fmt.Errorf("%v not found in %v", fieldName, any.cache)} -// } -// any.cache[fieldName] = element -// if fieldName == target { -// return element -// } -// } -// return nil -//} -// -//func (any *objectAny) fillCache() { -// if any.cache == nil { -// any.cache = map[string]Any{} -// } -// if len(any.cache) == any.val.NumField() { -// return -// } -// for i := 0; i < any.val.NumField(); i++ { -// field := any.val.Field(i) -// fieldName := any.val.Type().Field(i).Name -// var element Any -// if field.CanInterface() { -// element = Wrap(field.Interface()) -// } else { -// element = &invalidAny{baseAny{}, fmt.Errorf("%v not found in %v", fieldName, any.cache)} -// } -// any.cache[fieldName] = element -// } -//} func (any *objectAny) LastError() error { return any.err @@ -375,12 +329,11 @@ func (any *objectAny) GetInterface() interface{} { type mapAny struct { baseAny err error - cache map[string]Any val reflect.Value } func wrapMap(val interface{}) *mapAny { - return &mapAny{baseAny{}, nil, nil, reflect.ValueOf(val)} + return &mapAny{baseAny{}, nil, reflect.ValueOf(val)} } func (any *mapAny) ValueType() ValueType { @@ -391,43 +344,6 @@ func (any *mapAny) Parse() *Iterator { return nil } -func (any *mapAny) fillCacheUntil(target string) Any { - if any.cache == nil { - any.cache = map[string]Any{} - } - element, found := any.cache[target] - if found { - return element - } - for _, key := range any.val.MapKeys() { - keyAsStr := key.String() - _, found := any.cache[keyAsStr] - if found { - continue - } - element := Wrap(any.val.MapIndex(key).Interface()) - any.cache[keyAsStr] = element - if keyAsStr == target { - return element - } - } - return nil -} - -func (any *mapAny) fillCache() { - if any.cache == nil { - any.cache = map[string]Any{} - } - if len(any.cache) == any.val.Len() { - return - } - for _, key := range any.val.MapKeys() { - keyAsStr := key.String() - element := Wrap(any.val.MapIndex(key).Interface()) - any.cache[keyAsStr] = element - } -} - func (any *mapAny) LastError() error { return any.err } @@ -493,83 +409,66 @@ func (any *mapAny) ToFloat64() float64 { } func (any *mapAny) ToString() string { - if len(any.cache) == 0 { - str, err := MarshalToString(any.val.Interface()) - any.err = err - return str - } else { - any.fillCache() - str, err := MarshalToString(any.cache) - any.err = err - return str - } + str, err := MarshalToString(any.val.Interface()) + any.err = err + return str } func (any *mapAny) Get(path ...interface{}) Any { if len(path) == 0 { return any } - var element Any switch firstPath := path[0].(type) { - case string: - element = any.fillCacheUntil(firstPath) - if element == nil { - element = &invalidAny{baseAny{}, fmt.Errorf("%v not found in %v", firstPath, any.cache)} - } case int32: if '*' == firstPath { - any.fillCache() mappedAll := map[string]Any{} - for key, value := range any.cache { - mapped := value.Get(path[1:]...) + for _, key := range any.val.MapKeys() { + keyAsStr := key.String() + element := Wrap(any.val.MapIndex(key).Interface()) + mapped := element.Get(path[1:]...) if mapped.ValueType() != Invalid { - mappedAll[key] = mapped + mappedAll[keyAsStr] = mapped } } return wrapMap(mappedAll) } else { - element = &invalidAny{baseAny{}, fmt.Errorf("%v not found in %v", firstPath, any.cache)} + return newInvalidAny(path) } default: - element = &invalidAny{baseAny{}, fmt.Errorf("%v not found in %v", firstPath, any.cache)} - } - if len(path) == 1 { - return element - } else { - return element.Get(path[1:]...) + value := any.val.MapIndex(reflect.ValueOf(firstPath)) + if !value.IsValid() { + return newInvalidAny(path) + } + return Wrap(value.Interface()) } } func (any *mapAny) Keys() []string { - any.fillCache() - keys := make([]string, 0, len(any.cache)) - for key := range any.cache { - keys = append(keys, key) + keys := make([]string, 0, any.val.Len()) + for _, key := range any.val.MapKeys() { + keys = append(keys, key.String()) } return keys } func (any *mapAny) Size() int { - any.fillCache() - return len(any.cache) + return any.val.Len() } func (any *mapAny) GetObject() map[string]Any { - any.fillCache() - return any.cache + object := map[string]Any{} + for _, key := range any.val.MapKeys() { + keyAsStr := key.String() + element := Wrap(any.val.MapIndex(key).Interface()) + object[keyAsStr] = element + } + return object } func (any *mapAny) 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 *mapAny) GetInterface() interface{} { - any.fillCache() - return any.cache + return any.val.Interface() }