github.com/grbit/go-json@v0.11.0/internal/decoder/number.go (about)

     1  package decoder
     2  
     3  import (
     4  	"encoding/json"
     5  	"strconv"
     6  	"unsafe"
     7  
     8  	"github.com/grbit/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 _, err := strconv.ParseFloat(*(*string)(unsafe.Pointer(&bytes)), 64); err != nil {
    33  		return errors.ErrSyntax(err.Error(), s.totalOffset())
    34  	}
    35  	d.op(p, json.Number(string(bytes)))
    36  	s.reset()
    37  	return nil
    38  }
    39  
    40  func (d *numberDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
    41  	bytes, c, err := d.decodeByte(ctx.Buf, cursor)
    42  	if err != nil {
    43  		return 0, err
    44  	}
    45  	if _, err := strconv.ParseFloat(*(*string)(unsafe.Pointer(&bytes)), 64); err != nil {
    46  		return 0, errors.ErrSyntax(err.Error(), c)
    47  	}
    48  	cursor = c
    49  	s := *(*string)(unsafe.Pointer(&bytes))
    50  	d.op(p, json.Number(s))
    51  	return cursor, nil
    52  }
    53  
    54  func (d *numberDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) {
    55  	bytes, c, err := d.decodeByte(ctx.Buf, cursor)
    56  	if err != nil {
    57  		return nil, 0, err
    58  	}
    59  	if bytes == nil {
    60  		return [][]byte{nullbytes}, c, nil
    61  	}
    62  	return [][]byte{bytes}, c, nil
    63  }
    64  
    65  func (d *numberDecoder) decodeStreamByte(s *Stream) ([]byte, error) {
    66  	start := s.cursor
    67  	for {
    68  		switch s.char() {
    69  		case ' ', '\n', '\t', '\r':
    70  			s.cursor++
    71  			continue
    72  		case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
    73  			return floatBytes(s), nil
    74  		case 'n':
    75  			if err := nullBytes(s); err != nil {
    76  				return nil, err
    77  			}
    78  			return nil, nil
    79  		case '"':
    80  			return d.stringDecoder.decodeStreamByte(s)
    81  		case nul:
    82  			if s.read() {
    83  				continue
    84  			}
    85  			goto ERROR
    86  		default:
    87  			goto ERROR
    88  		}
    89  	}
    90  ERROR:
    91  	if s.cursor == start {
    92  		return nil, errors.ErrInvalidBeginningOfValue(s.char(), s.totalOffset())
    93  	}
    94  	return nil, errors.ErrUnexpectedEndOfJSON("json.Number", s.totalOffset())
    95  }
    96  
    97  func (d *numberDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) {
    98  	for {
    99  		switch buf[cursor] {
   100  		case ' ', '\n', '\t', '\r':
   101  			cursor++
   102  			continue
   103  		case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
   104  			start := cursor
   105  			cursor++
   106  			for floatTable[buf[cursor]] {
   107  				cursor++
   108  			}
   109  			num := buf[start:cursor]
   110  			return num, cursor, nil
   111  		case 'n':
   112  			if err := validateNull(buf, cursor); err != nil {
   113  				return nil, 0, err
   114  			}
   115  			cursor += 4
   116  			return nil, cursor, nil
   117  		case '"':
   118  			return d.stringDecoder.decodeByte(buf, cursor)
   119  		default:
   120  			return nil, 0, errors.ErrUnexpectedEndOfJSON("json.Number", cursor)
   121  		}
   122  	}
   123  }