Skip to content

Commit

Permalink
feat: RawNode supports concurrently read
Browse files Browse the repository at this point in the history
  • Loading branch information
AsterDY committed Jan 10, 2024
1 parent f806331 commit 376c98c
Show file tree
Hide file tree
Showing 4 changed files with 752 additions and 16 deletions.
43 changes: 27 additions & 16 deletions ast/api_compat.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,25 +91,15 @@ func (self *Node) encodeInterface(buf *[]byte) error {
func (self *Searcher) GetByPath(path ...interface{}) (Node, error) {
self.parser.p = 0

var err types.ParsingError
for _, p := range path {
if idx, ok := p.(int); ok && idx >= 0 {
if err = self.parser.searchIndex(idx); err != 0 {
return Node{}, self.parser.ExportError(err)
}
} else if key, ok := p.(string); ok {
if err = self.parser.searchKey(key); err != 0 {
return Node{}, self.parser.ExportError(err)
}
} else {
panic("path must be either int(>=0) or string")
}
start, err := self.parser.getByPath(path...)
if err != 0 {
return Node{}, err
}

var start = self.parser.p
if start, err = self.parser.skip(); err != 0 {

if _, 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)
Expand All @@ -121,4 +111,25 @@ func (self *Searcher) GetByPath(path ...interface{}) (Node, error) {
}

return newRawNode(self.parser.s[start:self.parser.p], t), nil
}

func (self *Parser) getByPath(path ...interface{}) (int, types.ParsingError) {
for _, p := range path {
if idx, ok := p.(int); ok && idx >= 0 {
if err := self.searchIndex(idx); err != 0 {
return self.p, err
}
} else if key, ok := p.(string); ok {
if err := self.searchKey(key); err != 0 {
return self.p, err
}
} else {
panic("path must be either int(>=0) or string")
}
}
start, e := self.skip()
if e != 0 {
return self.p, e
}
return start, 0
}
107 changes: 107 additions & 0 deletions ast/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,73 @@ func (self *Parser) Parse() (Node, types.ParsingError) {
}
}

func (self *Parser) key() (string, types.ParsingError) {
var njs types.JsonState
var err types.ParsingError

/* 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
}
return key, 0
}

func (self *Parser) objectBegin() (bool, types.ParsingError) {
ns := len(self.s)
if err := self.object(); err != 0 {
return false, err
}

/* check for EOF */
if self.p = self.lspace(self.p); self.p >= ns {
return false, types.ERR_EOF
}

/* check for empty object */
if self.s[self.p] == '}' {
self.p++
return true, 0
}

return false, 0
}

func (self *Parser) objectEnd() (bool, types.ParsingError) {
/* check for EOF */
self.p = self.lspace(self.p)
if self.p >= len(self.s) {
return false, types.ERR_EOF
}

/* check for the next character */
switch self.s[self.p] {
case ',':
self.p++
return false, 0
case '}':
self.p++
return true, 0
default:
return false, types.ERR_INVALID_CHAR
}
}

func (self *Parser) searchKey(match string) types.ParsingError {
ns := len(self.s)
if err := self.object(); err != 0 {
Expand Down Expand Up @@ -393,6 +460,46 @@ func (self *Parser) searchKey(match string) types.ParsingError {
}
}

func (self *Parser) arrayBegin() (bool, types.ParsingError) {
ns := len(self.s)
if err := self.array(); err != 0 {
return false, err
}

/* check for EOF */
if self.p = self.lspace(self.p); self.p >= ns {
return false, types.ERR_EOF
}

/* check for empty array */
if self.s[self.p] == ']' {
self.p++
return true, 0
}

return false, 0
}

func (self *Parser) arrayEnd() (bool, types.ParsingError) {
/* check for EOF */
self.p = self.lspace(self.p)
if self.p >= len(self.s) {
return false, types.ERR_EOF
}

/* check for the next character */
switch self.s[self.p] {
case ',':
self.p++
return false, 0
case ']':
self.p++
return true, 0
default:
return false, types.ERR_INVALID_CHAR
}
}

func (self *Parser) searchIndex(idx int) types.ParsingError {
ns := len(self.s)
if err := self.array(); err != 0 {
Expand Down
Loading

0 comments on commit 376c98c

Please sign in to comment.