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

     1  package decoder
     2  
     3  import (
     4  	"sync"
     5  	"unsafe"
     6  
     7  	"github.com/grbit/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() interface{} {
    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 skipWhiteSpace(buf []byte, cursor int64) int64 {
    49  	for isWhiteSpace[buf[cursor]] {
    50  		cursor++
    51  	}
    52  	return cursor
    53  }
    54  
    55  func skipObject(buf []byte, cursor, depth int64) (int64, error) {
    56  	braceCount := 1
    57  	for {
    58  		switch buf[cursor] {
    59  		case '{':
    60  			braceCount++
    61  			depth++
    62  			if depth > maxDecodeNestingDepth {
    63  				return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
    64  			}
    65  		case '}':
    66  			depth--
    67  			braceCount--
    68  			if braceCount == 0 {
    69  				return cursor + 1, nil
    70  			}
    71  		case '[':
    72  			depth++
    73  			if depth > maxDecodeNestingDepth {
    74  				return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
    75  			}
    76  		case ']':
    77  			depth--
    78  		case '"':
    79  			for {
    80  				cursor++
    81  				switch buf[cursor] {
    82  				case '\\':
    83  					cursor++
    84  					if buf[cursor] == nul {
    85  						return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor)
    86  					}
    87  				case '"':
    88  					goto SWITCH_OUT
    89  				case nul:
    90  					return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor)
    91  				}
    92  			}
    93  		case nul:
    94  			return 0, errors.ErrUnexpectedEndOfJSON("object of object", cursor)
    95  		}
    96  	SWITCH_OUT:
    97  		cursor++
    98  	}
    99  }
   100  
   101  func skipArray(buf []byte, cursor, depth int64) (int64, error) {
   102  	bracketCount := 1
   103  	for {
   104  		switch buf[cursor] {
   105  		case '[':
   106  			bracketCount++
   107  			depth++
   108  			if depth > maxDecodeNestingDepth {
   109  				return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
   110  			}
   111  		case ']':
   112  			bracketCount--
   113  			depth--
   114  			if bracketCount == 0 {
   115  				return cursor + 1, nil
   116  			}
   117  		case '{':
   118  			depth++
   119  			if depth > maxDecodeNestingDepth {
   120  				return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
   121  			}
   122  		case '}':
   123  			depth--
   124  		case '"':
   125  			for {
   126  				cursor++
   127  				switch buf[cursor] {
   128  				case '\\':
   129  					cursor++
   130  					if buf[cursor] == nul {
   131  						return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor)
   132  					}
   133  				case '"':
   134  					goto SWITCH_OUT
   135  				case nul:
   136  					return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor)
   137  				}
   138  			}
   139  		case nul:
   140  			return 0, errors.ErrUnexpectedEndOfJSON("array of object", cursor)
   141  		}
   142  	SWITCH_OUT:
   143  		cursor++
   144  	}
   145  }
   146  
   147  func skipValue(buf []byte, cursor, depth int64) (int64, error) {
   148  	for {
   149  		switch buf[cursor] {
   150  		case ' ', '\t', '\n', '\r':
   151  			cursor++
   152  			continue
   153  		case '{':
   154  			return skipObject(buf, cursor+1, depth+1)
   155  		case '[':
   156  			return skipArray(buf, cursor+1, depth+1)
   157  		case '"':
   158  			for {
   159  				cursor++
   160  				switch buf[cursor] {
   161  				case '\\':
   162  					cursor++
   163  					if buf[cursor] == nul {
   164  						return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor)
   165  					}
   166  				case '"':
   167  					return cursor + 1, nil
   168  				case nul:
   169  					return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor)
   170  				}
   171  			}
   172  		case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
   173  			for {
   174  				cursor++
   175  				if floatTable[buf[cursor]] {
   176  					continue
   177  				}
   178  				break
   179  			}
   180  			return cursor, nil
   181  		case 't':
   182  			if err := validateTrue(buf, cursor); err != nil {
   183  				return 0, err
   184  			}
   185  			cursor += 4
   186  			return cursor, nil
   187  		case 'f':
   188  			if err := validateFalse(buf, cursor); err != nil {
   189  				return 0, err
   190  			}
   191  			cursor += 5
   192  			return cursor, nil
   193  		case 'n':
   194  			if err := validateNull(buf, cursor); err != nil {
   195  				return 0, err
   196  			}
   197  			cursor += 4
   198  			return cursor, nil
   199  		default:
   200  			return cursor, errors.ErrUnexpectedEndOfJSON("null", cursor)
   201  		}
   202  	}
   203  }
   204  
   205  func validateTrue(buf []byte, cursor int64) error {
   206  	if cursor+3 >= int64(len(buf)) {
   207  		return errors.ErrUnexpectedEndOfJSON("true", cursor)
   208  	}
   209  	if buf[cursor+1] != 'r' {
   210  		return errors.ErrInvalidCharacter(buf[cursor+1], "true", cursor)
   211  	}
   212  	if buf[cursor+2] != 'u' {
   213  		return errors.ErrInvalidCharacter(buf[cursor+2], "true", cursor)
   214  	}
   215  	if buf[cursor+3] != 'e' {
   216  		return errors.ErrInvalidCharacter(buf[cursor+3], "true", cursor)
   217  	}
   218  	return nil
   219  }
   220  
   221  func validateFalse(buf []byte, cursor int64) error {
   222  	if cursor+4 >= int64(len(buf)) {
   223  		return errors.ErrUnexpectedEndOfJSON("false", cursor)
   224  	}
   225  	if buf[cursor+1] != 'a' {
   226  		return errors.ErrInvalidCharacter(buf[cursor+1], "false", cursor)
   227  	}
   228  	if buf[cursor+2] != 'l' {
   229  		return errors.ErrInvalidCharacter(buf[cursor+2], "false", cursor)
   230  	}
   231  	if buf[cursor+3] != 's' {
   232  		return errors.ErrInvalidCharacter(buf[cursor+3], "false", cursor)
   233  	}
   234  	if buf[cursor+4] != 'e' {
   235  		return errors.ErrInvalidCharacter(buf[cursor+4], "false", cursor)
   236  	}
   237  	return nil
   238  }
   239  
   240  func validateNull(buf []byte, cursor int64) error {
   241  	if cursor+3 >= int64(len(buf)) {
   242  		return errors.ErrUnexpectedEndOfJSON("null", cursor)
   243  	}
   244  	if buf[cursor+1] != 'u' {
   245  		return errors.ErrInvalidCharacter(buf[cursor+1], "null", cursor)
   246  	}
   247  	if buf[cursor+2] != 'l' {
   248  		return errors.ErrInvalidCharacter(buf[cursor+2], "null", cursor)
   249  	}
   250  	if buf[cursor+3] != 'l' {
   251  		return errors.ErrInvalidCharacter(buf[cursor+3], "null", cursor)
   252  	}
   253  	return nil
   254  }