github.com/goccy/go-json@v0.10.3-0.20240509105655-5e2ae3f23c1d/internal/decoder/context.go (about) 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 }