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