podman

Форк
0
315 строк · 9.2 Кб
1
/*
2
 * Copyright 2021 ByteDance Inc.
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16

17
package ast
18

19
import (
20
    `encoding/json`
21

22
    `github.com/bytedance/sonic/internal/native/types`
23
)
24

25
// Visitor handles the callbacks during preorder traversal of a JSON AST.
26
//
27
// According to the JSON RFC8259, a JSON AST can be defined by
28
// the following rules without seperator / whitespace tokens.
29
//
30
//  JSON-AST  = value
31
//  value     = false / null / true / object / array / number / string
32
//  object    = begin-object [ member *( member ) ] end-object
33
//  member    = string value
34
//  array     = begin-array [ value *( value ) ] end-array
35
//
36
type Visitor interface {
37

38
    // OnNull handles a JSON null value.
39
    OnNull() error
40

41
    // OnBool handles a JSON true / false value.
42
    OnBool(v bool) error
43

44
    // OnString handles a JSON string value.
45
    OnString(v string) error
46

47
    // OnInt64 handles a JSON number value with int64 type.
48
    OnInt64(v int64, n json.Number) error
49

50
    // OnFloat64 handles a JSON number value with float64 type.
51
    OnFloat64(v float64, n json.Number) error
52

53
    // OnObjectBegin handles the beginning of a JSON object value with a
54
    // suggested capacity that can be used to make your custom object container.
55
    //
56
    // After this point the visitor will receive a sequence of callbacks like
57
    // [string, value, string, value, ......, ObjectEnd].
58
    //
59
    // Note:
60
    // 1. This is a recursive definition which means the value can
61
    // also be a JSON object / array described by a sequence of callbacks.
62
    // 2. The suggested capacity will be 0 if current object is empty.
63
    // 3. Currently sonic use a fixed capacity for non-empty object (keep in
64
    // sync with ast.Node) which might not be very suitable. This may be
65
    // improved in future version.
66
    OnObjectBegin(capacity int) error
67

68
    // OnObjectKey handles a JSON object key string in member.
69
    OnObjectKey(key string) error
70

71
    // OnObjectEnd handles the ending of a JSON object value.
72
    OnObjectEnd() error
73

74
    // OnArrayBegin handles the beginning of a JSON array value with a
75
    // suggested capacity that can be used to make your custom array container.
76
    //
77
    // After this point the visitor will receive a sequence of callbacks like
78
    // [value, value, value, ......, ArrayEnd].
79
    //
80
    // Note:
81
    // 1. This is a recursive definition which means the value can
82
    // also be a JSON object / array described by a sequence of callbacks.
83
    // 2. The suggested capacity will be 0 if current array is empty.
84
    // 3. Currently sonic use a fixed capacity for non-empty array (keep in
85
    // sync with ast.Node) which might not be very suitable. This may be
86
    // improved in future version.
87
    OnArrayBegin(capacity int) error
88

89
    // OnArrayEnd handles the ending of a JSON array value.
90
    OnArrayEnd() error
91
}
92

93
// VisitorOptions contains all Visitor's options. The default value is an
94
// empty VisitorOptions{}.
95
type VisitorOptions struct {
96
    // OnlyNumber indicates parser to directly return number value without
97
    // conversion, then the first argument of OnInt64 / OnFloat64 will always
98
    // be zero.
99
    OnlyNumber bool
100
}
101

102
var defaultVisitorOptions = &VisitorOptions{}
103

104
// Preorder decodes the whole JSON string and callbacks each AST node to visitor
105
// during preorder traversal. Any visitor method with an error returned will
106
// break the traversal and the given error will be directly returned. The opts
107
// argument can be reused after every call.
108
func Preorder(str string, visitor Visitor, opts *VisitorOptions) error {
109
    if opts == nil {
110
        opts = defaultVisitorOptions
111
    }
112
    // process VisitorOptions first to guarantee that all options will be
113
    // constant during decoding and make options more readable.
114
    var (
115
        optDecodeNumber = !opts.OnlyNumber
116
    )
117

118
    tv := &traverser{
119
        parser: Parser{
120
            s:         str,
121
            noLazy:    true,
122
            skipValue: false,
123
        },
124
        visitor: visitor,
125
    }
126

127
    if optDecodeNumber {
128
        tv.parser.decodeNumber(true)
129
    }
130

131
    err := tv.decodeValue()
132

133
    if optDecodeNumber {
134
        tv.parser.decodeNumber(false)
135
    }
136
    return err
137
}
138

139
type traverser struct {
140
    parser  Parser
141
    visitor Visitor
142
}
143

144
// NOTE: keep in sync with (*Parser).Parse method.
145
func (self *traverser) decodeValue() error {
146
    switch val := self.parser.decodeValue(); val.Vt {
147
    case types.V_EOF:
148
        return types.ERR_EOF
149
    case types.V_NULL:
150
        return self.visitor.OnNull()
151
    case types.V_TRUE:
152
        return self.visitor.OnBool(true)
153
    case types.V_FALSE:
154
        return self.visitor.OnBool(false)
155
    case types.V_STRING:
156
        return self.decodeString(val.Iv, val.Ep)
157
    case types.V_DOUBLE:
158
        return self.visitor.OnFloat64(val.Dv,
159
            json.Number(self.parser.s[val.Ep:self.parser.p]))
160
    case types.V_INTEGER:
161
        return self.visitor.OnInt64(val.Iv,
162
            json.Number(self.parser.s[val.Ep:self.parser.p]))
163
    case types.V_ARRAY:
164
        return self.decodeArray()
165
    case types.V_OBJECT:
166
        return self.decodeObject()
167
    default:
168
        return types.ParsingError(-val.Vt)
169
    }
170
}
171

172
// NOTE: keep in sync with (*Parser).decodeArray method.
173
func (self *traverser) decodeArray() error {
174
    sp := self.parser.p
175
    ns := len(self.parser.s)
176

177
    /* check for EOF */
