gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

array.go (3969B)


      1 package decoder
      2 
      3 import (
      4 	"fmt"
      5 	"unsafe"
      6 
      7 	"github.com/goccy/go-json/internal/errors"
      8 	"github.com/goccy/go-json/internal/runtime"
      9 )
     10 
     11 type arrayDecoder struct {
     12 	elemType     *runtime.Type
     13 	size         uintptr
     14 	valueDecoder Decoder
     15 	alen         int
     16 	structName   string
     17 	fieldName    string
     18 	zeroValue    unsafe.Pointer
     19 }
     20 
     21 func newArrayDecoder(dec Decoder, elemType *runtime.Type, alen int, structName, fieldName string) *arrayDecoder {
     22 	// workaround to avoid checkptr errors. cannot use `*(*unsafe.Pointer)(unsafe_New(elemType))` directly.
     23 	zeroValuePtr := unsafe_New(elemType)
     24 	zeroValue := **(**unsafe.Pointer)(unsafe.Pointer(&zeroValuePtr))
     25 	return &arrayDecoder{
     26 		valueDecoder: dec,
     27 		elemType:     elemType,
     28 		size:         elemType.Size(),
     29 		alen:         alen,
     30 		structName:   structName,
     31 		fieldName:    fieldName,
     32 		zeroValue:    zeroValue,
     33 	}
     34 }
     35 
     36 func (d *arrayDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
     37 	depth++
     38 	if depth > maxDecodeNestingDepth {
     39 		return errors.ErrExceededMaxDepth(s.char(), s.cursor)
     40 	}
     41 
     42 	for {
     43 		switch s.char() {
     44 		case ' ', '\n', '\t', '\r':
     45 		case 'n':
     46 			if err := nullBytes(s); err != nil {
     47 				return err
     48 			}
     49 			return nil
     50 		case '[':
     51 			idx := 0
     52 			s.cursor++
     53 			if s.skipWhiteSpace() == ']' {
     54 				for idx < d.alen {
     55 					*(*unsafe.Pointer)(unsafe.Pointer(uintptr(p) + uintptr(idx)*d.size)) = d.zeroValue
     56 					idx++
     57 				}
     58 				s.cursor++
     59 				return nil
     60 			}
     61 			for {
     62 				if idx < d.alen {
     63 					if err := d.valueDecoder.DecodeStream(s, depth, unsafe.Pointer(uintptr(p)+uintptr(idx)*d.size)); err != nil {
     64 						return err
     65 					}
     66 				} else {
     67 					if err := s.skipValue(depth); err != nil {
     68 						return err
     69 					}
     70 				}
     71 				idx++
     72 				switch s.skipWhiteSpace() {
     73 				case ']':
     74 					for idx < d.alen {
     75 						*(*unsafe.Pointer)(unsafe.Pointer(uintptr(p) + uintptr(idx)*d.size)) = d.zeroValue
     76 						idx++
     77 					}
     78 					s.cursor++
     79 					return nil
     80 				case ',':
     81 					s.cursor++
     82 					continue
     83 				case nul:
     84 					if s.read() {
     85 						s.cursor++
     86 						continue
     87 					}
     88 					goto ERROR
     89 				default:
     90 					goto ERROR
     91 				}
     92 			}
     93 		case nul:
     94 			if s.read() {
     95 				continue
     96 			}
     97 			goto ERROR
     98 		default:
     99 			goto ERROR
    100 		}
    101 		s.cursor++
    102 	}
    103 ERROR:
    104 	return errors.ErrUnexpectedEndOfJSON("array", s.totalOffset())
    105 }
    106 
    107 func (d *arrayDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
    108 	buf := ctx.Buf
    109 	depth++
    110 	if depth > maxDecodeNestingDepth {
    111 		return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
    112 	}
    113 
    114 	for {
    115 		switch buf[cursor] {
    116 		case ' ', '\n', '\t', '\r':
    117 			cursor++
    118 			continue
    119 		case 'n':
    120 			if err := validateNull(buf, cursor); err != nil {
    121 				return 0, err
    122 			}
    123 			cursor += 4
    124 			return cursor, nil
    125 		case '[':
    126 			idx := 0
    127 			cursor++
    128 			cursor = skipWhiteSpace(buf, cursor)
    129 			if buf[cursor] == ']' {
    130 				for idx < d.alen {
    131 					*(*unsafe.Pointer)(unsafe.Pointer(uintptr(p) + uintptr(idx)*d.size)) = d.zeroValue
    132 					idx++
    133 				}
    134 				cursor++
    135 				return cursor, nil
    136 			}
    137 			for {
    138 				if idx < d.alen {
    139 					c, err := d.valueDecoder.Decode(ctx, cursor, depth, unsafe.Pointer(uintptr(p)+uintptr(idx)*d.size))
    140 					if err != nil {
    141 						return 0, err
    142 					}
    143 					cursor = c
    144 				} else {
    145 					c, err := skipValue(buf, cursor, depth)
    146 					if err != nil {
    147 						return 0, err
    148 					}
    149 					cursor = c
    150 				}
    151 				idx++
    152 				cursor = skipWhiteSpace(buf, cursor)
    153 				switch buf[cursor] {
    154 				case ']':
    155 					for idx < d.alen {
    156 						*(*unsafe.Pointer)(unsafe.Pointer(uintptr(p) + uintptr(idx)*d.size)) = d.zeroValue
    157 						idx++
    158 					}
    159 					cursor++
    160 					return cursor, nil
    161 				case ',':
    162 					cursor++
    163 					continue
    164 				default:
    165 					return 0, errors.ErrInvalidCharacter(buf[cursor], "array", cursor)
    166 				}
    167 			}
    168 		default:
    169 			return 0, errors.ErrUnexpectedEndOfJSON("array", cursor)
    170 		}
    171 	}
    172 }
    173 
    174 func (d *arrayDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) {
    175 	return nil, 0, fmt.Errorf("json: array decoder does not support decode path")
    176 }