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  }