podman
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
17package decoder18
19import (20`unsafe`21`encoding/json`22`reflect`23`runtime`24
25`github.com/bytedance/sonic/internal/native`26`github.com/bytedance/sonic/internal/native/types`27`github.com/bytedance/sonic/internal/rt`28`github.com/bytedance/sonic/option`29`github.com/bytedance/sonic/utf8`30)
31
32const (33_F_use_int64 = 034_F_disable_urc = 235_F_disable_unknown = 336_F_copy_string = 437
38_F_use_number = types.B_USE_NUMBER39_F_validate_string = types.B_VALIDATE_STRING40_F_allow_control = types.B_ALLOW_CONTROL41)
42
43type Options uint6444
45const (46OptionUseInt64 Options = 1 << _F_use_int6447OptionUseNumber Options = 1 << _F_use_number48OptionUseUnicodeErrors Options = 1 << _F_disable_urc49OptionDisableUnknown Options = 1 << _F_disable_unknown50OptionCopyString Options = 1 << _F_copy_string51OptionValidateString Options = 1 << _F_validate_string52)
53
54func (self *Decoder) SetOptions(opts Options) {55if (opts & OptionUseNumber != 0) && (opts & OptionUseInt64 != 0) {56panic("can't set OptionUseInt64 and OptionUseNumber both!")57}58self.f = uint64(opts)59}
60
61
62// Decoder is the decoder context object
63type Decoder struct {64i int65f uint6466s string67}
68
69// NewDecoder creates a new decoder instance.
70func NewDecoder(s string) *Decoder {71return &Decoder{s: s}72}
73
74// Pos returns the current decoding position.
75func (self *Decoder) Pos() int {76return self.i77}
78
79func (self *Decoder) Reset(s string) {80self.s = s81self.i = 082// self.f = 083}
84
85func (self *Decoder) CheckTrailings() error {86pos := self.i87buf := self.s88/* skip all the trailing spaces */89if pos != len(buf) {90for pos < len(buf) && (types.SPACE_MASK & (1 << buf[pos])) != 0 {91pos++92}93}94
95/* then it must be at EOF */96if pos == len(buf) {97return nil98}99
100/* junk after JSON value */101return SyntaxError {102Src : buf,103Pos : pos,104Code : types.ERR_INVALID_CHAR,105}106}
107
108
109// Decode parses the JSON-encoded data from current position and stores the result
110// in the value pointed to by val.
111func (self *Decoder) Decode(val interface{}) error {112/* validate json if needed */113if (self.f & (1 << _F_validate_string)) != 0 && !utf8.ValidateString(self.s){114dbuf := utf8.CorrectWith(nil, rt.Str2Mem(self.s), "\ufffd")115self.s = rt.Mem2Str(dbuf)116}117
118vv := rt.UnpackEface(val)119vp := vv.Value120
121/* check for nil type */122if vv.Type == nil {123return &json.InvalidUnmarshalError{}124}125
126/* must be a non-nil pointer */127if vp == nil || vv.Type.Kind() != reflect.Ptr {128return &json.InvalidUnmarshalError{Type: vv.Type.Pack()}129}130
131etp := rt.PtrElem(vv.Type)132
133/* check the defined pointer type for issue 379 */134if vv.Type.IsNamed() {135newp := vp136etp = vv.Type137vp = unsafe.Pointer(&newp)138}139
140/* create a new stack, and call the decoder */141sb := newStack()142nb, err := decodeTypedPointer(self.s, self.i, etp, vp, sb, self.f)143/* return the stack back */144self.i = nb145freeStack(sb)146
147/* avoid GC ahead */148runtime.KeepAlive(vv)149return err150}
151
152// UseInt64 indicates the Decoder to unmarshal an integer into an interface{} as an
153// int64 instead of as a float64.
154func (self *Decoder) UseInt64() {155self.f |= 1 << _F_use_int64156self.f &^= 1 << _F_use_number157}
158
159// UseNumber indicates the Decoder to unmarshal a number into an interface{} as a
160// json.Number instead of as a float64.
161func (self *Decoder) UseNumber() {162self.f &^= 1 << _F_use_int64163self.f |= 1 << _F_use_number164}
165
166// UseUnicodeErrors indicates the Decoder to return an error when encounter invalid
167// UTF-8 escape sequences.
168func (self *Decoder) UseUnicodeErrors() {169self.f |= 1 << _F_disable_urc170}
171
172// DisallowUnknownFields indicates the Decoder to return an error when the destination
173// is a struct and the input contains object keys which do not match any
174// non-ignored, exported fields in the destination.
175func (self *Decoder) DisallowUnknownFields() {176self.f |= 1 << _F_disable_unknown177}
178
179// CopyString indicates the Decoder to decode string values by copying instead of referring.
180func (self *Decoder) CopyString() {181self.f |= 1 << _F_copy_string182}
183
184// ValidateString causes the Decoder to validate string values when decoding string value
185// in JSON. Validation is that, returning error when unescaped control chars(0x00-0x1f) or
186// invalid UTF-8 chars in the string value of JSON.
187func (self *Decoder) ValidateString() {188self.f |= 1 << _F_validate_string189}
190
191// Pretouch compiles vt ahead-of-time to avoid JIT compilation on-the-fly, in
192// order to reduce the first-hit latency.
193//
194// Opts are the compile options, for example, "option.WithCompileRecursiveDepth" is
195// a compile option to set the depth of recursive compile for the nested struct type.
196func Pretouch(vt reflect.Type, opts ...option.CompileOption) error {197cfg := option.DefaultCompileOptions()198for _, opt := range opts {199opt(&cfg)200}201return pretouchRec(map[reflect.Type]bool{vt:true}, cfg)202}
203
204func pretouchType(_vt reflect.Type, opts option.CompileOptions) (map[reflect.Type]bool, error) {205/* compile function */206compiler := newCompiler().apply(opts)207decoder := func(vt *rt.GoType, _ ...interface{}) (interface{}, error) {208if pp, err := compiler.compile(_vt); err != nil {209return nil, err210} else {211as := newAssembler(pp)212as.name = _vt.String()213return as.Load(), nil214}215}216
217/* find or compile */218vt := rt.UnpackType(_vt)219if val := programCache.Get(vt); val != nil {220return nil, nil221} else if _, err := programCache.Compute(vt, decoder); err == nil {222return compiler.rec, nil223} else {224return nil, err225}226}
227
228func pretouchRec(vtm map[reflect.Type]bool, opts option.CompileOptions) error {229if opts.RecursiveDepth < 0 || len(vtm) == 0 {230return nil231}232next := make(map[reflect.Type]bool)233for vt := range(vtm) {234sub, err := pretouchType(vt, opts)235if err != nil {236return err237}238for svt := range(sub) {239next[svt] = true240}241}242opts.RecursiveDepth -= 1243return pretouchRec(next, opts)244}
245
246// Skip skips only one json value, and returns first non-blank character position and its ending position if it is valid.
247// Otherwise, returns negative error code using start and invalid character position using end
248func Skip(data []byte) (start int, end int) {249s := rt.Mem2Str(data)250p := 0251m := types.NewStateMachine()252ret := native.SkipOne(&s, &p, m, uint64(0))253types.FreeStateMachine(m)254return ret, p255}
256