github.com/bytedance/sonic@v1.11.7-0.20240517092252-d2edb31b167b/internal/encoder/primitives.go (about) 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/native/types` 27 `github.com/bytedance/sonic/internal/rt` 28 ) 29 30 /** Encoder Primitives **/ 31 32 func encodeNil(rb *[]byte) error { 33 *rb = append(*rb, 'n', 'u', 'l', 'l') 34 return nil 35 } 36 37 func encodeString(buf *[]byte, val string) error { 38 var sidx int 39 var pbuf *rt.GoSlice 40 var pstr *rt.GoString 41 42 /* opening quote */ 43 *buf = append(*buf, '"') 44 pbuf = (*rt.GoSlice)(unsafe.Pointer(buf)) 45 pstr = (*rt.GoString)(unsafe.Pointer(&val)) 46 47 /* encode with native library */ 48 for sidx < pstr.Len { 49 sn := pstr.Len - sidx 50 dn := pbuf.Cap - pbuf.Len 51 sp := padd(pstr.Ptr, sidx) 52 dp := padd(pbuf.Ptr, pbuf.Len) 53 nb := native.Quote(sp, sn, dp, &dn, 0) 54 55 /* check for errors */ 56 if pbuf.Len += dn; nb >= 0 { 57 break 58 } 59 60 /* not enough space, grow the slice and try again */ 61 sidx += ^nb 62 *pbuf = rt.GrowSlice(rt.UnpackType(byteType), *pbuf, pbuf.Cap * 2) 63 } 64 65 /* closing quote */ 66 *buf = append(*buf, '"') 67 return nil 68 } 69 70 func encodeTypedPointer(buf *[]byte, vt *rt.GoType, vp *unsafe.Pointer, sb *_Stack, fv uint64) error { 71 if vt == nil { 72 return encodeNil(buf) 73 } else if fn, err := findOrCompile(vt, (fv&(1<<bitPointerValue)) != 0); err != nil { 74 return err 75 } else if vt.Indirect() { 76 rt.MoreStack(_FP_size + native.MaxFrameSize) 77 err := fn(buf, *vp, sb, fv) 78 return err 79 } else { 80 rt.MoreStack(_FP_size + native.MaxFrameSize) 81 err := fn(buf, unsafe.Pointer(vp), sb, fv) 82 return err 83 } 84 } 85 86 func encodeJsonMarshaler(buf *[]byte, val json.Marshaler, opt Options) error { 87 if ret, err := val.MarshalJSON(); err != nil { 88 return err 89 } else { 90 if opt & CompactMarshaler != 0 { 91 return compact(buf, ret) 92 } 93 if opt & NoValidateJSONMarshaler == 0 { 94 if ok, s := Valid(ret); !ok { 95 return error_marshaler(ret, s) 96 } 97 } 98 *buf = append(*buf, ret...) 99 return nil 100 } 101 } 102 103 func encodeTextMarshaler(buf *[]byte, val encoding.TextMarshaler, opt Options) error { 104 if ret, err := val.MarshalText(); err != nil { 105 return err 106 } else { 107 if opt & NoQuoteTextMarshaler != 0 { 108 *buf = append(*buf, ret...) 109 return nil 110 } 111 return encodeString(buf, rt.Mem2Str(ret) ) 112 } 113 } 114 115 func htmlEscape(dst []byte, src []byte) []byte { 116 var sidx int 117 118 dst = append(dst, src[:0]...) // avoid check nil dst 119 sbuf := (*rt.GoSlice)(unsafe.Pointer(&src)) 120 dbuf := (*rt.GoSlice)(unsafe.Pointer(&dst)) 121 122 /* grow dst if it is shorter */ 123 if cap(dst) - len(dst) < len(src) + types.BufPaddingSize { 124 cap := len(src) * 3 / 2 + types.BufPaddingSize 125 *dbuf = rt.GrowSlice(typeByte, *dbuf, cap) 126 } 127 128 for sidx < sbuf.Len { 129 sp := padd(sbuf.Ptr, sidx) 130 dp := padd(dbuf.Ptr, dbuf.Len) 131 132 sn := sbuf.Len - sidx 133 dn := dbuf.Cap - dbuf.Len 134 nb := native.HTMLEscape(sp, sn, dp, &dn) 135 136 /* check for errors */ 137 if dbuf.Len += dn; nb >= 0 { 138 break 139 } 140 141 /* not enough space, grow the slice and try again */ 142 sidx += ^nb 143 *dbuf = rt.GrowSlice(typeByte, *dbuf, dbuf.Cap * 2) 144 } 145 return dst 146 } 147 148 var ( 149 argPtrs = []bool { true, true, true, false } 150 localPtrs = []bool{} 151 ) 152 153 var ( 154 _F_assertI2I = jit.Func(rt.AssertI2I2) 155 ) 156 157 func asText(v unsafe.Pointer) (string, error) { 158 text := rt.AssertI2I2(_T_encoding_TextMarshaler, *(*rt.GoIface)(v)) 159 r, e := (*(*encoding.TextMarshaler)(unsafe.Pointer(&text))).MarshalText() 160 return rt.Mem2Str(r), e 161 } 162 163 func asJson(v unsafe.Pointer) (string, error) { 164 text := rt.AssertI2I2(_T_json_Marshaler, *(*rt.GoIface)(v)) 165 r, e := (*(*json.Marshaler)(unsafe.Pointer(&text))).MarshalJSON() 166 return rt.Mem2Str(r), e 167 }