Skip to content

Commit

Permalink
feat:(ast) export API for other json lib
Browse files Browse the repository at this point in the history
  • Loading branch information
AsterDY committed Mar 12, 2024
1 parent 5d45952 commit 3739072
Show file tree
Hide file tree
Showing 29 changed files with 7,830 additions and 7,777 deletions.
4 changes: 3 additions & 1 deletion ast/api.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//go:build (amd64 && go1.16 && !go1.23) || (arm64 && go1.20 && !go1.23)
// +build amd64,go1.16,!go1.23 arm64,go1.20,!go1.23

/*
Expand Down Expand Up @@ -72,7 +73,8 @@ func quote(buf *[]byte, val string) {
*buf = append(*buf, '"')
}

func unquote(src string) (string, types.ParsingError) {
// Unquote unescapes a internal JSON string (it doesn't count quotas at the begining and end)
func Unquote(src string) (string, types.ParsingError) {
return uq.String(src)
}

Expand Down
77 changes: 37 additions & 40 deletions ast/api_compat.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,64 +19,65 @@
package ast

import (
`encoding/json`
`encoding/json`

`github.com/bytedance/sonic/internal/native/types`
`github.com/bytedance/sonic/internal/rt`
`github.com/bytedance/sonic/internal/native/types`
`github.com/bytedance/sonic/internal/rt`
)

func init() {
println("WARNING:(ast) sonic only supports Go1.16~1.22, but your environment is not suitable")
println("WARNING:(ast) sonic only supports Go1.16~1.22, but your environment is not suitable")
}

func quote(buf *[]byte, val string) {
quoteString(buf, val)
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
// Unquote unescapes a internal JSON string (it doesn't count quotas at the begining and end)
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 (self *Parser) decodeValue() (val types.JsonState) {
e, v := decodeValue(self.s, self.p, self.dbuf == nil)
if e < 0 {
return v
}
self.p = e
return v
e, v := decodeValue(self.s, self.p, self.dbuf == nil)
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
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) {
e, s := skipValueFast(self.s, self.p)
if e < 0 {
return self.p, types.ParsingError(-e)
}
self.p = e
return s, 0
e, s := skipValueFast(self.s, self.p)
if e < 0 {
return self.p, types.ParsingError(-e)
}
self.p = e
return s, 0
}

func (self *Node) encodeInterface(buf *[]byte) error {
out, err := json.Marshal(self.packAny())
if err != nil {
return err
}
*buf = append(*buf, out...)
return nil
out, err := json.Marshal(self.packAny())
if err != nil {
return err
}
*buf = append(*buf, out...)
return nil
}

func (self *Parser) getByPath(path ...interface{}) (int, types.ParsingError) {
Expand All @@ -97,9 +98,5 @@ func (self *Parser) getByPath(path ...interface{}) (int, types.ParsingError) {
if e != 0 {
return self.p, e
}
// t := switchRawType(self.s[start])
// if t == _V_NUMBER {
// self.p = 1 + backward(self.s, self.p-1)
// }
return start, 0
}
28 changes: 28 additions & 0 deletions ast/decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -583,3 +583,31 @@ func skipArray(src string, pos int) (ret int, start int) {
pos++
}
}

// DecoderString decodes a JSON string from pos and return golang string.
// - needEsc indicates if to unescaped escaping chars
// - hasEsc tells if the returned string has escaping chars
func DecodeString(src string, pos int, needEsc bool) (v string, ret int, hasEsc bool) {
p := NewParserObj(src)
p.p = pos
switch val := p.decodeValue(); val.Vt {
case types.V_STRING:
str := p.s[val.Iv : p.p-1]
/* fast path: no escape sequence */
if val.Ep == -1 {
return str, p.p, false
} else if !needEsc {
return str, p.p, true
}
/* unquote the string */
out, err := Unquote(str)
/* check for errors */
if err != 0 {
return "", -int(err), true
} else {
return out, p.p, true
}
default:
return "", -int(_ERR_UNSUPPORT_TYPE), false
}
}
10 changes: 5 additions & 5 deletions ast/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ func (self *Parser) decodeObject(ret *linkedPairs) (Node, types.ParsingError) {

/* check for escape sequence */
if njs.Ep != -1 {
if key, err = unquote(key); err != 0 {
if key, err = Unquote(key); err != 0 {
return Node{}, err
}
}
Expand Down Expand Up @@ -274,8 +274,8 @@ func (self *Parser) decodeString(iv int64, ep int) (Node, types.ParsingError) {
return NewString(s), 0
}

/* unquote the string */
out, err := unquote(s)
/* Unquote the string */
out, err := Unquote(s)

/* check for errors */
if err != 0 {
Expand Down Expand Up @@ -355,7 +355,7 @@ func (self *Parser) searchKey(match string) types.ParsingError {

/* check for escape sequence */
if njs.Ep != -1 {
if key, err = unquote(key); err != 0 {
if key, err = Unquote(key); err != 0 {
return err
}
}
Expand Down Expand Up @@ -536,7 +536,7 @@ func (self *Node) skipNextPair() (*Pair) {

/* check for escape sequence */
if njs.Ep != -1 {
if key, err = unquote(key); err != 0 {
if key, err = Unquote(key); err != 0 {
return &Pair{key, *newSyntaxError(parser.syntaxError(err))}
}
}
Expand Down
42 changes: 42 additions & 0 deletions ast/search.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,45 @@ func (self *Searcher) getByPath(copystring bool, path ...interface{}) (Node, err
}
return newRawNode(raw, t), nil
}

// GetByPath searches a path and returns relaction and types of target
func GetByPath(src string, path ...interface{}) (start int, end int, typ int, err error) {
p := NewParserObj(src)
s, e := p.getByPath(path...)
if e != 0 {
// for compatibility with old version
if e == types.ERR_NOT_FOUND {
return -1, -1, 0, ErrNotExist
}
if e == types.ERR_UNSUPPORT_TYPE {
panic("path must be either int(>=0) or string")
}
return -1, -1, 0, p.syntaxError(e)
}

t := switchRawType(p.s[s])
if t == _V_NONE {
return -1, -1, 0, ErrNotExist
}
return s, p.p, int(t), nil
}

// ValidSyntax check if a json has a valid JSON syntax,
// while not validate UTF-8 charset
func ValidSyntax(json string) bool {
p := NewParserObj(json)
_, e := p.skip()
return e == 0
}

// SkipFast skip a json value in fast-skip algs,
// while not strictly validate JSON syntax and UTF-8 charset.
func SkipFast(src string, i int) (int, int, error) {
p := NewParserObj(src)
p.p = i
s, e := p.skipFast()
if e != 0 {
return -1, -1, p.ExportError(e)
}
return s, p.p, nil
}
4 changes: 2 additions & 2 deletions ast/visitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ func (self *traverser) decodeObject() error {

/* check for escape sequence */
if njs.Ep != -1 {
if key, err = unquote(key); err != 0 {
if key, err = Unquote(key); err != 0 {
return err
}
}
Expand Down Expand Up @@ -307,7 +307,7 @@ func (self *traverser) decodeString(iv int64, ep int) error {
}

/* unquote the string */
out, err := unquote(s)
out, err := Unquote(s)
if err != 0 {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion internal/encoder/encoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ func Valid(data []byte) (ok bool, start int) {
s := rt.Mem2Str(data)
p := 0
m := types.NewStateMachine()
ret := native.ValidateOne(&s, &p, m)
ret := native.ValidateOne(&s, &p, m, types.F_VALIDATE_STRING)
types.FreeStateMachine(m)

if ret < 0 {
Expand Down
6 changes: 3 additions & 3 deletions internal/native/avx/native_amd64.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 3739072

Please sign in to comment.