summaryrefslogtreecommitdiff
path: root/vendor/github.com/bytedance/sonic/ast
diff options
context:
space:
mode:
authorLibravatar Daenney <daenney@users.noreply.github.com>2023-02-25 13:12:40 +0100
committerLibravatar GitHub <noreply@github.com>2023-02-25 12:12:40 +0000
commitecdc8379fa8f9d88faca626e7de748c2afbe4910 (patch)
tree8c20a5826db2136fc89bee45e15355c5899fa65b /vendor/github.com/bytedance/sonic/ast
parent[bugfix] Fix deleted status causing issues when getting bookmark (#1551) (diff)
downloadgotosocial-ecdc8379fa8f9d88faca626e7de748c2afbe4910.tar.xz
[chore] Update gin to v1.9.0 (#1553)
Diffstat (limited to 'vendor/github.com/bytedance/sonic/ast')
-rw-r--r--vendor/github.com/bytedance/sonic/ast/api_amd64.go126
-rw-r--r--vendor/github.com/bytedance/sonic/ast/api_compat.go102
-rw-r--r--vendor/github.com/bytedance/sonic/ast/asm.s0
-rw-r--r--vendor/github.com/bytedance/sonic/ast/decode.go430
-rw-r--r--vendor/github.com/bytedance/sonic/ast/encode.go259
-rw-r--r--vendor/github.com/bytedance/sonic/ast/error.go98
-rw-r--r--vendor/github.com/bytedance/sonic/ast/iterator.go164
-rw-r--r--vendor/github.com/bytedance/sonic/ast/node.go1802
-rw-r--r--vendor/github.com/bytedance/sonic/ast/parser.go618
-rw-r--r--vendor/github.com/bytedance/sonic/ast/search.go30
-rw-r--r--vendor/github.com/bytedance/sonic/ast/sort.go206
-rw-r--r--vendor/github.com/bytedance/sonic/ast/stubs_go115.go55
-rw-r--r--vendor/github.com/bytedance/sonic/ast/stubs_go120.go55
13 files changed, 3945 insertions, 0 deletions
diff --git a/vendor/github.com/bytedance/sonic/ast/api_amd64.go b/vendor/github.com/bytedance/sonic/ast/api_amd64.go
new file mode 100644
index 000000000..6b3458aee
--- /dev/null
+++ b/vendor/github.com/bytedance/sonic/ast/api_amd64.go
@@ -0,0 +1,126 @@
+// +build amd64,go1.15,!go1.21
+
+
+package ast
+
+import (
+ `runtime`
+ `unsafe`
+
+ `github.com/bytedance/sonic/encoder`
+ `github.com/bytedance/sonic/internal/native`
+ `github.com/bytedance/sonic/internal/native/types`
+ `github.com/bytedance/sonic/internal/rt`
+ uq `github.com/bytedance/sonic/unquote`
+ `github.com/chenzhuoyu/base64x`
+)
+
+var typeByte = rt.UnpackEface(byte(0)).Type
+
+func quote(buf *[]byte, val string) {
+ *buf = append(*buf, '"')
+ if len(val) == 0 {
+ *buf = append(*buf, '"')
+ }
+
+ sp := rt.IndexChar(val, 0)
+ nb := len(val)
+ b := (*rt.GoSlice)(unsafe.Pointer(buf))
+
+ // input buffer
+ for nb > 0 {
+ // output buffer
+ dp := unsafe.Pointer(uintptr(b.Ptr) + uintptr(b.Len))
+ dn := b.Cap - b.Len
+ // call native.Quote, dn is byte count it outputs
+ ret := native.Quote(sp, nb, dp, &dn, 0)
+ // update *buf length
+ b.Len += dn
+
+ // no need more output
+ if ret >= 0 {
+ break
+ }
+
+ // double buf size
+ *b = growslice(typeByte, *b, b.Cap*2)
+ // ret is the complement of consumed input
+ ret = ^ret
+ // update input buffer
+ nb -= ret
+ sp = unsafe.Pointer(uintptr(sp) + uintptr(ret))
+ }
+
+ runtime.KeepAlive(buf)
+ runtime.KeepAlive(sp)
+ *buf = append(*buf, '"')
+}
+
+func unquote(src string) (string, types.ParsingError) {
+ return uq.String(src)
+}
+
+func decodeBase64(src string) ([]byte, error) {
+ return base64x.StdEncoding.DecodeString(src)
+}
+
+func encodeBase64(src []byte) string {
+ return base64x.StdEncoding.EncodeToString(src)
+}
+
+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)
+ return
+}
+
+func (self *Parser) skip() (int, types.ParsingError) {
+ fsm := types.NewStateMachine()
+ start := native.SkipOne(&self.s, &self.p, fsm, 0)
+ types.FreeStateMachine(fsm)
+
+ if start < 0 {
+ return self.p, types.ParsingError(-start)
+ }
+ return start, 0
+}
+
+func (self *Node) encodeInterface(buf *[]byte) error {
+ //WARN: NOT compatible with json.Encoder
+ return encoder.EncodeInto(buf, self.packAny(), 0)
+}
+
+func (self *Parser) skipFast() (int, types.ParsingError) {
+ start := native.SkipOneFast(&self.s, &self.p)
+ if start < 0 {
+ return self.p, types.ParsingError(-start)
+ }
+ return start, 0
+}
+
+func (self *Parser) getByPath(path ...interface{}) (int, types.ParsingError) {
+ start := native.GetByPath(&self.s, &self.p, &path)
+ runtime.KeepAlive(path)
+ if start < 0 {
+ return self.p, types.ParsingError(-start)
+ }
+ 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 {
+ 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
+} \ 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
new file mode 100644
index 000000000..642330c51
--- /dev/null
+++ b/vendor/github.com/bytedance/sonic/ast/api_compat.go
@@ -0,0 +1,102 @@
+// +build !amd64 go1.21
+
+package ast
+
+import (
+ `encoding/base64`
+ `encoding/json`
+ `fmt`
+
+ `github.com/bytedance/sonic/internal/native/types`
+ `github.com/bytedance/sonic/internal/rt`
+)
+
+func quote(buf *[]byte, val string) {
+ quoteString(buf, val)
+}
+
+func unquote(src string) (string, types.ParsingError) {
+ sp := rt.IndexChar(src, -1)
+ out, ok := unquoteBytes(rt.BytesFrom(sp, len(src)+2, len(src)+2))
+ if !ok {
+ return "", types.ERR_INVALID_ESCAPE
+ }
+ return rt.Mem2Str(out), 0
+}
+
+
+
+func decodeBase64(src string) ([]byte, error) {
+ return base64.StdEncoding.DecodeString(src)
+}
+
+func encodeBase64(src []byte) string {
+ return base64.StdEncoding.EncodeToString(src)
+}
+
+func (self *Parser) decodeValue() (val types.JsonState) {
+ e, v := decodeValue(self.s, self.p)
+ if e < 0 {
+ return v
+ }
+ self.p = e
+ return v
+}
+
+func (self *Parser) skip() (int, types.ParsingError) {
+ e, s := skipValue(self.s, self.p)
+ if e < 0 {
+ return self.p, types.ParsingError(-e)
+ }
+ self.p = e
+ return s, 0
+}
+
+func (self *Parser) skipFast() (int, types.ParsingError) {
+ return self.skip()
+}
+
+func (self *Node) encodeInterface(buf *[]byte) error {
+ out, err := json.Marshal(self.packAny())
+ if err != nil {
+ return err
+ }
+ *buf = append(*buf, out...)
+ return nil
+}
+
+func (self *Searcher) GetByPath(path ...interface{}) (Node, error) {
+ self.parser.p = 0
+
+ var err types.ParsingError
+ for _, p := range path {
+ switch p := p.(type) {
+ case int:
+ if err = self.parser.searchIndex(p); err != 0 {
+ return Node{}, self.parser.ExportError(err)
+ }
+ case string:
+ if err = self.parser.searchKey(p); err != 0 {
+ return Node{}, self.parser.ExportError(err)
+ }
+ default:
+ panic("path must be either int 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)
+ }
+
+ 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/asm.s b/vendor/github.com/bytedance/sonic/ast/asm.s
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vendor/github.com/bytedance/sonic/ast/asm.s
diff --git a/vendor/github.com/bytedance/sonic/ast/decode.go b/vendor/github.com/bytedance/sonic/ast/decode.go
new file mode 100644
index 000000000..d54e98318
--- /dev/null
+++ b/vendor/github.com/bytedance/sonic/ast/decode.go
@@ -0,0 +1,430 @@
+package ast
+
+import (
+ `encoding/base64`
+ `runtime`
+ `strconv`
+ `unsafe`
+
+ `github.com/bytedance/sonic/internal/native/types`
+ `github.com/bytedance/sonic/internal/rt`
+)
+
+const _blankCharsMask = (1 << ' ') | (1 << '\t') | (1 << '\r') | (1 << '\n')
+
+const (
+ bytesNull = "null"
+ bytesTrue = "true"
+ bytesFalse = "false"
+ bytesObject = "{}"
+ bytesArray = "[]"
+)
+
+func isSpace(c byte) bool {
+ return (int(1<<c) & _blankCharsMask) != 0
+}
+
+func skipBlank(src string, pos int) int {
+ se := uintptr(rt.IndexChar(src, len(src)))
+ sp := uintptr(rt.IndexChar(src, pos))
+
+ for sp < se {
+ if !isSpace(*(*byte)(unsafe.Pointer(sp))) {
+ break
+ }
+ sp += 1
+ }
+ if sp >= se {
+ return -int(types.ERR_EOF)
+ }
+ runtime.KeepAlive(src)
+ return int(sp - uintptr(rt.IndexChar(src, 0)))
+}
+
+func decodeNull(src string, pos int) (ret int) {
+ ret = pos + 4
+ if ret > len(src) {
+ return -int(types.ERR_EOF)
+ }
+ if src[pos:ret] == bytesNull {
+ return ret
+ } else {
+ return -int(types.ERR_INVALID_CHAR)
+ }
+}
+
+func decodeTrue(src string, pos int) (ret int) {
+ ret = pos + 4
+ if ret > len(src) {
+ return -int(types.ERR_EOF)
+ }
+ if src[pos:ret] == bytesTrue {
+ return ret
+ } else {
+ return -int(types.ERR_INVALID_CHAR)
+ }
+
+}
+
+func decodeFalse(src string, pos int) (ret int) {
+ ret = pos + 5
+ if ret > len(src) {
+ return -int(types.ERR_EOF)
+ }
+ if src[pos:ret] == bytesFalse {
+ return ret
+ }
+ return -int(types.ERR_INVALID_CHAR)
+}
+
+func decodeString(src string, pos int) (ret int, v string) {
+ ret, ep := skipString(src, pos)
+ if ep == -1 {
+ (*rt.GoString)(unsafe.Pointer(&v)).Ptr = rt.IndexChar(src, pos+1)
+ (*rt.GoString)(unsafe.Pointer(&v)).Len = ret - pos - 2
+ return ret, v
+ }
+
+ vv, ok := unquoteBytes(rt.Str2Mem(src[pos:ret]))
+ if !ok {
+ return -int(types.ERR_INVALID_CHAR), ""
+ }
+
+ runtime.KeepAlive(src)
+ return ret, rt.Mem2Str(vv)
+}
+
+func decodeBinary(src string, pos int) (ret int, v []byte) {
+ var vv string
+ ret, vv = decodeString(src, pos)
+ if ret < 0 {
+ return ret, nil
+ }
+ var err error
+ v, err = base64.StdEncoding.DecodeString(vv)
+ if err != nil {
+ return -int(types.ERR_INVALID_CHAR), nil
+ }
+ return ret, v
+}
+
+func isDigit(c byte) bool {
+ return c >= '0' && c <= '9'
+}
+
+func decodeInt64(src string, pos int) (ret int, v int64, err error) {
+ sp := uintptr(rt.IndexChar(src, pos))
+ ss := uintptr(sp)
+ se := uintptr(rt.IndexChar(src, len(src)))
+ if uintptr(sp) >= se {
+ return -int(types.ERR_EOF), 0, nil
+ }
+
+ if c := *(*byte)(unsafe.Pointer(sp)); c == '-' {
+ sp += 1
+ }
+ if sp == se {
+ return -int(types.ERR_EOF), 0, nil
+ }
+
+ for ; sp < se; sp += uintptr(1) {
+ if !isDigit(*(*byte)(unsafe.Pointer(sp))) {
+ break
+ }
+ }
+
+ if sp < se {
+ if c := *(*byte)(unsafe.Pointer(sp)); c == '.' || c == 'e' || c == 'E' {
+ return -int(types.ERR_INVALID_NUMBER_FMT), 0, nil
+ }
+ }
+
+ var vv string
+ ret = int(uintptr(sp) - uintptr((*rt.GoString)(unsafe.Pointer(&src)).Ptr))
+ (*rt.GoString)(unsafe.Pointer(&vv)).Ptr = unsafe.Pointer(ss)
+ (*rt.GoString)(unsafe.Pointer(&vv)).Len = ret - pos
+
+ v, err = strconv.ParseInt(vv, 10, 64)
+ if err != nil {
+ //NOTICE: allow overflow here
+ if err.(*strconv.NumError).Err == strconv.ErrRange {
+ return ret, 0, err
+ }
+ return -int(types.ERR_INVALID_CHAR), 0, err
+ }
+
+ runtime.KeepAlive(src)
+ return ret, v, nil
+}
+
+func isNumberChars(c byte) bool {
+ return (c >= '0' && c <= '9') || c == '+' || c == '-' || c == 'e' || c == 'E' || c == '.'
+}
+
+func decodeFloat64(src string, pos int) (ret int, v float64, err error) {
+ sp := uintptr(rt.IndexChar(src, pos))
+ ss := uintptr(sp)
+ se := uintptr(rt.IndexChar(src, len(src)))
+ if uintptr(sp) >= se {
+ return -int(types.ERR_EOF), 0, nil
+ }
+
+ if c := *(*byte)(unsafe.Pointer(sp)); c == '-' {
+ sp += 1
+ }
+ if sp == se {
+ return -int(types.ERR_EOF), 0, nil
+ }
+
+ for ; sp < se; sp += uintptr(1) {
+ if !isNumberChars(*(*byte)(unsafe.Pointer(sp))) {
+ break
+ }
+ }
+
+ var vv string
+ ret = int(uintptr(sp) - uintptr((*rt.GoString)(unsafe.Pointer(&src)).Ptr))
+ (*rt.GoString)(unsafe.Pointer(&vv)).Ptr = unsafe.Pointer(ss)
+ (*rt.GoString)(unsafe.Pointer(&vv)).Len = ret - pos
+
+ v, err = strconv.ParseFloat(vv, 64)
+ if err != nil {
+ //NOTICE: allow overflow here
+ if err.(*strconv.NumError).Err == strconv.ErrRange {
+ return ret, 0, err
+ }
+ return -int(types.ERR_INVALID_CHAR), 0, err
+ }
+
+ runtime.KeepAlive(src)
+ return ret, v, nil
+}
+
+func decodeValue(src string, pos int) (ret int, v types.JsonState) {
+ pos = skipBlank(src, pos)
+ if pos < 0 {
+ return pos, types.JsonState{Vt: types.ValueType(pos)}
+ }
+ switch c := src[pos]; c {
+ case 'n':
+ ret = decodeNull(src, pos)
+ if ret < 0 {
+ return ret, types.JsonState{Vt: types.ValueType(ret)}
+ }
+ return ret, types.JsonState{Vt: types.V_NULL}
+ case '"':
+ var ep int
+ ret, ep = skipString(src, pos)
+ if ret < 0 {
+ return ret, types.JsonState{Vt: types.ValueType(ret)}
+ }
+ return ret, types.JsonState{Vt: types.V_STRING, Iv: int64(pos + 1), Ep: ep}
+ case '{':
+ return pos + 1, types.JsonState{Vt: types.V_OBJECT}
+ case '[':
+ return pos + 1, types.JsonState{Vt: types.V_ARRAY}
+ case 't':
+ ret = decodeTrue(src, pos)
+ if ret < 0 {
+ return ret, types.JsonState{Vt: types.ValueType(ret)}
+ }
+ return ret, types.JsonState{Vt: types.V_TRUE}
+ case 'f':
+ ret = decodeFalse(src, pos)
+ if ret < 0 {
+ return ret, types.JsonState{Vt: types.ValueType(ret)}
+ }
+ 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}
+ } 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)}
+ }
+}
+
+func skipNumber(src string, pos int) (ret int) {
+ sp := uintptr(rt.IndexChar(src, pos))
+ se := uintptr(rt.IndexChar(src, len(src)))
+ if uintptr(sp) >= se {
+ return -int(types.ERR_EOF)
+ }
+
+ if c := *(*byte)(unsafe.Pointer(sp)); c == '-' {
+ sp += 1
+ }
+ ss := sp
+
+ var pointer bool
+ var exponent bool
+ var lastIsDigit bool
+ var nextNeedDigit = true
+
+ for ; sp < se; sp += uintptr(1) {
+ c := *(*byte)(unsafe.Pointer(sp))
+ if isDigit(c) {
+ lastIsDigit = true
+ nextNeedDigit = false
+ continue
+ } else if nextNeedDigit {
+ return -int(types.ERR_INVALID_CHAR)
+ } else if c == '.' {
+ if !lastIsDigit || pointer || sp == ss {
+ return -int(types.ERR_INVALID_CHAR)
+ }
+ pointer = true
+ lastIsDigit = false
+ nextNeedDigit = true
+ continue
+ } else if c == 'e' || c == 'E' {
+ if !lastIsDigit || exponent {
+ return -int(types.ERR_INVALID_CHAR)
+ }
+ if sp == se-1 {
+ return -int(types.ERR_EOF)
+ }
+ exponent = true
+ lastIsDigit = false
+ nextNeedDigit = false
+ continue
+ } else if c == '-' || c == '+' {
+ if prev := *(*byte)(unsafe.Pointer(sp - 1)); prev != 'e' && prev != 'E' {
+ return -int(types.ERR_INVALID_CHAR)
+ }
+ lastIsDigit = false
+ nextNeedDigit = true
+ continue
+ } else {
+ break
+ }
+ }
+
+ if nextNeedDigit {
+ return -int(types.ERR_EOF)
+ }
+
+ runtime.KeepAlive(src)
+ return int(uintptr(sp) - uintptr((*rt.GoString)(unsafe.Pointer(&src)).Ptr))
+}
+
+func skipString(src string, pos int) (ret int, ep int) {
+ if pos+1 >= len(src) {
+ return -int(types.ERR_EOF), -1
+ }
+
+ sp := uintptr(rt.IndexChar(src, pos))
+ se := uintptr(rt.IndexChar(src, len(src)))
+
+ if *(*byte)(unsafe.Pointer(sp)) != '"' {
+ return -int(types.ERR_INVALID_CHAR), -1
+ }
+ sp += 1
+
+ ep = -1
+ for sp < se {
+ c := *(*byte)(unsafe.Pointer(sp))
+ if c == '\\' {
+ if ep == -1 {
+ ep = int(uintptr(sp) - uintptr((*rt.GoString)(unsafe.Pointer(&src)).Ptr))
+ }
+ sp += 2
+ continue
+ }
+ sp += 1
+ if c == '"' {
+ break
+ }
+ }
+
+ if sp > se {
+ return -int(types.ERR_EOF), -1
+ }
+
+ runtime.KeepAlive(src)
+ return int(uintptr(sp) - uintptr((*rt.GoString)(unsafe.Pointer(&src)).Ptr)), ep
+}
+
+func skipPair(src string, pos int, lchar byte, rchar byte) (ret int) {
+ if pos+1 >= len(src) {
+ return -int(types.ERR_EOF)
+ }
+
+ sp := uintptr(rt.IndexChar(src, pos))
+ se := uintptr(rt.IndexChar(src, len(src)))
+
+ if *(*byte)(unsafe.Pointer(sp)) != lchar {
+ return -int(types.ERR_INVALID_CHAR)
+ }
+
+ sp += 1
+ nbrace := 1
+ inquote := false
+
+ for sp < se {
+ c := *(*byte)(unsafe.Pointer(sp))
+ if c == '\\' {
+ sp += 2
+ continue
+ } else if c == '"' {
+ inquote = !inquote
+ } else if c == lchar {
+ if !inquote {
+ nbrace += 1
+ }
+ } else if c == rchar {
+ if !inquote {
+ nbrace -= 1
+ if nbrace == 0 {
+ sp += 1
+ break
+ }
+ }
+ }
+ sp += 1
+ }
+
+ if nbrace != 0 {
+ return -int(types.ERR_INVALID_CHAR)
+ }
+
+ runtime.KeepAlive(src)
+ return int(uintptr(sp) - uintptr((*rt.GoString)(unsafe.Pointer(&src)).Ptr))
+}
+
+func skipValue(src string, pos int) (ret int, start int) {
+ pos = skipBlank(src, pos)
+ if pos < 0 {
+ return pos, -1
+ }
+ switch c := src[pos]; c {
+ case 'n':
+ ret = decodeNull(src, pos)
+ case '"':
+ ret, _ = skipString(src, pos)
+ case '{':
+ ret = skipPair(src, pos, '{', '}')
+ case '[':
+ ret = skipPair(src, pos, '[', ']')
+ case 't':
+ ret = decodeTrue(src, pos)
+ case 'f':
+ ret = decodeFalse(src, pos)
+ case '-', '+', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+ ret = skipNumber(src, pos)
+ default:
+ ret = -int(types.ERR_INVALID_CHAR)
+ }
+ return ret, pos
+}
diff --git a/vendor/github.com/bytedance/sonic/ast/encode.go b/vendor/github.com/bytedance/sonic/ast/encode.go
new file mode 100644
index 000000000..1187e30c2
--- /dev/null
+++ b/vendor/github.com/bytedance/sonic/ast/encode.go
@@ -0,0 +1,259 @@
+/*
+ * 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 (
+ `sync`
+ `unicode/utf8`
+
+ `github.com/bytedance/sonic/internal/rt`
+)
+
+const (
+ _MaxBuffer = 1024 // 1KB buffer size
+)
+
+func quoteString(e *[]byte, s string) {
+ *e = append(*e, '"')
+ start := 0
+ for i := 0; i < len(s); {
+ if b := s[i]; b < utf8.RuneSelf {
+ if safeSet[b] {
+ i++
+ continue
+ }
+ if start < i {
+ *e = append(*e, s[start:i]...)
+ }
+ *e = append(*e, '\\')
+ switch b {
+ case '\\', '"':
+ *e = append(*e, b)
+ case '\n':
+ *e = append(*e, 'n')
+ case '\r':
+ *e = append(*e, 'r')
+ case '\t':
+ *e = append(*e, 't')
+ default:
+ // This encodes bytes < 0x20 except for \t, \n and \r.
+ // If escapeHTML is set, it also escapes <, >, and &
+ // because they can lead to security holes when
+ // user-controlled strings are rendered into JSON
+ // and served to some browsers.
+ *e = append(*e, `u00`...)
+ *e = append(*e, hex[b>>4])
+ *e = append(*e, hex[b&0xF])
+ }
+ i++
+ start = i
+ continue
+ }
+ c, size := utf8.DecodeRuneInString(s[i:])
+ // if c == utf8.RuneError && size == 1 {
+ // if start < i {
+ // e.Write(s[start:i])
+ // }
+ // e.WriteString(`\ufffd`)
+ // i += size
+ // start = i
+ // continue
+ // }
+ if c == '\u2028' || c == '\u2029' {
+ if start < i {
+ *e = append(*e, s[start:i]...)
+ }
+ *e = append(*e, `\u202`...)
+ *e = append(*e, hex[c&0xF])
+ i += size
+ start = i
+ continue
+ }
+ i += size
+ }
+ if start < len(s) {
+ *e = append(*e, s[start:]...)
+ }
+ *e = append(*e, '"')
+}
+
+var bytesPool = sync.Pool{}
+
+func (self *Node) MarshalJSON() ([]byte, error) {
+ buf := newBuffer()
+ err := self.encode(buf)
+ if err != nil {
+ freeBuffer(buf)
+ return nil, err
+ }
+
+ ret := make([]byte, len(*buf))
+ copy(ret, *buf)
+ freeBuffer(buf)
+ return ret, err
+}
+
+func newBuffer() *[]byte {
+ if ret := bytesPool.Get(); ret != nil {
+ return ret.(*[]byte)
+ } else {
+ buf := make([]byte, 0, _MaxBuffer)
+ return &buf
+ }
+}
+
+func freeBuffer(buf *[]byte) {
+ *buf = (*buf)[:0]
+ bytesPool.Put(buf)
+}
+
+func (self *Node) encode(buf *[]byte) error {
+ if self.IsRaw() {
+ return self.encodeRaw(buf)
+ }
+ switch self.Type() {
+ case V_NONE : return ErrNotExist
+ case V_ERROR : return self.Check()
+ case V_NULL : return self.encodeNull(buf)
+ case V_TRUE : return self.encodeTrue(buf)
+ case V_FALSE : return self.encodeFalse(buf)
+ case V_ARRAY : return self.encodeArray(buf)
+ case V_OBJECT: return self.encodeObject(buf)
+ case V_STRING: return self.encodeString(buf)
+ case V_NUMBER: return self.encodeNumber(buf)
+ case V_ANY : return self.encodeInterface(buf)
+ default : return ErrUnsupportType
+ }
+}
+
+func (self *Node) encodeRaw(buf *[]byte) error {
+ raw, err := self.Raw()
+ if err != nil {
+ return err
+ }
+ *buf = append(*buf, raw...)
+ return nil
+}
+
+func (self *Node) encodeNull(buf *[]byte) error {
+ *buf = append(*buf, bytesNull...)
+ return nil
+}
+
+func (self *Node) encodeTrue(buf *[]byte) error {
+ *buf = append(*buf, bytesTrue...)
+ return nil
+}
+
+func (self *Node) encodeFalse(buf *[]byte) error {
+ *buf = append(*buf, bytesFalse...)
+ return nil
+}
+
+func (self *Node) encodeNumber(buf *[]byte) error {
+ str := rt.StrFrom(self.p, self.v)
+ *buf = append(*buf, str...)
+ return nil
+}
+
+func (self *Node) encodeString(buf *[]byte) error {
+ if self.v == 0 {
+ *buf = append(*buf, '"', '"')
+ return nil
+ }
+
+ quote(buf, rt.StrFrom(self.p, self.v))
+ return nil
+}
+
+func (self *Node) encodeArray(buf *[]byte) error {
+ if self.isLazy() {
+ if err := self.skipAllIndex(); err != nil {
+ return err
+ }
+ }
+
+ nb := self.len()
+ if nb == 0 {
+ *buf = append(*buf, bytesArray...)
+ return nil
+ }
+
+ *buf = append(*buf, '[')
+
+ var p = (*Node)(self.p)
+ err := p.encode(buf)
+ if err != nil {
+ return err
+ }
+ for i := 1; i < nb; i++ {
+ *buf = append(*buf, ',')
+ p = p.unsafe_next()
+ err := p.encode(buf)
+ if err != nil {
+ return err
+ }
+ }
+
+ *buf = append(*buf, ']')
+ return nil
+}
+
+func (self *Pair) encode(buf *[]byte) error {
+ if len(*buf) == 0 {
+ *buf = append(*buf, '"', '"', ':')
+ return self.Value.encode(buf)
+ }
+
+ quote(buf, self.Key)
+ *buf = append(*buf, ':')
+
+ return self.Value.encode(buf)
+}
+
+func (self *Node) encodeObject(buf *[]byte) error {
+ if self.isLazy() {
+ if err := self.skipAllKey(); err != nil {
+ return err
+ }
+ }
+
+ nb := self.len()
+ if nb == 0 {
+ *buf = append(*buf, bytesObject...)
+ return nil
+ }
+
+ *buf = append(*buf, '{')
+
+ var p = (*Pair)(self.p)
+ err := p.encode(buf)
+ if err != nil {
+ return err
+ }
+ for i := 1; i < nb; i++ {
+ *buf = append(*buf, ',')
+ p = p.unsafe_next()
+ err := p.encode(buf)
+ if 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
new file mode 100644
index 000000000..f4c441ae6
--- /dev/null
+++ b/vendor/github.com/bytedance/sonic/ast/error.go
@@ -0,0 +1,98 @@
+package ast
+
+import (
+ `fmt`
+ `strings`
+ `unsafe`
+
+ `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 newSyntaxError(err SyntaxError) *Node {
+ msg := err.Description()
+ return &Node{
+ t: V_ERROR,
+ v: int64(err.Code),
+ p: unsafe.Pointer(&msg),
+ }
+}
+
+type SyntaxError struct {
+ Pos int
+ Src string
+ Code types.ParsingError
+ Msg string
+}
+
+func (self SyntaxError) Error() string {
+ return fmt.Sprintf("%q", self.Description())
+}
+
+func (self SyntaxError) Description() string {
+ return "Syntax error " + self.description()
+}
+
+func (self SyntaxError) description() string {
+ i := 16
+ p := self.Pos - i
+ q := self.Pos + i
+
+ /* check for empty source */
+ if self.Src == "" {
+ return fmt.Sprintf("no sources available: %#v", self)
+ }
+
+ /* prevent slicing before the beginning */
+ if p < 0 {
+ p, q, i = 0, q - p, i + p
+ }
+
+ /* prevent slicing beyond the end */
+ if n := len(self.Src); q > n {
+ n = q - n
+ q = len(self.Src)
+
+ /* move the left bound if possible */
+ if p > n {
+ i += n
+ p -= n
+ }
+ }
+
+ /* left and right length */
+ x := clamp_zero(i)
+ y := clamp_zero(q - p - i - 1)
+
+ /* compose the error description */
+ return fmt.Sprintf(
+ "at index %d: %s\n\n\t%s\n\t%s^%s\n",
+ self.Pos,
+ self.Message(),
+ self.Src[p:q],
+ strings.Repeat(".", x),
+ strings.Repeat(".", y),
+ )
+}
+
+func (self SyntaxError) Message() string {
+ if self.Msg == "" {
+ return self.Code.Message()
+ }
+ return self.Msg
+}
+
+func clamp_zero(v int) int {
+ if v < 0 {
+ return 0
+ } else {
+ return v
+ }
+}
diff --git a/vendor/github.com/bytedance/sonic/ast/iterator.go b/vendor/github.com/bytedance/sonic/ast/iterator.go
new file mode 100644
index 000000000..03a25b4e9
--- /dev/null
+++ b/vendor/github.com/bytedance/sonic/ast/iterator.go
@@ -0,0 +1,164 @@
+/*
+ * 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 (
+ `fmt`
+
+ `github.com/bytedance/sonic/internal/native/types`
+)
+
+type Pair struct {
+ Key string
+ Value Node
+}
+
+// Values returns iterator for array's children traversal
+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
+}
+
+// Properties returns iterator for object's children traversal
+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
+}
+
+type Iterator struct {
+ i int
+ p *Node
+}
+
+func (self *Iterator) Pos() int {
+ return self.i
+}
+
+func (self *Iterator) Len() int {
+ return self.p.len()
+}
+
+// HasNext reports if it is the end of iteration or has error.
+func (self *Iterator) HasNext() bool {
+ if !self.p.isLazy() {
+ return self.p.Valid() && self.i < self.p.len()
+ } else if self.p.t == _V_ARRAY_LAZY {
+ return self.p.skipNextNode().Valid()
+ } else if self.p.t == _V_OBJECT_LAZY {
+ pair := self.p.skipNextPair()
+ if pair == nil {
+ return false
+ }
+ return pair.Value.Valid()
+ }
+ return false
+}
+
+// ListIterator is specialized iterator for V_ARRAY
+type ListIterator struct {
+ Iterator
+}
+
+// ObjectIterator is specialized iterator for V_ARRAY
+type ObjectIterator struct {
+ Iterator
+}
+
+// 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() {
+ return false
+ } else {
+ *v, self.i = *self.p.nodeAt(self.i), self.i + 1
+ return true
+ }
+}
+
+// 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() {
+ return false
+ } else {
+ *p, self.i = *self.p.pairAt(self.i), self.i + 1
+ return true
+ }
+}
+
+// Sequence represents scanning path of single-layer nodes.
+// Index indicates the value's order in both V_ARRAY and V_OBJECT json.
+// Key is the value's key (for V_OBJECT json only, otherwise it will be nil).
+type Sequence struct {
+ Index int
+ Key *string
+ // Level int
+}
+
+// String is string representation of one Sequence
+func (s Sequence) String() string {
+ k := ""
+ if s.Key != nil {
+ k = *s.Key
+ }
+ return fmt.Sprintf("Sequence(%d, %q)", s.Index, k)
+}
+
+type Scanner func(path Sequence, node *Node) bool
+
+// ForEach scans one V_OBJECT node's children from JSON head to tail,
+// and pass the Sequence and Node of corresponding JSON value.
+//
+// Especailly, if the node is not V_ARRAY or V_OBJECT,
+// the node itself will be returned and Sequence.Index == -1.
+func (self *Node) ForEach(sc Scanner) error {
+ switch self.itype() {
+ case types.V_ARRAY:
+ ns, err := self.UnsafeArray()
+ if err != nil {
+ return err
+ }
+ for i := range ns {
+ if !sc(Sequence{i, nil}, &ns[i]) {
+ return err
+ }
+ }
+ case types.V_OBJECT:
+ ns, err := self.UnsafeMap()
+ if err != nil {
+ return err
+ }
+ for i := range ns {
+ if !sc(Sequence{i, &ns[i].Key}, &ns[i].Value) {
+ return err
+ }
+ }
+ default:
+ sc(Sequence{-1, nil}, self)
+ }
+ return self.Check()
+}
+
+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
new file mode 100644
index 000000000..0d37baf12
--- /dev/null
+++ b/vendor/github.com/bytedance/sonic/ast/node.go
@@ -0,0 +1,1802 @@
+/*
+ * 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`
+ `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
+ _V_RAW types.ValueType = 1 << 8
+ _V_NUMBER = _V_NODE_BASE + 1
+ _V_ANY = _V_NODE_BASE + 2
+ _V_ARRAY_LAZY = _V_LAZY | types.V_ARRAY
+ _V_OBJECT_LAZY = _V_LAZY | types.V_OBJECT
+ _MASK_LAZY = _V_LAZY - 1
+ _MASK_RAW = _V_RAW - 1
+)
+
+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_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
+ 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
+}
+
+/** Node Type Accessor **/
+
+// Type returns json type represented by the node
+// It will be one of belows:
+// V_NONE = 0 (empty node)
+// V_ERROR = 1 (error node)
+// V_NULL = 2 (json value `null`)
+// V_TRUE = 3 (json value `true`)
+// V_FALSE = 4 (json value `false`)
+// V_ARRAY = 5 (json value array)
+// V_OBJECT = 6 (json value object)
+// V_STRING = 7 (json value string)
+// V_NUMBER = 33 (json value number )
+// V_ANY = 34 (golang interface{})
+func (self Node) Type() int {
+ return int(self.t & _MASK_LAZY & _MASK_RAW)
+}
+
+func (self Node) itype() types.ValueType {
+ return self.t & _MASK_LAZY & _MASK_RAW
+}
+
+// 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
+}
+
+// Valid reports if self is NOT V_ERROR or nil
+func (self *Node) Valid() bool {
+ if self == nil {
+ return false
+ }
+ return self.t != V_ERROR
+}
+
+// Check checks if the node itself is valid, and return:
+// - ErrNotFound If the node is nil
+// - Its underlying error If the node is V_ERROR
+func (self *Node) Check() error {
+ if self == nil {
+ return ErrNotExist
+ } else if self.t != V_ERROR {
+ return nil
+ } else {
+ return self
+ }
+}
+
+// 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
+}
+
+func (self *Node) isLazy() bool {
+ return self != nil && self.t&_V_LAZY != 0
+}
+
+func (self *Node) isAny() bool {
+ return self != nil && self.t == _V_ANY
+}
+
+/** Simple Value Methods **/
+
+// Raw returns json representation of the node,
+func (self *Node) Raw() (string, error) {
+ if !self.IsRaw() {
+ buf, err := self.MarshalJSON()
+ return rt.Mem2Str(buf), err
+ }
+ return rt.StrFrom(self.p, self.v), nil
+}
+
+func (self *Node) checkRaw() error {
+ if err := self.Check(); err != nil {
+ return err
+ }
+ if self.IsRaw() {
+ self.parseRaw(false)
+ }
+ return nil
+}
+
+// Bool returns bool value represented by this node,
+// including types.V_TRUE|V_FALSE|V_NUMBER|V_STRING|V_ANY|V_NULL,
+// V_NONE will return error
+func (self *Node) Bool() (bool, error) {
+ if err := self.checkRaw(); err != nil {
+ return false, err
+ }
+ switch self.t {
+ case types.V_TRUE : return true , nil
+ case types.V_FALSE : return false, nil
+ case types.V_NULL : return false, nil
+ case _V_NUMBER :
+ if i, err := numberToInt64(self); err == nil {
+ return i != 0, nil
+ } else if f, err := numberToFloat64(self); err == nil {
+ return f != 0, nil
+ } else {
+ return false, err
+ }
+ case types.V_STRING: return strconv.ParseBool(rt.StrFrom(self.p, self.v))
+ case _V_ANY :
+ any := self.packAny()
+ switch v := any.(type) {
+ case bool : return v, nil
+ case int : return v != 0, nil
+ case int8 : return v != 0, nil
+ case int16 : return v != 0, nil
+ case int32 : return v != 0, nil
+ case int64 : return v != 0, nil
+ case uint : return v != 0, nil
+ case uint8 : return v != 0, nil
+ case uint16 : return v != 0, nil
+ case uint32 : return v != 0, nil
+ case uint64 : return v != 0, nil
+ case float32: return v != 0, nil
+ case float64: return v != 0, nil
+ case string : return strconv.ParseBool(v)
+ case json.Number:
+ if i, err := v.Int64(); err == nil {
+ return i != 0, nil
+ } else if f, err := v.Float64(); err == nil {
+ return f != 0, nil
+ } else {
+ return false, err
+ }
+ default: return false, ErrUnsupportType
+ }
+ default : return false, ErrUnsupportType
+ }
+}
+
+// Int64 casts the node to int64 value,
+// including V_NUMBER|V_TRUE|V_FALSE|V_ANY|V_STRING
+// V_NONE it will return error
+func (self *Node) Int64() (int64, error) {
+ if err := self.checkRaw(); err != nil {
+ return 0, err
+ }
+ switch self.t {
+ case _V_NUMBER, types.V_STRING :
+ if i, err := numberToInt64(self); err == nil {
+ return i, nil
+ } else if f, err := numberToFloat64(self); err == nil {
+ return int64(f), nil
+ } else {
+ return 0, err
+ }
+ case types.V_TRUE : return 1, nil
+ case types.V_FALSE : return 0, nil
+ case types.V_NULL : return 0, nil
+ case _V_ANY :
+ any := self.packAny()
+ switch v := any.(type) {
+ case bool : if v { return 1, nil } else { return 0, nil }
+ case int : return int64(v), nil
+ case int8 : return int64(v), nil
+ case int16 : return int64(v), nil
+ case int32 : return int64(v), nil
+ case int64 : return int64(v), nil
+ case uint : return int64(v), nil
+ case uint8 : return int64(v), nil
+ case uint16 : return int64(v), nil
+ case uint32 : return int64(v), nil
+ case uint64 : return int64(v), nil
+ case float32: return int64(v), nil
+ case float64: return int64(v), nil
+ case string :
+ if i, err := strconv.ParseInt(v, 10, 64); err == nil {
+ return i, nil
+ } else if f, err := strconv.ParseFloat(v, 64); err == nil {
+ return int64(f), nil
+ } else {
+ return 0, err
+ }
+ case json.Number:
+ if i, err := v.Int64(); err == nil {
+ return i, nil
+ } else if f, err := v.Float64(); err == nil {
+ return int64(f), nil
+ } else {
+ return 0, err
+ }
+ default: return 0, ErrUnsupportType
+ }
+ default : return 0, ErrUnsupportType
+ }
+}
+
+// StrictInt64 exports underlying int64 value, including V_NUMBER, V_ANY
+func (self *Node) StrictInt64() (int64, error) {
+ if err := self.checkRaw(); err != nil {
+ return 0, err
+ }
+ switch self.t {
+ case _V_NUMBER : return numberToInt64(self)
+ case _V_ANY :
+ any := self.packAny()
+ switch v := any.(type) {
+ case int : return int64(v), nil
+ case int8 : return int64(v), nil
+ case int16 : return int64(v), nil
+ case int32 : return int64(v), nil
+ case int64 : return int64(v), nil
+ case uint : return int64(v), nil
+ case uint8 : return int64(v), nil
+ case uint16: return int64(v), nil
+ case uint32: return int64(v), nil
+ case uint64: return int64(v), nil
+ case json.Number:
+ if i, err := v.Int64(); err == nil {
+ return i, nil
+ } else {
+ return 0, err
+ }
+ default: return 0, ErrUnsupportType
+ }
+ default : return 0, ErrUnsupportType
+ }
+}
+
+func castNumber(v bool) json.Number {
+ if v {
+ return json.Number("1")
+ } else {
+ return json.Number("0")
+ }
+}
+
+// Number casts node to float64,
+// including V_NUMBER|V_TRUE|V_FALSE|V_ANY|V_STRING|V_NULL,
+// V_NONE it will return error
+func (self *Node) Number() (json.Number, error) {
+ if err := self.checkRaw(); err != nil {
+ return json.Number(""), err
+ }
+ switch self.t {
+ case _V_NUMBER : return toNumber(self) , 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
+ } else {
+ return json.Number(""), err
+ }
+ case types.V_TRUE : return json.Number("1"), nil
+ case types.V_FALSE : return json.Number("0"), nil
+ case types.V_NULL : return json.Number("0"), nil
+ case _V_ANY :
+ any := self.packAny()
+ switch v := any.(type) {
+ case bool : return castNumber(v), nil
+ case int : return castNumber(v != 0), nil
+ case int8 : return castNumber(v != 0), nil
+ case int16 : return castNumber(v != 0), nil
+ case int32 : return castNumber(v != 0), nil
+ case int64 : return castNumber(v != 0), nil
+ case uint : return castNumber(v != 0), nil
+ case uint8 : return castNumber(v != 0), nil
+ case uint16 : return castNumber(v != 0), nil
+ case uint32 : return castNumber(v != 0), nil
+ case uint64 : return castNumber(v != 0), nil
+ case float32: return castNumber(v != 0), nil
+ case float64: return castNumber(v != 0), nil
+ case string :
+ if _, err := strconv.ParseFloat(v, 64); err == nil {
+ return json.Number(v), nil
+ } else {
+ return json.Number(""), err
+ }
+ case json.Number: return v, nil
+ default: return json.Number(""), ErrUnsupportType
+ }
+ default : return json.Number(""), ErrUnsupportType
+ }
+}
+
+// Number exports underlying float64 value, including V_NUMBER, V_ANY of json.Number
+func (self *Node) StrictNumber() (json.Number, error) {
+ if err := self.checkRaw(); err != nil {
+ return json.Number(""), err
+ }
+ switch self.t {
+ case _V_NUMBER : return toNumber(self) , nil
+ case _V_ANY :
+ if v, ok := self.packAny().(json.Number); ok {
+ return v, nil
+ } else {
+ return json.Number(""), ErrUnsupportType
+ }
+ default : return json.Number(""), ErrUnsupportType
+ }
+}
+
+// String cast node to string,
+// including V_NUMBER|V_TRUE|V_FALSE|V_ANY|V_STRING|V_NULL,
+// V_NONE it will return error
+func (self *Node) String() (string, error) {
+ if err := self.checkRaw(); err != nil {
+ return "", err
+ }
+ switch self.t {
+ 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 _V_ANY :
+ any := self.packAny()
+ switch v := any.(type) {
+ case bool : return strconv.FormatBool(v), nil
+ case int : return strconv.Itoa(v), nil
+ case int8 : return strconv.Itoa(int(v)), nil
+ case int16 : return strconv.Itoa(int(v)), nil
+ case int32 : return strconv.Itoa(int(v)), nil
+ case int64 : return strconv.Itoa(int(v)), nil
+ case uint : return strconv.Itoa(int(v)), nil
+ case uint8 : return strconv.Itoa(int(v)), nil
+ case uint16 : return strconv.Itoa(int(v)), nil
+ case uint32 : return strconv.Itoa(int(v)), nil
+ case uint64 : return strconv.Itoa(int(v)), nil
+ case float32: return strconv.FormatFloat(float64(v), 'g', -1, 64), nil
+ case float64: return strconv.FormatFloat(float64(v), 'g', -1, 64), nil
+ case string : return v, nil
+ case json.Number: return v.String(), nil
+ default: return "", ErrUnsupportType
+ }
+ default : return "" , ErrUnsupportType
+ }
+}
+
+// StrictString returns string value (unescaped), includeing V_STRING, V_ANY of string.
+// In other cases, it will return empty string.
+func (self *Node) StrictString() (string, error) {
+ if err := self.checkRaw(); err != nil {
+ return "", err
+ }
+ switch self.t {
+ case types.V_STRING : return rt.StrFrom(self.p, self.v), nil
+ case _V_ANY :
+ if v, ok := self.packAny().(string); ok {
+ return v, nil
+ } else {
+ return "", ErrUnsupportType
+ }
+ default : return "", ErrUnsupportType
+ }
+}
+
+// Float64 cast node to float64,
+// including V_NUMBER|V_TRUE|V_FALSE|V_ANY|V_STRING|V_NULL,
+// V_NONE it will return error
+func (self *Node) Float64() (float64, error) {
+ if err := self.checkRaw(); err != nil {
+ return 0.0, err
+ }
+ switch self.t {
+ case _V_NUMBER, types.V_STRING : return numberToFloat64(self)
+ case types.V_TRUE : return 1.0, nil
+ case types.V_FALSE : return 0.0, nil
+ case types.V_NULL : return 0.0, nil
+ case _V_ANY :
+ any := self.packAny()
+ switch v := any.(type) {
+ case bool :
+ if v {
+ return 1.0, nil
+ } else {
+ return 0.0, nil
+ }
+ case int : return float64(v), nil
+ case int8 : return float64(v), nil
+ case int16 : return float64(v), nil
+ case int32 : return float64(v), nil
+ case int64 : return float64(v), nil
+ case uint : return float64(v), nil
+ case uint8 : return float64(v), nil
+ case uint16 : return float64(v), nil
+ case uint32 : return float64(v), nil
+ case uint64 : return float64(v), nil
+ case float32: return float64(v), nil
+ case float64: return float64(v), nil
+ case string :
+ if f, err := strconv.ParseFloat(v, 64); err == nil {
+ return float64(f), nil
+ } else {
+ return 0, err
+ }
+ case json.Number:
+ if f, err := v.Float64(); err == nil {
+ return float64(f), nil
+ } else {
+ return 0, err
+ }
+ default : return 0, ErrUnsupportType
+ }
+ default : return 0.0, ErrUnsupportType
+ }
+}
+
+// Float64 exports underlying float64 value, includeing V_NUMBER, V_ANY
+func (self *Node) StrictFloat64() (float64, error) {
+ if err := self.checkRaw(); err != nil {
+ return 0.0, err
+ }
+ switch self.t {
+ case _V_NUMBER : return numberToFloat64(self)
+ case _V_ANY :
+ any := self.packAny()
+ switch v := any.(type) {
+ case float32 : return float64(v), nil
+ case float64 : return float64(v), nil
+ default : return 0, ErrUnsupportType
+ }
+ default : return 0.0, ErrUnsupportType
+ }
+}
+
+/** 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
+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
+ } else if self.t == _V_NONE || self.t == types.V_NULL {
+ return 0, nil
+ } else {
+ return 0, ErrUnsupportType
+ }
+}
+
+func (self Node) len() int {
+ return int(self.v & _LEN_MASK)
+}
+
+// Cap returns malloc capacity of a array|object node for children
+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
+ }
+}
+
+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 := node.Check(); err != nil {
+ return false, err
+ }
+
+ 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
+ }
+ v := self.pairAt(l)
+ v.Key = key
+ v.Value = node
+ self.setCapAndLen(c, l+1)
+ return false, nil
+
+ } else if err := p.Check(); err != nil {
+ return false, err
+ }
+
+ *p = node
+ return true, nil
+}
+
+// SetAny wraps val with V_ANY node, and Set() the node.
+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.
+func (self *Node) Unset(key string) (bool, error) {
+ self.must(types.V_OBJECT, "an object")
+ p, i := self.skipKey(key)
+ if !p.Exists() {
+ return false, nil
+ } else if err := p.Check(); err != nil {
+ return false, err
+ }
+
+ self.removePair(i)
+ return true, nil
+}
+
+// SetByIndex sets the node of given index, and reports if the key has existed.
+//
+// The index must be within self's children.
+func (self *Node) SetByIndex(index int, node Node) (bool, error) {
+ if err := node.Check(); err != nil {
+ return false, err
+ }
+
+ p := self.Index(index)
+ if !p.Exists() {
+ return false, ErrNotExist
+ } else if err := p.Check(); err != nil {
+ return false, err
+ }
+
+ *p = node
+ return true, nil
+}
+
+// SetAny wraps val with V_ANY node, and SetByIndex() the node.
+func (self *Node) SetAnyByIndex(index int, val interface{}) (bool, error) {
+ return self.SetByIndex(index, NewAny(val))
+}
+
+// UnsetByIndex remove the node of given index
+func (self *Node) UnsetByIndex(index int) (bool, error) {
+ var p *Node
+ it := self.itype()
+ if it == types.V_ARRAY {
+ p = self.Index(index)
+ }else if it == types.V_OBJECT {
+ pr := self.skipIndexPair(index)
+ if pr == nil {
+ return false, ErrNotExist
+ }
+ p = &pr.Value
+ } else {
+ return false, ErrUnsupportType
+ }
+
+ if !p.Exists() {
+ return false, ErrNotExist
+ }
+
+ if it == types.V_ARRAY {
+ self.removeNode(index)
+ }else if it == types.V_OBJECT {
+ self.removePair(index)
+ }
+ return true, nil
+}
+
+// Add appends the given node under self.
+//
+// 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 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 {
+ 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))
+ 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))
+}
+
+// GetByPath load given path on demands,
+// which only ensure nodes before this path got parsed.
+//
+// Note, the api expects the json is well-formed at least,
+// otherwise it may return unexpected result.
+func (self *Node) GetByPath(path ...interface{}) *Node {
+ if !self.Valid() {
+ return self
+ }
+ var s = self
+ for _, p := range path {
+ switch p := p.(type) {
+ case int:
+ s = s.Index(p)
+ if !s.Valid() {
+ return s
+ }
+ case string:
+ s = s.Get(p)
+ if !s.Valid() {
+ return s
+ }
+ default:
+ panic("path must be either int or string")
+ }
+ }
+ return s
+}
+
+// Get loads given key of an object node on demands
+func (self *Node) Get(key string) *Node {
+ if err := self.should(types.V_OBJECT, "an object"); err != nil {
+ return unwrapError(err)
+ }
+ n, _ := self.skipKey(key)
+ return n
+}
+
+// Index indexies node at given idx,
+// node type CAN be either V_OBJECT or V_ARRAY
+func (self *Node) Index(idx int) *Node {
+ if err := self.checkRaw(); err != nil {
+ return unwrapError(err)
+ }
+
+ it := self.itype()
+ if it == types.V_ARRAY {
+ return self.skipIndex(idx)
+
+ }else if it == types.V_OBJECT {
+ pr := self.skipIndexPair(idx)
+ if pr == nil {
+ return newError(_ERR_NOT_FOUND, "value not exists")
+ }
+ return &pr.Value
+
+ } else {
+ return newError(_ERR_UNSUPPORT_TYPE, fmt.Sprintf("unsupported type: %v", self.itype()))
+ }
+}
+
+// IndexPair indexies pair at given idx,
+// node type MUST be either V_OBJECT
+func (self *Node) IndexPair(idx int) *Pair {
+ if err := self.should(types.V_OBJECT, "an object"); err != nil {
+ return nil
+ }
+ return self.skipIndexPair(idx)
+}
+
+// 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)
+ }
+
+ pr := self.skipIndexPair(idx)
+ if pr != nil && pr.Key == key {
+ return &pr.Value
+ }
+ n, _ := self.skipKey(key)
+ return n
+}
+
+/** Generic Value Converters **/
+
+// Map loads all keys of an object node
+func (self *Node) Map() (map[string]interface{}, error) {
+ if self.isAny() {
+ any := self.packAny()
+ if v, ok := any.(map[string]interface{}); ok {
+ return v, nil
+ } else {
+ return nil, ErrUnsupportType
+ }
+ }
+ if err := self.should(types.V_OBJECT, "an object"); err != nil {
+ return nil, err
+ }
+ if err := self.loadAllKey(); err != nil {
+ return nil, err
+ }
+ return self.toGenericObject()
+}
+
+// MapUseNumber loads all keys of an object node, with numeric nodes casted to json.Number
+func (self *Node) MapUseNumber() (map[string]interface{}, error) {
+ if self.isAny() {
+ any := self.packAny()
+ if v, ok := any.(map[string]interface{}); ok {
+ return v, nil
+ } else {
+ return nil, ErrUnsupportType
+ }
+ }
+ if err := self.should(types.V_OBJECT, "an object"); err != nil {
+ return nil, err
+ }
+ if err := self.loadAllKey(); err != nil {
+ return nil, err
+ }
+ return self.toGenericObjectUseNumber()
+}
+
+// MapUseNode scans both parsed and non-parsed chidren nodes,
+// and map them by their keys
+func (self *Node) MapUseNode() (map[string]Node, error) {
+ if self.isAny() {
+ any := self.packAny()
+ if v, ok := any.(map[string]Node); ok {
+ return v, nil
+ } else {
+ return nil, ErrUnsupportType
+ }
+ }
+ 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.toGenericObjectUseNode()
+}
+
+// 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
+ }
+ if err := self.skipAllKey(); err != nil {
+ return nil, err
+ }
+ s := rt.Ptr2SlicePtr(self.p, int(self.len()), self.cap())
+ return *(*[]Pair)(s), 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()
+ if err != nil {
+ return err
+ }
+ PairSlice(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 {
+ return false
+ }
+ }
+ if node.itype() == types.V_ARRAY {
+ if err := node.ForEach(sc); err != nil {
+ return false
+ }
+ }
+ return true
+ }
+ self.ForEach(sc)
+ }
+ return nil
+}
+
+// Array loads all indexes of an array node
+func (self *Node) Array() ([]interface{}, error) {
+ if self.isAny() {
+ any := self.packAny()
+ if v, ok := any.([]interface{}); ok {
+ return v, nil
+ } else {
+ return nil, ErrUnsupportType
+ }
+ }
+ if err := self.should(types.V_ARRAY, "an array"); err != nil {
+ return nil, err
+ }
+ if err := self.loadAllIndex(); err != nil {
+ return nil, err
+ }
+ return self.toGenericArray()
+}
+
+// ArrayUseNumber loads all indexes of an array node, with numeric nodes casted to json.Number
+func (self *Node) ArrayUseNumber() ([]interface{}, error) {
+ if self.isAny() {
+ any := self.packAny()
+ if v, ok := any.([]interface{}); ok {
+ return v, nil
+ } else {
+ return nil, ErrUnsupportType
+ }
+ }
+ if err := self.should(types.V_ARRAY, "an array"); err != nil {
+ return nil, err
+ }
+ if err := self.loadAllIndex(); err != nil {
+ return nil, err
+ }
+ return self.toGenericArrayUseNumber()
+}
+
+// ArrayUseNode copys both parsed and non-parsed chidren nodes,
+// and indexes them by original order
+func (self *Node) ArrayUseNode() ([]Node, error) {
+ if self.isAny() {
+ any := self.packAny()
+ if v, ok := any.([]Node); ok {
+ return v, nil
+ } else {
+ return nil, ErrUnsupportType
+ }
+ }
+ 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()
+}
+
+// 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
+ }
+ if err := self.skipAllIndex(); err != nil {
+ return nil, err
+ }
+ s := rt.Ptr2SlicePtr(self.p, self.len(), self.cap())
+ return *(*[]Node)(s), nil
+}
+
+// Interface loads all children under all pathes from this node,
+// and converts itself as generic type.
+// WARN: all numberic nodes are casted to float64
+func (self *Node) Interface() (interface{}, error) {
+ if err := self.checkRaw(); err != nil {
+ return nil, err
+ }
+ switch self.t {
+ case V_ERROR : return nil, self.Check()
+ case types.V_NULL : return nil, nil
+ case types.V_TRUE : return true, nil
+ 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 _V_NUMBER :
+ v, err := numberToFloat64(self)
+ if err != nil {
+ return nil, err
+ }
+ return v, nil
+ case _V_ARRAY_LAZY :
+ if err := self.loadAllIndex(); err != nil {
+ return nil, err
+ }
+ return self.toGenericArray()
+ case _V_OBJECT_LAZY :
+ if err := self.loadAllKey(); err != nil {
+ return nil, err
+ }
+ return self.toGenericObject()
+ case _V_ANY:
+ switch v := self.packAny().(type) {
+ case Node : return v.Interface()
+ case *Node: return v.Interface()
+ default : return v, nil
+ }
+ default : return nil, ErrUnsupportType
+ }
+}
+
+func (self *Node) packAny() interface{} {
+ return *(*interface{})(self.p)
+}
+
+// InterfaceUseNumber works same with Interface()
+// except numberic nodes are casted to json.Number
+func (self *Node) InterfaceUseNumber() (interface{}, error) {
+ if err := self.checkRaw(); err != nil {
+ return nil, err
+ }
+ switch self.t {
+ case V_ERROR : return nil, self.Check()
+ case types.V_NULL : return nil, nil
+ case types.V_TRUE : return true, nil
+ 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 _V_ARRAY_LAZY :
+ if err := self.loadAllIndex(); err != nil {
+ return nil, err
+ }
+ return self.toGenericArrayUseNumber()
+ case _V_OBJECT_LAZY :
+ if err := self.loadAllKey(); err != nil {
+ return nil, err
+ }
+ return self.toGenericObjectUseNumber()
+ case _V_ANY : return self.packAny(), nil
+ default : return nil, ErrUnsupportType
+ }
+}
+
+// InterfaceUseNode clone itself as a new node,
+// or its children as map[string]Node (or []Node)
+func (self *Node) InterfaceUseNode() (interface{}, error) {
+ if err := self.checkRaw(); err != nil {
+ return nil, err
+ }
+ switch self.t {
+ case types.V_ARRAY : return self.toGenericArrayUseNode()
+ case types.V_OBJECT : return self.toGenericObjectUseNode()
+ case _V_ARRAY_LAZY :
+ if err := self.skipAllIndex(); err != nil {
+ return nil, err
+ }
+ return self.toGenericArrayUseNode()
+ case _V_OBJECT_LAZY :
+ if err := self.skipAllKey(); err != nil {
+ return nil, err
+ }
+ return self.toGenericObjectUseNode()
+ default : return *self, self.Check()
+ }
+}
+
+// LoadAll loads all the node's children and children's children as parsed.
+// After calling it, the node can be safely used on concurrency
+func (self *Node) LoadAll() error {
+ if self.IsRaw() {
+ self.parseRaw(true)
+ return self.Check()
+ }
+
+ switch self.itype() {
+ case types.V_ARRAY:
+ e := self.len()
+ if err := self.loadAllIndex(); err != nil {
+ return err
+ }
+ for i := 0; i < e; i++ {
+ n := self.nodeAt(i)
+ if n.IsRaw() {
+ n.parseRaw(true)
+ }
+ if err := n.Check(); err != nil {
+ return err
+ }
+ }
+ return nil
+ case types.V_OBJECT:
+ e := self.len()
+ if err := self.loadAllKey(); err != nil {
+ return err
+ }
+ for i := 0; i < e; i++ {
+ n := self.pairAt(i)
+ if n.Value.IsRaw() {
+ n.Value.parseRaw(true)
+ }
+ if err := n.Value.Check(); err != nil {
+ return err
+ }
+ }
+ return nil
+ default:
+ return self.Check()
+ }
+}
+
+// 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()
+ }
+
+ switch self.t {
+ case _V_ARRAY_LAZY:
+ return self.skipAllIndex()
+ case _V_OBJECT_LAZY:
+ return self.skipAllKey()
+ default:
+ return self.Check()
+ }
+}
+
+/**---------------------------------- 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
+ }
+ if self.itype() != t {
+ return ErrUnsupportType
+ }
+ return nil
+}
+
+func (self *Node) nodeAt(i int) *Node {
+ var p = self.p
+ if self.isLazy() {
+ _, stack := self.getParserAndArrayStack()
+ p = *(*unsafe.Pointer)(unsafe.Pointer(&stack.v))
+ }
+ return (*Node)(unsafe.Pointer(uintptr(p) + uintptr(i)*_NODE_SIZE))
+}
+
+func (self *Node) pairAt(i int) *Pair {
+ var p = self.p
+ if self.isLazy() {
+ _, stack := self.getParserAndObjectStack()
+ p = *(*unsafe.Pointer)(unsafe.Pointer(&stack.v))
+ }
+ 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
+}
+
+func (self *Node) skipAllIndex() error {
+ if !self.isLazy() {
+ return nil
+ }
+ var err types.ParsingError
+ parser, stack := self.getParserAndArrayStack()
+ parser.skipValue = true
+ parser.noLazy = true
+ *self, err = parser.decodeArray(stack.v)
+ if err != 0 {
+ return parser.ExportError(err)
+ }
+ return nil
+}
+
+func (self *Node) skipAllKey() error {
+ if !self.isLazy() {
+ return nil
+ }
+ var err types.ParsingError
+ parser, stack := self.getParserAndObjectStack()
+ parser.skipValue = true
+ parser.noLazy = true
+ *self, err = parser.decodeObject(stack.v)
+ if err != 0 {
+ return parser.ExportError(err)
+ }
+ return nil
+}
+
+func (self *Node) skipKey(key string) (*Node, int) {
+ nb := self.len()
+ lazy := self.isLazy()
+
+ if nb > 0 {
+ /* linear search */
+ var p *Pair
+ if lazy {
+ s := (*parseObjectStack)(self.p)
+ p = &s.v[0]
+ } else {
+ p = (*Pair)(self.p)
+ }
+
+ 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
+ }
+ }
+ }
+
+ /* not found */
+ if !lazy {
+ return nil, -1
+ }
+
+ // lazy load
+ for last, i := self.skipNextPair(), nb; last != nil; last, i = self.skipNextPair(), i+1 {
+ if last.Value.Check() != nil {
+ return &last.Value, -1
+ }
+ if last.Key == key {
+ return &last.Value, i
+ }
+ }
+
+ return nil, -1
+}
+
+func (self *Node) skipIndex(index int) *Node {
+ nb := self.len()
+ if nb > index {
+ v := self.nodeAt(index)
+ return v
+ }
+ if !self.isLazy() {
+ return nil
+ }
+
+ // lazy load
+ for last := self.skipNextNode(); last != nil; last = self.skipNextNode(){
+ if last.Check() != nil {
+ return last
+ }
+ if self.len() > index {
+ return last
+ }
+ }
+
+ return nil
+}
+
+func (self *Node) skipIndexPair(index int) *Pair {
+ nb := self.len()
+ if nb > index {
+ return self.pairAt(index)
+ }
+ if !self.isLazy() {
+ return nil
+ }
+
+ // lazy load
+ for last := self.skipNextPair(); last != nil; last = self.skipNextPair(){
+ if last.Value.Check() != nil {
+ return last
+ }
+ if self.len() > index {
+ return last
+ }
+ }
+
+ return nil
+}
+
+func (self *Node) loadAllIndex() error {
+ if !self.isLazy() {
+ return nil
+ }
+ var err types.ParsingError
+ parser, stack := self.getParserAndArrayStack()
+ parser.noLazy = true
+ *self, err = parser.decodeArray(stack.v)
+ if err != 0 {
+ return parser.ExportError(err)
+ }
+ return nil
+}
+
+func (self *Node) loadAllKey() error {
+ if !self.isLazy() {
+ return nil
+ }
+ var err types.ParsingError
+ parser, stack := self.getParserAndObjectStack()
+ parser.noLazy = true
+ *self, err = parser.decodeObject(stack.v)
+ if err != 0 {
+ return parser.ExportError(err)
+ }
+ return nil
+}
+
+func (self *Node) removeNode(i int) {
+ nb := self.len() - 1
+ node := self.nodeAt(i)
+ if i == nb {
+ self.setCapAndLen(self.cap(), nb)
+ *node = Node{}
+ 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)
+}
+
+func (self *Node) removePair(i int) {
+ nb := self.len() - 1
+ node := self.pairAt(i)
+ if i == nb {
+ self.setCapAndLen(self.cap(), nb)
+ *node = Pair{}
+ 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)
+}
+
+func (self *Node) toGenericArray() ([]interface{}, error) {
+ nb := self.len()
+ ret := make([]interface{}, nb)
+ if nb == 0 {
+ return ret, nil
+ }
+
+ /* 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()
+ x, err := p.Interface()
+ if err != nil {
+ return nil, err
+ }
+ ret[i] = x
+ }
+
+ /* all done */
+ return ret, nil
+}
+
+func (self *Node) toGenericArrayUseNumber() ([]interface{}, error) {
+ nb := self.len()
+ ret := make([]interface{}, nb)
+ if nb == 0 {
+ return ret, nil
+ }
+
+ /* 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()
+ x, err := p.InterfaceUseNumber()
+ if err != nil {
+ return nil, err
+ }
+ ret[i] = x
+ }
+
+ /* all done */
+ return ret, nil
+}
+
+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
+ }
+
+ for i := 1; i < nb; i++ {
+ p = p.unsafe_next()
+ if err := p.Check(); err != nil {
+ return nil, err
+ }
+ out[i] = *p
+ }
+
+ 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
+ }
+
+ /* 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()
+ x, err := p.Value.Interface()
+ if err != nil {
+ return nil, err
+ }
+ ret[p.Key] = x
+ }
+
+ /* all done */
+ return ret, nil
+}
+
+
+func (self *Node) toGenericObjectUseNumber() (map[string]interface{}, error) {
+ nb := self.len()
+ ret := make(map[string]interface{}, nb)
+ if nb == 0 {
+ return ret, nil
+ }
+
+ /* 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()
+ x, err := p.Value.InterfaceUseNumber()
+ if err != nil {
+ return nil, err
+ }
+ ret[p.Key] = x
+ }
+
+ /* all done */
+ return ret, nil
+}
+
+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
+ }
+
+ 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
+ }
+
+ /* all done */
+ return out, nil
+}
+
+/**------------------------------------ Factory Methods ------------------------------------**/
+
+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, and decides its type by first char.
+func NewRaw(json string) Node {
+ if json == "" {
+ panic("empty json string")
+ }
+ it := switchRawType(json[0])
+ return newRawNode(json, it)
+}
+
+// NewAny creates a node of type V_ANY if any's type isn't Node or *Node,
+// which stores interface{} and can be only used for `.Interface()`\`.MarshalJSON()`.
+func NewAny(any interface{}) Node {
+ switch n := any.(type) {
+ case Node:
+ return n
+ case *Node:
+ return *n
+ default:
+ return Node{
+ t: _V_ANY,
+ v: 0,
+ p: unsafe.Pointer(&any),
+ }
+ }
+}
+
+// NewBytes encodes given src with Base64 (RFC 4648), and creates a node of type V_STRING.
+func NewBytes(src []byte) Node {
+ if len(src) == 0 {
+ panic("empty src bytes")
+ }
+ out := encodeBase64(src)
+ return NewString(out)
+}
+
+// NewNull creates a node of type V_NULL
+func NewNull() Node {
+ return Node{
+ v: 0,
+ p: nil,
+ t: types.V_NULL,
+ }
+}
+
+// NewBool creates a node of type bool:
+// If v is true, returns V_TRUE node
+// If v is false, returns V_FALSE node
+func NewBool(v bool) Node {
+ var t = types.V_FALSE
+ if v {
+ t = types.V_TRUE
+ }
+ return Node{
+ v: 0,
+ p: nil,
+ t: t,
+ }
+}
+
+// NewNumber creates a json.Number node
+// v must be a decimal string complying with RFC8259
+func NewNumber(v string) Node {
+ return Node{
+ v: int64(len(v) & _LEN_MASK),
+ p: rt.StrPtr(v),
+ t: _V_NUMBER,
+ }
+}
+
+func toNumber(node *Node) json.Number {
+ return json.Number(rt.StrFrom(node.p, node.v))
+}
+
+func numberToFloat64(node *Node) (float64, error) {
+ ret,err := toNumber(node).Float64()
+ if err != nil {
+ return 0, err
+ }
+ return ret, nil
+}
+
+func numberToInt64(node *Node) (int64, error) {
+ ret,err := toNumber(node).Int64()
+ if err != nil {
+ return 0, err
+ }
+ return ret, nil
+}
+
+func newBytes(v []byte) Node {
+ return Node{
+ t: types.V_STRING,
+ p: mem2ptr(v),
+ v: int64(len(v) & _LEN_MASK),
+ }
+}
+
+// NewString creates a node of type V_STRING.
+// v is considered to be a valid UTF-8 string,
+// which means it won't be validated and unescaped.
+// when the node is encoded to json, v will be escaped.
+func NewString(v string) Node {
+ return Node{
+ t: types.V_STRING,
+ p: rt.StrPtr(v),
+ v: int64(len(v) & _LEN_MASK),
+ }
+}
+
+// NewArray creates a node of type V_ARRAY,
+// using v as its underlying children
+func NewArray(v []Node) Node {
+ return Node{
+ t: types.V_ARRAY,
+ v: int64(len(v)&_LEN_MASK | cap(v)<<_CAP_BITS),
+ p: *(*unsafe.Pointer)(unsafe.Pointer(&v)),
+ }
+}
+
+func (self *Node) setArray(v []Node) {
+ self.t = types.V_ARRAY
+ self.setCapAndLen(cap(v), len(v))
+ self.p = *(*unsafe.Pointer)(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)
+}
+
+func newLazyObject(p *Parser, v []Pair) Node {
+ s := new(parseObjectStack)
+ s.parser = *p
+ s.v = v
+ return Node{
+ t: _V_OBJECT_LAZY,
+ v: int64(len(v)&_LEN_MASK | cap(v)<<_CAP_BITS),
+ p: unsafe.Pointer(s),
+ }
+}
+
+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 newRawNode(str string, typ types.ValueType) Node {
+ return Node{
+ t: _V_RAW | typ,
+ p: rt.StrPtr(str),
+ v: int64(len(str) & _LEN_MASK),
+ }
+}
+
+func (self *Node) parseRaw(full bool) {
+ raw := rt.StrFrom(self.p, self.v)
+ parser := NewParser(raw)
+ if full {
+ parser.noLazy = true
+ parser.skipValue = false
+ }
+ var e types.ParsingError
+ *self, e = parser.Parse()
+ if e != 0 {
+ *self = *newSyntaxError(parser.syntaxError(e))
+ }
+}
+
+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,
+ '0' : _V_NUMBER,
+ '1' : _V_NUMBER,
+ '2' : _V_NUMBER,
+ '3' : _V_NUMBER,
+ '4' : _V_NUMBER,
+ '5' : _V_NUMBER,
+ '6' : _V_NUMBER,
+ '7' : _V_NUMBER,
+ '8' : _V_NUMBER,
+ '9' : _V_NUMBER,
+ '[' : types.V_ARRAY,
+ 'f' : types.V_FALSE,
+ 'n' : types.V_NULL,
+ 't' : types.V_TRUE,
+ '{' : types.V_OBJECT,
+}
+
+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
new file mode 100644
index 000000000..ebb7bb097
--- /dev/null
+++ b/vendor/github.com/bytedance/sonic/ast/parser.go
@@ -0,0 +1,618 @@
+/*
+ * 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 (
+ `fmt`
+ `github.com/bytedance/sonic/internal/native/types`
+ `github.com/bytedance/sonic/internal/rt`
+)
+
+const _DEFAULT_NODE_CAP int = 16
+
+const (
+ _ERR_NOT_FOUND types.ParsingError = 33
+ _ERR_UNSUPPORT_TYPE types.ParsingError = 34
+)
+
+var (
+ ErrNotExist error = newError(_ERR_NOT_FOUND, "value not exists")
+ ErrUnsupportType error = newError(_ERR_UNSUPPORT_TYPE, "unsupported type")
+)
+
+type Parser struct {
+ p int
+ s string
+ noLazy bool
+ skipValue bool
+}
+
+/** Parser Private Methods **/
+
+func (self *Parser) delim() types.ParsingError {
+ n := len(self.s)
+ p := self.lspace(self.p)
+
+ /* check for EOF */
+ if p >= n {
+ return types.ERR_EOF
+ }
+
+ /* check for the delimtier */
+ if self.s[p] != ':' {
+ return types.ERR_INVALID_CHAR
+ }
+
+ /* update the read pointer */
+ self.p = p + 1
+ return 0
+}
+
+func (self *Parser) object() types.ParsingError {
+ n := len(self.s)
+ p := self.lspace(self.p)
+
+ /* check for EOF */
+ if p >= n {
+ return types.ERR_EOF
+ }
+
+ /* check for the delimtier */
+ if self.s[p] != '{' {
+ return types.ERR_INVALID_CHAR
+ }
+
+ /* update the read pointer */
+ self.p = p + 1
+ return 0
+}
+
+func (self *Parser) array() types.ParsingError {
+ n := len(self.s)
+ p := self.lspace(self.p)
+
+ /* check for EOF */
+ if p >= n {
+ return types.ERR_EOF
+ }
+
+ /* check for the delimtier */
+ if self.s[p] != '[' {
+ return types.ERR_INVALID_CHAR
+ }
+
+ /* update the read pointer */
+ self.p = p + 1
+ return 0
+}
+
+func (self *Parser) lspace(sp int) int {
+ ns := len(self.s)
+ for ; sp<ns && isSpace(self.s[sp]); sp+=1 {}
+
+ return sp
+}
+
+func (self *Parser) decodeArray(ret []Node) (Node, types.ParsingError) {
+ sp := self.p
+ ns := len(self.s)
+
+ /* check for EOF */
+ if self.p = self.lspace(sp); self.p >= ns {
+ return Node{}, types.ERR_EOF
+ }
+
+ /* check for empty array */
+ if self.s[self.p] == ']' {
+ self.p++
+ return emptyArrayNode, 0
+ }
+
+ /* allocate array space and parse every element */
+ for {
+ var val Node
+ var err types.ParsingError
+
+ if self.skipValue {
+ /* skip the value */
+ var start int
+ if start, err = self.skipFast(); err != 0 {
+ return Node{}, err
+ }
+ if self.p > ns {
+ return Node{}, types.ERR_EOF
+ }
+ t := switchRawType(self.s[start])
+ if t == _V_NONE {
+ return Node{}, types.ERR_INVALID_CHAR
+ }
+ val = newRawNode(self.s[start:self.p], t)
+ }else{
+ /* decode the value */
+ if val, err = self.Parse(); err != 0 {
+ return Node{}, err
+ }
+ }
+
+ /* add the value to result */
+ ret = append(ret, val)
+ self.p = self.lspace(self.p)
+
+ /* check for EOF */
+ if self.p >= ns {
+ return Node{}, types.ERR_EOF
+ }
+
+ /* 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
+ }
+ }
+}
+
+func (self *Parser) decodeObject(ret []Pair) (Node, types.ParsingError) {
+ sp := self.p
+ ns := len(self.s)
+
+ /* check for EOF */
+ if self.p = self.lspace(sp); self.p >= ns {
+ return Node{}, types.ERR_EOF
+ }
+
+ /* check for empty object */
+ if self.s[self.p] == '}' {
+ self.p++
+ return emptyObjectNode, 0
+ }
+
+ /* decode each pair */
+ for {
+ var val Node
+ var njs types.JsonState
+ var err types.ParsingError
+
+ /* decode the key */
+ if njs = self.decodeValue(); njs.Vt != types.V_STRING {
+ return Node{}, types.ERR_INVALID_CHAR
+ }
+
+ /* extract the key */
+ idx := self.p - 1
+ key := self.s[njs.Iv:idx]
+
+ /* check for escape sequence */
+ if njs.Ep != -1 {
+ if key, err = unquote(key); err != 0 {
+ return Node{}, err
+ }
+ }
+
+ /* expect a ':' delimiter */
+ if err = self.delim(); err != 0 {
+ return Node{}, err
+ }
+
+
+ if self.skipValue {
+ /* skip the value */
+ var start int
+ if start, err = self.skipFast(); err != 0 {
+ return Node{}, err
+ }
+ if self.p > ns {
+ return Node{}, types.ERR_EOF
+ }
+ t := switchRawType(self.s[start])
+ if t == _V_NONE {
+ return Node{}, types.ERR_INVALID_CHAR
+ }
+ val = newRawNode(self.s[start:self.p], t)
+ } else {
+ /* decode the value */
+ if val, err = self.Parse(); err != 0 {
+ return Node{}, err
+ }
+ }
+
+ /* add the value to result */
+ ret = append(ret, Pair{Key: key, Value: val})
+ self.p = self.lspace(self.p)
+
+ /* check for EOF */
+ if self.p >= ns {
+ return Node{}, types.ERR_EOF
+ }
+
+ /* check for the next character */
+ switch self.s[self.p] {
+ case ',' : self.p++
+ case '}' : self.p++; return NewObject(ret), 0
+ default:
+ if val.isLazy() {
+ return newLazyObject(self, ret), 0
+ }
+ return Node{}, types.ERR_INVALID_CHAR
+ }
+ }
+}
+
+func (self *Parser) decodeString(iv int64, ep int) (Node, types.ParsingError) {
+ p := self.p - 1
+ s := self.s[iv:p]
+
+ /* fast path: no escape sequence */
+ if ep == -1 {
+ return NewString(s), 0
+ }
+
+ /* unquote the string */
+ out, err := unquote(s)
+
+ /* check for errors */
+ if err != 0 {
+ return Node{}, err
+ } else {
+ return newBytes(rt.Str2Mem(out)), 0
+ }
+}
+
+/** Parser Interface **/
+
+func (self *Parser) Pos() int {
+ return self.p
+}
+
+func (self *Parser) Parse() (Node, types.ParsingError) {
+ switch val := self.decodeValue(); val.Vt {
+ case types.V_EOF : return Node{}, types.ERR_EOF
+ case types.V_NULL : return nullNode, 0
+ case types.V_TRUE : return trueNode, 0
+ case types.V_FALSE : return falseNode, 0
+ case types.V_STRING : return self.decodeString(val.Iv, val.Ep)
+ case types.V_ARRAY:
+ if self.noLazy {
+ return self.decodeArray(make([]Node, 0, _DEFAULT_NODE_CAP))
+ }
+ return newLazyArray(self, make([]Node, 0, _DEFAULT_NODE_CAP)), 0
+ case types.V_OBJECT:
+ if self.noLazy {
+ return self.decodeObject(make([]Pair, 0, _DEFAULT_NODE_CAP))
+ }
+ return newLazyObject(self, make([]Pair, 0, _DEFAULT_NODE_CAP)), 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)
+ }
+}
+
+func (self *Parser) searchKey(match string) types.ParsingError {
+ ns := len(self.s)
+ if err := self.object(); err != 0 {
+ return err
+ }
+
+ /* check for EOF */
+ if self.p = self.lspace(self.p); self.p >= ns {
+ return types.ERR_EOF
+ }
+
+ /* check for empty object */
+ if self.s[self.p] == '}' {
+ self.p++
+ return _ERR_NOT_FOUND
+ }
+
+ var njs types.JsonState
+ var err types.ParsingError
+ /* decode each pair */
+ for {
+
+ /* decode the key */
+ if njs = self.decodeValue(); njs.Vt != types.V_STRING {
+ return types.ERR_INVALID_CHAR
+ }
+
+ /* extract the key */
+ idx := self.p - 1
+ key := self.s[njs.Iv:idx]
+
+ /* check for escape sequence */
+ if njs.Ep != -1 {
+ if key, err = unquote(key); err != 0 {
+ return err
+ }
+ }
+
+ /* expect a ':' delimiter */
+ if err = self.delim(); err != 0 {
+ return err
+ }
+
+ /* skip value */
+ if key != match {
+ if _, err = self.skip(); err != 0 {
+ return err
+ }
+ } else {
+ return 0
+ }
+
+ /* check for EOF */
+ self.p = self.lspace(self.p)
+ if self.p >= ns {
+ return types.ERR_EOF
+ }
+
+ /* check for the next character */
+ switch self.s[self.p] {
+ case ',':
+ self.p++
+ case '}':
+ self.p++
+ return _ERR_NOT_FOUND
+ default:
+ return types.ERR_INVALID_CHAR
+ }
+ }
+}
+
+func (self *Parser) searchIndex(idx int) types.ParsingError {
+ ns := len(self.s)
+ if err := self.array(); err != 0 {
+ return err
+ }
+
+ /* check for EOF */
+ if self.p = self.lspace(self.p); self.p >= ns {
+ return types.ERR_EOF
+ }
+
+ /* check for empty array */
+ if self.s[self.p] == ']' {
+ self.p++
+ return _ERR_NOT_FOUND
+ }
+
+ var err types.ParsingError
+ /* allocate array space and parse every element */
+ for i := 0; i < idx; i++ {
+
+ /* decode the value */
+ if _, err = self.skip(); err != 0 {
+ return err
+ }
+
+ /* check for EOF */
+ self.p = self.lspace(self.p)
+ if self.p >= ns {
+ return types.ERR_EOF
+ }
+
+ /* check for the next character */
+ switch self.s[self.p] {
+ case ',':
+ self.p++
+ case ']':
+ self.p++
+ return _ERR_NOT_FOUND
+ default:
+ return types.ERR_INVALID_CHAR
+ }
+ }
+
+ return 0
+}
+
+func (self *Node) skipNextNode() *Node {
+ if !self.isLazy() {
+ return nil
+ }
+
+ parser, stack := self.getParserAndArrayStack()
+ ret := stack.v
+ sp := parser.p
+ ns := len(parser.s)
+
+ /* check for EOF */
+ if parser.p = parser.lspace(sp); parser.p >= ns {
+ return newSyntaxError(parser.syntaxError(types.ERR_EOF))
+ }
+
+ /* check for empty array */
+ if parser.s[parser.p] == ']' {
+ parser.p++
+ self.setArray(ret)
+ return nil
+ }
+
+ var val Node
+ /* skip the value */
+ if start, err := parser.skipFast(); err != 0 {
+ return newSyntaxError(parser.syntaxError(err))
+ } else {
+ t := switchRawType(parser.s[start])
+ if t == _V_NONE {
+ return newSyntaxError(parser.syntaxError(types.ERR_INVALID_CHAR))
+ }
+ val = newRawNode(parser.s[start:parser.p], t)
+ }
+
+ /* add the value to result */
+ ret = append(ret, val)
+ parser.p = parser.lspace(parser.p)
+
+ /* check for EOF */
+ if parser.p >= ns {
+ return newSyntaxError(parser.syntaxError(types.ERR_EOF))
+ }
+
+ /* check for the next character */
+ switch parser.s[parser.p] {
+ case ',':
+ parser.p++
+ self.setLazyArray(parser, ret)
+ return &ret[len(ret)-1]
+ case ']':
+ parser.p++
+ self.setArray(ret)
+ return &ret[len(ret)-1]
+ default:
+ return newSyntaxError(parser.syntaxError(types.ERR_INVALID_CHAR))
+ }
+}
+
+func (self *Node) skipNextPair() (*Pair) {
+ if !self.isLazy() {
+ return nil
+ }
+
+ parser, stack := self.getParserAndObjectStack()
+ ret := stack.v
+ sp := parser.p
+ ns := len(parser.s)
+
+ /* check for EOF */
+ if parser.p = parser.lspace(sp); parser.p >= ns {
+ return &Pair{"", *newSyntaxError(parser.syntaxError(types.ERR_EOF))}
+ }
+
+ /* check for empty object */
+ if parser.s[parser.p] == '}' {
+ parser.p++
+ self.setObject(ret)
+ return nil
+ }
+
+ /* decode one pair */
+ var val Node
+ var njs types.JsonState
+ var err types.ParsingError
+
+ /* decode the key */
+ if njs = parser.decodeValue(); njs.Vt != types.V_STRING {
+ return &Pair{"", *newSyntaxError(parser.syntaxError(types.ERR_INVALID_CHAR))}
+ }
+
+ /* extract the key */
+ idx := parser.p - 1
+ key := parser.s[njs.Iv:idx]
+
+ /* check for escape sequence */
+ if njs.Ep != -1 {
+ if key, err = unquote(key); err != 0 {
+ return &Pair{key, *newSyntaxError(parser.syntaxError(err))}
+ }
+ }
+
+ /* expect a ':' delimiter */
+ if err = parser.delim(); err != 0 {
+ return &Pair{key, *newSyntaxError(parser.syntaxError(err))}
+ }
+
+ /* skip the value */
+ if start, err := parser.skipFast(); err != 0 {
+ return &Pair{key, *newSyntaxError(parser.syntaxError(err))}
+ } else {
+ t := switchRawType(parser.s[start])
+ if t == _V_NONE {
+ return &Pair{key, *newSyntaxError(parser.syntaxError(types.ERR_INVALID_CHAR))}
+ }
+ val = newRawNode(parser.s[start:parser.p], t)
+ }
+
+ /* add the value to result */
+ ret = append(ret, Pair{Key: key, Value: val})
+ parser.p = parser.lspace(parser.p)
+
+ /* check for EOF */
+ if parser.p >= ns {
+ return &Pair{key, *newSyntaxError(parser.syntaxError(types.ERR_EOF))}
+ }
+
+ /* check for the next character */
+ switch parser.s[parser.p] {
+ case ',':
+ parser.p++
+ self.setLazyObject(parser, ret)
+ return &ret[len(ret)-1]
+ case '}':
+ parser.p++
+ self.setObject(ret)
+ return &ret[len(ret)-1]
+ default:
+ return &Pair{key, *newSyntaxError(parser.syntaxError(types.ERR_INVALID_CHAR))}
+ }
+}
+
+
+/** Parser Factory **/
+
+// Loads parse all json into interface{}
+func Loads(src string) (int, interface{}, error) {
+ ps := &Parser{s: src}
+ np, err := ps.Parse()
+
+ /* check for errors */
+ if err != 0 {
+ return 0, nil, ps.ExportError(err)
+ } else {
+ x, err := np.Interface()
+ if err != nil {
+ return 0, nil, err
+ }
+ return ps.Pos(), x, nil
+ }
+}
+
+// LoadsUseNumber parse all json into interface{}, with numeric nodes casted to json.Number
+func LoadsUseNumber(src string) (int, interface{}, error) {
+ ps := &Parser{s: src}
+ np, err := ps.Parse()
+
+ /* check for errors */
+ if err != 0 {
+ return 0, nil, err
+ } else {
+ x, err := np.InterfaceUseNumber()
+ if err != nil {
+ return 0, nil, err
+ }
+ return ps.Pos(), x, nil
+ }
+}
+
+func NewParser(src string) *Parser {
+ return &Parser{s: src}
+}
+
+// ExportError converts types.ParsingError to std Error
+func (self *Parser) ExportError(err types.ParsingError) error {
+ if err == _ERR_NOT_FOUND {
+ return ErrNotExist
+ }
+ return fmt.Errorf("%q", SyntaxError{
+ Pos : self.p,
+ Src : self.s,
+ Code: err,
+ }.Description())
+} \ No newline at end of file
diff --git a/vendor/github.com/bytedance/sonic/ast/search.go b/vendor/github.com/bytedance/sonic/ast/search.go
new file mode 100644
index 000000000..bb6fceaa7
--- /dev/null
+++ b/vendor/github.com/bytedance/sonic/ast/search.go
@@ -0,0 +1,30 @@
+/*
+ * 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
+
+type Searcher struct {
+ parser Parser
+}
+
+func NewSearcher(str string) *Searcher {
+ return &Searcher{
+ parser: Parser{
+ s: str,
+ noLazy: false,
+ },
+ }
+}
diff --git a/vendor/github.com/bytedance/sonic/ast/sort.go b/vendor/github.com/bytedance/sonic/ast/sort.go
new file mode 100644
index 000000000..0a9f14559
--- /dev/null
+++ b/vendor/github.com/bytedance/sonic/ast/sort.go
@@ -0,0 +1,206 @@
+/*
+ * 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_go115.go b/vendor/github.com/bytedance/sonic/ast/stubs_go115.go
new file mode 100644
index 000000000..37b9451f0
--- /dev/null
+++ b/vendor/github.com/bytedance/sonic/ast/stubs_go115.go
@@ -0,0 +1,55 @@
+// +build !go1.20
+
+/*
+ * 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 (
+ `unsafe`
+ `unicode/utf8`
+
+ `github.com/bytedance/sonic/internal/rt`
+)
+
+//go:noescape
+//go:linkname memmove runtime.memmove
+//goland:noinspection GoUnusedParameter
+func memmove(to unsafe.Pointer, from unsafe.Pointer, n uintptr)
+
+//go:linkname unsafe_NewArray reflect.unsafe_NewArray
+//goland:noinspection GoUnusedParameter
+func unsafe_NewArray(typ *rt.GoType, n int) unsafe.Pointer
+
+//go:linkname growslice runtime.growslice
+//goland:noinspection GoUnusedParameter
+func growslice(et *rt.GoType, old rt.GoSlice, cap int) rt.GoSlice
+
+//go:nosplit
+func mem2ptr(s []byte) unsafe.Pointer {
+ return (*rt.GoSlice)(unsafe.Pointer(&s)).Ptr
+}
+
+var (
+ //go:linkname safeSet encoding/json.safeSet
+ safeSet [utf8.RuneSelf]bool
+
+ //go:linkname hex encoding/json.hex
+ hex string
+)
+
+//go:linkname unquoteBytes encoding/json.unquoteBytes
+func unquoteBytes(s []byte) (t []byte, ok bool) \ No newline at end of file
diff --git a/vendor/github.com/bytedance/sonic/ast/stubs_go120.go b/vendor/github.com/bytedance/sonic/ast/stubs_go120.go
new file mode 100644
index 000000000..bd6fff680
--- /dev/null
+++ b/vendor/github.com/bytedance/sonic/ast/stubs_go120.go
@@ -0,0 +1,55 @@
+// +build go1.20
+
+/*
+ * 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 (
+ `unsafe`
+ `unicode/utf8`
+
+ `github.com/bytedance/sonic/internal/rt`
+)
+
+//go:noescape
+//go:linkname memmove runtime.memmove
+//goland:noinspection GoUnusedParameter
+func memmove(to unsafe.Pointer, from unsafe.Pointer, n uintptr)
+
+//go:linkname unsafe_NewArray reflect.unsafe_NewArray
+//goland:noinspection GoUnusedParameter
+func unsafe_NewArray(typ *rt.GoType, n int) unsafe.Pointer
+
+//go:linkname growslice reflect.growslice
+//goland:noinspection GoUnusedParameter
+func growslice(et *rt.GoType, old rt.GoSlice, cap int) rt.GoSlice
+
+//go:nosplit
+func mem2ptr(s []byte) unsafe.Pointer {
+ return (*rt.GoSlice)(unsafe.Pointer(&s)).Ptr
+}
+
+var (
+ //go:linkname safeSet encoding/json.safeSet
+ safeSet [utf8.RuneSelf]bool
+
+ //go:linkname hex encoding/json.hex
+ hex string
+)
+
+//go:linkname unquoteBytes encoding/json.unquoteBytes
+func unquoteBytes(s []byte) (t []byte, ok bool) \ No newline at end of file