1
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
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
43 *buf = append(*buf, '"')
44 pbuf = (*rt.GoSlice)(unsafe.Pointer(buf))
45 pstr = (*rt.GoString)(unsafe.Pointer(&val))
46
47
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
56 if pbuf.Len += dn; nb >= 0 {
57 break
58 }
59
60
61 sidx += ^nb
62 *pbuf = growslice(rt.UnpackType(byteType), *pbuf, pbuf.Cap * 2)
63 }
64
65
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]...)
119 sbuf := (*rt.GoSlice)(unsafe.Pointer(&src))
120 dbuf := (*rt.GoSlice)(unsafe.Pointer(&dst))
121
122
123 if cap(dst) - len(dst) < len(src) + types.BufPaddingSize {
124 cap := len(src) * 3 / 2 + types.BufPaddingSize
125 *dbuf = 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
137 if dbuf.Len += dn; nb >= 0 {
138 break
139 }
140
141
142 sidx += ^nb
143 *dbuf = 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 }
168
View as plain text