178
    self.parser.p = self.parser.lspace(sp)
179
    if self.parser.p >= ns {
180
        return types.ERR_EOF
181
    }
182

183
    /* check for empty array */
184
    if self.parser.s[self.parser.p] == ']' {
185
        self.parser.p++
186
        if err := self.visitor.OnArrayBegin(0); err != nil {
187
            return err
188
        }
189
        return self.visitor.OnArrayEnd()
190
    }
191

192
    /* allocate array space and parse every element */
193
    if err := self.visitor.OnArrayBegin(_DEFAULT_NODE_CAP); err != nil {
194
        return err
195
    }
196
    for {
197
        /* decode the value */
198
        if err := self.decodeValue(); err != nil {
199
            return err
200
        }
201
        self.parser.p = self.parser.lspace(self.parser.p)
202

203
        /* check for EOF */
204
        if self.parser.p >= ns {
205
            return types.ERR_EOF
206
        }
207

208
        /* check for the next character */
209
        switch self.parser.s[self.parser.p] {
210
        case ',':
211
            self.parser.p++
212
        case ']':
213
            self.parser.p++
214
            return self.visitor.OnArrayEnd()
215
        default:
216
            return types.ERR_INVALID_CHAR
217
        }
218
    }
219
}
220

221
// NOTE: keep in sync with (*Parser).decodeObject method.
222
func (self *traverser) decodeObject() error {
223
    sp := self.parser.p
224
    ns := len(self.parser.s)
225

226
    /* check for EOF */
227
    self.parser.p = self.parser.lspace(sp)
228
    if self.parser.p >= ns {
229
        return types.ERR_EOF
230
    }
231

232
    /* check for empty object */
233
    if self.parser.s[self.parser.p] == '}' {
234
        self.parser.p++
235
        if err := self.visitor.OnObjectBegin(0); err != nil {
236
            return err
237
        }
238
        return self.visitor.OnObjectEnd()
239
    }
240

241
    /* allocate object space and decode each pair */
242
    if err := self.visitor.OnObjectBegin(_DEFAULT_NODE_CAP); err != nil {
243
        return err
244
    }
245
    for {
246
        var njs types.JsonState
247
        var err types.ParsingError
248

249
        /* decode the key */
250
        if njs = self.parser.decodeValue(); njs.Vt != types.V_STRING {
251
            return types.ERR_INVALID_CHAR
252
        }
253

254
        /* extract the key */
255
        idx := self.parser.p - 1
256
        key := self.parser.s[njs.Iv:idx]
257

258
        /* check for escape sequence */
259
        if njs.Ep != -1 {
260
            if key, err = unquote(key); err != 0 {
261
                return err
262
            }
263
        }
264

265
        if err := self.visitor.OnObjectKey(key); err != nil {
266
            return err
267
        }
268

269
        /* expect a ':' delimiter */
270
        if err = self.parser.delim(); err != 0 {
271
            return err
272
        }
273

274
        /* decode the value */
275
        if err := self.decodeValue(); err != nil {
276
            return err
277
        }
278

279
        self.parser.p = self.parser.lspace(self.parser.p)
280

281
        /* check for EOF */
282
        if self.parser.p >= ns {
283
            return types.ERR_EOF
284
        }
285

286
        /* check for the next character */
287
        switch self.parser.s[self.parser.p] {
288
        case ',':
289
            self.parser.p++
290
        case '}':
291
            self.parser.p++
292
            return self.visitor.OnObjectEnd()
293
        default:
294
            return types.ERR_INVALID_CHAR
295
        }
296
    }
297
}
298

299
// NOTE: keep in sync with (*Parser).decodeString method.
300
func (self *traverser) decodeString(iv int64, ep int) error {
301
    p := self.parser.p - 1
302
    s := self.parser.s[iv:p]
303

304
    /* fast path: no escape sequence */
305
    if ep == -1 {
306
        return self.visitor.OnString(s)
307
    }
308

309
    /* unquote the string */
310
    out, err := unquote(s)
311
    if err != 0 {
312
        return err
313
    }
314
    return self.visitor.OnString(out)
315
}
316

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.