diff options
| author | 2023-11-27 13:15:03 +0000 | |
|---|---|---|
| committer | 2023-11-27 13:15:03 +0000 | |
| commit | 66b77acb1c8b86f0be3836ccaf31683c0bfa317a (patch) | |
| tree | 9a255a8ea8ef97229b6d75d17de45bdac1755be9 /vendor/github.com/bytedance/sonic/ast | |
| parent | [bugfix] Add Actor to outgoing poll vote Create; other fixes (#2384) (diff) | |
| download | gotosocial-66b77acb1c8b86f0be3836ccaf31683c0bfa317a.tar.xz | |
[chore]: Bump github.com/gin-contrib/cors from 1.4.0 to 1.5.0 (#2388)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Diffstat (limited to 'vendor/github.com/bytedance/sonic/ast')
| -rw-r--r-- | vendor/github.com/bytedance/sonic/ast/api_amd64.go | 12 | ||||
| -rw-r--r-- | vendor/github.com/bytedance/sonic/ast/api_compat.go | 8 | ||||
| -rw-r--r-- | vendor/github.com/bytedance/sonic/ast/buffer.go | 329 | ||||
| -rw-r--r-- | vendor/github.com/bytedance/sonic/ast/decode.go | 36 | ||||
| -rw-r--r-- | vendor/github.com/bytedance/sonic/ast/encode.go | 66 | ||||
| -rw-r--r-- | vendor/github.com/bytedance/sonic/ast/error.go | 44 | ||||
| -rw-r--r-- | vendor/github.com/bytedance/sonic/ast/iterator.go | 75 | ||||
| -rw-r--r-- | vendor/github.com/bytedance/sonic/ast/node.go | 657 | ||||
| -rw-r--r-- | vendor/github.com/bytedance/sonic/ast/parser.go | 101 | ||||
| -rw-r--r-- | vendor/github.com/bytedance/sonic/ast/sort.go | 206 | ||||
| -rw-r--r-- | vendor/github.com/bytedance/sonic/ast/stubs_go120.go | 2 | ||||
| -rw-r--r-- | vendor/github.com/bytedance/sonic/ast/visitor.go | 315 |
12 files changed, 1151 insertions, 700 deletions
diff --git a/vendor/github.com/bytedance/sonic/ast/api_amd64.go b/vendor/github.com/bytedance/sonic/ast/api_amd64.go index 3047f59c3..da6738efd 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.15,!go1.21 +// +build amd64,go1.16,!go1.22 /* * Copyright 2022 ByteDance Inc. @@ -87,7 +87,13 @@ func encodeBase64(src []byte) string { func (self *Parser) decodeValue() (val types.JsonState) { sv := (*rt.GoString)(unsafe.Pointer(&self.s)) - self.p = native.Value(sv.Ptr, sv.Len, self.p, &val, 0) + flag := types.F_USE_NUMBER + if self.dbuf != nil { + flag = 0 + val.Dbuf = self.dbuf + val.Dcap = types.MaxDigitNums + } + self.p = native.Value(sv.Ptr, sv.Len, self.p, &val, uint64(flag)) return } @@ -148,4 +154,4 @@ func (self *Searcher) GetByPath(path ...interface{}) (Node, error) { return Node{}, self.parser.ExportError(err) } return newRawNode(self.parser.s[start:self.parser.p], t), nil -}
\ No newline at end of file +} diff --git a/vendor/github.com/bytedance/sonic/ast/api_compat.go b/vendor/github.com/bytedance/sonic/ast/api_compat.go index b18b5ae8c..7b475eb61 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.21 +// +build !amd64 !go1.16 go1.22 /* * Copyright 2022 ByteDance Inc. @@ -27,6 +27,10 @@ import ( `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") +} + func quote(buf *[]byte, val string) { quoteString(buf, val) } @@ -49,7 +53,7 @@ func encodeBase64(src []byte) string { } func (self *Parser) decodeValue() (val types.JsonState) { - e, v := decodeValue(self.s, self.p) + e, v := decodeValue(self.s, self.p, self.dbuf == nil) if e < 0 { return v } diff --git a/vendor/github.com/bytedance/sonic/ast/buffer.go b/vendor/github.com/bytedance/sonic/ast/buffer.go new file mode 100644 index 000000000..93f4ff47a --- /dev/null +++ b/vendor/github.com/bytedance/sonic/ast/buffer.go @@ -0,0 +1,329 @@ +/** + * Copyright 2023 ByteDance Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ast + +import ( + `sort` + `unsafe` +) + +type nodeChunk [_DEFAULT_NODE_CAP]Node + +type linkedNodes struct { + head nodeChunk + tail []*nodeChunk + size int +} + +func (self *linkedNodes) Cap() int { + if self == nil { + return 0 + } + return (len(self.tail)+1)*_DEFAULT_NODE_CAP +} + +func (self *linkedNodes) Len() int { + if self == nil { + return 0 + } + return self.size +} + +func (self *linkedNodes) At(i int) (*Node) { + if self == nil { + return nil + } + if i >= 0 && i<self.size && i < _DEFAULT_NODE_CAP { + return &self.head[i] + } else if i >= _DEFAULT_NODE_CAP && i<self.size { + a, b := i/_DEFAULT_NODE_CAP-1, i%_DEFAULT_NODE_CAP + if a < len(self.tail) { + return &self.tail[a][b] + } + } + return nil +} + +func (self *linkedNodes) Add(v Node) { + if self.size < _DEFAULT_NODE_CAP { + self.head[self.size] = v + self.size++ + return + } + + a, b, c := self.size/_DEFAULT_NODE_CAP-1 , self.size%_DEFAULT_NODE_CAP, cap(self.tail) + if a - c >= 0 { + 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) + } + (*n)[b] = v + self.size++ +} + +func (self *linkedNodes) ToSlice(con []Node) { + if len(con) < self.size { + return + } + i := (self.size-1) + a, b := i/_DEFAULT_NODE_CAP-1, i%_DEFAULT_NODE_CAP + if a < 0 { + copy(con, self.head[:b+1]) + return + } else { + copy(con, self.head[:]) + con = con[_DEFAULT_NODE_CAP:] + } + + for i:=0; i<a; i++ { + copy(con, self.tail[i][:]) + con = con[_DEFAULT_NODE_CAP:] + } + copy(con, self.tail[a][:b+1]) +} + +func (self *linkedNodes) FromSlice(con []Node) { + self.size = len(con) + i := self.size-1 + a, b := i/_DEFAULT_NODE_CAP-1, i%_DEFAULT_NODE_CAP + if a < 0 { + copy(self.head[:b+1], con) + return + } else { + copy(self.head[:], con) + con = con[_DEFAULT_NODE_CAP:] + } + + if cap(self.tail) <= a { + c := (a+1) + (a+1)>>_APPEND_GROW_SHIFT + self.tail = make([]*nodeChunk, a+1, c) + } + self.tail = self.tail[:a+1] + + for i:=0; i<a; i++ { + self.tail[i] = new(nodeChunk) + copy(self.tail[i][:], con) + con = con[_DEFAULT_NODE_CAP:] + } + + self.tail[a] = new(nodeChunk) + copy(self.tail[a][:b+1], con) +} + +type pairChunk [_DEFAULT_NODE_CAP]Pair + +type linkedPairs struct { + head pairChunk + tail []*pairChunk + size int +} + +func (self *linkedPairs) Cap() int { + if self == nil { + return 0 + } + return (len(self.tail)+1)*_DEFAULT_NODE_CAP +} + +func (self *linkedPairs) Len() int { + if self == nil { + return 0 + } + return self.size +} + +func (self *linkedPairs) At(i int) *Pair { + if self == nil { + return nil + } + if i >= 0 && i < _DEFAULT_NODE_CAP && i<self.size { + return &self.head[i] + } else if i >= _DEFAULT_NODE_CAP && i<self.size { + a, b := i/_DEFAULT_NODE_CAP-1, i%_DEFAULT_NODE_CAP + if a < len(self.tail) { + return &self.tail[a][b] + } + } + return nil +} + +func (self *linkedPairs) Add(v Pair) { + if self.size < _DEFAULT_NODE_CAP { + self.head[self.size] = v + self.size++ + return + } + + a, b, c := self.size/_DEFAULT_NODE_CAP-1 , self.size%_DEFAULT_NODE_CAP, cap(self.tail) + if a - c >= 0 { + 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) + } + (*n)[b] = v + self.size++ +} + +// linear search +func (self *linkedPairs) Get(key string) (*Pair, int) { + for i:=0; i<self.size; i++ { + if n := self.At(i); n.Key == key { + return n, i + } + } + return nil, -1 +} + +func (self *linkedPairs) ToSlice(con []Pair) { + if len(con) < self.size { + return + } + i := self.size-1 + a, b := i/_DEFAULT_NODE_CAP-1, i%_DEFAULT_NODE_CAP + + if a < 0 { + copy(con, self.head[:b+1]) + return + } else { + copy(con, self.head[:]) + con = con[_DEFAULT_NODE_CAP:] + } + + for i:=0; i<a; i++ { + copy(con, self.tail[i][:]) + con = con[_DEFAULT_NODE_CAP:] + } + copy(con, self.tail[a][:b+1]) +} + +func (self *linkedPairs) ToMap(con map[string]Node) { + for i:=0; i<self.size; i++ { + n := self.At(i) + con[n.Key] = n.Value + } +} + +func (self *linkedPairs) FromSlice(con []Pair) { + self.size = len(con) + i := self.size-1 + a, b := i/_DEFAULT_NODE_CAP-1, i%_DEFAULT_NODE_CAP + if a < 0 { + copy(self.head[:b+1], con) + return + } else { + copy(self.head[:], con) + con = con[_DEFAULT_NODE_CAP:] + } + + if cap(self.tail) <= a { + c := (a+1) + (a+1)>>_APPEND_GROW_SHIFT + self.tail = make([]*pairChunk, a+1, c) + } + self.tail = self.tail[:a+1] + + for i:=0; i<a; i++ { + self.tail[i] = new(pairChunk) + copy(self.tail[i][:], con) + con = con[_DEFAULT_NODE_CAP:] + } + + self.tail[a] = new(pairChunk) + copy(self.tail[a][:b+1], con) +} + +func (self *linkedPairs) Less(i, j int) bool { + return lessFrom(self.At(i).Key, self.At(j).Key, 0) +} + +func (self *linkedPairs) Swap(i, j int) { + a, b := self.At(i), self.At(j) + *a, *b = *b, *a +} + +func (self *linkedPairs) Sort() { + sort.Sort(self) +} + +// Compare two strings from the pos d. +func lessFrom(a, b string, d int) bool { + l := len(a) + if l > len(b) { + l = len(b) + } + for i := d; i < l; i++ { + if a[i] == b[i] { + continue + } + return a[i] < b[i] + } + return len(a) < len(b) +} + +type parseObjectStack struct { + parser Parser + v linkedPairs +} + +type parseArrayStack struct { + parser Parser + v linkedNodes +} + +func newLazyArray(p *Parser) Node { + s := new(parseArrayStack) + s.parser = *p + return Node{ + t: _V_ARRAY_LAZY, + p: unsafe.Pointer(s), + } +} + +func newLazyObject(p *Parser) Node { + s := new(parseObjectStack) + s.parser = *p + return Node{ + t: _V_OBJECT_LAZY, + p: unsafe.Pointer(s), + } +} + +func (self *Node) getParserAndArrayStack() (*Parser, *parseArrayStack) { + stack := (*parseArrayStack)(self.p) + return &stack.parser, stack +} + +func (self *Node) getParserAndObjectStack() (*Parser, *parseObjectStack) { + stack := (*parseObjectStack)(self.p) + return &stack.parser, stack +} + diff --git a/vendor/github.com/bytedance/sonic/ast/decode.go b/vendor/github.com/bytedance/sonic/ast/decode.go index 6a5f6fea3..3e08bfcb2 100644 --- a/vendor/github.com/bytedance/sonic/ast/decode.go +++ b/vendor/github.com/bytedance/sonic/ast/decode.go @@ -220,7 +220,7 @@ func decodeFloat64(src string, pos int) (ret int, v float64, err error) { return ret, v, nil } -func decodeValue(src string, pos int) (ret int, v types.JsonState) { +func decodeValue(src string, pos int, skipnum bool) (ret int, v types.JsonState) { pos = skipBlank(src, pos) if pos < 0 { return pos, types.JsonState{Vt: types.ValueType(pos)} @@ -256,20 +256,30 @@ func decodeValue(src string, pos int) (ret int, v types.JsonState) { } return ret, types.JsonState{Vt: types.V_FALSE} case '-', '+', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': - var iv int64 - ret, iv, _ = decodeInt64(src, pos) - if ret >= 0 { - return ret, types.JsonState{Vt: types.V_INTEGER, Iv: iv, Ep: pos} - } else if ret != -int(types.ERR_INVALID_NUMBER_FMT) { - return ret, types.JsonState{Vt: types.ValueType(ret)} - } - var fv float64 - ret, fv, _ = decodeFloat64(src, pos) - if ret >= 0 { - return ret, types.JsonState{Vt: types.V_DOUBLE, Dv: fv, Ep: pos} + if skipnum { + ret = skipNumber(src, pos) + if ret >= 0 { + return ret, types.JsonState{Vt: types.V_DOUBLE, Iv: 0, Ep: pos} + } else { + return ret, types.JsonState{Vt: types.ValueType(ret)} + } } else { - return ret, types.JsonState{Vt: types.ValueType(ret)} + var iv int64 + ret, iv, _ = decodeInt64(src, pos) + if ret >= 0 { + return ret, types.JsonState{Vt: types.V_INTEGER, Iv: iv, Ep: pos} + } else if ret != -int(types.ERR_INVALID_NUMBER_FMT) { + return ret, types.JsonState{Vt: types.ValueType(ret)} + } + var fv float64 + ret, fv, _ = decodeFloat64(src, pos) + if ret >= 0 { + return ret, types.JsonState{Vt: types.V_DOUBLE, Dv: fv, Ep: pos} + } else { + return ret, types.JsonState{Vt: types.ValueType(ret)} + } } + default: return -int(types.ERR_INVALID_CHAR), types.JsonState{Vt:-types.ValueType(types.ERR_INVALID_CHAR)} } diff --git a/vendor/github.com/bytedance/sonic/ast/encode.go b/vendor/github.com/bytedance/sonic/ast/encode.go index 1187e30c2..263ae5a9d 100644 --- a/vendor/github.com/bytedance/sonic/ast/encode.go +++ b/vendor/github.com/bytedance/sonic/ast/encode.go @@ -19,8 +19,6 @@ package ast import ( `sync` `unicode/utf8` - - `github.com/bytedance/sonic/internal/rt` ) const ( @@ -165,18 +163,18 @@ func (self *Node) encodeFalse(buf *[]byte) error { } func (self *Node) encodeNumber(buf *[]byte) error { - str := rt.StrFrom(self.p, self.v) + str := self.toString() *buf = append(*buf, str...) return nil } func (self *Node) encodeString(buf *[]byte) error { - if self.v == 0 { + if self.l == 0 { *buf = append(*buf, '"', '"') return nil } - quote(buf, rt.StrFrom(self.p, self.v)) + quote(buf, self.toString()) return nil } @@ -195,16 +193,28 @@ func (self *Node) encodeArray(buf *[]byte) error { *buf = append(*buf, '[') - var p = (*Node)(self.p) - err := p.encode(buf) - if err != nil { - return err + 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++ { - *buf = append(*buf, ',') - p = p.unsafe_next() - err := p.encode(buf) - if err != nil { + n := s.At(i) + if !n.Exists() { + continue + } + if started { + *buf = append(*buf, ',') + } + started = true + if err := n.encode(buf); err != nil { return err } } @@ -240,20 +250,32 @@ func (self *Node) encodeObject(buf *[]byte) error { *buf = append(*buf, '{') - var p = (*Pair)(self.p) - err := p.encode(buf) - if err != nil { - return err + 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++ { - *buf = append(*buf, ',') - p = p.unsafe_next() - err := p.encode(buf) - if err != nil { + n := s.At(i) + if !n.Value.Exists() { + continue + } + if started { + *buf = append(*buf, ',') + } + started = true + if err := n.encode(buf); err != nil { return err } } *buf = append(*buf, '}') return nil -}
\ No newline at end of file +} diff --git a/vendor/github.com/bytedance/sonic/ast/error.go b/vendor/github.com/bytedance/sonic/ast/error.go index f4c441ae6..00a04468e 100644 --- a/vendor/github.com/bytedance/sonic/ast/error.go +++ b/vendor/github.com/bytedance/sonic/ast/error.go @@ -8,23 +8,55 @@ import ( `github.com/bytedance/sonic/internal/native/types` ) -func (self *Parser) syntaxError(err types.ParsingError) SyntaxError { - return SyntaxError{ - Pos : self.p, - Src : self.s, - Code: err, + +func newError(err types.ParsingError, msg string) *Node { + return &Node{ + t: V_ERROR, + l: uint(err), + p: unsafe.Pointer(&msg), } } +// Error returns error message if the node is invalid +func (self Node) Error() string { + if self.t != V_ERROR { + return "" + } else { + return *(*string)(self.p) + } +} + func newSyntaxError(err SyntaxError) *Node { msg := err.Description() return &Node{ t: V_ERROR, - v: int64(err.Code), + l: uint(err.Code), p: unsafe.Pointer(&msg), } } +func (self *Parser) syntaxError(err types.ParsingError) SyntaxError { + return SyntaxError{ + Pos : self.p, + Src : self.s, + Code: err, + } +} + +func unwrapError(err error) *Node { + if se, ok := err.(*Node); ok { + return se + }else if sse, ok := err.(Node); ok { + return &sse + } else { + msg := err.Error() + return &Node{ + t: V_ERROR, + p: unsafe.Pointer(&msg), + } + } +} + type SyntaxError struct { Pos int Src string diff --git a/vendor/github.com/bytedance/sonic/ast/iterator.go b/vendor/github.com/bytedance/sonic/ast/iterator.go index 03a25b4e9..3c4187a9c 100644 --- a/vendor/github.com/bytedance/sonic/ast/iterator.go +++ b/vendor/github.com/bytedance/sonic/ast/iterator.go @@ -82,26 +82,54 @@ type ObjectIterator struct { Iterator } +func (self *ListIterator) next() *Node { +next_start: + if !self.HasNext() { + return nil + } else { + n := self.p.nodeAt(self.i) + self.i++ + if !n.Exists() { + goto next_start + } + return n + } +} + // Next scans through children of underlying V_ARRAY, // copies each child to v, and returns .HasNext(). func (self *ListIterator) Next(v *Node) bool { - if !self.HasNext() { + n := self.next() + if n == nil { return false + } + *v = *n + return true +} + +func (self *ObjectIterator) next() *Pair { +next_start: + if !self.HasNext() { + return nil } else { - *v, self.i = *self.p.nodeAt(self.i), self.i + 1 - return true + n := self.p.pairAt(self.i) + self.i++ + if !n.Value.Exists() { + goto next_start + } + return n } } // Next scans through children of underlying V_OBJECT, // copies each child to v, and returns .HasNext(). func (self *ObjectIterator) Next(p *Pair) bool { - if !self.HasNext() { + n := self.next() + if n == nil { return false - } else { - *p, self.i = *self.p.pairAt(self.i), self.i + 1 - return true } + *p = *n + return true } // Sequence represents scanning path of single-layer nodes. @@ -129,36 +157,39 @@ type Scanner func(path Sequence, node *Node) bool // // Especailly, if the node is not V_ARRAY or V_OBJECT, // the node itself will be returned and Sequence.Index == -1. +// +// NOTICE: A unsetted node WON'T trigger sc, but its index still counts into Path.Index func (self *Node) ForEach(sc Scanner) error { switch self.itype() { case types.V_ARRAY: - ns, err := self.UnsafeArray() + iter, err := self.Values() if err != nil { return err } - for i := range ns { - if !sc(Sequence{i, nil}, &ns[i]) { - return err + v := iter.next() + for v != nil { + if !sc(Sequence{iter.i-1, nil}, v) { + return nil } + v = iter.next() } case types.V_OBJECT: - ns, err := self.UnsafeMap() + iter, err := self.Properties() if err != nil { return err } - for i := range ns { - if !sc(Sequence{i, &ns[i].Key}, &ns[i].Value) { - return err + v := iter.next() + for v != nil { + if !sc(Sequence{iter.i-1, &v.Key}, &v.Value) { + return nil } + v = iter.next() } default: + if self.Check() != nil { + return self + } sc(Sequence{-1, nil}, self) } - return self.Check() + return nil } - -type PairSlice []Pair - -func (self PairSlice) Sort() { - radixQsort(self, 0, maxDepth(len(self))) -}
\ No newline at end of file diff --git a/vendor/github.com/bytedance/sonic/ast/node.go b/vendor/github.com/bytedance/sonic/ast/node.go index 6b5ad8a3e..990908ddd 100644 --- a/vendor/github.com/bytedance/sonic/ast/node.go +++ b/vendor/github.com/bytedance/sonic/ast/node.go @@ -21,21 +21,12 @@ import ( `fmt` `strconv` `unsafe` - `reflect` `github.com/bytedance/sonic/internal/native/types` `github.com/bytedance/sonic/internal/rt` ) const ( - _CAP_BITS = 32 - _LEN_MASK = 1 << _CAP_BITS - 1 - - _NODE_SIZE = unsafe.Sizeof(Node{}) - _PAIR_SIZE = unsafe.Sizeof(Pair{}) -) - -const ( _V_NONE types.ValueType = 0 _V_NODE_BASE types.ValueType = 1 << 5 _V_LAZY types.ValueType = 1 << 7 @@ -51,40 +42,36 @@ const ( const ( V_NONE = 0 V_ERROR = 1 - V_NULL = 2 - V_TRUE = 3 - V_FALSE = 4 - V_ARRAY = 5 - V_OBJECT = 6 - V_STRING = 7 + V_NULL = int(types.V_NULL) + V_TRUE = int(types.V_TRUE) + V_FALSE = int(types.V_FALSE) + V_ARRAY = int(types.V_ARRAY) + V_OBJECT = int(types.V_OBJECT) + V_STRING = int(types.V_STRING) V_NUMBER = int(_V_NUMBER) V_ANY = int(_V_ANY) ) -var ( - byteType = rt.UnpackType(reflect.TypeOf(byte(0))) -) - type Node struct { - v int64 t types.ValueType + l uint p unsafe.Pointer } // UnmarshalJSON is just an adapter to json.Unmarshaler. // If you want better performance, use Searcher.GetByPath() directly func (self *Node) UnmarshalJSON(data []byte) (err error) { - *self, err = NewSearcher(string(data)).GetByPath() - return + *self = NewRaw(string(data)) + return self.Check() } /** Node Type Accessor **/ // Type returns json type represented by the node // It will be one of belows: -// V_NONE = 0 (empty node) +// V_NONE = 0 (empty node, key not exists) // V_ERROR = 1 (error node) -// V_NULL = 2 (json value `null`) +// V_NULL = 2 (json value `null`, key exists) // V_TRUE = 3 (json value `true`) // V_FALSE = 4 (json value `false`) // V_ARRAY = 5 (json value array) @@ -102,7 +89,7 @@ func (self Node) itype() types.ValueType { // Exists returns false only if the self is nil or empty node V_NONE func (self *Node) Exists() bool { - return self != nil && self.t != _V_NONE + return self.Valid() && self.t != _V_NONE } // Valid reports if self is NOT V_ERROR or nil @@ -114,7 +101,7 @@ func (self *Node) Valid() bool { } // Check checks if the node itself is valid, and return: -// - ErrNotFound If the node is nil +// - ErrNotExist If the node is nil // - Its underlying error If the node is V_ERROR func (self *Node) Check() error { if self == nil { @@ -126,15 +113,6 @@ func (self *Node) Check() error { } } -// Error returns error message if the node is invalid -func (self Node) Error() string { - if self.t != V_ERROR { - return "" - } else { - return *(*string)(self.p) - } -} - // IsRaw returns true if node's underlying value is raw json func (self Node) IsRaw() bool { return self.t&_V_RAW != 0 @@ -152,11 +130,14 @@ func (self *Node) isAny() bool { // Raw returns json representation of the node, func (self *Node) Raw() (string, error) { + if self == nil { + return "", ErrNotExist + } if !self.IsRaw() { buf, err := self.MarshalJSON() return rt.Mem2Str(buf), err } - return rt.StrFrom(self.p, self.v), nil + return self.toString(), nil } func (self *Node) checkRaw() error { @@ -166,7 +147,7 @@ func (self *Node) checkRaw() error { if self.IsRaw() { self.parseRaw(false) } - return nil + return self.Check() } // Bool returns bool value represented by this node, @@ -181,14 +162,14 @@ func (self *Node) Bool() (bool, error) { case types.V_FALSE : return false, nil case types.V_NULL : return false, nil case _V_NUMBER : - if i, err := numberToInt64(self); err == nil { + if i, err := self.toInt64(); err == nil { return i != 0, nil - } else if f, err := numberToFloat64(self); err == nil { + } else if f, err := self.toFloat64(); err == nil { return f != 0, nil } else { return false, err } - case types.V_STRING: return strconv.ParseBool(rt.StrFrom(self.p, self.v)) + case types.V_STRING: return strconv.ParseBool(self.toString()) case _V_ANY : any := self.packAny() switch v := any.(type) { @@ -229,9 +210,9 @@ func (self *Node) Int64() (int64, error) { } switch self.t { case _V_NUMBER, types.V_STRING : - if i, err := numberToInt64(self); err == nil { + if i, err := self.toInt64(); err == nil { return i, nil - } else if f, err := numberToFloat64(self); err == nil { + } else if f, err := self.toFloat64(); err == nil { return int64(f), nil } else { return 0, err @@ -283,7 +264,7 @@ func (self *Node) StrictInt64() (int64, error) { return 0, err } switch self.t { - case _V_NUMBER : return numberToInt64(self) + case _V_NUMBER : return self.toInt64() case _V_ANY : any := self.packAny() switch v := any.(type) { @@ -325,12 +306,12 @@ func (self *Node) Number() (json.Number, error) { return json.Number(""), err } switch self.t { - case _V_NUMBER : return toNumber(self) , nil + case _V_NUMBER : return self.toNumber(), nil case types.V_STRING : - if _, err := numberToInt64(self); err == nil { - return toNumber(self), nil - } else if _, err := numberToFloat64(self); err == nil { - return toNumber(self), nil + if _, err := self.toInt64(); err == nil { + return self.toNumber(), nil + } else if _, err := self.toFloat64(); err == nil { + return self.toNumber(), nil } else { return json.Number(""), err } @@ -372,7 +353,7 @@ func (self *Node) StrictNumber() (json.Number, error) { return json.Number(""), err } switch self.t { - case _V_NUMBER : return toNumber(self) , nil + case _V_NUMBER : return self.toNumber() , nil case _V_ANY : if v, ok := self.packAny().(json.Number); ok { return v, nil @@ -394,7 +375,7 @@ func (self *Node) String() (string, error) { case types.V_NULL : return "" , nil case types.V_TRUE : return "true" , nil case types.V_FALSE : return "false", nil - case types.V_STRING, _V_NUMBER : return rt.StrFrom(self.p, self.v), nil + case types.V_STRING, _V_NUMBER : return self.toString(), nil case _V_ANY : any := self.packAny() switch v := any.(type) { @@ -426,7 +407,7 @@ func (self *Node) StrictString() (string, error) { return "", err } switch self.t { - case types.V_STRING : return rt.StrFrom(self.p, self.v), nil + case types.V_STRING : return self.toString(), nil case _V_ANY : if v, ok := self.packAny().(string); ok { return v, nil @@ -445,7 +426,7 @@ func (self *Node) Float64() (float64, error) { return 0.0, err } switch self.t { - case _V_NUMBER, types.V_STRING : return numberToFloat64(self) + case _V_NUMBER, types.V_STRING : return self.toFloat64() case types.V_TRUE : return 1.0, nil case types.V_FALSE : return 0.0, nil case types.V_NULL : return 0.0, nil @@ -494,7 +475,7 @@ func (self *Node) StrictFloat64() (float64, error) { return 0.0, err } switch self.t { - case _V_NUMBER : return numberToFloat64(self) + case _V_NUMBER : return self.toFloat64() case _V_ANY : any := self.packAny() switch v := any.(type) { @@ -509,15 +490,14 @@ func (self *Node) StrictFloat64() (float64, error) { /** Sequencial Value Methods **/ // Len returns children count of a array|object|string node -// For partially loaded node, it also works but only counts the parsed children +// 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 } - if self.t == types.V_ARRAY || self.t == types.V_OBJECT || self.t == _V_ARRAY_LAZY || self.t == _V_OBJECT_LAZY { - return int(self.v & _LEN_MASK), nil - } else if self.t == types.V_STRING { - return int(self.v), nil + if self.t == types.V_ARRAY || self.t == types.V_OBJECT || self.t == _V_ARRAY_LAZY || self.t == _V_OBJECT_LAZY || self.t == types.V_STRING { + return int(self.l), nil } else if self.t == _V_NONE || self.t == types.V_NULL { return 0, nil } else { @@ -526,7 +506,7 @@ func (self *Node) Len() (int, error) { } func (self Node) len() int { - return int(self.v & _LEN_MASK) + return int(self.l) } // Cap returns malloc capacity of a array|object node for children @@ -534,47 +514,42 @@ func (self *Node) Cap() (int, error) { if err := self.checkRaw(); err != nil { return 0, err } - if self.t == types.V_ARRAY || self.t == types.V_OBJECT || self.t == _V_ARRAY_LAZY || self.t == _V_OBJECT_LAZY { - return int(self.v >> _CAP_BITS), nil - } else if self.t == _V_NONE || self.t == types.V_NULL { - return 0, nil - } else { - return 0, ErrUnsupportType + switch self.t { + case types.V_ARRAY: return (*linkedNodes)(self.p).Cap(), nil + case types.V_OBJECT: return (*linkedPairs)(self.p).Cap(), nil + case _V_ARRAY_LAZY: return (*parseArrayStack)(self.p).v.Cap(), nil + case _V_OBJECT_LAZY: return (*parseObjectStack)(self.p).v.Cap(), nil + case _V_NONE, types.V_NULL: return 0, nil + default: return 0, ErrUnsupportType } } -func (self Node) cap() int { - return int(self.v >> _CAP_BITS) -} - // Set sets the node of given key under self, and reports if the key has existed. // // If self is V_NONE or V_NULL, it becomes V_OBJECT and sets the node at the key. func (self *Node) Set(key string, node Node) (bool, error) { - if self != nil && (self.t == _V_NONE || self.t == types.V_NULL) { - *self = NewObject([]Pair{{key, node}}) - return false, nil + if err := self.Check(); err != nil { + return false, err } - 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 + } + p := self.Get(key) + if !p.Exists() { - l := self.len() - c := self.cap() - if l == c { - // TODO: maybe change append size in future - c += _DEFAULT_NODE_CAP - mem := unsafe_NewArray(_PAIR_TYPE, c) - memmove(mem, self.p, _PAIR_SIZE * uintptr(l)) - self.p = mem + // self must be fully-loaded here + if self.len() == 0 { + *self = newObject(new(linkedPairs)) } - v := self.pairAt(l) - v.Key = key - v.Value = node - self.setCapAndLen(c, l+1) + s := (*linkedPairs)(self.p) + s.Add(Pair{key, node}) + self.l++ return false, nil } else if err := p.Check(); err != nil { @@ -590,9 +565,12 @@ func (self *Node) SetAny(key string, val interface{}) (bool, error) { return self.Set(key, NewAny(val)) } -// Unset remove the node of given key under object parent, and reports if the key has existed. +// 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 func (self *Node) Unset(key string) (bool, error) { - self.must(types.V_OBJECT, "an object") + if err := self.should(types.V_OBJECT, "an object"); err != nil { + return false, err + } p, i := self.skipKey(key) if !p.Exists() { return false, nil @@ -608,10 +586,18 @@ func (self *Node) Unset(key string) (bool, error) { // // The index must be within self's children. func (self *Node) SetByIndex(index int, node Node) (bool, error) { + if err := self.Check(); err != nil { + return false, err + } if err := node.Check(); err != nil { return false, err } + if index == 0 && (self.t == _V_NONE || self.t == types.V_NULL) { + *self = NewArray([]Node{node}) + return false, nil + } + p := self.Index(index) if !p.Exists() { return false, ErrNotExist @@ -629,12 +615,20 @@ func (self *Node) SetAnyByIndex(index int, val interface{}) (bool, error) { } // UnsetByIndex remove the node of given index +// WARN: After conducting `UnsetXX()`, the node's length WON'T change func (self *Node) UnsetByIndex(index int) (bool, error) { + if err := self.Check(); 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 { + return false, err + } pr := self.skipIndexPair(index) if pr == nil { return false, ErrNotExist @@ -660,31 +654,28 @@ func (self *Node) UnsetByIndex(index int) (bool, error) { // // If self is V_NONE or V_NULL, it becomes V_ARRAY and sets the node at index 0. func (self *Node) Add(node Node) error { + if err := self.Check(); err != nil { + return err + } + if self != nil && (self.t == _V_NONE || self.t == types.V_NULL) { *self = NewArray([]Node{node}) return nil } - if err := self.should(types.V_ARRAY, "an array"); err != nil { return err } - if err := self.skipAllIndex(); err != nil { + s, err := self.unsafeArray() + if err != nil { return err } - var p rt.GoSlice - p.Cap = self.cap() - p.Len = self.len() - p.Ptr = self.p - - s := *(*[]Node)(unsafe.Pointer(&p)) - s = append(s, node) - - self.p = unsafe.Pointer(&s[0]) - self.setCapAndLen(cap(s), len(s)) + s.Add(node) + self.l++ return nil } + // SetAny wraps val with V_ANY node, and Add() the node. func (self *Node) AddAny(val interface{}) error { return self.Add(NewAny(val)) @@ -730,6 +721,8 @@ 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) @@ -753,6 +746,8 @@ 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 @@ -837,30 +832,68 @@ func (self *Node) MapUseNode() (map[string]Node, error) { // MapUnsafe exports the underlying pointer to its children map // WARN: don't use it unless you know what you are doing -func (self *Node) UnsafeMap() ([]Pair, error) { - if err := self.should(types.V_OBJECT, "an object"); err != nil { - return nil, err - } +// +// Deprecated: this API now returns copied nodes instead of directly reference, +// func (self *Node) UnsafeMap() ([]Pair, error) { +// if err := self.should(types.V_OBJECT, "an object"); err != nil { +// return nil, err +// } +// if err := self.skipAllKey(); err != nil { +// return nil, err +// } +// return self.toGenericObjectUsePair() +// } + +//go:nocheckptr +func (self *Node) unsafeMap() (*linkedPairs, error) { if err := self.skipAllKey(); err != nil { return nil, err } - s := rt.Ptr2SlicePtr(self.p, int(self.len()), self.cap()) - return *(*[]Pair)(s), nil + if self.p == nil { + *self = newObject(new(linkedPairs)) + } + return (*linkedPairs)(self.p), nil } // SortKeys sorts children of a V_OBJECT node in ascending key-order. // If recurse is true, it recursively sorts children's children as long as a V_OBJECT node is found. -func (self *Node) SortKeys(recurse bool) (err error) { - ps, err := self.UnsafeMap() +func (self *Node) SortKeys(recurse bool) error { + // check raw node first + if err := self.checkRaw(); err != nil { + return err + } + if self.itype() == types.V_OBJECT { + return self.sortKeys(recurse) + } else { + var err error + err2 := self.ForEach(func(path Sequence, node *Node) bool { + it := node.itype() + if it == types.V_ARRAY || it == types.V_OBJECT { + err = node.SortKeys(recurse) + if err != nil { + return false + } + } + return true + }) + if err != nil { + return err + } + return err2 + } +} + +func (self *Node) sortKeys(recurse bool) (err error) { + ps, err := self.unsafeMap() if err != nil { return err } - PairSlice(ps).Sort() + ps.Sort() if recurse { var sc Scanner sc = func(path Sequence, node *Node) bool { if node.itype() == types.V_OBJECT { - if err := node.SortKeys(recurse); err != nil { + if err := node.sortKeys(recurse); err != nil { return false } } @@ -871,7 +904,9 @@ func (self *Node) SortKeys(recurse bool) (err error) { } return true } - self.ForEach(sc) + if err := self.ForEach(sc); err != nil { + return err + } } return nil } @@ -936,15 +971,27 @@ func (self *Node) ArrayUseNode() ([]Node, error) { // ArrayUnsafe exports the underlying pointer to its children array // WARN: don't use it unless you know what you are doing -func (self *Node) UnsafeArray() ([]Node, error) { - if err := self.should(types.V_ARRAY, "an array"); err != nil { - return nil, err - } +// +// Deprecated: this API now returns copied nodes instead of directly reference, +// which has no difference with ArrayUseNode +// func (self *Node) UnsafeArray() ([]Node, error) { +// if err := self.should(types.V_ARRAY, "an array"); err != nil { +// return nil, err +// } +// if err := self.skipAllIndex(); err != nil { +// return nil, err +// } +// return self.toGenericArrayUseNode() +// } + +func (self *Node) unsafeArray() (*linkedNodes, error) { if err := self.skipAllIndex(); err != nil { return nil, err } - s := rt.Ptr2SlicePtr(self.p, self.len(), self.cap()) - return *(*[]Node)(s), nil + if self.p == nil { + *self = newArray(new(linkedNodes)) + } + return (*linkedNodes)(self.p), nil } // Interface loads all children under all pathes from this node, @@ -961,9 +1008,9 @@ func (self *Node) Interface() (interface{}, error) { case types.V_FALSE : return false, nil case types.V_ARRAY : return self.toGenericArray() case types.V_OBJECT : return self.toGenericObject() - case types.V_STRING : return rt.StrFrom(self.p, self.v), nil + case types.V_STRING : return self.toString(), nil case _V_NUMBER : - v, err := numberToFloat64(self) + v, err := self.toFloat64() if err != nil { return nil, err } @@ -1005,8 +1052,8 @@ func (self *Node) InterfaceUseNumber() (interface{}, error) { case types.V_FALSE : return false, nil case types.V_ARRAY : return self.toGenericArrayUseNumber() case types.V_OBJECT : return self.toGenericObjectUseNumber() - case types.V_STRING : return rt.StrFrom(self.p, self.v), nil - case _V_NUMBER : return toNumber(self), nil + case types.V_STRING : return self.toString(), nil + case _V_NUMBER : return self.toNumber(), nil case _V_ARRAY_LAZY : if err := self.loadAllIndex(); err != nil { return nil, err @@ -1092,9 +1139,8 @@ func (self *Node) LoadAll() error { // Load loads the node's children as parsed. // After calling it, only the node itself can be used on concurrency (not include its children) func (self *Node) Load() error { - if self.IsRaw() { - self.parseRaw(false) - return self.Load() + if err := self.checkRaw(); err != nil { + return err } switch self.t { @@ -1109,39 +1155,6 @@ func (self *Node) Load() error { /**---------------------------------- Internal Helper Methods ----------------------------------**/ -var ( - _NODE_TYPE = rt.UnpackEface(Node{}).Type - _PAIR_TYPE = rt.UnpackEface(Pair{}).Type -) - -func (self *Node) setCapAndLen(cap int, len int) { - if self.t == types.V_ARRAY || self.t == types.V_OBJECT || self.t == _V_ARRAY_LAZY || self.t == _V_OBJECT_LAZY { - self.v = int64(len&_LEN_MASK | cap<<_CAP_BITS) - } else { - panic("value does not have a length") - } -} - -func (self *Node) unsafe_next() *Node { - return (*Node)(unsafe.Pointer(uintptr(unsafe.Pointer(self)) + _NODE_SIZE)) -} - -func (self *Pair) unsafe_next() *Pair { - return (*Pair)(unsafe.Pointer(uintptr(unsafe.Pointer(self)) + _PAIR_SIZE)) -} - -func (self *Node) must(t types.ValueType, s string) { - if err := self.checkRaw(); err != nil { - panic(err) - } - if err := self.Check(); err != nil { - panic(err) - } - if self.itype() != t { - panic("value cannot be represented as " + s) - } -} - func (self *Node) should(t types.ValueType, s string) error { if err := self.checkRaw(); err != nil { return err @@ -1153,37 +1166,25 @@ func (self *Node) should(t types.ValueType, s string) error { } func (self *Node) nodeAt(i int) *Node { - var p = self.p + var p *linkedNodes if self.isLazy() { _, stack := self.getParserAndArrayStack() - p = *(*unsafe.Pointer)(unsafe.Pointer(&stack.v)) + p = &stack.v + } else { + p = (*linkedNodes)(self.p) } - return (*Node)(unsafe.Pointer(uintptr(p) + uintptr(i)*_NODE_SIZE)) + return p.At(i) } func (self *Node) pairAt(i int) *Pair { - var p = self.p + var p *linkedPairs if self.isLazy() { _, stack := self.getParserAndObjectStack() - p = *(*unsafe.Pointer)(unsafe.Pointer(&stack.v)) + p = &stack.v + } else { + p = (*linkedPairs)(self.p) } - return (*Pair)(unsafe.Pointer(uintptr(p) + uintptr(i)*_PAIR_SIZE)) -} - -func (self *Node) getParserAndArrayStack() (*Parser, *parseArrayStack) { - stack := (*parseArrayStack)(self.p) - ret := (*rt.GoSlice)(unsafe.Pointer(&stack.v)) - ret.Len = self.len() - ret.Cap = self.cap() - return &stack.parser, stack -} - -func (self *Node) getParserAndObjectStack() (*Parser, *parseObjectStack) { - stack := (*parseObjectStack)(self.p) - ret := (*rt.GoSlice)(unsafe.Pointer(&stack.v)) - ret.Len = self.len() - ret.Cap = self.cap() - return &stack.parser, stack + return p.At(i) } func (self *Node) skipAllIndex() error { @@ -1194,7 +1195,7 @@ func (self *Node) skipAllIndex() error { parser, stack := self.getParserAndArrayStack() parser.skipValue = true parser.noLazy = true - *self, err = parser.decodeArray(stack.v) + *self, err = parser.decodeArray(&stack.v) if err != 0 { return parser.ExportError(err) } @@ -1209,7 +1210,7 @@ func (self *Node) skipAllKey() error { parser, stack := self.getParserAndObjectStack() parser.skipValue = true parser.noLazy = true - *self, err = parser.decodeObject(stack.v) + *self, err = parser.decodeObject(&stack.v) if err != 0 { return parser.ExportError(err) } @@ -1223,21 +1224,16 @@ func (self *Node) skipKey(key string) (*Node, int) { if nb > 0 { /* linear search */ var p *Pair + var i int if lazy { s := (*parseObjectStack)(self.p) - p = &s.v[0] + p, i = s.v.Get(key) } else { - p = (*Pair)(self.p) + p, i = (*linkedPairs)(self.p).Get(key) } - if p.Key == key { - return &p.Value, 0 - } - for i := 1; i < nb; i++ { - p = p.unsafe_next() - if p.Key == key { - return &p.Value, i - } + if p != nil { + return &p.Value, i } } @@ -1311,7 +1307,7 @@ func (self *Node) loadAllIndex() error { var err types.ParsingError parser, stack := self.getParserAndArrayStack() parser.noLazy = true - *self, err = parser.decodeArray(stack.v) + *self, err = parser.decodeArray(&stack.v) if err != 0 { return parser.ExportError(err) } @@ -1325,7 +1321,7 @@ func (self *Node) loadAllKey() error { var err types.ParsingError parser, stack := self.getParserAndObjectStack() parser.noLazy = true - *self, err = parser.decodeObject(stack.v) + *self, err = parser.decodeObject(&stack.v) if err != 0 { return parser.ExportError(err) } @@ -1333,58 +1329,36 @@ func (self *Node) loadAllKey() error { } func (self *Node) removeNode(i int) { - nb := self.len() - 1 node := self.nodeAt(i) - if i == nb { - self.setCapAndLen(self.cap(), nb) - *node = Node{} + if node == nil { return } - - from := self.nodeAt(i + 1) - memmove(unsafe.Pointer(node), unsafe.Pointer(from), _NODE_SIZE * uintptr(nb - i)) - - last := self.nodeAt(nb) - *last = Node{} - - self.setCapAndLen(self.cap(), nb) + *node = Node{} + // NOTICE: for consistency with linkedNodes, we DOSEN'T reduce size here + // self.l-- } func (self *Node) removePair(i int) { - nb := self.len() - 1 - node := self.pairAt(i) - if i == nb { - self.setCapAndLen(self.cap(), nb) - *node = Pair{} + last := self.pairAt(i) + if last == nil { return } - - from := self.pairAt(i + 1) - memmove(unsafe.Pointer(node), unsafe.Pointer(from), _PAIR_SIZE * uintptr(nb - i)) - - last := self.pairAt(nb) *last = Pair{} - - self.setCapAndLen(self.cap(), nb) + // NOTICE: for consistency with linkedNodes, we DOSEN'T reduce size here + // self.l-- } func (self *Node) toGenericArray() ([]interface{}, error) { nb := self.len() - ret := make([]interface{}, nb) if nb == 0 { - return ret, nil + return []interface{}{}, nil } - + ret := make([]interface{}, nb) + /* convert each item */ - var p = (*Node)(self.p) - x, err := p.Interface() - if err != nil { - return nil, err - } - ret[0] = x - - for i := 1; i < nb; i++ { - p = p.unsafe_next() + var s = (*linkedNodes)(self.p) + for i := 0; i < nb; i++ { + p := s.At(i) x, err := p.Interface() if err != nil { return nil, err @@ -1398,21 +1372,15 @@ func (self *Node) toGenericArray() ([]interface{}, error) { func (self *Node) toGenericArrayUseNumber() ([]interface{}, error) { nb := self.len() - ret := make([]interface{}, nb) if nb == 0 { - return ret, nil + return []interface{}{}, nil } + ret := make([]interface{}, nb) /* convert each item */ - var p = (*Node)(self.p) - x, err := p.InterfaceUseNumber() - if err != nil { - return nil, err - } - ret[0] = x - - for i := 1; i < nb; i++ { - p = p.unsafe_next() + var s = (*linkedNodes)(self.p) + for i := 0; i < nb; i++ { + p := s.At(i) x, err := p.InterfaceUseNumber() if err != nil { return nil, err @@ -1426,45 +1394,28 @@ func (self *Node) toGenericArrayUseNumber() ([]interface{}, error) { func (self *Node) toGenericArrayUseNode() ([]Node, error) { var nb = self.len() - var out = make([]Node, nb) if nb == 0 { - return out, nil - } - - var p = (*Node)(self.p) - out[0] = *p - if err := p.Check(); err != nil { - return nil, err + return []Node{}, nil } - for i := 1; i < nb; i++ { - p = p.unsafe_next() - if err := p.Check(); err != nil { - return nil, err - } - out[i] = *p - } + var s = (*linkedNodes)(self.p) + var out = make([]Node, nb) + s.ToSlice(out) return out, nil } func (self *Node) toGenericObject() (map[string]interface{}, error) { nb := self.len() - ret := make(map[string]interface{}, nb) if nb == 0 { - return ret, nil + return map[string]interface{}{}, nil } + ret := make(map[string]interface{}, nb) /* convert each item */ - var p = (*Pair)(self.p) - x, err := p.Value.Interface() - if err != nil { - return nil, err - } - ret[p.Key] = x - - for i := 1; i < nb; i++ { - p = p.unsafe_next() + var s = (*linkedPairs)(self.p) + for i := 0; i < nb; i++ { + p := s.At(i) x, err := p.Value.Interface() if err != nil { return nil, err @@ -1479,21 +1430,15 @@ func (self *Node) toGenericObject() (map[string]interface{}, error) { func (self *Node) toGenericObjectUseNumber() (map[string]interface{}, error) { nb := self.len() - ret := make(map[string]interface{}, nb) if nb == 0 { - return ret, nil + return map[string]interface{}{}, nil } + ret := make(map[string]interface{}, nb) /* convert each item */ - var p = (*Pair)(self.p) - x, err := p.Value.InterfaceUseNumber() - if err != nil { - return nil, err - } - ret[p.Key] = x - - for i := 1; i < nb; i++ { - p = p.unsafe_next() + var s = (*linkedPairs)(self.p) + for i := 0; i < nb; i++ { + p := s.At(i) x, err := p.Value.InterfaceUseNumber() if err != nil { return nil, err @@ -1507,24 +1452,13 @@ func (self *Node) toGenericObjectUseNumber() (map[string]interface{}, error) { func (self *Node) toGenericObjectUseNode() (map[string]Node, error) { var nb = self.len() - var out = make(map[string]Node, nb) if nb == 0 { - return out, nil - } - - var p = (*Pair)(self.p) - out[p.Key] = p.Value - if err := p.Value.Check(); err != nil { - return nil, err + return map[string]Node{}, nil } - for i := 1; i < nb; i++ { - p = p.unsafe_next() - if err := p.Value.Check(); err != nil { - return nil, err - } - out[p.Key] = p.Value - } + var s = (*linkedPairs)(self.p) + var out = make(map[string]Node, nb) + s.ToMap(out) /* all done */ return out, nil @@ -1536,15 +1470,12 @@ var ( nullNode = Node{t: types.V_NULL} trueNode = Node{t: types.V_TRUE} falseNode = Node{t: types.V_FALSE} - - emptyArrayNode = Node{t: types.V_ARRAY} - emptyObjectNode = Node{t: types.V_OBJECT} ) // NewRaw creates a node of raw json. // If the input json is invalid, NewRaw returns a error Node. func NewRaw(json string) Node { - parser := NewParser(json) + parser := NewParserObj(json) start, err := parser.skip() if err != 0 { return *newError(err, err.Message()) @@ -1567,7 +1498,6 @@ func NewAny(any interface{}) Node { default: return Node{ t: _V_ANY, - v: 0, p: unsafe.Pointer(&any), } } @@ -1585,7 +1515,6 @@ func NewBytes(src []byte) Node { // NewNull creates a node of type V_NULL func NewNull() Node { return Node{ - v: 0, p: nil, t: types.V_NULL, } @@ -1600,7 +1529,6 @@ func NewBool(v bool) Node { t = types.V_TRUE } return Node{ - v: 0, p: nil, t: t, } @@ -1610,26 +1538,30 @@ func NewBool(v bool) Node { // v must be a decimal string complying with RFC8259 func NewNumber(v string) Node { return Node{ - v: int64(len(v) & _LEN_MASK), + l: uint(len(v)), p: rt.StrPtr(v), t: _V_NUMBER, } } -func toNumber(node *Node) json.Number { - return json.Number(rt.StrFrom(node.p, node.v)) +func (node Node) toNumber() json.Number { + return json.Number(rt.StrFrom(node.p, int64(node.l))) +} + +func (self Node) toString() string { + return rt.StrFrom(self.p, int64(self.l)) } -func numberToFloat64(node *Node) (float64, error) { - ret,err := toNumber(node).Float64() +func (node Node) toFloat64() (float64, error) { + ret, err := node.toNumber().Float64() if err != nil { return 0, err } return ret, nil } -func numberToInt64(node *Node) (int64, error) { - ret,err := toNumber(node).Int64() +func (node Node) toInt64() (int64, error) { + ret,err := node.toNumber().Int64() if err != nil { return 0, err } @@ -1640,7 +1572,7 @@ func newBytes(v []byte) Node { return Node{ t: types.V_STRING, p: mem2ptr(v), - v: int64(len(v) & _LEN_MASK), + l: uint(len(v)), } } @@ -1652,103 +1584,65 @@ func NewString(v string) Node { return Node{ t: types.V_STRING, p: rt.StrPtr(v), - v: int64(len(v) & _LEN_MASK), + l: uint(len(v)), } } // NewArray creates a node of type V_ARRAY, // using v as its underlying children func NewArray(v []Node) Node { + s := new(linkedNodes) + s.FromSlice(v) + return newArray(s) +} + +func newArray(v *linkedNodes) Node { return Node{ t: types.V_ARRAY, - v: int64(len(v)&_LEN_MASK | cap(v)<<_CAP_BITS), - p: *(*unsafe.Pointer)(unsafe.Pointer(&v)), + l: uint(v.Len()), + p: unsafe.Pointer(v), } } -func (self *Node) setArray(v []Node) { +func (self *Node) setArray(v *linkedNodes) { self.t = types.V_ARRAY - self.setCapAndLen(cap(v), len(v)) - self.p = *(*unsafe.Pointer)(unsafe.Pointer(&v)) + self.l = uint(v.Len()) + self.p = unsafe.Pointer(v) } // NewObject creates a node of type V_OBJECT, // using v as its underlying children func NewObject(v []Pair) Node { - return Node{ - t: types.V_OBJECT, - v: int64(len(v)&_LEN_MASK | cap(v)<<_CAP_BITS), - p: *(*unsafe.Pointer)(unsafe.Pointer(&v)), - } -} - -func (self *Node) setObject(v []Pair) { - self.t = types.V_OBJECT - self.setCapAndLen(cap(v), len(v)) - self.p = *(*unsafe.Pointer)(unsafe.Pointer(&v)) -} - -type parseObjectStack struct { - parser Parser - v []Pair -} - -type parseArrayStack struct { - parser Parser - v []Node -} - -func newLazyArray(p *Parser, v []Node) Node { - s := new(parseArrayStack) - s.parser = *p - s.v = v - return Node{ - t: _V_ARRAY_LAZY, - v: int64(len(v)&_LEN_MASK | cap(v)<<_CAP_BITS), - p: unsafe.Pointer(s), - } -} - -func (self *Node) setLazyArray(p *Parser, v []Node) { - s := new(parseArrayStack) - s.parser = *p - s.v = v - self.t = _V_ARRAY_LAZY - self.setCapAndLen(cap(v), len(v)) - self.p = (unsafe.Pointer)(s) + s := new(linkedPairs) + s.FromSlice(v) + return newObject(s) } -func newLazyObject(p *Parser, v []Pair) Node { - s := new(parseObjectStack) - s.parser = *p - s.v = v +func newObject(v *linkedPairs) Node { return Node{ - t: _V_OBJECT_LAZY, - v: int64(len(v)&_LEN_MASK | cap(v)<<_CAP_BITS), - p: unsafe.Pointer(s), + t: types.V_OBJECT, + l: uint(v.Len()), + p: unsafe.Pointer(v), } } -func (self *Node) setLazyObject(p *Parser, v []Pair) { - s := new(parseObjectStack) - s.parser = *p - s.v = v - self.t = _V_OBJECT_LAZY - self.setCapAndLen(cap(v), len(v)) - self.p = (unsafe.Pointer)(s) +func (self *Node) setObject(v *linkedPairs) { + self.t = types.V_OBJECT + self.l = uint(v.Len()) + self.p = unsafe.Pointer(v) } func newRawNode(str string, typ types.ValueType) Node { return Node{ t: _V_RAW | typ, p: rt.StrPtr(str), - v: int64(len(str) & _LEN_MASK), + l: uint(len(str)), } } func (self *Node) parseRaw(full bool) { - raw := rt.StrFrom(self.p, self.v) - parser := NewParser(raw) + raw := self.toString() + parser := NewParserObj(raw) if full { parser.noLazy = true parser.skipValue = false @@ -1760,14 +1654,6 @@ func (self *Node) parseRaw(full bool) { } } -func newError(err types.ParsingError, msg string) *Node { - return &Node{ - t: V_ERROR, - v: int64(err), - p: unsafe.Pointer(&msg), - } -} - var typeJumpTable = [256]types.ValueType{ '"' : types.V_STRING, '-' : _V_NUMBER, @@ -1791,18 +1677,3 @@ var typeJumpTable = [256]types.ValueType{ func switchRawType(c byte) types.ValueType { return typeJumpTable[c] } - -func unwrapError(err error) *Node { - if se, ok := err.(*Node); ok { - return se - }else if sse, ok := err.(Node); ok { - return &sse - } else { - msg := err.Error() - return &Node{ - t: V_ERROR, - v: 0, - p: unsafe.Pointer(&msg), - } - } -}
\ No newline at end of file diff --git a/vendor/github.com/bytedance/sonic/ast/parser.go b/vendor/github.com/bytedance/sonic/ast/parser.go index 0a8e7b068..cb16f20bb 100644 --- a/vendor/github.com/bytedance/sonic/ast/parser.go +++ b/vendor/github.com/bytedance/sonic/ast/parser.go @@ -18,11 +18,15 @@ package ast import ( `fmt` + `github.com/bytedance/sonic/internal/native/types` `github.com/bytedance/sonic/internal/rt` ) -const _DEFAULT_NODE_CAP int = 16 +const ( + _DEFAULT_NODE_CAP int = 8 + _APPEND_GROW_SHIFT = 1 +) const ( _ERR_NOT_FOUND types.ParsingError = 33 @@ -30,7 +34,10 @@ const ( ) var ( + // ErrNotExist means both key and value doesn't exist ErrNotExist error = newError(_ERR_NOT_FOUND, "value not exists") + + // ErrUnsupportType means API on the node is unsupported ErrUnsupportType error = newError(_ERR_UNSUPPORT_TYPE, "unsupported type") ) @@ -39,6 +46,7 @@ type Parser struct { s string noLazy bool skipValue bool + dbuf *byte } /** Parser Private Methods **/ @@ -107,7 +115,7 @@ func (self *Parser) lspace(sp int) int { return sp } -func (self *Parser) decodeArray(ret []Node) (Node, types.ParsingError) { +func (self *Parser) decodeArray(ret *linkedNodes) (Node, types.ParsingError) { sp := self.p ns := len(self.s) @@ -119,7 +127,7 @@ func (self *Parser) decodeArray(ret []Node) (Node, types.ParsingError) { /* check for empty array */ if self.s[self.p] == ']' { self.p++ - return emptyArrayNode, 0 + return Node{t: types.V_ARRAY}, 0 } /* allocate array space and parse every element */ @@ -149,7 +157,7 @@ func (self *Parser) decodeArray(ret []Node) (Node, types.ParsingError) { } /* add the value to result */ - ret = append(ret, val) + ret.Add(val) self.p = self.lspace(self.p) /* check for EOF */ @@ -160,17 +168,17 @@ func (self *Parser) decodeArray(ret []Node) (Node, types.ParsingError) { /* check for the next character */ switch self.s[self.p] { case ',' : self.p++ - case ']' : self.p++; return NewArray(ret), 0 - default: - if val.isLazy() { - return newLazyArray(self, ret), 0 - } - return Node{}, types.ERR_INVALID_CHAR + case ']' : self.p++; return newArray(ret), 0 + default: + // if val.isLazy() { + // return newLazyArray(self, ret), 0 + // } + return Node{}, types.ERR_INVALID_CHAR } } } -func (self *Parser) decodeObject(ret []Pair) (Node, types.ParsingError) { +func (self *Parser) decodeObject(ret *linkedPairs) (Node, types.ParsingError) { sp := self.p ns := len(self.s) @@ -182,7 +190,7 @@ func (self *Parser) decodeObject(ret []Pair) (Node, types.ParsingError) { /* check for empty object */ if self.s[self.p] == '}' { self.p++ - return emptyObjectNode, 0 + return Node{t: types.V_OBJECT}, 0 } /* decode each pair */ @@ -235,7 +243,8 @@ func (self *Parser) decodeObject(ret []Pair) (Node, types.ParsingError) { } /* add the value to result */ - ret = append(ret, Pair{Key: key, Value: val}) + // FIXME: ret's address may change here, thus previous referred node in ret may be invalid !! + ret.Add(Pair{Key: key, Value: val}) self.p = self.lspace(self.p) /* check for EOF */ @@ -246,11 +255,11 @@ func (self *Parser) decodeObject(ret []Pair) (Node, types.ParsingError) { /* check for the next character */ switch self.s[self.p] { case ',' : self.p++ - case '}' : self.p++; return NewObject(ret), 0 + case '}' : self.p++; return newObject(ret), 0 default: - if val.isLazy() { - return newLazyObject(self, ret), 0 - } + // if val.isLazy() { + // return newLazyObject(self, ret), 0 + // } return Node{}, types.ERR_INVALID_CHAR } } @@ -290,15 +299,23 @@ func (self *Parser) Parse() (Node, types.ParsingError) { case types.V_FALSE : return falseNode, 0 case types.V_STRING : return self.decodeString(val.Iv, val.Ep) case types.V_ARRAY: + if p := skipBlank(self.s, self.p); p >= self.p && self.s[p] == ']' { + self.p = p + 1 + return Node{t: types.V_ARRAY}, 0 + } if self.noLazy { - return self.decodeArray(make([]Node, 0, _DEFAULT_NODE_CAP)) + return self.decodeArray(new(linkedNodes)) } - return newLazyArray(self, make([]Node, 0, _DEFAULT_NODE_CAP)), 0 + return newLazyArray(self), 0 case types.V_OBJECT: + if p := skipBlank(self.s, self.p); p >= self.p && self.s[p] == '}' { + self.p = p + 1 + return Node{t: types.V_OBJECT}, 0 + } if self.noLazy { - return self.decodeObject(make([]Pair, 0, _DEFAULT_NODE_CAP)) + return self.decodeObject(new(linkedPairs)) } - return newLazyObject(self, make([]Pair, 0, _DEFAULT_NODE_CAP)), 0 + return newLazyObject(self), 0 case types.V_DOUBLE : return NewNumber(self.s[val.Ep:self.p]), 0 case types.V_INTEGER : return NewNumber(self.s[val.Ep:self.p]), 0 default : return Node{}, types.ParsingError(-val.Vt) @@ -429,7 +446,7 @@ func (self *Node) skipNextNode() *Node { } parser, stack := self.getParserAndArrayStack() - ret := stack.v + ret := &stack.v sp := parser.p ns := len(parser.s) @@ -458,7 +475,8 @@ func (self *Node) skipNextNode() *Node { } /* add the value to result */ - ret = append(ret, val) + ret.Add(val) + self.l++ parser.p = parser.lspace(parser.p) /* check for EOF */ @@ -470,12 +488,11 @@ func (self *Node) skipNextNode() *Node { switch parser.s[parser.p] { case ',': parser.p++ - self.setLazyArray(parser, ret) - return &ret[len(ret)-1] + return ret.At(ret.Len()-1) case ']': parser.p++ self.setArray(ret) - return &ret[len(ret)-1] + return ret.At(ret.Len()-1) default: return newSyntaxError(parser.syntaxError(types.ERR_INVALID_CHAR)) } @@ -487,7 +504,7 @@ func (self *Node) skipNextPair() (*Pair) { } parser, stack := self.getParserAndObjectStack() - ret := stack.v + ret := &stack.v sp := parser.p ns := len(parser.s) @@ -541,7 +558,8 @@ func (self *Node) skipNextPair() (*Pair) { } /* add the value to result */ - ret = append(ret, Pair{Key: key, Value: val}) + ret.Add(Pair{Key: key, Value: val}) + self.l++ parser.p = parser.lspace(parser.p) /* check for EOF */ @@ -553,12 +571,11 @@ func (self *Node) skipNextPair() (*Pair) { switch parser.s[parser.p] { case ',': parser.p++ - self.setLazyObject(parser, ret) - return &ret[len(ret)-1] + return ret.At(ret.Len()-1) case '}': parser.p++ self.setObject(ret) - return &ret[len(ret)-1] + return ret.At(ret.Len()-1) default: return &Pair{key, *newSyntaxError(parser.syntaxError(types.ERR_INVALID_CHAR))} } @@ -601,10 +618,30 @@ func LoadsUseNumber(src string) (int, interface{}, error) { } } +// NewParser returns pointer of new allocated parser func NewParser(src string) *Parser { return &Parser{s: src} } +// NewParser returns new allocated parser +func NewParserObj(src string) Parser { + return Parser{s: src} +} + +// decodeNumber controls if parser decodes the number values instead of skip them +// WARN: once you set decodeNumber(true), please set decodeNumber(false) before you drop the parser +// otherwise the memory CANNOT be reused +func (self *Parser) decodeNumber(decode bool) { + if !decode && self.dbuf != nil { + types.FreeDbuf(self.dbuf) + self.dbuf = nil + return + } + if decode && self.dbuf == nil { + self.dbuf = types.NewDbuf() + } +} + // ExportError converts types.ParsingError to std Error func (self *Parser) ExportError(err types.ParsingError) error { if err == _ERR_NOT_FOUND { @@ -615,4 +652,4 @@ func (self *Parser) ExportError(err types.ParsingError) error { Src : self.s, Code: err, }.Description()) -}
\ No newline at end of file +} diff --git a/vendor/github.com/bytedance/sonic/ast/sort.go b/vendor/github.com/bytedance/sonic/ast/sort.go deleted file mode 100644 index 0a9f14559..000000000 --- a/vendor/github.com/bytedance/sonic/ast/sort.go +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright 2021 ByteDance Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package ast - -// Algorithm 3-way Radix Quicksort, d means the radix. -// Reference: https://algs4.cs.princeton.edu/51radix/Quick3string.java.html -func radixQsort(kvs PairSlice, d, maxDepth int) { - for len(kvs) > 11 { - // To avoid the worst case of quickSort (time: O(n^2)), use introsort here. - // Reference: https://en.wikipedia.org/wiki/Introsort and - // https://github.com/golang/go/issues/467 - if maxDepth == 0 { - heapSort(kvs, 0, len(kvs)) - return - } - maxDepth-- - - p := pivot(kvs, d) - lt, i, gt := 0, 0, len(kvs) - for i < gt { - c := byteAt(kvs[i].Key, d) - if c < p { - swap(kvs, lt, i) - i++ - lt++ - } else if c > p { - gt-- - swap(kvs, i, gt) - } else { - i++ - } - } - - // kvs[0:lt] < v = kvs[lt:gt] < kvs[gt:len(kvs)] - // Native implemention: - // radixQsort(kvs[:lt], d, maxDepth) - // if p > -1 { - // radixQsort(kvs[lt:gt], d+1, maxDepth) - // } - // radixQsort(kvs[gt:], d, maxDepth) - // Optimize as follows: make recursive calls only for the smaller parts. - // Reference: https://www.geeksforgeeks.org/quicksort-tail-call-optimization-reducing-worst-case-space-log-n/ - if p == -1 { - if lt > len(kvs) - gt { - radixQsort(kvs[gt:], d, maxDepth) - kvs = kvs[:lt] - } else { - radixQsort(kvs[:lt], d, maxDepth) - kvs = kvs[gt:] - } - } else { - ml := maxThree(lt, gt-lt, len(kvs)-gt) - if ml == lt { - radixQsort(kvs[lt:gt], d+1, maxDepth) - radixQsort(kvs[gt:], d, maxDepth) - kvs = kvs[:lt] - } else if ml == gt-lt { - radixQsort(kvs[:lt], d, maxDepth) - radixQsort(kvs[gt:], d, maxDepth) - kvs = kvs[lt:gt] - d += 1 - } else { - radixQsort(kvs[:lt], d, maxDepth) - radixQsort(kvs[lt:gt], d+1, maxDepth) - kvs = kvs[gt:] - } - } - } - insertRadixSort(kvs, d) -} - -func insertRadixSort(kvs PairSlice, d int) { - for i := 1; i < len(kvs); i++ { - for j := i; j > 0 && lessFrom(kvs[j].Key, kvs[j-1].Key, d); j-- { - swap(kvs, j, j-1) - } - } -} - -func pivot(kvs PairSlice, d int) int { - m := len(kvs) >> 1 - if len(kvs) > 40 { - // Tukey's ``Ninther,'' median of three mediankvs of three. - t := len(kvs) / 8 - return medianThree( - medianThree(byteAt(kvs[0].Key, d), byteAt(kvs[t].Key, d), byteAt(kvs[2*t].Key, d)), - medianThree(byteAt(kvs[m].Key, d), byteAt(kvs[m-t].Key, d), byteAt(kvs[m+t].Key, d)), - medianThree(byteAt(kvs[len(kvs)-1].Key, d), - byteAt(kvs[len(kvs)-1-t].Key, d), - byteAt(kvs[len(kvs)-1-2*t].Key, d))) - } - return medianThree(byteAt(kvs[0].Key, d), byteAt(kvs[m].Key, d), byteAt(kvs[len(kvs)-1].Key, d)) -} - -func medianThree(i, j, k int) int { - if i > j { - i, j = j, i - } // i < j - if k < i { - return i - } - if k > j { - return j - } - return k -} - -func maxThree(i, j, k int) int { - max := i - if max < j { - max = j - } - if max < k { - max = k - } - return max -} - -// maxDepth returns a threshold at which quicksort should switch -// to heapsort. It returnkvs 2*ceil(lg(n+1)). -func maxDepth(n int) int { - var depth int - for i := n; i > 0; i >>= 1 { - depth++ - } - return depth * 2 -} - -// siftDown implements the heap property on kvs[lo:hi]. -// first is an offset into the array where the root of the heap lies. -func siftDown(kvs PairSlice, lo, hi, first int) { - root := lo - for { - child := 2*root + 1 - if child >= hi { - break - } - if child+1 < hi && kvs[first+child].Key < kvs[first+child+1].Key { - child++ - } - if kvs[first+root].Key >= kvs[first+child].Key { - return - } - swap(kvs, first+root, first+child) - root = child - } -} - -func heapSort(kvs PairSlice, a, b int) { - first := a - lo := 0 - hi := b - a - - // Build heap with the greatest element at top. - for i := (hi - 1) / 2; i >= 0; i-- { - siftDown(kvs, i, hi, first) - } - - // Pop elements, the largest first, into end of kvs. - for i := hi - 1; i >= 0; i-- { - swap(kvs, first, first+i) - siftDown(kvs, lo, i, first) - } -} - -// Note that Pair.Key is NOT pointed to Pair.m when map key is integer after swap -func swap(kvs PairSlice, a, b int) { - kvs[a].Key, kvs[b].Key = kvs[b].Key, kvs[a].Key - kvs[a].Value, kvs[b].Value = kvs[b].Value, kvs[a].Value -} - -// Compare two strings from the pos d. -func lessFrom(a, b string, d int) bool { - l := len(a) - if l > len(b) { - l = len(b) - } - for i := d; i < l; i++ { - if a[i] == b[i] { - continue - } - return a[i] < b[i] - } - return len(a) < len(b) -} - -func byteAt(b string, p int) int { - if p < len(b) { - return int(b[p]) - } - return -1 -} diff --git a/vendor/github.com/bytedance/sonic/ast/stubs_go120.go b/vendor/github.com/bytedance/sonic/ast/stubs_go120.go index bd6fff680..6f830529d 100644 --- a/vendor/github.com/bytedance/sonic/ast/stubs_go120.go +++ b/vendor/github.com/bytedance/sonic/ast/stubs_go120.go @@ -52,4 +52,4 @@ var ( ) //go:linkname unquoteBytes encoding/json.unquoteBytes -func unquoteBytes(s []byte) (t []byte, ok bool)
\ No newline at end of file +func unquoteBytes(s []byte) (t []byte, ok bool) diff --git a/vendor/github.com/bytedance/sonic/ast/visitor.go b/vendor/github.com/bytedance/sonic/ast/visitor.go new file mode 100644 index 000000000..4019c31a2 --- /dev/null +++ b/vendor/github.com/bytedance/sonic/ast/visitor.go @@ -0,0 +1,315 @@ +/* + * Copyright 2021 ByteDance Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ast + +import ( + `encoding/json` + + `github.com/bytedance/sonic/internal/native/types` +) + +// Visitor handles the callbacks during preorder traversal of a JSON AST. +// +// According to the JSON RFC8259, a JSON AST can be defined by +// the following rules without seperator / whitespace tokens. +// +// JSON-AST = value +// value = false / null / true / object / array / number / string +// object = begin-object [ member *( member ) ] end-object +// member = string value +// array = begin-array [ value *( value ) ] end-array +// +type Visitor interface { + + // OnNull handles a JSON null value. + OnNull() error + + // OnBool handles a JSON true / false value. + OnBool(v bool) error + + // OnString handles a JSON string value. + OnString(v string) error + + // OnInt64 handles a JSON number value with int64 type. + OnInt64(v int64, n json.Number) error + + // OnFloat64 handles a JSON number value with float64 type. + OnFloat64(v float64, n json.Number) error + + // OnObjectBegin handles the beginning of a JSON object value with a + // suggested capacity that can be used to make your custom object container. + // + // After this point the visitor will receive a sequence of callbacks like + // [string, value, string, value, ......, ObjectEnd]. + // + // Note: + // 1. This is a recursive definition which means the value can + // also be a JSON object / array described by a sequence of callbacks. + // 2. The suggested capacity will be 0 if current object is empty. + // 3. Currently sonic use a fixed capacity for non-empty object (keep in + // sync with ast.Node) which might not be very suitable. This may be + // improved in future version. + OnObjectBegin(capacity int) error + + // OnObjectKey handles a JSON object key string in member. + OnObjectKey(key string) error + + // OnObjectEnd handles the ending of a JSON object value. + OnObjectEnd() error + + // OnArrayBegin handles the beginning of a JSON array value with a + // suggested capacity that can be used to make your custom array container. + // + // After this point the visitor will receive a sequence of callbacks like + // [value, value, value, ......, ArrayEnd]. + // + // Note: + // 1. This is a recursive definition which means the value can + // also be a JSON object / array described by a sequence of callbacks. + // 2. The suggested capacity will be 0 if current array is empty. + // 3. Currently sonic use a fixed capacity for non-empty array (keep in + // sync with ast.Node) which might not be very suitable. This may be + // improved in future version. + OnArrayBegin(capacity int) error + + // OnArrayEnd handles the ending of a JSON array value. + OnArrayEnd() error +} + +// VisitorOptions contains all Visitor's options. The default value is an +// empty VisitorOptions{}. +type VisitorOptions struct { + // OnlyNumber indicates parser to directly return number value without + // conversion, then the first argument of OnInt64 / OnFloat64 will always + // be zero. + OnlyNumber bool +} + +var defaultVisitorOptions = &VisitorOptions{} + +// Preorder decodes the whole JSON string and callbacks each AST node to visitor +// during preorder traversal. Any visitor method with an error returned will +// break the traversal and the given error will be directly returned. The opts +// argument can be reused after every call. +func Preorder(str string, visitor Visitor, opts *VisitorOptions) error { + if opts == nil { + opts = defaultVisitorOptions + } + // process VisitorOptions first to guarantee that all options will be + // constant during decoding and make options more readable. + var ( + optDecodeNumber = !opts.OnlyNumber + ) + + tv := &traverser{ + parser: Parser{ + s: str, + noLazy: true, + skipValue: false, + }, + visitor: visitor, + } + + if optDecodeNumber { + tv.parser.decodeNumber(true) + } + + err := tv.decodeValue() + + if optDecodeNumber { + tv.parser.decodeNumber(false) + } + return err +} + +type traverser struct { + parser Parser + visitor Visitor +} + +// NOTE: keep in sync with (*Parser).Parse method. +func (self *traverser) decodeValue() error { + switch val := self.parser.decodeValue(); val.Vt { + case types.V_EOF: + return types.ERR_EOF + case types.V_NULL: + return self.visitor.OnNull() + case types.V_TRUE: + return self.visitor.OnBool(true) + case types.V_FALSE: + return self.visitor.OnBool(false) + case types.V_STRING: + return self.decodeString(val.Iv, val.Ep) + case types.V_DOUBLE: + return self.visitor.OnFloat64(val.Dv, + json.Number(self.parser.s[val.Ep:self.parser.p])) + case types.V_INTEGER: + return self.visitor.OnInt64(val.Iv, + json.Number(self.parser.s[val.Ep:self.parser.p])) + case types.V_ARRAY: + return self.decodeArray() + case types.V_OBJECT: + return self.decodeObject() + default: + return types.ParsingError(-val.Vt) + } +} + +// NOTE: keep in sync with (*Parser).decodeArray method. +func (self *traverser) decodeArray() error { + sp := self.parser.p + ns := len(self.parser.s) + + /* check for EOF */ + self.parser.p = self.parser.lspace(sp) + if self.parser.p >= ns { + return types.ERR_EOF + } + + /* check for empty array */ + if self.parser.s[self.parser.p] == ']' { + self.parser.p++ + if err := self.visitor.OnArrayBegin(0); err != nil { + return err + } + return self.visitor.OnArrayEnd() + } + + /* allocate array space and parse every element */ + if err := self.visitor.OnArrayBegin(_DEFAULT_NODE_CAP); err != nil { + return err + } + for { + /* decode the value */ + if err := self.decodeValue(); err != nil { + return err + } + self.parser.p = self.parser.lspace(self.parser.p) + + /* check for EOF */ + if self.parser.p >= ns { + return types.ERR_EOF + } + + /* check for the next character */ + switch self.parser.s[self.parser.p] { + case ',': + self.parser.p++ + case ']': + self.parser.p++ + return self.visitor.OnArrayEnd() + default: + return types.ERR_INVALID_CHAR + } + } +} + +// NOTE: keep in sync with (*Parser).decodeObject method. +func (self *traverser) decodeObject() error { + sp := self.parser.p + ns := len(self.parser.s) + + /* check for EOF */ + self.parser.p = self.parser.lspace(sp) + if self.parser.p >= ns { + return types.ERR_EOF + } + + /* check for empty object */ + if self.parser.s[self.parser.p] == '}' { + self.parser.p++ + if err := self.visitor.OnObjectBegin(0); err != nil { + return err + } + return self.visitor.OnObjectEnd() + } + + /* allocate object space and decode each pair */ + if err := self.visitor.OnObjectBegin(_DEFAULT_NODE_CAP); err != nil { + return err + } + for { + var njs types.JsonState + var err types.ParsingError + + /* decode the key */ + if njs = self.parser.decodeValue(); njs.Vt != types.V_STRING { + return types.ERR_INVALID_CHAR + } + + /* extract the key */ + idx := self.parser.p - 1 + key := self.parser.s[njs.Iv:idx] + + /* check for escape sequence */ + if njs.Ep != -1 { + if key, err = unquote(key); err != 0 { + return err + } + } + + if err := self.visitor.OnObjectKey(key); err != nil { + return err + } + + /* expect a ':' delimiter */ + if err = self.parser.delim(); err != 0 { + return err + } + + /* decode the value */ + if err := self.decodeValue(); err != nil { + return err + } + + self.parser.p = self.parser.lspace(self.parser.p) + + /* check for EOF */ + if self.parser.p >= ns { + return types.ERR_EOF + } + + /* check for the next character */ + switch self.parser.s[self.parser.p] { + case ',': + self.parser.p++ + case '}': + self.parser.p++ + return self.visitor.OnObjectEnd() + default: + return types.ERR_INVALID_CHAR + } + } +} + +// NOTE: keep in sync with (*Parser).decodeString method. +func (self *traverser) decodeString(iv int64, ep int) error { + p := self.parser.p - 1 + s := self.parser.s[iv:p] + + /* fast path: no escape sequence */ + if ep == -1 { + return self.visitor.OnString(s) + } + + /* unquote the string */ + out, err := unquote(s) + if err != 0 { + return err + } + return self.visitor.OnString(out) +} |
