github.com/night-codes/go-json@v0.9.15/internal/decoder/stream.go (about)

     1  package decoder
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"io"
     7  	"strconv"
     8  	"unsafe"
     9  
    10  	"github.com/night-codes/go-json/internal/errors"
    11  )
    12  
    13  const (
    14  	initBufSize = 512
    15  )
    16  
    17  type Stream struct {
    18  	buf                   []byte
    19  	bufSize               int64
    20  	length                int64
    21  	r                     io.Reader
    22  	offset                int64
    23  	cursor                int64
    24  	filledBuffer          bool
    25  	allRead               bool
    26  	UseNumber             bool
    27  	DisallowUnknownFields bool
    28  	Option                *Option
    29  }
    30  
    31  func NewStream(r io.Reader) *Stream {
    32  	return &Stream{
    33  		r:       r,
    34  		bufSize: initBufSize,
    35  		buf:     make([]byte, initBufSize),
    36  		Option:  &Option{},
    37  	}
    38  }
    39  
    40  func (s *Stream) TotalOffset() int64 {
    41  	return s.totalOffset()
    42  }
    43  
    44  func (s *Stream) Buffered() io.Reader {
    45  	buflen := int64(len(s.buf))
    46  	for i := s.cursor; i < buflen; i++ {
    47  		if s.buf[i] == nul {
    48  			return bytes.NewReader(s.buf[s.cursor:i])
    49  		}
    50  	}
    51  	return bytes.NewReader(s.buf[s.cursor:])
    52  }
    53  
    54  func (s *Stream) PrepareForDecode() error {
    55  	for {
    56  		switch s.char() {
    57  		case ' ', '\t', '\r', '\n':
    58  			s.cursor++
    59  			continue
    60  		case ',', ':':
    61  			s.cursor++
    62  			return nil
    63  		case nul:
    64  			if s.read() {
    65  				continue
    66  			}
    67  			return io.EOF
    68  		}
    69  		break
    70  	}
    71  	return nil
    72  }
    73  
    74  func (s *Stream) totalOffset() int64 {
    75  	return s.offset + s.cursor
    76  }
    77  
    78  func (s *Stream) char() byte {
    79  	return s.buf[s.cursor]
    80  }
    81  
    82  func (s *Stream) equalChar(c byte) bool {
    83  	cur := s.buf[s.cursor]
    84  	if cur == nul {
    85  		s.read()
    86  		cur = s.buf[s.cursor]
    87  	}
    88  	return cur == c
    89  }
    90  
    91  func (s *Stream) stat() ([]byte, int64, unsafe.Pointer) {
    92  	return s.buf, s.cursor, (*sliceHeader)(unsafe.Pointer(&s.buf)).data
    93  }
    94  
    95  func (s *Stream) bufptr() unsafe.Pointer {
    96  	return (*sliceHeader)(unsafe.Pointer(&s.buf)).data
    97  }
    98  
    99  func (s *Stream) statForRetry() ([]byte, int64, unsafe.Pointer) {
   100  	s.cursor-- // for retry ( because caller progress cursor position in each loop )
   101  	return s.buf, s.cursor, (*sliceHeader)(unsafe.Pointer(&s.buf)).data
   102  }
   103  
   104  func (s *Stream) Reset() {
   105  	s.reset()
   106  	s.bufSize = int64(len(s.buf))
   107  }
   108  
   109  func (s *Stream) More() bool {
   110  	for {
   111  		switch s.char() {
   112  		case ' ', '\n', '\r', '\t':
   113  			s.cursor++
   114  			continue
   115  		case '}', ']':
   116  			return false
   117  		case nul:
   118  			if s.read() {
   119  				continue
   120  			}
   121  			return false
   122  		}
   123  		break
   124  	}
   125  	return true
   126  }
   127  
   128  func (s *Stream) Token() (interface{}, error) {
   129  	for {
   130  		c := s.char()
   131  		switch c {
   132  		case ' ', '\n', '\r', '\t':
   133  			s.cursor++
   134  		case '{', '[', ']', '}':
   135  			s.cursor++
   136  			return json.Delim(c), nil
   137  		case ',', ':':
   138  			s.cursor++
   139  		case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
   140  			bytes := floatBytes(s)
   141  			if len(bytes) == 0 {
   142  				bytes = []byte("0")
   143  			}
   144  			str := *(*string)(unsafe.Pointer(&bytes))
   145  			if s.UseNumber {
   146  				return json.Number(str), nil
   147  			}
   148  			f64, err := strconv.ParseFloat(str, 64)
   149  			if err != nil {
   150  				return nil, err
   151  			}
   152  			return f64, nil
   153  		case '"':
   154  			bytes, err := stringBytes(s)
   155  			if err != nil {
   156  				return nil, err
   157  			}
   158  			return string(bytes), nil
   159  		case 't':
   160  			if err := trueBytes(s); err != nil {
   161  				return nil, err
   162  			}
   163  			return true, nil
   164  		case 'f':
   165  			if err := falseBytes(s); err != nil {
   166  				return nil, err
   167  			}
   168  			return false, nil
   169  		case 'n':
   170  			if err := nullBytes(s); err != nil {
   171  				return nil, err
   172  			}
   173  			return nil, nil
   174  		case nul:
   175  			if s.read() {
   176  				continue
   177  			}
   178  			goto END
   179  		default:
   180  			return nil, errors.ErrInvalidCharacter(s.char(), "token", s.totalOffset())
   181  		}
   182  	}
   183  END:
   184  	return nil, io.EOF
   185  }
   186  
   187  func (s *Stream) reset() {
   188  	s.offset += s.cursor
   189  	s.buf = s.buf[s.cursor:]
   190  	s.length -= s.cursor
   191  	s.cursor = 0
   192  }
   193  
   194  func (s *Stream) readBuf() []byte {
   195  	if s.filledBuffer {
   196  		s.bufSize *= 2
   197  		remainBuf := s.buf
   198  		s.buf = make([]byte, s.bufSize)
   199  		copy(s.buf, remainBuf)
   200  	}
   201  	remainLen := s.length - s.cursor
   202  	remainNotNulCharNum := int64(0)
   203  	for i := int64(0); i < remainLen; i++ {
   204  		if s.buf[s.cursor+i] == nul {
   205  			break
   206  		}
   207  		remainNotNulCharNum++
   208  	}
   209  	s.length = s.cursor + remainNotNulCharNum
   210  	return s.buf[s.cursor+remainNotNulCharNum:]
   211  }
   212  
   213  func (s *Stream) read() bool {
   214  	if s.allRead {
   215  		return false
   216  	}
   217  	buf := s.readBuf()
   218  	last := len(buf) - 1
   219  	buf[last] = nul
   220  	n, err := s.r.Read(buf[:last])
   221  	s.length += int64(n)
   222  	if n == last {
   223  		s.filledBuffer = true
   224  	} else {
   225  		s.filledBuffer = false
   226  	}
   227  	if err == io.EOF {
   228  		s.allRead = true
   229  	} else if err != nil {
   230  		return false
   231  	}
   232  	return true
   233  }
   234  
   235  func (s *Stream) skipWhiteSpace() byte {
   236  	p := s.bufptr()
   237  LOOP:
   238  	c := char(p, s.cursor)
   239  	switch c {
   240  	case ' ', '\n', '\t', '\r':
   241  		s.cursor++
   242  		goto LOOP
   243  	case nul:
   244  		if s.read() {
   245  			p = s.bufptr()
   246  			goto LOOP
   247  		}
   248  	}
   249  	return c
   250  }
   251  
   252  func (s *Stream) skipObject(depth int64) error {
   253  	braceCount := 1
   254  	_, cursor, p := s.stat()
   255  	for {
   256  		switch char(p, cursor) {
   257  		case '{':
   258  			braceCount++
   259  			depth++
   260  			if depth > maxDecodeNestingDepth {
   261  				return errors.ErrExceededMaxDepth(s.char(), s.cursor)
   262  			}
   263  		case '}':
   264  			braceCount--
   265  			depth--
   266  			if braceCount == 0 {
   267  				s.cursor = cursor + 1
   268  				return nil
   269  			}
   270  		case '[':
   271  			depth++
   272  			if depth > maxDecodeNestingDepth {
   273  				return errors.ErrExceededMaxDepth(s.char(), s.cursor)
   274  			}
   275  		case ']':
   276  			depth--
   277  		case '"':
   278  			for {
   279  				cursor++
   280  				switch char(p, cursor) {
   281  				case '\\':
   282  					cursor++
   283  					if char(p, cursor) == nul {
   284  						s.cursor = cursor
   285  						if s.read() {
   286  							_, cursor, p = s.stat()
   287  							continue
   288  						}
   289  						return errors.ErrUnexpectedEndOfJSON("string of object", cursor)
   290  					}
   291  				case '"':
   292  					goto SWITCH_OUT
   293  				case nul:
   294  					s.cursor = cursor
   295  					if s.read() {
   296  						_, cursor, p = s.statForRetry()
   297  						continue
   298  					}
   299  					return errors.ErrUnexpectedEndOfJSON("string of object", cursor)
   300  				}
   301  			}
   302  		case nul:
   303  			s.cursor = cursor
   304  			if s.read() {
   305  				_, cursor, p = s.stat()
   306  				continue
   307  			}
   308  			return errors.ErrUnexpectedEndOfJSON("object of object", cursor)
   309  		}
   310  	SWITCH_OUT:
   311  		cursor++
   312  	}
   313  }
   314  
   315  func (s *Stream) skipArray(depth int64) error {
   316  	bracketCount := 1
   317  	_, cursor, p := s.stat()
   318  	for {
   319  		switch char(p, cursor) {
   320  		case '[':
   321  			bracketCount++
   322  			depth++
   323  			if depth > maxDecodeNestingDepth {
   324  				return errors.ErrExceededMaxDepth(s.char(), s.cursor)
   325  			}
   326  		case ']':
   327  			bracketCount--
   328  			depth--
   329  			if bracketCount == 0 {
   330  				s.cursor = cursor + 1
   331  				return nil
   332  			}
   333  		case '{':
   334  			depth++
   335  			if depth > maxDecodeNestingDepth {
   336  				return errors.ErrExceededMaxDepth(s.char(), s.cursor)
   337  			}
   338  		case '}':
   339  			depth--
   340  		case '"':
   341  			for {
   342  				cursor++
   343  				switch char(p, cursor) {
   344  				case '\\':
   345  					cursor++
   346  					if char(p, cursor) == nul {
   347  						s.cursor = cursor
   348  						if s.read() {
   349  							_, cursor, p = s.stat()
   350  							continue
   351  						}
   352  						return errors.ErrUnexpectedEndOfJSON("string of object", cursor)
   353  					}
   354  				case '"':
   355  					goto SWITCH_OUT
   356  				case nul:
   357  					s.cursor = cursor
   358  					if s.read() {
   359  						_, cursor, p = s.statForRetry()
   360  						continue
   361  					}
   362  					return errors.ErrUnexpectedEndOfJSON("string of object", cursor)
   363  				}
   364  			}
   365  		case nul:
   366  			s.cursor = cursor
   367  			if s.read() {
   368  				_, cursor, p = s.stat()
   369  				continue
   370  			}
   371  			return errors.ErrUnexpectedEndOfJSON("array of object", cursor)
   372  		}
   373  	SWITCH_OUT:
   374  		cursor++
   375  	}
   376  }
   377  
   378  func (s *Stream) skipValue(depth int64) error {
   379  	_, cursor, p := s.stat()
   380  	for {
   381  		switch char(p, cursor) {
   382  		case ' ', '\n', '\t', '\r':
   383  			cursor++
   384  			continue
   385  		case nul:
   386  			s.cursor = cursor
   387  			if s.read() {
   388  				_, cursor, p = s.stat()
   389  				continue
   390  			}
   391  			return errors.ErrUnexpectedEndOfJSON("value of object", s.totalOffset())
   392  		case '{':
   393  			s.cursor = cursor + 1
   394  			return s.skipObject(depth + 1)
   395  		case '[':
   396  			s.cursor = cursor + 1
   397  			return s.skipArray(depth + 1)
   398  		case '"':
   399  			for {
   400  				cursor++
   401  				switch char(p, cursor) {
   402  				case '\\':
   403  					cursor++
   404  					if char(p, cursor) == nul {
   405  						s.cursor = cursor
   406  						if s.read() {
   407  							_, cursor, p = s.stat()
   408  							continue
   409  						}
   410  						return errors.ErrUnexpectedEndOfJSON("value of string", s.totalOffset())
   411  					}
   412  				case '"':
   413  					s.cursor = cursor + 1
   414  					return nil
   415  				case nul:
   416  					s.cursor = cursor
   417  					if s.read() {
   418  						_, cursor, p = s.statForRetry()
   419  						continue
   420  					}
   421  					return errors.ErrUnexpectedEndOfJSON("value of string", s.totalOffset())
   422  				}
   423  			}
   424  		case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
   425  			for {
   426  				cursor++
   427  				c := char(p, cursor)
   428  				if floatTable[c] {
   429  					continue
   430  				} else if c == nul {
   431  					if s.read() {
   432  						_, cursor, p = s.stat()
   433  						continue
   434  					}
   435  				}
   436  				s.cursor = cursor
   437  				return nil
   438  			}
   439  		case 't':
   440  			s.cursor = cursor
   441  			if err := trueBytes(s); err != nil {
   442  				return err
   443  			}
   444  			return nil
   445  		case 'f':
   446  			s.cursor = cursor
   447  			if err := falseBytes(s); err != nil {
   448  				return err
   449  			}
   450  			return nil
   451  		case 'n':
   452  			s.cursor = cursor
   453  			if err := nullBytes(s); err != nil {
   454  				return err
   455  			}
   456  			return nil
   457  		}
   458  		cursor++
   459  	}
   460  }
   461  
   462  func nullBytes(s *Stream) error {
   463  	// current cursor's character is 'n'
   464  	s.cursor++
   465  	if s.char() != 'u' {
   466  		if err := retryReadNull(s); err != nil {
   467  			return err
   468  		}
   469  	}
   470  	s.cursor++
   471  	if s.char() != 'l' {
   472  		if err := retryReadNull(s); err != nil {
   473  			return err
   474  		}
   475  	}
   476  	s.cursor++
   477  	if s.char() != 'l' {
   478  		if err := retryReadNull(s); err != nil {
   479  			return err
   480  		}
   481  	}
   482  	s.cursor++
   483  	return nil
   484  }
   485  
   486  func retryReadNull(s *Stream) error {
   487  	if s.char() == nul && s.read() {
   488  		return nil
   489  	}
   490  	return errors.ErrInvalidCharacter(s.char(), "null", s.totalOffset())
   491  }
   492  
   493  func trueBytes(s *Stream) error {
   494  	// current cursor's character is 't'
   495  	s.cursor++
   496  	if s.char() != 'r' {
   497  		if err := retryReadTrue(s); err != nil {
   498  			return err
   499  		}
   500  	}
   501  	s.cursor++
   502  	if s.char() != 'u' {
   503  		if err := retryReadTrue(s); err != nil {
   504  			return err
   505  		}
   506  	}
   507  	s.cursor++
   508  	if s.char() != 'e' {
   509  		if err := retryReadTrue(s); err != nil {
   510  			return err
   511  		}
   512  	}
   513  	s.cursor++
   514  	return nil
   515  }
   516  
   517  func retryReadTrue(s *Stream) error {
   518  	if s.char() == nul && s.read() {
   519  		return nil
   520  	}
   521  	return errors.ErrInvalidCharacter(s.char(), "bool(true)", s.totalOffset())
   522  }
   523  
   524  func falseBytes(s *Stream) error {
   525  	// current cursor's character is 'f'
   526  	s.cursor++
   527  	if s.char() != 'a' {
   528  		if err := retryReadFalse(s); err != nil {
   529  			return err
   530  		}
   531  	}
   532  	s.cursor++
   533  	if s.char() != 'l' {
   534  		if err := retryReadFalse(s); err != nil {
   535  			return err
   536  		}
   537  	}
   538  	s.cursor++
   539  	if s.char() != 's' {
   540  		if err := retryReadFalse(s); err != nil {
   541  			return err
   542  		}
   543  	}
   544  	s.cursor++
   545  	if s.char() != 'e' {
   546  		if err := retryReadFalse(s); err != nil {
   547  			return err
   548  		}
   549  	}
   550  	s.cursor++
   551  	return nil
   552  }
   553  
   554  func retryReadFalse(s *Stream) error {
   555  	if s.char() == nul && s.read() {
   556  		return nil
   557  	}
   558  	return errors.ErrInvalidCharacter(s.char(), "bool(false)", s.totalOffset())
   559  }