...

Source file src/github.com/bytedance/sonic/internal/encoder/primitives.go

Documentation: github.com/bytedance/sonic/internal/encoder

     1  /*
     2   * Copyright 2021 ByteDance Inc.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package encoder
    18  
    19  import (
    20      `encoding`
    21      `encoding/json`
    22      `unsafe`
    23  
    24      `github.com/bytedance/sonic/internal/jit`
    25      `github.com/bytedance/sonic/internal/native`
    26      `github.com/bytedance/sonic/internal/rt`
    27  )
    28  
    29  /** Encoder Primitives **/
    30  
    31  func encodeNil(rb *[]byte) error {
    32      *rb = append(*rb, 'n', 'u', 'l', 'l')
    33      return nil
    34  }
    35  
    36  func encodeString(buf *[]byte, val string) error {
    37      var sidx int
    38      var pbuf *rt.GoSlice
    39      var pstr *rt.GoString
    40  
    41      /* opening quote */
    42      *buf = append(*buf, '"')
    43      pbuf = (*rt.GoSlice)(unsafe.Pointer(buf))
    44      pstr = (*rt.GoString)(unsafe.Pointer(&val))
    45  
    46      /* encode with native library */
    47      for sidx < pstr.Len {
    48          sn := pstr.Len - sidx
    49          dn := pbuf.Cap - pbuf.Len
    50          sp := padd(pstr.Ptr, sidx)
    51          dp := padd(pbuf.Ptr, pbuf.Len)
    52          nb := native.Quote(sp, sn, dp, &dn, 0)
    53  
    54          /* check for errors */
    55          if pbuf.Len += dn; nb >= 0 {
    56              break
    57          }
    58  
    59          /* not enough space, grow the slice and try again */
    60          sidx += ^nb
    61          *pbuf = growslice(rt.UnpackType(byteType), *pbuf, pbuf.Cap * 2)
    62      }
    63  
    64      /* closing quote */
    65      *buf = append(*buf, '"')
    66      return nil
    67  }
    68  
    69  func encodeTypedPointer(buf *[]byte, vt *rt.GoType, vp *unsafe.Pointer, sb *_Stack, fv uint64) error {
    70      if vt == nil {
    71          return encodeNil(buf)
    72      } else if fn, err := findOrCompile(vt, (fv&(1<<bitPointerValue)) != 0); err != nil {
    73          return err
    74      } else if vt.Indirect() {
    75          rt.MoreStack(_FP_size + native.MaxFrameSize)
    76          rt.StopProf()
    77          err := fn(buf, *vp, sb, fv)
    78          rt.StartProf()
    79          return err
    80      } else {
    81          rt.MoreStack(_FP_size + native.MaxFrameSize)
    82          rt.StopProf()
    83          err := fn(buf, unsafe.Pointer(vp), sb, fv)
    84          rt.StartProf()
    85          return err
    86      }
    87  }
    88  
    89  func encodeJsonMarshaler(buf *[]byte, val json.Marshaler, opt Options) error {
    90      if ret, err := val.MarshalJSON(); err != nil {
    91          return err
    92      } else {
    93          if opt & CompactMarshaler != 0 {
    94              return compact(buf, ret)
    95          }
    96          if opt & NoValidateJSONMarshaler == 0 {
    97              if ok, s := Valid(ret); !ok {
    98                  return error_marshaler(ret, s)
    99              }
   100          }
   101          *buf = append(*buf, ret...)
   102          return nil
   103      }
   104  }
   105  
   106  func encodeTextMarshaler(buf *[]byte, val encoding.TextMarshaler, opt Options) error {
   107      if ret, err := val.MarshalText(); err != nil {
   108          return err
   109      } else {
   110          if opt & NoQuoteTextMarshaler != 0 {
   111              *buf = append(*buf, ret...)
   112              return nil
   113          }
   114          return encodeString(buf, rt.Mem2Str(ret) )
   115      }
   116  }
   117  
   118  func htmlEscape(dst []byte, src []byte) []byte {
   119      var sidx int
   120  
   121      dst  = append(dst, src[:0]...) // avoid check nil dst
   122      sbuf := (*rt.GoSlice)(unsafe.Pointer(&src))
   123      dbuf := (*rt.GoSlice)(unsafe.Pointer(&dst))
   124  
   125      /* grow dst if it is shorter */
   126      if cap(dst) - len(dst) < len(src) + native.BufPaddingSize {
   127          cap :=  len(src) * 3 / 2 + native.BufPaddingSize
   128          *dbuf = growslice(typeByte, *dbuf, cap)
   129      }
   130  
   131      for sidx < sbuf.Len {
   132          sp := padd(sbuf.Ptr, sidx)
   133          dp := padd(dbuf.Ptr, dbuf.Len)
   134  
   135          sn := sbuf.Len - sidx
   136          dn := dbuf.Cap - dbuf.Len
   137          nb := native.HTMLEscape(sp, sn, dp, &dn)
   138  
   139          /* check for errors */
   140          if dbuf.Len += dn; nb >= 0 {
   141              break
   142          }
   143  
   144          /* not enough space, grow the slice and try again */
   145          sidx += ^nb
   146          *dbuf = growslice(typeByte, *dbuf, dbuf.Cap * 2)
   147      }
   148      return dst
   149  }
   150  
   151  var (
   152      argPtrs   = []bool { true, true, true, false }
   153      localPtrs = []bool{}
   154  )
   155  
   156  var (
   157      _F_assertI2I = jit.Func(rt.AssertI2I2)
   158  )
   159  
   160  func asText(v unsafe.Pointer) (string, error) {
   161      text := rt.AssertI2I2(_T_encoding_TextMarshaler, *(*rt.GoIface)(v))
   162      r, e := (*(*encoding.TextMarshaler)(unsafe.Pointer(&text))).MarshalText()
   163      return rt.Mem2Str(r), e
   164  }
   165  
   166  func asJson(v unsafe.Pointer) (string, error) {
   167      text := rt.AssertI2I2(_T_json_Marshaler, *(*rt.GoIface)(v))
   168      r, e := (*(*json.Marshaler)(unsafe.Pointer(&text))).MarshalJSON()
   169      return rt.Mem2Str(r), e
   170  }
   171  

View as plain text