1 package decoder
2
3 import (
4 "reflect"
5 "sync"
6 "unsafe"
7
8 "github.com/goccy/go-json/internal/errors"
9 "github.com/goccy/go-json/internal/runtime"
10 )
11
12 var (
13 sliceType = runtime.Type2RType(
14 reflect.TypeOf((*sliceHeader)(nil)).Elem(),
15 )
16 nilSlice = unsafe.Pointer(&sliceHeader{})
17 )
18
19 type sliceDecoder struct {
20 elemType *runtime.Type
21 isElemPointerType bool
22 valueDecoder Decoder
23 size uintptr
24 arrayPool sync.Pool
25 structName string
26 fieldName string
27 }
28
29
30
31
32 type sliceHeader struct {
33 data unsafe.Pointer
34 len int
35 cap int
36 }
37
38 const (
39 defaultSliceCapacity = 2
40 )
41
42 func newSliceDecoder(dec Decoder, elemType *runtime.Type, size uintptr, structName, fieldName string) *sliceDecoder {
43 return &sliceDecoder{
44 valueDecoder: dec,
45 elemType: elemType,
46 isElemPointerType: elemType.Kind() == reflect.Ptr || elemType.Kind() == reflect.Map,
47 size: size,
48 arrayPool: sync.Pool{
49 New: func() interface{} {
50 return &sliceHeader{
51 data: newArray(elemType, defaultSliceCapacity),
52 len: 0,
53 cap: defaultSliceCapacity,
54 }
55 },
56 },
57 structName: structName,
58 fieldName: fieldName,
59 }
60 }
61
62 func (d *sliceDecoder) newSlice(src *sliceHeader) *sliceHeader {
63 slice := d.arrayPool.Get().(*sliceHeader)
64 if src.len > 0 {
65
66 if slice.cap < src.cap {
67 data := newArray(d.elemType, src.cap)
68 slice = &sliceHeader{data: data, len: src.len, cap: src.cap}
69 } else {
70 slice.len = src.len
71 }
72 copySlice(d.elemType, *slice, *src)
73 } else {
74 slice.len = 0
75 }
76 return slice
77 }
78
79 func (d *sliceDecoder) releaseSlice(p *sliceHeader) {
80 d.arrayPool.Put(p)
81 }
82
83
84 func copySlice(elemType *runtime.Type, dst, src sliceHeader) int
85
86
87 func newArray(*runtime.Type, int) unsafe.Pointer
88
89
90 func typedmemmove(t *runtime.Type, dst, src unsafe.Pointer)
91
92 func (d *sliceDecoder) errNumber(offset int64) *errors.UnmarshalTypeError {
93 return &errors.UnmarshalTypeError{
94 Value: "number",
95 Type: reflect.SliceOf(runtime.RType2Type(d.elemType)),
96 Struct: d.structName,
97 Field: d.fieldName,
98 Offset: offset,
99 }
100 }
101
102 func (d *sliceDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
103 depth++
104 if depth > maxDecodeNestingDepth {
105 return errors.ErrExceededMaxDepth(s.char(), s.cursor)
106 }
107
108 for {
109 switch s.char() {
110 case ' ', '\n', '\t', '\r':
111 s.cursor++
112 continue
113 case 'n':
114 if err := nullBytes(s); err != nil {
115 return err
116 }
117 typedmemmove(sliceType, p, nilSlice)
118 return nil
119 case '[':
120 s.cursor++
121 if s.skipWhiteSpace() == ']' {
122 dst := (*sliceHeader)(p)
123 if dst.data == nil {
124 dst.data = newArray(d.elemType, 0)
125 } else {
126 dst.len = 0
127 }
128 s.cursor++
129 return nil
130 }
131 idx := 0
132 slice := d.newSlice((*sliceHeader)(p))
133 srcLen := slice.len
134 capacity := slice.cap
135 data := slice.data
136 for {
137 if capacity <= idx {
138 src := sliceHeader{data: data, len: idx, cap: capacity}
139 capacity *= 2
140 data = newArray(d.elemType, capacity)
141 dst := sliceHeader{data: data, len: idx, cap: capacity}
142 copySlice(d.elemType, dst, src)
143 }
144 ep := unsafe.Pointer(uintptr(data) + uintptr(idx)*d.size)
145
146
147 if srcLen <= idx {
148 if d.isElemPointerType {
149 **(**unsafe.Pointer)(unsafe.Pointer(&ep)) = nil
150 } else {
151
152 typedmemmove(d.elemType, ep, unsafe_New(d.elemType))
153 }
154 }
155
156 if err := d.valueDecoder.DecodeStream(s, depth, ep); err != nil {
157 return err
158 }
159 s.skipWhiteSpace()
160 RETRY:
161 switch s.char() {
162 case ']':
163 slice.cap = capacity
164 slice.len = idx + 1
165 slice.data = data
166 dst := (*sliceHeader)(p)
167 dst.len = idx + 1
168 if dst.len > dst.cap {
169 dst.data = newArray(d.elemType, dst.len)
170 dst.cap = dst.len
171 }
172 copySlice(d.elemType, *dst, *slice)
173 d.releaseSlice(slice)
174 s.cursor++
175 return nil
176 case ',':
177 idx++
178 case nul:
179 if s.read() {
180 goto RETRY
181 }
182 slice.cap = capacity
183 slice.data = data
184 d.releaseSlice(slice)
185 goto ERROR
186 default:
187 slice.cap = capacity
188 slice.data = data
189 d.releaseSlice(slice)
190 goto ERROR
191 }
192 s.cursor++
193 }
194 case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
195 return d.errNumber(s.totalOffset())
196 case nul:
197 if s.read() {
198 continue
199 }
200 goto ERROR
201 default:
202 goto ERROR
203 }
204 }
205 ERROR:
206 return errors.ErrUnexpectedEndOfJSON("slice", s.totalOffset())
207 }
208
209 func (d *sliceDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
210 buf := ctx.Buf
211 depth++
212 if depth > maxDecodeNestingDepth {
213 return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
214 }
215
216 for {
217 switch buf[cursor] {
218 case ' ', '\n', '\t', '\r':
219 cursor++
220 continue
221 case 'n':
222 if err := validateNull(buf, cursor); err != nil {
223 return 0, err
224 }
225 cursor += 4
226 typedmemmove(sliceType, p, nilSlice)
227 return cursor, nil
228 case '[':
229 cursor++
230 cursor = skipWhiteSpace(buf, cursor)
231 if buf[cursor] == ']' {
232 dst := (*sliceHeader)(p)
233 if dst.data == nil {
234 dst.data = newArray(d.elemType, 0)
235 } else {
236 dst.len = 0
237 }
238 cursor++
239 return cursor, nil
240 }
241 idx := 0
242 slice := d.newSlice((*sliceHeader)(p))
243 srcLen := slice.len
244 capacity := slice.cap
245 data := slice.data
246 for {
247 if capacity <= idx {
248 src := sliceHeader{data: data, len: idx, cap: capacity}
249 capacity *= 2
250 data = newArray(d.elemType, capacity)
251 dst := sliceHeader{data: data, len: idx, cap: capacity}
252 copySlice(d.elemType, dst, src)
253 }
254 ep := unsafe.Pointer(uintptr(data) + uintptr(idx)*d.size)
255
256 if srcLen <= idx {
257 if d.isElemPointerType {
258 **(**unsafe.Pointer)(unsafe.Pointer(&ep)) = nil
259 } else {
260
261 typedmemmove(d.elemType, ep, unsafe_New(d.elemType))
262 }
263 }
264 c, err := d.valueDecoder.Decode(ctx, cursor, depth, ep)
265 if err != nil {
266 return 0, err
267 }
268 cursor = c
269 cursor = skipWhiteSpace(buf, cursor)
270 switch buf[cursor] {
271 case ']':
272 slice.cap = capacity
273 slice.len = idx + 1
274 slice.data = data
275 dst := (*sliceHeader)(p)
276 dst.len = idx + 1
277 if dst.len > dst.cap {
278 dst.data = newArray(d.elemType, dst.len)
279 dst.cap = dst.len
280 }
281 copySlice(d.elemType, *dst, *slice)
282 d.releaseSlice(slice)
283 cursor++
284 return cursor, nil
285 case ',':
286 idx++
287 default:
288 slice.cap = capacity
289 slice.data = data
290 d.releaseSlice(slice)
291 return 0, errors.ErrInvalidCharacter(buf[cursor], "slice", cursor)
292 }
293 cursor++
294 }
295 case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
296 return 0, d.errNumber(cursor)
297 default:
298 return 0, errors.ErrUnexpectedEndOfJSON("slice", cursor)
299 }
300 }
301 }
302
303 func (d *sliceDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) {
304 buf := ctx.Buf
305 depth++
306 if depth > maxDecodeNestingDepth {
307 return nil, 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
308 }
309
310 ret := [][]byte{}
311 for {
312 switch buf[cursor] {
313 case ' ', '\n', '\t', '\r':
314 cursor++
315 continue
316 case 'n':
317 if err := validateNull(buf, cursor); err != nil {
318 return nil, 0, err
319 }
320 cursor += 4
321 return [][]byte{nullbytes}, cursor, nil
322 case '[':
323 cursor++
324 cursor = skipWhiteSpace(buf, cursor)
325 if buf[cursor] == ']' {
326 cursor++
327 return ret, cursor, nil
328 }
329 idx := 0
330 for {
331 child, found, err := ctx.Option.Path.node.Index(idx)
332 if err != nil {
333 return nil, 0, err
334 }
335 if found {
336 if child != nil {
337 oldPath := ctx.Option.Path.node
338 ctx.Option.Path.node = child
339 paths, c, err := d.valueDecoder.DecodePath(ctx, cursor, depth)
340 if err != nil {
341 return nil, 0, err
342 }
343 ctx.Option.Path.node = oldPath
344 ret = append(ret, paths...)
345 cursor = c
346 } else {
347 start := cursor
348 end, err := skipValue(buf, cursor, depth)
349 if err != nil {
350 return nil, 0, err
351 }
352 ret = append(ret, buf[start:end])
353 cursor = end
354 }
355 } else {
356 c, err := skipValue(buf, cursor, depth)
357 if err != nil {
358 return nil, 0, err
359 }
360 cursor = c
361 }
362 cursor = skipWhiteSpace(buf, cursor)
363 switch buf[cursor] {
364 case ']':
365 cursor++
366 return ret, cursor, nil
367 case ',':
368 idx++
369 default:
370 return nil, 0, errors.ErrInvalidCharacter(buf[cursor], "slice", cursor)
371 }
372 cursor++
373 }
374 case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
375 return nil, 0, d.errNumber(cursor)
376 default:
377 return nil, 0, errors.ErrUnexpectedEndOfJSON("slice", cursor)
378 }
379 }
380 }
381
View as plain text