mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-11-01 01:42:25 -05:00 
			
		
		
		
	Bumps [github.com/gin-contrib/gzip](https://github.com/gin-contrib/gzip) from 1.0.0 to 1.0.1. - [Release notes](https://github.com/gin-contrib/gzip/releases) - [Changelog](https://github.com/gin-contrib/gzip/blob/master/.goreleaser.yaml) - [Commits](https://github.com/gin-contrib/gzip/compare/v1.0.0...v1.0.1) --- updated-dependencies: - dependency-name: github.com/gin-contrib/gzip dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
		
			
				
	
	
		
			660 lines
		
	
	
	
		
			16 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			660 lines
		
	
	
	
		
			16 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| /*
 | |
|  * 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 = 8
 | |
|     _APPEND_GROW_SHIFT = 1
 | |
| )
 | |
| 
 | |
| const (
 | |
|     _ERR_NOT_FOUND      types.ParsingError = 33
 | |
|     _ERR_UNSUPPORT_TYPE types.ParsingError = 34
 | |
| )
 | |
| 
 | |
| var (
 | |
|     // ErrNotExist means both key and value doesn't exist 
 | |
|     ErrNotExist error = newError(_ERR_NOT_FOUND, "value not exists")
 | |
| 
 | |
|     // ErrUnsupportType means API on the node is unsupported
 | |
|     ErrUnsupportType error = newError(_ERR_UNSUPPORT_TYPE, "unsupported type")
 | |
| )
 | |
| 
 | |
| type Parser struct {
 | |
|     p           int
 | |
|     s           string
 | |
|     noLazy      bool
 | |
|     skipValue   bool
 | |
|     dbuf        *byte
 | |
| }
 | |
| 
 | |
| /** 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 *linkedNodes) (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 Node{t: types.V_ARRAY}, 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.Push(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 *linkedPairs) (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 Node{t: types.V_OBJECT}, 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 */
 | |
|         // FIXME: ret's address may change here, thus previous referred node in ret may be invalid !!
 | |
|         ret.Push(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 p := skipBlank(self.s, self.p); p >= self.p && self.s[p] == ']' {
 | |
|                 self.p = p + 1
 | |
|                 return Node{t: types.V_ARRAY}, 0
 | |
|             }
 | |
|             if self.noLazy {
 | |
|                 return self.decodeArray(new(linkedNodes))
 | |
|             }
 | |
|             return newLazyArray(self), 0
 | |
|         case types.V_OBJECT:
 | |
|             if p := skipBlank(self.s, self.p); p >= self.p && self.s[p] == '}' {
 | |
|                 self.p = p + 1
 | |
|                 return Node{t: types.V_OBJECT}, 0
 | |
|             }
 | |
|             if self.noLazy {
 | |
|                 return self.decodeObject(new(linkedPairs))
 | |
|             }
 | |
|             return newLazyObject(self), 0
 | |
|         case types.V_DOUBLE  : return NewNumber(self.s[val.Ep:self.p]), 0
 | |
|         case types.V_INTEGER : return NewNumber(self.s[val.Ep:self.p]), 0
 | |
|         default              : return Node{}, types.ParsingError(-val.Vt)
 | |
|     }
 | |
| }
 | |
| 
 | |
| 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.skipFast(); 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.skipFast(); 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.Push(val)
 | |
|     self.l++
 | |
|     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++
 | |
|         return ret.At(ret.Len()-1)
 | |
|     case ']':
 | |
|         parser.p++
 | |
|         self.setArray(ret)
 | |
|         return ret.At(ret.Len()-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.Push(Pair{Key: key, Value: val})
 | |
|     self.l++
 | |
|     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++
 | |
|         return ret.At(ret.Len()-1)
 | |
|     case '}':
 | |
|         parser.p++
 | |
|         self.setObject(ret)
 | |
|         return ret.At(ret.Len()-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
 | |
|     }
 | |
| }
 | |
| 
 | |
| // NewParser returns pointer of new allocated parser
 | |
| func NewParser(src string) *Parser {
 | |
|     return &Parser{s: src}
 | |
| }
 | |
| 
 | |
| // NewParser returns new allocated parser
 | |
| func NewParserObj(src string) Parser {
 | |
|     return Parser{s: src}
 | |
| }
 | |
| 
 | |
| // decodeNumber controls if parser decodes the number values instead of skip them
 | |
| //   WARN: once you set decodeNumber(true), please set decodeNumber(false) before you drop the parser 
 | |
| //   otherwise the memory CANNOT be reused
 | |
| func (self *Parser) decodeNumber(decode bool) {
 | |
|     if !decode && self.dbuf != nil {
 | |
|         types.FreeDbuf(self.dbuf)
 | |
|         self.dbuf = nil
 | |
|         return
 | |
|     }
 | |
|     if decode && self.dbuf == nil {
 | |
|         self.dbuf = types.NewDbuf()
 | |
|     }
 | |
| }
 | |
| 
 | |
| // ExportError converts types.ParsingError to std Error
 | |
| func (self *Parser) ExportError(err types.ParsingError) error {
 | |
|     if err == _ERR_NOT_FOUND {
 | |
|         return ErrNotExist
 | |
|     }
 | |
|     return fmt.Errorf("%q", SyntaxError{
 | |
|         Pos : self.p,
 | |
|         Src : self.s,
 | |
|         Code: err,
 | |
|     }.Description())
 | |
| }
 | |
| 
 | |
| func backward(src string, i int) int {
 | |
|     for ; i>=0 && isSpace(src[i]); i-- {}
 | |
|     return i
 | |
| }
 |