github.com/bytedance/sonic@v1.11.7-0.20240517092252-d2edb31b167b/ast/api.go (about)

     1  //go:build (amd64 && go1.16 && !go1.23) || (arm64 && go1.20 && !go1.23)
     2  // +build amd64,go1.16,!go1.23 arm64,go1.20,!go1.23
     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/bytedance/sonic/encoder`
    27      `github.com/bytedance/sonic/internal/native`
    28      `github.com/bytedance/sonic/internal/native/types`
    29      `github.com/bytedance/sonic/internal/rt`
    30      uq `github.com/bytedance/sonic/unquote`
    31      `github.com/bytedance/sonic/utf8`
    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 = rt.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 (self *Parser) decodeValue() (val types.JsonState) {
    82      sv := (*rt.GoString)(unsafe.Pointer(&self.s))
    83      flag := types.F_USE_NUMBER
    84      if self.dbuf != nil {
    85          flag = 0
    86          val.Dbuf = self.dbuf
    87          val.Dcap = types.MaxDigitNums
    88      }
    89      self.p = native.Value(sv.Ptr, sv.Len, self.p, &val, uint64(flag))
    90      return
    91  }
    92  
    93  func (self *Parser) skip() (int, types.ParsingError) {
    94      fsm := types.NewStateMachine()
    95      start := native.SkipOne(&self.s, &self.p, fsm, 0)
    96      types.FreeStateMachine(fsm)
    97  
    98      if start < 0 {
    99          return self.p, types.ParsingError(-start)
   100      }
   101      return start, 0
   102  }
   103  
   104  func (self *Node) encodeInterface(buf *[]byte) error {
   105      //WARN: NOT compatible with json.Encoder
   106      return encoder.EncodeInto(buf, self.packAny(), encoder.NoEncoderNewline)
   107  }
   108  
   109  func (self *Parser) skipFast() (int, types.ParsingError) {
   110      start := native.SkipOneFast(&self.s, &self.p)
   111      if start < 0 {
   112          return self.p, types.ParsingError(-start)
   113      }
   114      return start, 0
   115  }
   116  
   117  func (self *Parser) getByPath(validate bool, path ...interface{}) (int, types.ParsingError) {
   118      var fsm *types.StateMachine
   119      if validate {
   120          fsm = types.NewStateMachine()
   121      }
   122      start := native.GetByPath(&self.s, &self.p, &path, fsm)
   123      if validate {
   124          types.FreeStateMachine(fsm)
   125      }
   126      runtime.KeepAlive(path)
   127      if start < 0 {
   128          return self.p, types.ParsingError(-start)
   129      }
   130      return start, 0
   131  }
   132  
   133  func validate_utf8(str string) bool {
   134      return utf8.ValidateString(str)
   135  }