github.com/goccy/go-json@v0.10.3-0.20240509105655-5e2ae3f23c1d/internal/decoder/int.go (about)

     1  package decoder
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  	"unsafe"
     7  
     8  	"github.com/goccy/go-json/internal/errors"
     9  	"github.com/goccy/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  }