1 package encoder
2
3 import (
4 "bytes"
5 "encoding"
6 "encoding/base64"
7 "encoding/json"
8 "fmt"
9 "math"
10 "reflect"
11 "strconv"
12 "strings"
13 "sync"
14 "unsafe"
15
16 "github.com/goccy/go-json/internal/errors"
17 "github.com/goccy/go-json/internal/runtime"
18 )
19
20 func (t OpType) IsMultipleOpHead() bool {
21 switch t {
22 case OpStructHead:
23 return true
24 case OpStructHeadSlice:
25 return true
26 case OpStructHeadArray:
27 return true
28 case OpStructHeadMap:
29 return true
30 case OpStructHeadStruct:
31 return true
32 case OpStructHeadOmitEmpty:
33 return true
34 case OpStructHeadOmitEmptySlice:
35 return true
36 case OpStructHeadOmitEmptyArray:
37 return true
38 case OpStructHeadOmitEmptyMap:
39 return true
40 case OpStructHeadOmitEmptyStruct:
41 return true
42 case OpStructHeadSlicePtr:
43 return true
44 case OpStructHeadOmitEmptySlicePtr:
45 return true
46 case OpStructHeadArrayPtr:
47 return true
48 case OpStructHeadOmitEmptyArrayPtr:
49 return true
50 case OpStructHeadMapPtr:
51 return true
52 case OpStructHeadOmitEmptyMapPtr:
53 return true
54 }
55 return false
56 }
57
58 func (t OpType) IsMultipleOpField() bool {
59 switch t {
60 case OpStructField:
61 return true
62 case OpStructFieldSlice:
63 return true
64 case OpStructFieldArray:
65 return true
66 case OpStructFieldMap:
67 return true
68 case OpStructFieldStruct:
69 return true
70 case OpStructFieldOmitEmpty:
71 return true
72 case OpStructFieldOmitEmptySlice:
73 return true
74 case OpStructFieldOmitEmptyArray:
75 return true
76 case OpStructFieldOmitEmptyMap:
77 return true
78 case OpStructFieldOmitEmptyStruct:
79 return true
80 case OpStructFieldSlicePtr:
81 return true
82 case OpStructFieldOmitEmptySlicePtr:
83 return true
84 case OpStructFieldArrayPtr:
85 return true
86 case OpStructFieldOmitEmptyArrayPtr:
87 return true
88 case OpStructFieldMapPtr:
89 return true
90 case OpStructFieldOmitEmptyMapPtr:
91 return true
92 }
93 return false
94 }
95
96 type OpcodeSet struct {
97 Type *runtime.Type
98 NoescapeKeyCode *Opcode
99 EscapeKeyCode *Opcode
100 InterfaceNoescapeKeyCode *Opcode
101 InterfaceEscapeKeyCode *Opcode
102 CodeLength int
103 EndCode *Opcode
104 Code Code
105 QueryCache map[string]*OpcodeSet
106 cacheMu sync.RWMutex
107 }
108
109 func (s *OpcodeSet) getQueryCache(hash string) *OpcodeSet {
110 s.cacheMu.RLock()
111 codeSet := s.QueryCache[hash]
112 s.cacheMu.RUnlock()
113 return codeSet
114 }
115
116 func (s *OpcodeSet) setQueryCache(hash string, codeSet *OpcodeSet) {
117 s.cacheMu.Lock()
118 s.QueryCache[hash] = codeSet
119 s.cacheMu.Unlock()
120 }
121
122 type CompiledCode struct {
123 Code *Opcode
124 Linked bool
125 CurLen uintptr
126 NextLen uintptr
127 }
128
129 const StartDetectingCyclesAfter = 1000
130
131 func Load(base uintptr, idx uintptr) uintptr {
132 addr := base + idx
133 return **(**uintptr)(unsafe.Pointer(&addr))
134 }
135
136 func Store(base uintptr, idx uintptr, p uintptr) {
137 addr := base + idx
138 **(**uintptr)(unsafe.Pointer(&addr)) = p
139 }
140
141 func LoadNPtr(base uintptr, idx uintptr, ptrNum int) uintptr {
142 addr := base + idx
143 p := **(**uintptr)(unsafe.Pointer(&addr))
144 if p == 0 {
145 return 0
146 }
147 return PtrToPtr(p)
148
157 }
158
159 func PtrToUint64(p uintptr) uint64 { return **(**uint64)(unsafe.Pointer(&p)) }
160 func PtrToFloat32(p uintptr) float32 { return **(**float32)(unsafe.Pointer(&p)) }
161 func PtrToFloat64(p uintptr) float64 { return **(**float64)(unsafe.Pointer(&p)) }
162 func PtrToBool(p uintptr) bool { return **(**bool)(unsafe.Pointer(&p)) }
163 func PtrToBytes(p uintptr) []byte { return **(**[]byte)(unsafe.Pointer(&p)) }
164 func PtrToNumber(p uintptr) json.Number { return **(**json.Number)(unsafe.Pointer(&p)) }
165 func PtrToString(p uintptr) string { return **(**string)(unsafe.Pointer(&p)) }
166 func PtrToSlice(p uintptr) *runtime.SliceHeader { return *(**runtime.SliceHeader)(unsafe.Pointer(&p)) }
167 func PtrToPtr(p uintptr) uintptr {
168 return uintptr(**(**unsafe.Pointer)(unsafe.Pointer(&p)))
169 }
170 func PtrToNPtr(p uintptr, ptrNum int) uintptr {
171 for i := 0; i < ptrNum; i++ {
172 if p == 0 {
173 return 0
174 }
175 p = PtrToPtr(p)
176 }
177 return p
178 }
179
180 func PtrToUnsafePtr(p uintptr) unsafe.Pointer {
181 return *(*unsafe.Pointer)(unsafe.Pointer(&p))
182 }
183 func PtrToInterface(code *Opcode, p uintptr) interface{} {
184 return *(*interface{})(unsafe.Pointer(&emptyInterface{
185 typ: code.Type,
186 ptr: *(*unsafe.Pointer)(unsafe.Pointer(&p)),
187 }))
188 }
189
190 func ErrUnsupportedValue(code *Opcode, ptr uintptr) *errors.UnsupportedValueError {
191 v := *(*interface{})(unsafe.Pointer(&emptyInterface{
192 typ: code.Type,
193 ptr: *(*unsafe.Pointer)(unsafe.Pointer(&ptr)),
194 }))
195 return &errors.UnsupportedValueError{
196 Value: reflect.ValueOf(v),
197 Str: fmt.Sprintf("encountered a cycle via %s", code.Type),
198 }
199 }
200
201 func ErrUnsupportedFloat(v float64) *errors.UnsupportedValueError {
202 return &errors.UnsupportedValueError{
203 Value: reflect.ValueOf(v),
204 Str: strconv.FormatFloat(v, 'g', -1, 64),
205 }
206 }
207
208 func ErrMarshalerWithCode(code *Opcode, err error) *errors.MarshalerError {
209 return &errors.MarshalerError{
210 Type: runtime.RType2Type(code.Type),
211 Err: err,
212 }
213 }
214
215 type emptyInterface struct {
216 typ *runtime.Type
217 ptr unsafe.Pointer
218 }
219
220 type MapItem struct {
221 Key []byte
222 Value []byte
223 }
224
225 type Mapslice struct {
226 Items []MapItem
227 }
228
229 func (m *Mapslice) Len() int {
230 return len(m.Items)
231 }
232
233 func (m *Mapslice) Less(i, j int) bool {
234 return bytes.Compare(m.Items[i].Key, m.Items[j].Key) < 0
235 }
236
237 func (m *Mapslice) Swap(i, j int) {
238 m.Items[i], m.Items[j] = m.Items[j], m.Items[i]
239 }
240
241
242 type mapIter struct {
243 key unsafe.Pointer
244 elem unsafe.Pointer
245 t unsafe.Pointer
246 h unsafe.Pointer
247 buckets unsafe.Pointer
248 bptr unsafe.Pointer
249 overflow unsafe.Pointer
250 oldoverflow unsafe.Pointer
251 startBucket uintptr
252 offset uint8
253 wrapped bool
254 B uint8
255 i uint8
256 bucket uintptr
257 checkBucket uintptr
258 }
259
260 type MapContext struct {
261 Start int
262 First int
263 Idx int
264 Slice *Mapslice
265 Buf []byte
266 Len int
267 Iter mapIter
268 }
269
270 var mapContextPool = sync.Pool{
271 New: func() interface{} {
272 return &MapContext{
273 Slice: &Mapslice{},
274 }
275 },
276 }
277
278 func NewMapContext(mapLen int, unorderedMap bool) *MapContext {
279 ctx := mapContextPool.Get().(*MapContext)
280 if !unorderedMap {
281 if len(ctx.Slice.Items) < mapLen {
282 ctx.Slice.Items = make([]MapItem, mapLen)
283 } else {
284 ctx.Slice.Items = ctx.Slice.Items[:mapLen]
285 }
286 }
287 ctx.Buf = ctx.Buf[:0]
288 ctx.Iter = mapIter{}
289 ctx.Idx = 0
290 ctx.Len = mapLen
291 return ctx
292 }
293
294 func ReleaseMapContext(c *MapContext) {
295 mapContextPool.Put(c)
296 }
297
298
299
300 func MapIterInit(mapType *runtime.Type, m unsafe.Pointer, it *mapIter)
301
302
303
304 func MapIterKey(it *mapIter) unsafe.Pointer
305
306
307
308 func MapIterNext(it *mapIter)
309
310
311
312 func MapLen(m unsafe.Pointer) int
313
314 func AppendByteSlice(_ *RuntimeContext, b []byte, src []byte) []byte {
315 if src == nil {
316 return append(b, `null`...)
317 }
318 encodedLen := base64.StdEncoding.EncodedLen(len(src))
319 b = append(b, '"')
320 pos := len(b)
321 remainLen := cap(b[pos:])
322 var buf []byte
323 if remainLen > encodedLen {
324 buf = b[pos : pos+encodedLen]
325 } else {
326 buf = make([]byte, encodedLen)
327 }
328 base64.StdEncoding.Encode(buf, src)
329 return append(append(b, buf...), '"')
330 }
331
332 func AppendFloat32(_ *RuntimeContext, b []byte, v float32) []byte {
333 f64 := float64(v)
334 abs := math.Abs(f64)
335 fmt := byte('f')
336
337 if abs != 0 {
338 f32 := float32(abs)
339 if f32 < 1e-6 || f32 >= 1e21 {
340 fmt = 'e'
341 }
342 }
343 return strconv.AppendFloat(b, f64, fmt, -1, 32)
344 }
345
346 func AppendFloat64(_ *RuntimeContext, b []byte, v float64) []byte {
347 abs := math.Abs(v)
348 fmt := byte('f')
349
350 if abs != 0 {
351 if abs < 1e-6 || abs >= 1e21 {
352 fmt = 'e'
353 }
354 }
355 return strconv.AppendFloat(b, v, fmt, -1, 64)
356 }
357
358 func AppendBool(_ *RuntimeContext, b []byte, v bool) []byte {
359 if v {
360 return append(b, "true"...)
361 }
362 return append(b, "false"...)
363 }
364
365 var (
366 floatTable = [256]bool{
367 '0': true,
368 '1': true,
369 '2': true,
370 '3': true,
371 '4': true,
372 '5': true,
373 '6': true,
374 '7': true,
375 '8': true,
376 '9': true,
377 '.': true,
378 'e': true,
379 'E': true,
380 '+': true,
381 '-': true,
382 }
383 )
384
385 func AppendNumber(_ *RuntimeContext, b []byte, n json.Number) ([]byte, error) {
386 if len(n) == 0 {
387 return append(b, '0'), nil
388 }
389 for i := 0; i < len(n); i++ {
390 if !floatTable[n[i]] {
391 return nil, fmt.Errorf("json: invalid number literal %q", n)
392 }
393 }
394 b = append(b, n...)
395 return b, nil
396 }
397
398 func AppendMarshalJSON(ctx *RuntimeContext, code *Opcode, b []byte, v interface{}) ([]byte, error) {
399 rv := reflect.ValueOf(v)
400 if (code.Flags & AddrForMarshalerFlags) != 0 {
401 if rv.CanAddr() {
402 rv = rv.Addr()
403 } else {
404 newV := reflect.New(rv.Type())
405 newV.Elem().Set(rv)
406 rv = newV
407 }
408 }
409 v = rv.Interface()
410 var bb []byte
411 if (code.Flags & MarshalerContextFlags) != 0 {
412 marshaler, ok := v.(marshalerContext)
413 if !ok {
414 return AppendNull(ctx, b), nil
415 }
416 stdctx := ctx.Option.Context
417 if ctx.Option.Flag&FieldQueryOption != 0 {
418 stdctx = SetFieldQueryToContext(stdctx, code.FieldQuery)
419 }
420 b, err := marshaler.MarshalJSON(stdctx)
421 if err != nil {
422 return nil, &errors.MarshalerError{Type: reflect.TypeOf(v), Err: err}
423 }
424 bb = b
425 } else {
426 marshaler, ok := v.(json.Marshaler)
427 if !ok {
428 return AppendNull(ctx, b), nil
429 }
430 b, err := marshaler.MarshalJSON()
431 if err != nil {
432 return nil, &errors.MarshalerError{Type: reflect.TypeOf(v), Err: err}
433 }
434 bb = b
435 }
436 marshalBuf := ctx.MarshalBuf[:0]
437 marshalBuf = append(append(marshalBuf, bb...), nul)
438 compactedBuf, err := compact(b, marshalBuf, (ctx.Option.Flag&HTMLEscapeOption) != 0)
439 if err != nil {
440 return nil, &errors.MarshalerError{Type: reflect.TypeOf(v), Err: err}
441 }
442 ctx.MarshalBuf = marshalBuf
443 return compactedBuf, nil
444 }
445
446 func AppendMarshalJSONIndent(ctx *RuntimeContext, code *Opcode, b []byte, v interface{}) ([]byte, error) {
447 rv := reflect.ValueOf(v)
448 if (code.Flags & AddrForMarshalerFlags) != 0 {
449 if rv.CanAddr() {
450 rv = rv.Addr()
451 } else {
452 newV := reflect.New(rv.Type())
453 newV.Elem().Set(rv)
454 rv = newV
455 }
456 }
457 v = rv.Interface()
458 var bb []byte
459 if (code.Flags & MarshalerContextFlags) != 0 {
460 marshaler, ok := v.(marshalerContext)
461 if !ok {
462 return AppendNull(ctx, b), nil
463 }
464 b, err := marshaler.MarshalJSON(ctx.Option.Context)
465 if err != nil {
466 return nil, &errors.MarshalerError{Type: reflect.TypeOf(v), Err: err}
467 }
468 bb = b
469 } else {
470 marshaler, ok := v.(json.Marshaler)
471 if !ok {
472 return AppendNull(ctx, b), nil
473 }
474 b, err := marshaler.MarshalJSON()
475 if err != nil {
476 return nil, &errors.MarshalerError{Type: reflect.TypeOf(v), Err: err}
477 }
478 bb = b
479 }
480 marshalBuf := ctx.MarshalBuf[:0]
481 marshalBuf = append(append(marshalBuf, bb...), nul)
482 indentedBuf, err := doIndent(
483 b,
484 marshalBuf,
485 string(ctx.Prefix)+strings.Repeat(string(ctx.IndentStr), int(ctx.BaseIndent+code.Indent)),
486 string(ctx.IndentStr),
487 (ctx.Option.Flag&HTMLEscapeOption) != 0,
488 )
489 if err != nil {
490 return nil, &errors.MarshalerError{Type: reflect.TypeOf(v), Err: err}
491 }
492 ctx.MarshalBuf = marshalBuf
493 return indentedBuf, nil
494 }
495
496 func AppendMarshalText(ctx *RuntimeContext, code *Opcode, b []byte, v interface{}) ([]byte, error) {
497 rv := reflect.ValueOf(v)
498 if (code.Flags & AddrForMarshalerFlags) != 0 {
499 if rv.CanAddr() {
500 rv = rv.Addr()
501 } else {
502 newV := reflect.New(rv.Type())
503 newV.Elem().Set(rv)
504 rv = newV
505 }
506 }
507 v = rv.Interface()
508 marshaler, ok := v.(encoding.TextMarshaler)
509 if !ok {
510 return AppendNull(ctx, b), nil
511 }
512 bytes, err := marshaler.MarshalText()
513 if err != nil {
514 return nil, &errors.MarshalerError{Type: reflect.TypeOf(v), Err: err}
515 }
516 return AppendString(ctx, b, *(*string)(unsafe.Pointer(&bytes))), nil
517 }
518
519 func AppendMarshalTextIndent(ctx *RuntimeContext, code *Opcode, b []byte, v interface{}) ([]byte, error) {
520 rv := reflect.ValueOf(v)
521 if (code.Flags & AddrForMarshalerFlags) != 0 {
522 if rv.CanAddr() {
523 rv = rv.Addr()
524 } else {
525 newV := reflect.New(rv.Type())
526 newV.Elem().Set(rv)
527 rv = newV
528 }
529 }
530 v = rv.Interface()
531 marshaler, ok := v.(encoding.TextMarshaler)
532 if !ok {
533 return AppendNull(ctx, b), nil
534 }
535 bytes, err := marshaler.MarshalText()
536 if err != nil {
537 return nil, &errors.MarshalerError{Type: reflect.TypeOf(v), Err: err}
538 }
539 return AppendString(ctx, b, *(*string)(unsafe.Pointer(&bytes))), nil
540 }
541
542 func AppendNull(_ *RuntimeContext, b []byte) []byte {
543 return append(b, "null"...)
544 }
545
546 func AppendComma(_ *RuntimeContext, b []byte) []byte {
547 return append(b, ',')
548 }
549
550 func AppendCommaIndent(_ *RuntimeContext, b []byte) []byte {
551 return append(b, ',', '\n')
552 }
553
554 func AppendStructEnd(_ *RuntimeContext, b []byte) []byte {
555 return append(b, '}', ',')
556 }
557
558 func AppendStructEndIndent(ctx *RuntimeContext, code *Opcode, b []byte) []byte {
559 b = append(b, '\n')
560 b = append(b, ctx.Prefix...)
561 indentNum := ctx.BaseIndent + code.Indent - 1
562 for i := uint32(0); i < indentNum; i++ {
563 b = append(b, ctx.IndentStr...)
564 }
565 return append(b, '}', ',', '\n')
566 }
567
568 func AppendIndent(ctx *RuntimeContext, b []byte, indent uint32) []byte {
569 b = append(b, ctx.Prefix...)
570 indentNum := ctx.BaseIndent + indent
571 for i := uint32(0); i < indentNum; i++ {
572 b = append(b, ctx.IndentStr...)
573 }
574 return b
575 }
576
577 func IsNilForMarshaler(v interface{}) bool {
578 rv := reflect.ValueOf(v)
579 switch rv.Kind() {
580 case reflect.Bool:
581 return !rv.Bool()
582 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
583 return rv.Int() == 0
584 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
585 return rv.Uint() == 0
586 case reflect.Float32, reflect.Float64:
587 return math.Float64bits(rv.Float()) == 0
588 case reflect.Interface, reflect.Map, reflect.Ptr, reflect.Func:
589 return rv.IsNil()
590 case reflect.Slice:
591 return rv.IsNil() || rv.Len() == 0
592 case reflect.String:
593 return rv.Len() == 0
594 }
595 return false
596 }
597
View as plain text