github.com/goshafaq/sonic@v0.0.0-20231026082336-871835fb94c6/ast/api_amd64.go (about)

     1  //go:build amd64 && go1.16 && !go1.22
     2  // +build amd64,go1.16,!go1.22
     3  
     4  /*
     5   * Copyright 2022 ByteDance Inc.
     6   *
     7   * Licensed under the Apache License, Version 2.0 (the "License");
     8   * you may not use this file except in compliance with the License.
     9   * You may obtain a copy of the License at
    10   *
    11   *     http://www.apache.org/licenses/LICENSE-2.0
    12   *
    13   * Unless required by applicable law or agreed to in writing, software
    14   * distributed under the License is distributed on an "AS IS" BASIS,
    15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    16   * See the License for the specific language governing permissions and
    17   * limitations under the License.
    18   */
    19  
    20  package ast
    21  
    22  import (
    23  	"runtime"
    24  	"unsafe"
    25  
    26  	"github.com/chenzhuoyu/base64x"
    27  	"github.com/goshafaq/sonic/encoder"
    28  	"github.com/goshafaq/sonic/internal/native"
    29  	"github.com/goshafaq/sonic/internal/native/types"
    30  	"github.com/goshafaq/sonic/internal/rt"
    31  	uq "github.com/goshafaq/sonic/unquote"
    32  )
    33  
    34  var typeByte = rt.UnpackEface(byte(0)).Type
    35  
    36  //go:nocheckptr
    37  func quote(buf *[]byte, val string) {
    38  	*buf = append(*buf, '"')
    39  	if len(val) == 0 {
    40  		*buf = append(*buf, '"')
    41  		return
    42  	}
    43  
    44  	sp := rt.IndexChar(val, 0)
    45  	nb := len(val)
    46  	b := (*rt.GoSlice)(unsafe.Pointer(buf))
    47  
    48  	// input buffer
    49  	for nb > 0 {
    50  		// output buffer
    51  		dp := unsafe.Pointer(uintptr(b.Ptr) + uintptr(b.Len))
    52  		dn := b.Cap - b.Len
    53  		// call native.Quote, dn is byte count it outputs
    54  		ret := native.Quote(sp, nb, dp, &dn, 0)
    55  		// update *buf length
    56  		b.Len += dn
    57  
    58  		// no need more output
    59  		if ret >= 0 {
    60  			break
    61  		}
    62  
    63  		// double buf size
    64  		*b = growslice(typeByte, *b, b.Cap*2)
    65  		// ret is the complement of consumed input
    66  		ret = ^ret
    67  		// update input buffer
    68  		nb -= ret
    69  		sp = unsafe.Pointer(uintptr(sp) + uintptr(ret))
    70  	}
    71  
    72  	runtime.KeepAlive(buf)
    73  	runtime.KeepAlive(sp)
    74  	*buf = append(*buf, '"')
    75  }
    76  
    77  func unquote(src string) (string, types.ParsingError) {
    78  	return uq.String(src)
    79  }
    80  
    81  func decodeBase64(src string) ([]byte, error) {
    82  	return base64x.StdEncoding.DecodeString(src)
    83  }
    84  
    85  func encodeBase64(src []byte) string {
    86  	return base64x.StdEncoding.EncodeToString(src)
    87  }
    88  
    89  func (self *Parser) decodeValue() (val types.JsonState) {
    90  	sv := (*rt.GoString)(unsafe.Pointer(&self.s))
    91  	flag := types.F_USE_NUMBER
    92  	if self.dbuf != nil {
    93  		flag = 0
    94  		val.Dbuf = self.dbuf
    95  		val.Dcap = types.MaxDigitNums
    96  	}
    97  	self.p = native.Value(sv.Ptr, sv.Len, self.p, &val, uint64(flag))
    98  	return
    99  }
   100  
   101  func (self *Parser) skip() (int, types.ParsingError) {
   102  	fsm := types.NewStateMachine()
   103  	start := native.SkipOne(&self.s, &self.p, fsm, 0)
   104  	types.FreeStateMachine(fsm)
   105  
   106  	if start < 0 {
   107  		return self.p, types.ParsingError(-start)
   108  	}
   109  	return start, 0
   110  }
   111  
   112  func (self *Node) encodeInterface(buf *[]byte) error {
   113  	//WARN: NOT compatible with json.Encoder
   114  	return encoder.EncodeInto(buf, self.packAny(), 0)
   115  }
   116  
   117  func (self *Parser) skipFast() (int, types.ParsingError) {
   118  	start := native.SkipOneFast(&self.s, &self.p)
   119  	if start < 0 {
   120  		return self.p, types.ParsingError(-start)
   121  	}
   122  	return start, 0
   123  }
   124  
   125  func (self *Parser) getByPath(path ...interface{}) (int, types.ParsingError) {
   126  	fsm := types.NewStateMachine()
   127  	start := native.GetByPath(&self.s, &self.p, &path, fsm)
   128  	types.FreeStateMachine(fsm)
   129  	runtime.KeepAlive(path)
   130  	if start < 0 {
   131  		return self.p, types.ParsingError(-start)
   132  	}
   133  	return start, 0
   134  }
   135  
   136  func (self *Searcher) GetByPath(path ...interface{}) (Node, error) {
   137  	var err types.ParsingError
   138  	var start int
   139  
   140  	self.parser.p = 0
   141  	start, err = self.parser.getByPath(path...)
   142  	if err != 0 {
   143  		// for compatibility with old version
   144  		if err == types.ERR_NOT_FOUND {
   145  			return Node{}, ErrNotExist
   146  		}
   147  		if err == types.ERR_UNSUPPORT_TYPE {
   148  			panic("path must be either int(>=0) or string")
   149  		}
   150  		return Node{}, self.parser.syntaxError(err)
   151  	}
   152  
   153  	t := switchRawType(self.parser.s[start])
   154  	if t == _V_NONE {
   155  		return Node{}, self.parser.ExportError(err)
   156  	}
   157  	return newRawNode(self.parser.s[start:self.parser.p], t), nil
   158  }