github.com/grbit/go-json@v0.11.0/internal/decoder/int.go (about) 1 package decoder 2 3 import ( 4 "fmt" 5 "reflect" 6 "unsafe" 7 8 "github.com/grbit/go-json/internal/errors" 9 "github.com/grbit/go-json/internal/runtime" 10 ) 11 12 type intDecoder struct { 13 typ *runtime.Type 14 kind reflect.Kind 15 op func(unsafe.Pointer, int64) 16 structName string 17 fieldName string 18 } 19 20 func newIntDecoder(typ *runtime.Type, structName, fieldName string, op func(unsafe.Pointer, int64)) *intDecoder { 21 return &intDecoder{ 22 typ: typ, 23 kind: typ.Kind(), 24 op: op, 25 structName: structName, 26 fieldName: fieldName, 27 } 28 } 29 30 func (d *intDecoder) typeError(buf []byte, offset int64) *errors.UnmarshalTypeError { 31 return &errors.UnmarshalTypeError{ 32 Value: fmt.Sprintf("number %s", string(buf)), 33 Type: runtime.RType2Type(d.typ), 34 Struct: d.structName, 35 Field: d.fieldName, 36 Offset: offset, 37 } 38 } 39 40 var ( 41 pow10i64 = [...]int64{ 42 1e00, 1e01, 1e02, 1e03, 1e04, 1e05, 1e06, 1e07, 1e08, 1e09, 43 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 44 } 45 pow10i64Len = len(pow10i64) 46 ) 47 48 func (d *intDecoder) parseInt(b []byte) (int64, error) { 49 isNegative := false 50 if b[0] == '-' { 51 b = b[1:] 52 isNegative = true 53 } 54 maxDigit := len(b) 55 if maxDigit > pow10i64Len { 56 return 0, fmt.Errorf("invalid length of number") 57 } 58 sum := int64(0) 59 for i := 0; i < maxDigit; i++ { 60 c := int64(b[i]) - 48 61 digitValue := pow10i64[maxDigit-i-1] 62 sum += c * digitValue 63 } 64 if isNegative { 65 return -1 * sum, nil 66 } 67 return sum, nil 68 } 69 70 var ( 71 numTable = [256]bool{ 72 '0': true, 73 '1': true, 74 '2': true, 75 '3': true, 76 '4': true, 77 '5': true, 78 '6': true, 79 '7': true, 80 '8': true, 81 '9': true, 82 } 83 ) 84 85 var ( 86 numZeroBuf = []byte{'0'} 87 ) 88 89 func (d *intDecoder) decodeStreamByte(s *Stream) ([]byte, error) { 90 for { 91 switch s.char() { 92 case ' ', '\n', '\t', '\r': 93 s.cursor++ 94 continue 95 case '-': 96 start := s.cursor 97 for { 98 s.cursor++ 99 if numTable[s.char()] { 100 continue 101 } else if s.char() == nul { 102 if s.read() { 103 s.cursor-- // for retry current character 104 continue 105 } 106 } 107 break 108 } 109 num := s.buf[start:s.cursor] 110 if len(num) < 2 { 111 goto ERROR 112 } 113 return num, nil 114 case '0': 115 s.cursor++ 116 return numZeroBuf, nil 117 case '1', '2', '3', '4', '5', '6', '7', '8', '9': 118 start := s.cursor 119 for { 120 s.cursor++ 121 if numTable[s.char()] { 122 continue 123 } else if s.char() == nul { 124 if s.read() { 125 s.cursor-- // for retry current character 126 continue 127 } 128 } 129 break 130 } 131 num := s.buf[start:s.cursor] 132 return num, nil 133 case 'n': 134 if err := nullBytes(s); err != nil { 135 return nil, err 136 } 137 return nil, nil 138 case nul: 139 if s.read() { 140 continue 141 } 142 goto ERROR 143 default: 144 return nil, d.typeError([]byte{s.char()}, s.totalOffset()) 145 } 146 } 147 ERROR: 148 return nil, errors.ErrUnexpectedEndOfJSON("number(integer)", s.totalOffset()) 149 } 150 151 func (d *intDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) { 152 b := (*sliceHeader)(unsafe.Pointer(&buf)).data 153 for { 154 switch char(b, cursor) { 155 case ' ', '\n', '\t', '\r': 156 cursor++ 157 continue 158 case '0': 159 cursor++ 160 return numZeroBuf, cursor, nil 161 case '-', '1', '2', '3', '4', '5', '6', '7', '8', '9': 162 start := cursor 163 cursor++ 164 for numTable[char(b, cursor)] { 165 cursor++ 166 } 167 num := buf[start:cursor] 168 return num, cursor, nil 169 case 'n': 170 if err := validateNull(buf, cursor); err != nil { 171 return nil, 0, err 172 } 173 cursor += 4 174 return nil, cursor, nil 175 default: 176 return nil, 0, d.typeError([]byte{char(b, cursor)}, cursor) 177 } 178 } 179 } 180 181 func (d *intDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error { 182 bytes, err := d.decodeStreamByte(s) 183 if err != nil { 184 return err 185 } 186 if bytes == nil { 187 return nil 188 } 189 i64, err := d.parseInt(bytes) 190 if err != nil { 191 return d.typeError(bytes, s.totalOffset()) 192 } 193 switch d.kind { 194 case reflect.Int8: 195 if i64 < -1*(1<<7) || (1<<7) <= i64 { 196 return d.typeError(bytes, s.totalOffset()) 197 } 198 case reflect.Int16: 199 if i64 < -1*(1<<15) || (1<<15) <= i64 { 200 return d.typeError(bytes, s.totalOffset()) 201 } 202 case reflect.Int32: 203 if i64 < -1*(1<<31) || (1<<31) <= i64 { 204 return d.typeError(bytes, s.totalOffset()) 205 } 206 } 207 d.op(p, i64) 208 s.reset() 209 return nil 210 } 211 212 func (d *intDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) { 213 bytes, c, err := d.decodeByte(ctx.Buf, cursor) 214 if err != nil { 215 return 0, err 216 } 217 if bytes == nil { 218 return c, nil 219 } 220 cursor = c 221 222 i64, err := d.parseInt(bytes) 223 if err != nil { 224 return 0, d.typeError(bytes, cursor) 225 } 226 switch d.kind { 227 case reflect.Int8: 228 if i64 < -1*(1<<7) || (1<<7) <= i64 { 229 return 0, d.typeError(bytes, cursor) 230 } 231 case reflect.Int16: 232 if i64 < -1*(1<<15) || (1<<15) <= i64 { 233 return 0, d.typeError(bytes, cursor) 234 } 235 case reflect.Int32: 236 if i64 < -1*(1<<31) || (1<<31) <= i64 { 237 return 0, d.typeError(bytes, cursor) 238 } 239 } 240 d.op(p, i64) 241 return cursor, nil 242 } 243 244 func (d *intDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) { 245 return nil, 0, fmt.Errorf("json: int decoder does not support decode path") 246 }