github.com/night-codes/go-json@v0.9.15/internal/decoder/uint.go (about) 1 package decoder 2 3 import ( 4 "fmt" 5 "reflect" 6 "strconv" 7 "unsafe" 8 9 "github.com/night-codes/go-json/internal/errors" 10 "github.com/night-codes/go-json/internal/runtime" 11 ) 12 13 type uintDecoder struct { 14 stringDecoder *stringDecoder 15 typ *runtime.Type 16 kind reflect.Kind 17 op func(unsafe.Pointer, uint64) 18 structName string 19 fieldName string 20 } 21 22 func newUintDecoder(typ *runtime.Type, structName, fieldName string, op func(unsafe.Pointer, uint64)) *uintDecoder { 23 return &uintDecoder{ 24 stringDecoder: newStringDecoder(structName, fieldName), 25 typ: typ, 26 kind: typ.Kind(), 27 op: op, 28 structName: structName, 29 fieldName: fieldName, 30 } 31 } 32 33 func (d *uintDecoder) typeError(buf []byte, offset int64) *errors.UnmarshalTypeError { 34 return &errors.UnmarshalTypeError{ 35 Value: fmt.Sprintf("number %s", string(buf)), 36 Type: runtime.RType2Type(d.typ), 37 Offset: offset, 38 } 39 } 40 41 var ( 42 pow10u64 = [...]uint64{ 43 1e00, 1e01, 1e02, 1e03, 1e04, 1e05, 1e06, 1e07, 1e08, 1e09, 44 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 45 } 46 pow10u64Len = len(pow10u64) 47 ) 48 49 func (d *uintDecoder) decodeStreamByte(s *Stream) ([]byte, error) { 50 for { 51 switch s.char() { 52 case ' ', '\n', '\t', '\r': 53 s.cursor++ 54 continue 55 case '0': 56 s.cursor++ 57 return numZeroBuf, nil 58 case '1', '2', '3', '4', '5', '6', '7', '8', '9': 59 start := s.cursor 60 for { 61 s.cursor++ 62 if numTable[s.char()] { 63 continue 64 } else if s.char() == nul { 65 if s.read() { 66 s.cursor-- // for retry current character 67 continue 68 } 69 } 70 break 71 } 72 num := s.buf[start:s.cursor] 73 return num, nil 74 case '"': 75 return d.stringDecoder.decodeStreamByte(s) 76 case 'n': 77 if err := nullBytes(s); err != nil { 78 return nil, err 79 } 80 return nil, nil 81 case nul: 82 if s.read() { 83 continue 84 } 85 default: 86 return nil, d.typeError([]byte{s.char()}, s.totalOffset()) 87 } 88 break 89 } 90 return nil, errors.ErrUnexpectedEndOfJSON("number(unsigned integer)", s.totalOffset()) 91 } 92 93 func (d *uintDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) { 94 for { 95 switch buf[cursor] { 96 case ' ', '\n', '\t', '\r': 97 cursor++ 98 continue 99 case '0': 100 cursor++ 101 return numZeroBuf, cursor, nil 102 case '1', '2', '3', '4', '5', '6', '7', '8', '9': 103 start := cursor 104 cursor++ 105 for numTable[buf[cursor]] { 106 cursor++ 107 } 108 num := buf[start:cursor] 109 return num, cursor, nil 110 case 'n': 111 if err := validateNull(buf, cursor); err != nil { 112 return nil, 0, err 113 } 114 cursor += 4 115 return nil, cursor, nil 116 case '"': 117 return d.stringDecoder.decodeByte(buf, cursor) 118 default: 119 return nil, 0, d.typeError([]byte{buf[cursor]}, cursor) 120 } 121 } 122 } 123 124 func (d *uintDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error { 125 bytes, err := d.decodeStreamByte(s) 126 if err != nil { 127 return err 128 } 129 if len(bytes) == 0 { 130 return nil 131 } 132 str := *(*string)(unsafe.Pointer(&bytes)) 133 u64, err := strconv.ParseUint(str, 10, 64) 134 if err != nil { 135 return d.typeError(bytes, s.totalOffset()) 136 } 137 switch d.kind { 138 case reflect.Uint8: 139 if (1 << 8) <= u64 { 140 return d.typeError(bytes, s.totalOffset()) 141 } 142 case reflect.Uint16: 143 if (1 << 16) <= u64 { 144 return d.typeError(bytes, s.totalOffset()) 145 } 146 case reflect.Uint32: 147 if (1 << 32) <= u64 { 148 return d.typeError(bytes, s.totalOffset()) 149 } 150 } 151 d.op(p, u64) 152 return nil 153 } 154 155 func (d *uintDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) { 156 bytes, c, err := d.decodeByte(ctx.Buf, cursor) 157 if err != nil { 158 return 0, err 159 } 160 if len(bytes) == 0 { 161 return c, nil 162 } 163 cursor = c 164 str := *(*string)(unsafe.Pointer(&bytes)) 165 u64, err := strconv.ParseUint(str, 10, 64) 166 if err != nil { 167 return 0, d.typeError(bytes, cursor) 168 } 169 switch d.kind { 170 case reflect.Uint8: 171 if (1 << 8) <= u64 { 172 return 0, d.typeError(bytes, cursor) 173 } 174 case reflect.Uint16: 175 if (1 << 16) <= u64 { 176 return 0, d.typeError(bytes, cursor) 177 } 178 case reflect.Uint32: 179 if (1 << 32) <= u64 { 180 return 0, d.typeError(bytes, cursor) 181 } 182 } 183 d.op(p, u64) 184 return cursor, nil 185 }