gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

context.go (5462B)


      1 package decoder
      2 
      3 import (
      4 	"sync"
      5 	"unsafe"
      6 
      7 	"github.com/goccy/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 }