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