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 }
255
View as plain text