diff options
Diffstat (limited to 'vendor/github.com/bytedance/sonic/ast')
-rw-r--r-- | vendor/github.com/bytedance/sonic/ast/api_amd64.go | 26 | ||||
-rw-r--r-- | vendor/github.com/bytedance/sonic/ast/api_compat.go | 37 | ||||
-rw-r--r-- | vendor/github.com/bytedance/sonic/ast/buffer.go | 150 | ||||
-rw-r--r-- | vendor/github.com/bytedance/sonic/ast/encode.go | 32 | ||||
-rw-r--r-- | vendor/github.com/bytedance/sonic/ast/iterator.go | 14 | ||||
-rw-r--r-- | vendor/github.com/bytedance/sonic/ast/node.go | 255 | ||||
-rw-r--r-- | vendor/github.com/bytedance/sonic/ast/parser.go | 8 | ||||
-rw-r--r-- | vendor/github.com/bytedance/sonic/ast/search.go | 50 |
8 files changed, 398 insertions, 174 deletions
diff --git a/vendor/github.com/bytedance/sonic/ast/api_amd64.go b/vendor/github.com/bytedance/sonic/ast/api_amd64.go index da6738efd..fa4375630 100644 --- a/vendor/github.com/bytedance/sonic/ast/api_amd64.go +++ b/vendor/github.com/bytedance/sonic/ast/api_amd64.go @@ -1,4 +1,4 @@ -// +build amd64,go1.16,!go1.22 +// +build amd64,go1.16,!go1.23 /* * Copyright 2022 ByteDance Inc. @@ -131,27 +131,3 @@ func (self *Parser) getByPath(path ...interface{}) (int, types.ParsingError) { } return start, 0 } - -func (self *Searcher) GetByPath(path ...interface{}) (Node, error) { - var err types.ParsingError - var start int - - self.parser.p = 0 - start, err = self.parser.getByPath(path...) - if err != 0 { - // for compatibility with old version - if err == types.ERR_NOT_FOUND { - return Node{}, ErrNotExist - } - if err == types.ERR_UNSUPPORT_TYPE { - panic("path must be either int(>=0) or string") - } - return Node{}, self.parser.syntaxError(err) - } - - t := switchRawType(self.parser.s[start]) - if t == _V_NONE { - return Node{}, self.parser.ExportError(err) - } - return newRawNode(self.parser.s[start:self.parser.p], t), nil -} diff --git a/vendor/github.com/bytedance/sonic/ast/api_compat.go b/vendor/github.com/bytedance/sonic/ast/api_compat.go index 7b475eb61..9244e76e1 100644 --- a/vendor/github.com/bytedance/sonic/ast/api_compat.go +++ b/vendor/github.com/bytedance/sonic/ast/api_compat.go @@ -1,4 +1,4 @@ -// +build !amd64 !go1.16 go1.22 +// +build !amd64 !go1.16 go1.23 /* * Copyright 2022 ByteDance Inc. @@ -21,14 +21,13 @@ package ast import ( `encoding/base64` `encoding/json` - `fmt` `github.com/bytedance/sonic/internal/native/types` `github.com/bytedance/sonic/internal/rt` ) func init() { - println("WARNING: sonic only supports Go1.16~1.20 && CPU amd64, but your environment is not suitable") + println("WARNING: sonic only supports Go1.16~1.22 && CPU amd64, but your environment is not suitable") } func quote(buf *[]byte, val string) { @@ -88,37 +87,25 @@ func (self *Node) encodeInterface(buf *[]byte) error { return nil } -func (self *Searcher) GetByPath(path ...interface{}) (Node, error) { - self.parser.p = 0 - +func (self *Parser) getByPath(path ...interface{}) (int, types.ParsingError) { var err types.ParsingError for _, p := range path { if idx, ok := p.(int); ok && idx >= 0 { - if err = self.parser.searchIndex(idx); err != 0 { - return Node{}, self.parser.ExportError(err) + if err = self.searchIndex(idx); err != 0 { + return -1, err } } else if key, ok := p.(string); ok { - if err = self.parser.searchKey(key); err != 0 { - return Node{}, self.parser.ExportError(err) + if err = self.searchKey(key); err != 0 { + return -1, err } } else { panic("path must be either int(>=0) or string") } } - var start = self.parser.p - if start, err = self.parser.skip(); err != 0 { - return Node{}, self.parser.ExportError(err) - } - ns := len(self.parser.s) - if self.parser.p > ns || start >= ns || start>=self.parser.p { - return Node{}, fmt.Errorf("skip %d char out of json boundary", start) - } - - t := switchRawType(self.parser.s[start]) - if t == _V_NONE { - return Node{}, self.parser.ExportError(err) + var start int + if start, err = self.skip(); err != 0 { + return -1, err } - - return newRawNode(self.parser.s[start:self.parser.p], t), nil -}
\ No newline at end of file + return start, 0 +} diff --git a/vendor/github.com/bytedance/sonic/ast/buffer.go b/vendor/github.com/bytedance/sonic/ast/buffer.go index 93f4ff47a..bccbf4814 100644 --- a/vendor/github.com/bytedance/sonic/ast/buffer.go +++ b/vendor/github.com/bytedance/sonic/ast/buffer.go @@ -58,29 +58,89 @@ func (self *linkedNodes) At(i int) (*Node) { return nil } -func (self *linkedNodes) Add(v Node) { - if self.size < _DEFAULT_NODE_CAP { - self.head[self.size] = v - self.size++ +func (self *linkedNodes) MoveOne(source int, target int) { + if source == target { return } + if source < 0 || source >= self.size || target < 0 || target >= self.size { + return + } + // reserve source + n := *self.At(source) + if source < target { + // move every element (source,target] one step back + for i:=source; i<target; i++ { + *self.At(i) = *self.At(i+1) + } + } else { + // move every element [target,source) one step forward + for i:=source; i>target; i-- { + *self.At(i) = *self.At(i-1) + } + } + // set target + *self.At(target) = n +} + +func (self *linkedNodes) Pop() { + if self == nil || self.size == 0 { + return + } + self.Set(self.size-1, Node{}) + self.size-- +} + +func (self *linkedPairs) Pop() { + if self == nil || self.size == 0 { + return + } + self.Set(self.size-1, Pair{}) + self.size-- +} + +func (self *linkedNodes) Push(v Node) { + self.Set(self.size, v) +} - a, b, c := self.size/_DEFAULT_NODE_CAP-1 , self.size%_DEFAULT_NODE_CAP, cap(self.tail) - if a - c >= 0 { +func (self *linkedNodes) Set(i int, v Node) { + if i < _DEFAULT_NODE_CAP { + self.head[i] = v + if self.size <= i { + self.size = i+1 + } + return + } + a, b := i/_DEFAULT_NODE_CAP-1, i%_DEFAULT_NODE_CAP + if a < 0 { + self.head[b] = v + } else { + self.growTailLength(a+1) + var n = &self.tail[a] + if *n == nil { + *n = new(nodeChunk) + } + (*n)[b] = v + } + if self.size <= i { + self.size = i+1 + } +} + +func (self *linkedNodes) growTailLength(l int) { + if l <= len(self.tail) { + return + } + c := cap(self.tail) + for c < l { c += 1 + c>>_APPEND_GROW_SHIFT - tmp := make([]*nodeChunk, a + 1, c) - copy(tmp, self.tail) - self.tail = tmp - } else if a >= len(self.tail) { - self.tail = self.tail[:a+1] } - - var n = &self.tail[a] - if *n == nil { - *n = new(nodeChunk) + if c == cap(self.tail) { + self.tail = self.tail[:l] + return } - (*n)[b] = v - self.size++ + tmp := make([]*nodeChunk, l, c) + copy(tmp, self.tail) + self.tail = tmp } func (self *linkedNodes) ToSlice(con []Node) { @@ -169,29 +229,49 @@ func (self *linkedPairs) At(i int) *Pair { return nil } -func (self *linkedPairs) Add(v Pair) { - if self.size < _DEFAULT_NODE_CAP { - self.head[self.size] = v - self.size++ +func (self *linkedPairs) Push(v Pair) { + self.Set(self.size, v) +} + +func (self *linkedPairs) Set(i int, v Pair) { + if i < _DEFAULT_NODE_CAP { + self.head[i] = v + if self.size <= i { + self.size = i+1 + } return } + a, b := i/_DEFAULT_NODE_CAP-1, i%_DEFAULT_NODE_CAP + if a < 0 { + self.head[b] = v + } else { + self.growTailLength(a+1) + var n = &self.tail[a] + if *n == nil { + *n = new(pairChunk) + } + (*n)[b] = v + } + if self.size <= i { + self.size = i+1 + } +} - a, b, c := self.size/_DEFAULT_NODE_CAP-1 , self.size%_DEFAULT_NODE_CAP, cap(self.tail) - if a - c >= 0 { +func (self *linkedPairs) growTailLength(l int) { + if l <= len(self.tail) { + return + } + c := cap(self.tail) + for c < l { c += 1 + c>>_APPEND_GROW_SHIFT - tmp := make([]*pairChunk, a + 1, c) - copy(tmp, self.tail) - self.tail = tmp - } else if a >= len(self.tail) { - self.tail = self.tail[:a+1] } - - var n = &self.tail[a] - if *n == nil { - *n = new(pairChunk) + if c == cap(self.tail) { + self.tail = self.tail[:l] + return } - (*n)[b] = v - self.size++ + tmp := make([]*pairChunk, l, c) + copy(tmp, self.tail) + self.tail = tmp } // linear search @@ -271,7 +351,7 @@ func (self *linkedPairs) Swap(i, j int) { } func (self *linkedPairs) Sort() { - sort.Sort(self) + sort.Stable(self) } // Compare two strings from the pos d. diff --git a/vendor/github.com/bytedance/sonic/ast/encode.go b/vendor/github.com/bytedance/sonic/ast/encode.go index 263ae5a9d..956809c2c 100644 --- a/vendor/github.com/bytedance/sonic/ast/encode.go +++ b/vendor/github.com/bytedance/sonic/ast/encode.go @@ -193,20 +193,9 @@ func (self *Node) encodeArray(buf *[]byte) error { *buf = append(*buf, '[') - var s = (*linkedNodes)(self.p) var started bool - if nb > 0 { - n := s.At(0) - if n.Exists() { - if err := n.encode(buf); err != nil { - return err - } - started = true - } - } - - for i := 1; i < nb; i++ { - n := s.At(i) + for i := 0; i < nb; i++ { + n := self.nodeAt(i) if !n.Exists() { continue } @@ -250,21 +239,10 @@ func (self *Node) encodeObject(buf *[]byte) error { *buf = append(*buf, '{') - var s = (*linkedPairs)(self.p) var started bool - if nb > 0 { - n := s.At(0) - if n.Value.Exists() { - if err := n.encode(buf); err != nil { - return err - } - started = true - } - } - - for i := 1; i < nb; i++ { - n := s.At(i) - if !n.Value.Exists() { + for i := 0; i < nb; i++ { + n := self.pairAt(i) + if n == nil || !n.Value.Exists() { continue } if started { diff --git a/vendor/github.com/bytedance/sonic/ast/iterator.go b/vendor/github.com/bytedance/sonic/ast/iterator.go index 3c4187a9c..64e1e5a90 100644 --- a/vendor/github.com/bytedance/sonic/ast/iterator.go +++ b/vendor/github.com/bytedance/sonic/ast/iterator.go @@ -32,7 +32,11 @@ func (self *Node) Values() (ListIterator, error) { if err := self.should(types.V_ARRAY, "an array"); err != nil { return ListIterator{}, err } - return ListIterator{Iterator{p: self}}, nil + return self.values(), nil +} + +func (self *Node) values() ListIterator { + return ListIterator{Iterator{p: self}} } // Properties returns iterator for object's children traversal @@ -40,7 +44,11 @@ func (self *Node) Properties() (ObjectIterator, error) { if err := self.should(types.V_OBJECT, "an object"); err != nil { return ObjectIterator{}, err } - return ObjectIterator{Iterator{p: self}}, nil + return self.properties(), nil +} + +func (self *Node) properties() ObjectIterator { + return ObjectIterator{Iterator{p: self}} } type Iterator struct { @@ -114,7 +122,7 @@ next_start: } else { n := self.p.pairAt(self.i) self.i++ - if !n.Value.Exists() { + if n == nil || !n.Value.Exists() { goto next_start } return n diff --git a/vendor/github.com/bytedance/sonic/ast/node.go b/vendor/github.com/bytedance/sonic/ast/node.go index 990908ddd..9637659b1 100644 --- a/vendor/github.com/bytedance/sonic/ast/node.go +++ b/vendor/github.com/bytedance/sonic/ast/node.go @@ -491,7 +491,6 @@ func (self *Node) StrictFloat64() (float64, error) { // Len returns children count of a array|object|string node // WARN: For partially loaded node, it also works but only counts the parsed children -// WARN: For ARRAY|OBJECT nodes which has been conducted `UnsetXX()`, its length WON'T change func (self *Node) Len() (int, error) { if err := self.checkRaw(); err != nil { return 0, err @@ -534,10 +533,12 @@ func (self *Node) Set(key string, node Node) (bool, error) { if err := node.Check(); err != nil { return false, err } - + if self.t == _V_NONE || self.t == types.V_NULL { *self = NewObject([]Pair{{key, node}}) return false, nil + } else if self.itype() != types.V_OBJECT { + return false, ErrUnsupportType } p := self.Get(key) @@ -548,7 +549,7 @@ func (self *Node) Set(key string, node Node) (bool, error) { *self = newObject(new(linkedPairs)) } s := (*linkedPairs)(self.p) - s.Add(Pair{key, node}) + s.Push(Pair{key, node}) self.l++ return false, nil @@ -565,20 +566,22 @@ func (self *Node) SetAny(key string, val interface{}) (bool, error) { return self.Set(key, NewAny(val)) } -// Unset RESET the node of given key under object parent, and reports if the key has existed. -// WARN: After conducting `UnsetXX()`, the node's length WON'T change +// Unset REMOVE (soft) the node of given key under object parent, and reports if the key has existed. func (self *Node) Unset(key string) (bool, error) { if err := self.should(types.V_OBJECT, "an object"); err != nil { return false, err } + // NOTICE: must get acurate length before deduct + if err := self.skipAllKey(); err != nil { + return false, err + } p, i := self.skipKey(key) if !p.Exists() { return false, nil } else if err := p.Check(); err != nil { return false, err } - - self.removePair(i) + self.removePairAt(i) return true, nil } @@ -614,22 +617,28 @@ func (self *Node) SetAnyByIndex(index int, val interface{}) (bool, error) { return self.SetByIndex(index, NewAny(val)) } -// UnsetByIndex remove the node of given index -// WARN: After conducting `UnsetXX()`, the node's length WON'T change +// UnsetByIndex REOMVE (softly) the node of given index. +// +// WARN: this will change address of elements, which is a dangerous action. +// Use Unset() for object or Pop() for array instead. func (self *Node) UnsetByIndex(index int) (bool, error) { - if err := self.Check(); err != nil { + if err := self.checkRaw(); err != nil { return false, err } var p *Node it := self.itype() + if it == types.V_ARRAY { - p = self.Index(index) - }else if it == types.V_OBJECT { - if err := self.checkRaw(); err != nil { + if err := self.skipAllIndex(); err != nil { return false, err } - pr := self.skipIndexPair(index) + p = self.nodeAt(index) + } else if it == types.V_OBJECT { + if err := self.skipAllKey(); err != nil { + return false, err + } + pr := self.pairAt(index) if pr == nil { return false, ErrNotExist } @@ -642,6 +651,12 @@ func (self *Node) UnsetByIndex(index int) (bool, error) { return false, ErrNotExist } + // last elem + if index == self.len() - 1 { + return true, self.Pop() + } + + // not last elem, self.len() change but linked-chunk not change if it == types.V_ARRAY { self.removeNode(index) }else if it == types.V_OBJECT { @@ -665,16 +680,101 @@ func (self *Node) Add(node Node) error { if err := self.should(types.V_ARRAY, "an array"); err != nil { return err } + s, err := self.unsafeArray() if err != nil { return err } - s.Add(node) + // Notice: array won't have unset node in tail + s.Push(node) self.l++ return nil } +// Pop remove the last child of the V_Array or V_Object node. +func (self *Node) Pop() error { + if err := self.checkRaw(); err != nil { + return err + } + + if it := self.itype(); it == types.V_ARRAY { + s, err := self.unsafeArray() + if err != nil { + return err + } + // remove tail unset nodes + for i := s.Len()-1; i >= 0; i-- { + if s.At(i).Exists() { + s.Pop() + self.l-- + break + } + s.Pop() + } + + } else if it == types.V_OBJECT { + s, err := self.unsafeMap() + if err != nil { + return err + } + // remove tail unset nodes + for i := s.Len()-1; i >= 0; i-- { + if p := s.At(i); p != nil && p.Value.Exists() { + s.Pop() + self.l-- + break + } + s.Pop() + } + + } else { + return ErrUnsupportType + } + + return nil +} + +// Move moves the child at src index to dst index, +// meanwhile slides sliblings from src+1 to dst. +// +// WARN: this will change address of elements, which is a dangerous action. +func (self *Node) Move(dst, src int) error { + if err := self.should(types.V_ARRAY, "an array"); err != nil { + return err + } + + s, err := self.unsafeArray() + if err != nil { + return err + } + + // check if any unset node exists + if l := s.Len(); self.len() != l { + di, si := dst, src + // find real pos of src and dst + for i := 0; i < l; i++ { + if s.At(i).Exists() { + di-- + si-- + } + if di == -1 { + dst = i + di-- + } + if si == -1 { + src = i + si-- + } + if di == -2 && si == -2 { + break + } + } + } + + s.MoveOne(src, dst) + return nil +} // SetAny wraps val with V_ANY node, and Add() the node. func (self *Node) AddAny(val interface{}) error { @@ -721,8 +821,6 @@ func (self *Node) Get(key string) *Node { // Index indexies node at given idx, // node type CAN be either V_OBJECT or V_ARRAY -// WARN: After conducting `UnsetXX()`, the node's length WON'T change, -// thus its children's indexing WON'T change too func (self *Node) Index(idx int) *Node { if err := self.checkRaw(); err != nil { return unwrapError(err) @@ -746,8 +844,6 @@ func (self *Node) Index(idx int) *Node { // IndexPair indexies pair at given idx, // node type MUST be either V_OBJECT -// WARN: After conducting `UnsetXX()`, the node's length WON'T change, -// thus its children's indexing WON'T change too func (self *Node) IndexPair(idx int) *Pair { if err := self.should(types.V_OBJECT, "an object"); err != nil { return nil @@ -755,19 +851,30 @@ func (self *Node) IndexPair(idx int) *Pair { return self.skipIndexPair(idx) } +func (self *Node) indexOrGet(idx int, key string) (*Node, int) { + if err := self.should(types.V_OBJECT, "an object"); err != nil { + return unwrapError(err), idx + } + + pr := self.skipIndexPair(idx) + if pr != nil && pr.Key == key { + return &pr.Value, idx + } + + return self.skipKey(key) +} + // IndexOrGet firstly use idx to index a value and check if its key matches // If not, then use the key to search value func (self *Node) IndexOrGet(idx int, key string) *Node { - if err := self.should(types.V_OBJECT, "an object"); err != nil { - return unwrapError(err) - } + node, _ := self.indexOrGet(idx, key) + return node +} - pr := self.skipIndexPair(idx) - if pr != nil && pr.Key == key { - return &pr.Value - } - n, _ := self.skipKey(key) - return n +// IndexOrGetWithIdx attempts to retrieve a node by index and key, returning the node and its correct index. +// If the key does not match at the given index, it searches by key and returns the node with its updated index. +func (self *Node) IndexOrGetWithIdx(idx int, key string) (*Node, int) { + return self.indexOrGet(idx, key) } /** Generic Value Converters **/ @@ -864,7 +971,7 @@ func (self *Node) SortKeys(recurse bool) error { } if self.itype() == types.V_OBJECT { return self.sortKeys(recurse) - } else { + } else if self.itype() == types.V_ARRAY { var err error err2 := self.ForEach(func(path Sequence, node *Node) bool { it := node.itype() @@ -880,10 +987,16 @@ func (self *Node) SortKeys(recurse bool) error { return err } return err2 + } else { + return nil } } func (self *Node) sortKeys(recurse bool) (err error) { + // check raw node first + if err := self.checkRaw(); err != nil { + return err + } ps, err := self.unsafeMap() if err != nil { return err @@ -1172,6 +1285,19 @@ func (self *Node) nodeAt(i int) *Node { p = &stack.v } else { p = (*linkedNodes)(self.p) + if l := p.Len(); l != self.len() { + // some nodes got unset, iterate to skip them + for j:=0; j<l; j++ { + v := p.At(j) + if v.Exists() { + i-- + } + if i < 0 { + return v + } + } + return nil + } } return p.At(i) } @@ -1183,6 +1309,19 @@ func (self *Node) pairAt(i int) *Pair { p = &stack.v } else { p = (*linkedPairs)(self.p) + if l := p.Len(); l != self.len() { + // some nodes got unset, iterate to skip them + for j:=0; j<l; j++ { + v := p.At(j) + if v != nil && v.Value.Exists() { + i-- + } + if i < 0 { + return v + } + } + return nil + } } return p.At(i) } @@ -1334,8 +1473,8 @@ func (self *Node) removeNode(i int) { return } *node = Node{} - // NOTICE: for consistency with linkedNodes, we DOSEN'T reduce size here - // self.l-- + // NOTICE: not be consistent with linkedNode.Len() + self.l-- } func (self *Node) removePair(i int) { @@ -1344,8 +1483,18 @@ func (self *Node) removePair(i int) { return } *last = Pair{} - // NOTICE: for consistency with linkedNodes, we DOSEN'T reduce size here - // self.l-- + // NOTICE: should be consistent with linkedPair.Len() + self.l-- +} + +func (self *Node) removePairAt(i int) { + p := (*linkedPairs)(self.p).At(i) + if p == nil { + return + } + *p = Pair{} + // NOTICE: should be consistent with linkedPair.Len() + self.l-- } func (self *Node) toGenericArray() ([]interface{}, error) { @@ -1353,17 +1502,16 @@ func (self *Node) toGenericArray() ([]interface{}, error) { if nb == 0 { return []interface{}{}, nil } - ret := make([]interface{}, nb) + ret := make([]interface{}, 0, nb) /* convert each item */ - var s = (*linkedNodes)(self.p) - for i := 0; i < nb; i++ { - p := s.At(i) - x, err := p.Interface() + it := self.values() + for v := it.next(); v != nil; v = it.next() { + vv, err := v.Interface() if err != nil { return nil, err } - ret[i] = x + ret = append(ret, vv) } /* all done */ @@ -1375,17 +1523,16 @@ func (self *Node) toGenericArrayUseNumber() ([]interface{}, error) { if nb == 0 { return []interface{}{}, nil } - ret := make([]interface{}, nb) + ret := make([]interface{}, 0, nb) /* convert each item */ - var s = (*linkedNodes)(self.p) - for i := 0; i < nb; i++ { - p := s.At(i) - x, err := p.InterfaceUseNumber() + it := self.values() + for v := it.next(); v != nil; v = it.next() { + vv, err := v.InterfaceUseNumber() if err != nil { return nil, err } - ret[i] = x + ret = append(ret, vv) } /* all done */ @@ -1413,14 +1560,13 @@ func (self *Node) toGenericObject() (map[string]interface{}, error) { ret := make(map[string]interface{}, nb) /* convert each item */ - var s = (*linkedPairs)(self.p) - for i := 0; i < nb; i++ { - p := s.At(i) - x, err := p.Value.Interface() + it := self.properties() + for v := it.next(); v != nil; v = it.next() { + vv, err := v.Value.Interface() if err != nil { return nil, err } - ret[p.Key] = x + ret[v.Key] = vv } /* all done */ @@ -1436,14 +1582,13 @@ func (self *Node) toGenericObjectUseNumber() (map[string]interface{}, error) { ret := make(map[string]interface{}, nb) /* convert each item */ - var s = (*linkedPairs)(self.p) - for i := 0; i < nb; i++ { - p := s.At(i) - x, err := p.Value.InterfaceUseNumber() + it := self.properties() + for v := it.next(); v != nil; v = it.next() { + vv, err := v.Value.InterfaceUseNumber() if err != nil { return nil, err } - ret[p.Key] = x + ret[v.Key] = vv } /* all done */ diff --git a/vendor/github.com/bytedance/sonic/ast/parser.go b/vendor/github.com/bytedance/sonic/ast/parser.go index cb16f20bb..3e5309c19 100644 --- a/vendor/github.com/bytedance/sonic/ast/parser.go +++ b/vendor/github.com/bytedance/sonic/ast/parser.go @@ -157,7 +157,7 @@ func (self *Parser) decodeArray(ret *linkedNodes) (Node, types.ParsingError) { } /* add the value to result */ - ret.Add(val) + ret.Push(val) self.p = self.lspace(self.p) /* check for EOF */ @@ -244,7 +244,7 @@ func (self *Parser) decodeObject(ret *linkedPairs) (Node, types.ParsingError) { /* add the value to result */ // FIXME: ret's address may change here, thus previous referred node in ret may be invalid !! - ret.Add(Pair{Key: key, Value: val}) + ret.Push(Pair{Key: key, Value: val}) self.p = self.lspace(self.p) /* check for EOF */ @@ -475,7 +475,7 @@ func (self *Node) skipNextNode() *Node { } /* add the value to result */ - ret.Add(val) + ret.Push(val) self.l++ parser.p = parser.lspace(parser.p) @@ -558,7 +558,7 @@ func (self *Node) skipNextPair() (*Pair) { } /* add the value to result */ - ret.Add(Pair{Key: key, Value: val}) + ret.Push(Pair{Key: key, Value: val}) self.l++ parser.p = parser.lspace(parser.p) diff --git a/vendor/github.com/bytedance/sonic/ast/search.go b/vendor/github.com/bytedance/sonic/ast/search.go index bb6fceaa7..7108e7ea6 100644 --- a/vendor/github.com/bytedance/sonic/ast/search.go +++ b/vendor/github.com/bytedance/sonic/ast/search.go @@ -16,6 +16,11 @@ package ast +import ( + `github.com/bytedance/sonic/internal/rt` + `github.com/bytedance/sonic/internal/native/types` +) + type Searcher struct { parser Parser } @@ -28,3 +33,48 @@ func NewSearcher(str string) *Searcher { }, } } + +// GetByPathCopy search in depth from top json and returns a **Copied** json node at the path location +func (self *Searcher) GetByPathCopy(path ...interface{}) (Node, error) { + return self.getByPath(true, path...) +} + +// GetByPathNoCopy search in depth from top json and returns a **Referenced** json node at the path location +// +// WARN: this search directly refer partial json from top json, which has faster speed, +// may consumes more memory. +func (self *Searcher) GetByPath(path ...interface{}) (Node, error) { + return self.getByPath(false, path...) +} + +func (self *Searcher) getByPath(copystring bool, path ...interface{}) (Node, error) { + var err types.ParsingError + var start int + + self.parser.p = 0 + start, err = self.parser.getByPath(path...) + if err != 0 { + // for compatibility with old version + if err == types.ERR_NOT_FOUND { + return Node{}, ErrNotExist + } + if err == types.ERR_UNSUPPORT_TYPE { + panic("path must be either int(>=0) or string") + } + return Node{}, self.parser.syntaxError(err) + } + + t := switchRawType(self.parser.s[start]) + if t == _V_NONE { + return Node{}, self.parser.ExportError(err) + } + + // copy string to reducing memory usage + var raw string + if copystring { + raw = rt.Mem2Str([]byte(self.parser.s[start:self.parser.p])) + } else { + raw = self.parser.s[start:self.parser.p] + } + return newRawNode(raw, t), nil +} |