gtsocial-umbx

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

decoder.go (7347B)


      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 decoder
     18 
     19 import (
     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 
     32 const (
     33     _F_use_int64 = iota
     34     _F_use_number
     35     _F_disable_urc
     36     _F_disable_unknown
     37     _F_copy_string
     38     _F_validate_string
     39 
     40     _F_allow_control = 31
     41 )
     42 
     43 type Options uint64
     44 
     45 const (
     46     OptionUseInt64         Options = 1 << _F_use_int64
     47     OptionUseNumber        Options = 1 << _F_use_number
     48     OptionUseUnicodeErrors Options = 1 << _F_disable_urc
     49     OptionDisableUnknown   Options = 1 << _F_disable_unknown
     50     OptionCopyString       Options = 1 << _F_copy_string
     51     OptionValidateString   Options = 1 << _F_validate_string
     52 )
     53 
     54 func (self *Decoder) SetOptions(opts Options) {
     55     if (opts & OptionUseNumber != 0) && (opts & OptionUseInt64 != 0) {
     56         panic("can't set OptionUseInt64 and OptionUseNumber both!")
     57     }
     58     self.f = uint64(opts)
     59 }
     60 
     61 
     62 // Decoder is the decoder context object
     63 type Decoder struct {
     64     i int
     65     f uint64
     66     s string
     67 }
     68 
     69 // NewDecoder creates a new decoder instance.
     70 func NewDecoder(s string) *Decoder {
     71     return &Decoder{s: s}
     72 }
     73 
     74 // Pos returns the current decoding position.
     75 func (self *Decoder) Pos() int {
     76     return self.i
     77 }
     78 
     79 func (self *Decoder) Reset(s string) {
     80     self.s = s
     81     self.i = 0
     82     // self.f = 0
     83 }
     84 
     85 func (self *Decoder) CheckTrailings() error {
     86     pos := self.i
     87     buf := self.s
     88     /* skip all the trailing spaces */
     89     if pos != len(buf) {
     90         for pos < len(buf) && (types.SPACE_MASK & (1 << buf[pos])) != 0 {
     91             pos++
     92         }
     93     }
     94 
     95     /* then it must be at EOF */
     96     if pos == len(buf) {
     97         return nil
     98     }
     99 
    100     /* junk after JSON value */
    101     return SyntaxError {
    102         Src  : buf,
    103         Pos  : pos,
    104         Code : 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.
    111 func (self *Decoder) Decode(val interface{}) error {
    112     /* validate json if needed */
    113     if (self.f & (1 << _F_validate_string)) != 0  && !utf8.ValidateString(self.s){
    114         dbuf := utf8.CorrectWith(nil, rt.Str2Mem(self.s), "\ufffd")
    115         self.s = rt.Mem2Str(dbuf)
    116     }
    117 
    118     vv := rt.UnpackEface(val)
    119     vp := vv.Value
    120 
    121     /* check for nil type */
    122     if vv.Type == nil {
    123         return &json.InvalidUnmarshalError{}
    124     }
    125 
    126     /* must be a non-nil pointer */
    127     if vp == nil || vv.Type.Kind() != reflect.Ptr {
    128         return &json.InvalidUnmarshalError{Type: vv.Type.Pack()}
    129     }
    130 
    131     etp := rt.PtrElem(vv.Type)
    132 
    133     /* check the defined pointer type for issue 379 */
    134     if vv.Type.IsNamed() {
    135         newp := vp
    136         etp  = vv.Type
    137         vp   = unsafe.Pointer(&newp)
    138     }
    139 
    140     /* create a new stack, and call the decoder */
    141     sb := newStack()
    142     nb, err := decodeTypedPointer(self.s, self.i, etp, vp, sb, self.f)
    143     /* return the stack back */
    144     self.i = nb
    145     freeStack(sb)
    146 
    147     /* avoid GC ahead */
    148     runtime.KeepAlive(vv)
    149     return err
    150 }
    151 
    152 // UseInt64 indicates the Decoder to unmarshal an integer into an interface{} as an
    153 // int64 instead of as a float64.
    154 func (self *Decoder) UseInt64() {
    155     self.f  |= 1 << _F_use_int64
    156     self.f &^= 1 << _F_use_number
    157 }
    158 
    159 // UseNumber indicates the Decoder to unmarshal a number into an interface{} as a
    160 // json.Number instead of as a float64.
    161 func (self *Decoder) UseNumber() {
    162     self.f &^= 1 << _F_use_int64
    163     self.f  |= 1 << _F_use_number
    164 }
    165 
    166 // UseUnicodeErrors indicates the Decoder to return an error when encounter invalid
    167 // UTF-8 escape sequences.
    168 func (self *Decoder) UseUnicodeErrors() {
    169     self.f |= 1 << _F_disable_urc
    170 }
    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.
    175 func (self *Decoder) DisallowUnknownFields() {
    176     self.f |= 1 << _F_disable_unknown
    177 }
    178 
    179 // CopyString indicates the Decoder to decode string values by copying instead of referring.
    180 func (self *Decoder) CopyString() {
    181     self.f |= 1 << _F_copy_string
    182 }
    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.
    187 func (self *Decoder) ValidateString() {
    188     self.f |= 1 << _F_validate_string
    189 }
    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.
    196 func Pretouch(vt reflect.Type, opts ...option.CompileOption) error {
    197     cfg := option.DefaultCompileOptions()
    198     for _, opt := range opts {
    199         opt(&cfg)
    200     }
    201     return pretouchRec(map[reflect.Type]bool{vt:true}, cfg)
    202 }
    203 
    204 func pretouchType(_vt reflect.Type, opts option.CompileOptions) (map[reflect.Type]bool, error) {
    205     /* compile function */
    206     compiler := newCompiler().apply(opts)
    207     decoder := func(vt *rt.GoType, _ ...interface{}) (interface{}, error) {
    208         if pp, err := compiler.compile(_vt); err != nil {
    209             return nil, err
    210         } else {
    211             as := newAssembler(pp)
    212             as.name = _vt.String()
    213             return as.Load(), nil
    214         }
    215     }
    216 
    217     /* find or compile */
    218     vt := rt.UnpackType(_vt)
    219     if val := programCache.Get(vt); val != nil {
    220         return nil, nil
    221     } else if _, err := programCache.Compute(vt, decoder); err == nil {
    222         return compiler.rec, nil
    223     } else {
    224         return nil, err
    225     }
    226 }
    227 
    228 func pretouchRec(vtm map[reflect.Type]bool, opts option.CompileOptions) error {
    229     if opts.RecursiveDepth < 0 || len(vtm) == 0 {
    230         return nil
    231     }
    232     next := make(map[reflect.Type]bool)
    233     for vt := range(vtm) {
    234         sub, err := pretouchType(vt, opts)
    235         if err != nil {
    236             return err
    237         }
    238         for svt := range(sub) {
    239             next[svt] = true
    240         }
    241     }
    242     opts.RecursiveDepth -= 1
    243     return 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
    248 func Skip(data []byte) (start int, end int) {
    249     s := rt.Mem2Str(data)
    250     p := 0
    251     m := types.NewStateMachine()
    252     ret := native.SkipOne(&s, &p, m, uint64(0))
    253     types.FreeStateMachine(m) 
    254     return ret, p
    255 }