github.com/grbit/go-json@v0.11.0/internal/decoder/array.go (about) 1 package decoder 2 3 import ( 4 "fmt" 5 "unsafe" 6 7 "github.com/grbit/go-json/internal/errors" 8 "github.com/grbit/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 }