github.com/night-codes/go-json@v0.9.15/internal/decoder/number.go (about) 1 package decoder 2 3 import ( 4 "encoding/json" 5 "strconv" 6 "unsafe" 7 8 "github.com/night-codes/go-json/internal/errors" 9 ) 10 11 type numberDecoder struct { 12 stringDecoder *stringDecoder 13 op func(unsafe.Pointer, json.Number) 14 structName string 15 fieldName string 16 } 17 18 func newNumberDecoder(structName, fieldName string, op func(unsafe.Pointer, json.Number)) *numberDecoder { 19 return &numberDecoder{ 20 stringDecoder: newStringDecoder(structName, fieldName), 21 op: op, 22 structName: structName, 23 fieldName: fieldName, 24 } 25 } 26 27 func (d *numberDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error { 28 bytes, err := d.decodeStreamByte(s) 29 if err != nil { 30 return err 31 } 32 if len(bytes) == 0 { 33 return nil 34 } 35 if _, err := strconv.ParseFloat(*(*string)(unsafe.Pointer(&bytes)), 64); err != nil { 36 return errors.ErrSyntax(err.Error(), s.totalOffset()) 37 } 38 d.op(p, json.Number(string(bytes))) 39 s.reset() 40 return nil 41 } 42 43 func (d *numberDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) { 44 bytes, c, err := d.decodeByte(ctx.Buf, cursor) 45 if err != nil { 46 return 0, err 47 } 48 if len(bytes) == 0 { 49 return c, nil 50 } 51 if _, err := strconv.ParseFloat(*(*string)(unsafe.Pointer(&bytes)), 64); err != nil { 52 return 0, errors.ErrSyntax(err.Error(), c) 53 } 54 cursor = c 55 s := *(*string)(unsafe.Pointer(&bytes)) 56 d.op(p, json.Number(s)) 57 return cursor, nil 58 } 59 60 func (d *numberDecoder) decodeStreamByte(s *Stream) ([]byte, error) { 61 start := s.cursor 62 for { 63 switch s.char() { 64 case ' ', '\n', '\t', '\r': 65 s.cursor++ 66 continue 67 case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': 68 return floatBytes(s), nil 69 case 'n': 70 if err := nullBytes(s); err != nil { 71 return nil, err 72 } 73 return nil, nil 74 case '"': 75 return d.stringDecoder.decodeStreamByte(s) 76 case nul: 77 if s.read() { 78 continue 79 } 80 goto ERROR 81 default: 82 goto ERROR 83 } 84 } 85 ERROR: 86 if s.cursor == start { 87 return nil, errors.ErrInvalidBeginningOfValue(s.char(), s.totalOffset()) 88 } 89 return nil, errors.ErrUnexpectedEndOfJSON("json.Number", s.totalOffset()) 90 } 91 92 func (d *numberDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) { 93 for { 94 switch buf[cursor] { 95 case ' ', '\n', '\t', '\r': 96 cursor++ 97 continue 98 case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': 99 start := cursor 100 cursor++ 101 for floatTable[buf[cursor]] { 102 cursor++ 103 } 104 num := buf[start:cursor] 105 return num, cursor, nil 106 case 'n': 107 if err := validateNull(buf, cursor); err != nil { 108 return nil, 0, err 109 } 110 cursor += 4 111 return nil, cursor, nil 112 case '"': 113 return d.stringDecoder.decodeByte(buf, cursor) 114 default: 115 return nil, 0, errors.ErrUnexpectedEndOfJSON("json.Number", cursor) 116 } 117 } 118 }