github.com/3JoB/go-json@v0.10.4/internal/decoder/context.go (about)

     1  package decoder
     2  
     3  import (
     4  	"sync"
     5  	"unsafe"
     6  
     7  	"github.com/3JoB/go-json/internal/errors"
     8  )
     9  
    10  type RuntimeContext struct {
    11  	Buf    []byte
    12  	Option *Option
    13  }
    14  
    15  var (
    16  	runtimeContextPool = sync.Pool{
    17  		New: func() any {
    18  			return &RuntimeContext{
    19  				Option: &Option{},
    20  			}
    21  		},
    22  	}
    23  )
    24  
    25  func TakeRuntimeContext() *RuntimeContext {
    26  	return runtimeContextPool.Get().(*RuntimeContext)
    27  }
    28  
    29  func ReleaseRuntimeContext(ctx *RuntimeContext) {
    30  	runtimeContextPool.Put(ctx)
    31  }
    32  
    33  var (
    34  	isWhiteSpace = [256]bool{}
    35  )
    36  
    37  func init() {
    38  	isWhiteSpace[' '] = true
    39  	isWhiteSpace['\n'] = true
    40  	isWhiteSpace['\t'] = true
    41  	isWhiteSpace['\r'] = true
    42  }
    43  
    44  func char(ptr unsafe.Pointer, offset int64) byte {
    45  	return *(*byte)(unsafe.Pointer(uintptr(ptr) + uintptr(offset)))
    46  }
    47  
    48  func ptrUint16(ptr unsafe.Pointer, offset int64) *uint16 {
    49  	return (*uint16)(unsafe.Pointer(uintptr(ptr) + uintptr(offset)))
    50  }
    51  
    52  func skipWhiteSpace(buf []byte, cursor int64) int64 {
    53  	for isWhiteSpace[buf[cursor]] {
    54  		cursor++
    55  	}
    56  	return cursor
    57  }
    58  
    59  func skipObject(buf []byte, cursor, depth int64) (int64, error) {
    60  	braceCount := 1
    61  	for {
    62  		switch buf[cursor] {
    63  		case '{':
    64  			braceCount++
    65  			depth++
    66  			if depth > maxDecodeNestingDepth {
    67  				return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
    68  			}
    69  		case '}':
    70  			depth--
    71  			braceCount--
    72  			if braceCount == 0 {
    73  				return cursor + 1, nil
    74  			}
    75  		case '[':
    76  			depth++
    77  			if depth > maxDecodeNestingDepth {
    78  				return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
    79  			}
    80  		case ']':
    81  			depth--
    82  		case '"':
    83  			for {
    84  				cursor++
    85  				switch buf[cursor] {
    86  				case '\\':
    87  					cursor++
    88  					if buf[cursor] == nul {
    89  						return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor)
    90  					}
    91  				case '"':
    92  					goto SWITCH_OUT
    93  				case nul:
    94  					return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor)
    95  				}
    96  			}
    97  		case nul:
    98  			return 0, errors.ErrUnexpectedEndOfJSON("object of object", cursor)
    99  		}
   100  	SWITCH_OUT:
   101  		cursor++
   102  	}
   103  }
   104  
   105  func skipArray(buf []byte, cursor, depth int64) (int64, error) {
   106  	bracketCount := 1
   107  	for {
   108  		switch buf[cursor] {
   109  		case '[':
   110  			bracketCount++
   111  			depth++
   112  			if depth > maxDecodeNestingDepth {
   113  				return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
   114  			}
   115  		case ']':
   116  			bracketCount--
   117  			depth--
   118  			if bracketCount == 0 {
   119  				return cursor + 1, nil
   120  			}
   121  		case '{':
   122  			depth++
   123  			if depth > maxDecodeNestingDepth {
   124  				return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
   125  			}
   126  		case '}':
   127  			depth--
   128  		case '"':
   129  			for {
   130  				cursor++
   131  				switch buf[cursor] {
   132  				case '\\':
   133  					cursor++
   134  					if buf[cursor] == nul {
   135  						return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor)
   136  					}
   137  				case '"':
   138  					goto SWITCH_OUT
   139  				case nul:
   140  					return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor)
   141  				}
   142  			}
   143  		case nul:
   144  			return 0, errors.ErrUnexpectedEndOfJSON("array of object", cursor)
   145  		}
   146  	SWITCH_OUT:
   147  		cursor++
   148  	}
   149  }
   150  
   151  func skipValue(buf []byte, cursor, depth int64) (int64, error) {
   152  	for {
   153  		switch buf[cursor] {
   154  		case ' ', '\t', '\n', '\r':
   155  			cursor++
   156  			continue
   157  		case '{':
   158  			return skipObject(buf, cursor+1, depth+1)
   159  		case '[':
   160  			return skipArray(buf, cursor+1, depth+1)
   161  		case '"':
   162  			for {
   163  				cursor++
   164  				switch buf[cursor] {
   165  				case '\\':
   166  					cursor++
   167  					if buf[cursor] == nul {
   168  						return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor)
   169  					}
   170  				case '"':
   171  					return cursor + 1, nil
   172  				case nul:
   173  					return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor)
   174  				}
   175  			}
   176  		case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
   177  			for {
   178  				cursor++
   179  				if floatTable[buf[cursor]] {
   180  					continue
   181  				}
   182  				break
   183  			}
   184  			return cursor, nil
   185  		case 't':
   186  			if err := validateTrue(buf, cursor); err != nil {
   187  				return 0, err
   188  			}
   189  			cursor += 4
   190  			return cursor, nil
   191  		case 'f':
   192  			if err := validateFalse(buf, cursor); err != nil {
   193  				return 0, err
   194  			}
   195  			cursor += 5
   196  			return cursor, nil
   197  		case 'n':
   198  			if err := validateNull(buf, cursor); err != nil {
   199  				return 0, err
   200  			}
   201  			cursor += 4
   202  			return cursor, nil
   203  		default:
   204  			return cursor, errors.ErrUnexpectedEndOfJSON("null", cursor)
   205  		}
   206  	}
   207  }
   208  
   209  func validateTrue(buf []byte, cursor int64) error {
   210  	if cursor+3 >= int64(len(buf)) {
   211  		return errors.ErrUnexpectedEndOfJSON("true", cursor)
   212  	}
   213  	if buf[cursor+1] != 'r' {
   214  		return errors.ErrInvalidCharacter(buf[cursor+1], "true", cursor)
   215  	}
   216  	if buf[cursor+2] != 'u' {
   217  		return errors.ErrInvalidCharacter(buf[cursor+2], "true", cursor)
   218  	}
   219  	if buf[cursor+3] != 'e' {
   220  		return errors.ErrInvalidCharacter(buf[cursor+3], "true", cursor)
   221  	}
   222  	return nil
   223  }
   224  
   225  func validateFalse(buf []byte, cursor int64) error {
   226  	if cursor+4 >= int64(len(buf)) {
   227  		return errors.ErrUnexpectedEndOfJSON("false", cursor)
   228  	}
   229  	if buf[cursor+1] != 'a' {
   230  		return errors.ErrInvalidCharacter(buf[cursor+1], "false", cursor)
   231  	}
   232  	if buf[cursor+2] != 'l' {
   233  		return errors.ErrInvalidCharacter(buf[cursor+2], "false", cursor)
   234  	}
   235  	if buf[cursor+3] != 's' {
   236  		return errors.ErrInvalidCharacter(buf[cursor+3], "false", cursor)
   237  	}
   238  	if buf[cursor+4] != 'e' {
   239  		return errors.ErrInvalidCharacter(buf[cursor+4], "false", cursor)
   240  	}
   241  	return nil
   242  }
   243  
   244  func validateNull(buf []byte, cursor int64) error {
   245  	if cursor+3 >= int64(len(buf)) {
   246  		return errors.ErrUnexpectedEndOfJSON("null", cursor)
   247  	}
   248  	if buf[cursor+1] != 'u' {
   249  		return errors.ErrInvalidCharacter(buf[cursor+1], "null", cursor)
   250  	}
   251  	if buf[cursor+2] != 'l' {
   252  		return errors.ErrInvalidCharacter(buf[cursor+2], "null", cursor)
   253  	}
   254  	if buf[cursor+3] != 'l' {
   255  		return errors.ErrInvalidCharacter(buf[cursor+3], "null", cursor)
   256  	}
   257  	return nil
   258  }