12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298 |
- package optdec
- import (
- "encoding/json"
- "math"
- "unsafe"
- "github.com/bytedance/sonic/internal/envs"
- "github.com/bytedance/sonic/internal/rt"
- )
- type Context struct {
- Parser *Parser
- efacePool *efacePool
- Stack bounedStack
- Utf8Inv bool
- }
- func (ctx *Context) Options() uint64 {
- return ctx.Parser.options
- }
- /************************* Stack and Pool Helper *******************/
- type parentStat struct {
- con unsafe.Pointer
- remain uint64
- }
- type bounedStack struct {
- stack []parentStat
- index int
- }
- func newStack(size int) bounedStack {
- return bounedStack{
- stack: make([]parentStat, size + 2),
- index: 0,
- }
- }
- //go:nosplit
- func (s *bounedStack) Pop() (unsafe.Pointer, int, bool){
- s.index--
- con := s.stack[s.index].con
- remain := s.stack[s.index].remain &^ (uint64(1) << 63)
- isObj := (s.stack[s.index].remain & (uint64(1) << 63)) != 0
- s.stack[s.index].con = nil
- s.stack[s.index].remain = 0
- return con, int(remain), isObj
- }
- //go:nosplit
- func (s *bounedStack) Push(p unsafe.Pointer, remain int, isObj bool) {
- s.stack[s.index].con = p
- s.stack[s.index].remain = uint64(remain)
- if isObj {
- s.stack[s.index].remain |= (uint64(1) << 63)
- }
- s.index++
- }
- type efacePool struct{
- t64 rt.T64Pool
- tslice rt.TslicePool
- tstring rt.TstringPool
- efaceSlice rt.SlicePool
- }
- func newEfacePool(stat *jsonStat, useNumber bool) *efacePool {
- strs := int(stat.str)
- nums := 0
- if useNumber {
- strs += int(stat.number)
- } else {
- nums = int(stat.number)
- }
- return &efacePool{
- t64: rt.NewT64Pool(nums),
- tslice: rt.NewTslicePool(int(stat.array)),
- tstring: rt.NewTstringPool(strs),
- efaceSlice: rt.NewPool(rt.AnyType, int(stat.array_elems)),
- }
- }
- func (self *efacePool) GetMap(hint int) unsafe.Pointer {
- m := make(map[string]interface{}, hint)
- return *(*unsafe.Pointer)(unsafe.Pointer(&m))
- }
- func (self *efacePool) GetSlice(hint int) unsafe.Pointer {
- return unsafe.Pointer(self.efaceSlice.GetSlice(hint))
- }
- func (self *efacePool) ConvTSlice(val rt.GoSlice, typ *rt.GoType, dst unsafe.Pointer) {
- self.tslice.Conv(val, typ, (*interface{})(dst))
- }
- func (self *efacePool) ConvF64(val float64, dst unsafe.Pointer) {
- self.t64.Conv(castU64(val), rt.Float64Type, (*interface{})(dst))
- }
- func (self *efacePool) ConvTstring(val string, dst unsafe.Pointer) {
- self.tstring.Conv(val, (*interface{})(dst))
- }
- func (self *efacePool) ConvTnum(val json.Number, dst unsafe.Pointer) {
- self.tstring.ConvNum(val, (*interface{})(dst))
- }
- /********************************************************/
- func canUseFastMap( opts uint64, root *rt.GoType) bool {
- return envs.UseFastMap && (opts & (1 << _F_copy_string)) == 0 && (opts & (1 << _F_use_int64)) == 0 && (root == rt.AnyType || root == rt.MapEfaceType || root == rt.SliceEfaceType)
- }
- func NewContext(json string, pos int, opts uint64, root *rt.GoType) (Context, error) {
- ctx := Context{
- Parser: newParser(json, pos, opts),
- }
- if root == rt.AnyType || root == rt.MapEfaceType || root == rt.SliceEfaceType {
- ctx.Parser.isEface = true
- }
- ecode := ctx.Parser.parse()
- if ecode != 0 {
- return ctx, ctx.Parser.fixError(ecode)
- }
- useNumber := (opts & (1 << _F_use_number )) != 0
- if canUseFastMap(opts, root) {
- ctx.efacePool = newEfacePool(&ctx.Parser.nbuf.stat, useNumber)
- ctx.Stack = newStack(int(ctx.Parser.nbuf.stat.max_depth))
- }
- return ctx, nil
- }
- func (ctx *Context) Delete() {
- ctx.Parser.free()
- ctx.Parser = nil
- }
- type Node struct {
- cptr uintptr
- }
- func NewNode(cptr uintptr) Node {
- return Node{cptr: cptr}
- }
- type Dom struct {
- cdom uintptr
- }
- func (ctx *Context) Root() Node {
- root := (uintptr)(((*rt.GoSlice)(unsafe.Pointer(&ctx.Parser.nodes))).Ptr)
- return Node{cptr: root}
- }
- type Array struct {
- cptr uintptr
- }
- type Object struct {
- cptr uintptr
- }
- func (obj Object) Len() int {
- cobj := ptrCast(obj.cptr)
- return int(uint64(cobj.val) & ConLenMask)
- }
- func (arr Array) Len() int {
- carr := ptrCast(arr.cptr)
- return int(uint64(carr.val) & ConLenMask)
- }
- // / Helper functions to eliminate CGO calls
- func (val Node) Type() uint8 {
- ctype := ptrCast(val.cptr)
- return uint8(ctype.typ & TypeMask)
- }
- func (val Node) Next() uintptr {
- if val.Type() != KObject && val.Type() != KArray {
- return PtrOffset(val.cptr, 1)
- }
- cobj := ptrCast(val.cptr)
- offset := int64(uint64(cobj.val) >> ConLenBits)
- return PtrOffset(val.cptr, offset)
- }
- func (val *Node) next() {
- *val = NewNode(val.Next())
- }
- type NodeIter struct {
- next uintptr
- }
- func NewNodeIter(node Node) NodeIter {
- return NodeIter{next: node.cptr}
- }
- func (iter *NodeIter) Next() Node {
- ret := NewNode(iter.next)
- iter.next = PtrOffset(iter.next, 1)
- return ret
- }
- func (iter *NodeIter) Peek() Node {
- return NewNode(iter.next)
- }
- func (val Node) U64() uint64 {
- cnum := ptrCast(val.cptr)
- return *(*uint64)((unsafe.Pointer)(&(cnum.val)))
- }
- func (val Node) I64() int64 {
- cnum := ptrCast(val.cptr)
- return *(*int64)((unsafe.Pointer)(&(cnum.val)))
- }
- func (val Node) IsNull() bool {
- return val.Type() == KNull
- }
- func (val Node) IsNumber() bool {
- return val.Type() & KNumber != 0
- }
- func (val Node) F64() float64 {
- cnum := ptrCast(val.cptr)
- return *(*float64)((unsafe.Pointer)(&(cnum.val)))
- }
- func (val Node) Bool() bool {
- return val.Type() == KTrue
- }
- func (self Node) AsU64(ctx *Context) (uint64, bool) {
- if self.Type() == KUint {
- return self.U64(), true
- } else if self.Type() == KRawNumber {
- num, err := ParseU64(self.Raw(ctx))
- if err != nil {
- return 0, false
- }
- return num, true
- } else {
- return 0, false
- }
- }
- func (val *Node) AsObj() (Object, bool) {
- var ret Object
- if val.Type() != KObject {
- return ret, false
- }
- return Object{
- cptr: val.cptr,
- }, true
- }
- func (val Node) Obj() Object {
- return Object{cptr: val.cptr}
- }
- func (val Node) Arr() Array {
- return Array{cptr: val.cptr}
- }
- func (val *Node) AsArr() (Array, bool) {
- var ret Array
- if val.Type() != KArray {
- return ret, false
- }
- return Array{
- cptr: val.cptr,
- }, true
- }
- func (self Node) AsI64(ctx *Context) (int64, bool) {
- typ := self.Type()
- if typ == KUint && self.U64() <= math.MaxInt64 {
- return int64(self.U64()), true
- } else if typ == KSint {
- return self.I64(), true
- } else if typ == KRawNumber {
- val, err := self.Number(ctx).Int64()
- if err != nil {
- return 0, false
- }
- return val, true
- } else {
- return 0, false
- }
- }
- func (self Node) AsByte(ctx *Context) (uint8, bool) {
- typ := self.Type()
- if typ == KUint && self.U64() <= math.MaxUint8 {
- return uint8(self.U64()), true
- } else if typ == KSint && self.I64() == 0 {
- return 0, true
- } else {
- return 0, false
- }
- }
- /********* Parse Node String into Value ***************/
- func (val Node) ParseI64(ctx *Context) (int64, bool) {
- s, ok := val.AsStrRef(ctx)
- if !ok {
- return 0, false
- }
- if s == "null" {
- return 0, true
- }
- i, err := ParseI64(s)
- if err != nil {
- return 0, false
- }
- return i, true
- }
- func (val Node) ParseBool(ctx *Context) (bool, bool) {
- s, ok := val.AsStrRef(ctx)
- if !ok {
- return false, false
- }
- if s == "null" {
- return false, true
- }
- b, err := ParseBool(s)
- if err != nil {
- return false, false
- }
- return b, true
- }
- func (val Node) ParseU64(ctx *Context) (uint64, bool) {
- s, ok := val.AsStrRef(ctx)
- if !ok {
- return 0, false
- }
- if s == "null" {
- return 0, true
- }
- i, err := ParseU64(s)
- if err != nil {
- return 0, false
- }
- return i, true
- }
- func (val Node) ParseF64(ctx *Context) (float64, bool) {
- s, ok := val.AsStrRef(ctx)
- if !ok {
- return 0, false
- }
- if s == "null" {
- return 0, true
- }
- i, err := ParseF64(s)
- if err != nil {
- return 0, false
- }
- return i, true
- }
- func (val Node) ParseString(ctx *Context) (string, bool) {
- // should not use AsStrRef
- s, ok := val.AsStr(ctx)
- if !ok {
- return "", false
- }
- if s == "null" {
- return "", true
- }
- s, err := Unquote(s)
- if err != nil {
- return "", false
- }
- return s, true
- }
- func (val Node) ParseNumber(ctx *Context) (json.Number, bool) {
- // should not use AsStrRef
- s, ok := val.AsStr(ctx)
- if !ok {
- return json.Number(""), false
- }
- if s == "null" {
- return json.Number(""), true
- }
- end, ok := SkipNumberFast(s, 0)
- // has error or trailing chars
- if !ok || end != len(s) {
- return json.Number(""), false
- }
- return json.Number(s), true
- }
- func (val Node) AsF64(ctx *Context) (float64, bool) {
- switch val.Type() {
- case KUint: return float64(val.U64()), true
- case KSint: return float64(val.I64()), true
- case KReal: return float64(val.F64()), true
- case KRawNumber: f, err := val.Number(ctx).Float64(); return f, err == nil
- default: return 0, false
- }
- }
- func (val Node) AsBool() (bool, bool) {
- switch val.Type() {
- case KTrue: return true, true
- case KFalse: return false, true
- default: return false, false
- }
- }
- func (val Node) AsStr(ctx *Context) (string, bool) {
- switch val.Type() {
- case KStringCommon:
- s := val.StringRef(ctx)
- if (ctx.Options() & (1 << _F_copy_string) == 0) {
- return s, true
- }
- return string(rt.Str2Mem(s)), true
- case KStringEscaped:
- return val.StringCopyEsc(ctx), true
- default: return "", false
- }
- }
- func (val Node) AsStrRef(ctx *Context) (string, bool) {
- switch val.Type() {
- case KStringEscaped:
- node := ptrCast(val.cptr)
- offset := val.Position()
- len := int(node.val)
- return rt.Mem2Str(ctx.Parser.JsonBytes()[offset : offset + len]), true
- case KStringCommon:
- return val.StringRef(ctx), true
- default:
- return "", false
- }
- }
- func (val Node) AsStringText(ctx *Context) ([]byte, bool) {
- if !val.IsStr() {
- return nil, false
- }
- // clone to new bytes
- s, b := val.AsStrRef(ctx)
- return []byte(s), b
- }
- func (val Node) IsStr() bool {
- return (val.Type() == KStringCommon) || (val.Type() == KStringEscaped)
- }
- func (val Node) IsRawNumber() bool {
- return val.Type() == KRawNumber
- }
- func (val Node) Number(ctx *Context) json.Number {
- return json.Number(val.Raw(ctx))
- }
- func (val Node) Raw(ctx *Context) string {
- node := ptrCast(val.cptr)
- len := int(node.val)
- offset := val.Position()
- return ctx.Parser.Json[offset:int(offset+len)]
- }
- func (val Node) Position() int {
- node := ptrCast(val.cptr)
- return int(node.typ >> PosBits)
- }
- func (val Node) AsNumber(ctx *Context) (json.Number, bool) {
- // parse JSON string as number
- if val.IsStr() {
- s, _ := val.AsStr(ctx)
- if !ValidNumberFast(s) {
- return "", false
- } else {
- return json.Number(s), true
- }
- }
- return val.NonstrAsNumber(ctx)
- }
- func (val Node) NonstrAsNumber(ctx *Context) (json.Number, bool) {
- // deal with raw number
- if val.IsRawNumber() {
- return val.Number(ctx), true
- }
- // deal with parse number
- if !val.IsNumber() {
- return json.Number(""), false
- }
- start := val.Position()
- end, ok := SkipNumberFast(ctx.Parser.Json, start)
- if !ok {
- return "", false
- }
- return json.Number(ctx.Parser.Json[start:end]), true
- }
- func (val Node) AsRaw(ctx *Context) string {
- // fast path for unescaped strings
- switch val.Type() {
- case KNull:
- return "null"
- case KTrue:
- return "true"
- case KFalse:
- return "false"
- case KStringCommon:
- node := ptrCast(val.cptr)
- len := int(node.val)
- offset := val.Position()
- // add start and end quote
- ref := rt.Str2Mem(ctx.Parser.Json)[offset-1 : offset+len+1]
- return rt.Mem2Str(ref)
- case KRawNumber: fallthrough
- case KRaw: return val.Raw(ctx)
- case KStringEscaped:
- raw, _ := SkipOneFast(ctx.Parser.Json, val.Position() - 1)
- return raw
- default:
- raw, err := SkipOneFast(ctx.Parser.Json, val.Position())
- if err != nil {
- break
- }
- return raw
- }
- panic("should always be valid json here")
- }
- // reference from the input JSON as possible
- func (val Node) StringRef(ctx *Context) string {
- return val.Raw(ctx)
- }
- //go:nocheckptr
- func ptrCast(p uintptr) *node {
- return (*node)(unsafe.Pointer(p))
- }
- func (val Node) StringCopyEsc(ctx *Context) string {
- // check whether there are in padded
- node := ptrCast(val.cptr)
- len := int(node.val)
- offset := val.Position()
- return string(ctx.Parser.JsonBytes()[offset : offset + len])
- }
- func (val Node) Object() Object {
- return Object{cptr: val.cptr}
- }
- func (val Node) Array() Array {
- return Array{cptr: val.cptr}
- }
- func (val *Array) Children() uintptr {
- return PtrOffset(val.cptr, 1)
- }
- func (val *Object) Children() uintptr {
- return PtrOffset(val.cptr, 1)
- }
- func (val *Node) Equal(ctx *Context, lhs string) bool {
- // check whether escaped
- cstr := ptrCast(val.cptr)
- offset := int(val.Position())
- len := int(cstr.val)
- return lhs == ctx.Parser.Json[offset:offset+len]
- }
- func (node *Node) AsMapEface(ctx *Context, vp unsafe.Pointer) error {
- if node.IsNull() {
- return nil
- }
- obj, ok := node.AsObj()
- if !ok {
- return newUnmatched(node.Position(), rt.MapEfaceType)
- }
- var err, gerr error
- size := obj.Len()
- var m map[string]interface{}
- if *(*unsafe.Pointer)(vp) == nil {
- if ctx.efacePool != nil {
- p := ctx.efacePool.GetMap(size)
- m = *(*map[string]interface{})(unsafe.Pointer(&p))
- } else {
- m = make(map[string]interface{}, size)
- }
- } else {
- m = *(*map[string]interface{})(vp)
- }
- next := obj.Children()
- for i := 0; i < size; i++ {
- knode := NewNode(next)
- key, _ := knode.AsStr(ctx)
- val := NewNode(PtrOffset(next, 1))
- m[key], err = val.AsEface(ctx)
- next = val.cptr
- if gerr == nil && err != nil {
- gerr = err
- }
- }
- *(*map[string]interface{})(vp) = m
- return gerr
- }
- func (node *Node) AsMapString(ctx *Context, vp unsafe.Pointer) error {
- obj, ok := node.AsObj()
- if !ok {
- return newUnmatched(node.Position(), rt.MapStringType)
- }
- size := obj.Len()
- var m map[string]string
- if *(*unsafe.Pointer)(vp) == nil {
- m = make(map[string]string, size)
- } else {
- m = *(*map[string]string)(vp)
- }
- var gerr error
- next := obj.Children()
- for i := 0; i < size; i++ {
- knode := NewNode(next)
- key, _ := knode.AsStr(ctx)
- val := NewNode(PtrOffset(next, 1))
- m[key], ok = val.AsStr(ctx)
- if !ok {
- if gerr == nil {
- gerr = newUnmatched(val.Position(), rt.StringType)
- }
- next = val.Next()
- } else {
- next = PtrOffset(val.cptr, 1)
- }
- }
- *(*map[string]string)(vp) = m
- return gerr
- }
- func (node *Node) AsSliceEface(ctx *Context, vp unsafe.Pointer) error {
- arr, ok := node.AsArr()
- if !ok {
- return newUnmatched(node.Position(), rt.SliceEfaceType)
- }
- size := arr.Len()
- var s []interface{}
- if size != 0 && ctx.efacePool != nil {
- slice := rt.GoSlice {
- Ptr: ctx.efacePool.GetSlice(size),
- Len: size,
- Cap: size,
- }
- *(*rt.GoSlice)(unsafe.Pointer(&s)) = slice
- } else {
- s = *(*[]interface{})((unsafe.Pointer)(rt.MakeSlice(vp, rt.AnyType, size)))
- }
- *node = NewNode(arr.Children())
- var err, gerr error
- for i := 0; i < size; i++ {
- s[i], err = node.AsEface(ctx)
- if gerr == nil && err != nil {
- gerr = err
- }
- }
- *(*[]interface{})(vp) = s
- return nil
- }
- func (node *Node) AsSliceI32(ctx *Context, vp unsafe.Pointer) error {
- arr, ok := node.AsArr()
- if !ok {
- return newUnmatched(node.Position(), rt.SliceI32Type)
- }
- size := arr.Len()
- s := *(*[]int32)((unsafe.Pointer)(rt.MakeSlice(vp, rt.Int32Type, size)))
- next := arr.Children()
- var gerr error
- for i := 0; i < size; i++ {
- val := NewNode(next)
- ret, ok := val.AsI64(ctx)
- if !ok || ret > math.MaxInt32 || ret < math.MinInt32 {
- if gerr == nil {
- gerr = newUnmatched(val.Position(), rt.Int32Type)
- }
- next = val.Next()
- } else {
- s[i] = int32(ret)
- next = PtrOffset(val.cptr, 1)
- }
- }
- *(*[]int32)(vp) = s
- return gerr
- }
- func (node *Node) AsSliceI64(ctx *Context, vp unsafe.Pointer) error {
- arr, ok := node.AsArr()
- if !ok {
- return newUnmatched(node.Position(), rt.SliceI64Type)
- }
- size := arr.Len()
- s := *(*[]int64)((unsafe.Pointer)(rt.MakeSlice(vp, rt.Int64Type, size)))
- next := arr.Children()
- var gerr error
- for i := 0; i < size; i++ {
- val := NewNode(next)
- ret, ok := val.AsI64(ctx)
- if !ok {
- if gerr == nil {
- gerr = newUnmatched(val.Position(), rt.Int64Type)
- }
- next = val.Next()
- } else {
- s[i] = ret
- next = PtrOffset(val.cptr, 1)
- }
- }
- *(*[]int64)(vp) = s
- return gerr
- }
- func (node *Node) AsSliceU32(ctx *Context, vp unsafe.Pointer) error {
- arr, ok := node.AsArr()
- if !ok {
- return newUnmatched(node.Position(), rt.SliceU32Type)
- }
- size := arr.Len()
- next := arr.Children()
- s := *(*[]uint32)((unsafe.Pointer)(rt.MakeSlice(vp, rt.Uint32Type, size)))
- var gerr error
- for i := 0; i < size; i++ {
- val := NewNode(next)
- ret, ok := val.AsU64(ctx)
- if !ok || ret > math.MaxUint32 {
- if gerr == nil {
- gerr = newUnmatched(val.Position(), rt.Uint32Type)
- }
- next = val.Next()
- } else {
- s[i] = uint32(ret)
- next = PtrOffset(val.cptr, 1)
- }
- }
- *(*[]uint32)(vp) = s
- return gerr
- }
- func (node *Node) AsSliceU64(ctx *Context, vp unsafe.Pointer) error {
- arr, ok := node.AsArr()
- if !ok {
- return newUnmatched(node.Position(), rt.SliceU64Type)
- }
- size := arr.Len()
- next := arr.Children()
- s := *(*[]uint64)((unsafe.Pointer)(rt.MakeSlice(vp, rt.Uint64Type, size)))
- var gerr error
- for i := 0; i < size; i++ {
- val := NewNode(next)
- ret, ok := val.AsU64(ctx)
- if !ok {
- if gerr == nil {
- gerr = newUnmatched(val.Position(), rt.Uint64Type)
- }
- next = val.Next()
- } else {
- s[i] = ret
- next = PtrOffset(val.cptr, 1)
- }
- }
- *(*[]uint64)(vp) = s
- return gerr
- }
- func (node *Node) AsSliceString(ctx *Context, vp unsafe.Pointer) error {
- arr, ok := node.AsArr()
- if !ok {
- return newUnmatched(node.Position(), rt.SliceStringType)
- }
- size := arr.Len()
- next := arr.Children()
- s := *(*[]string)((unsafe.Pointer)(rt.MakeSlice(vp, rt.StringType, size)))
- var gerr error
- for i := 0; i < size; i++ {
- val := NewNode(next)
- ret, ok := val.AsStr(ctx)
- if !ok {
- if gerr == nil {
- gerr = newUnmatched(val.Position(), rt.StringType)
- }
- next = val.Next()
- } else {
- s[i] = ret
- next = PtrOffset(val.cptr, 1)
- }
- }
- *(*[]string)(vp) = s
- return gerr
- }
- func (val *Node) AsSliceBytes(ctx *Context) ([]byte, error) {
- var origin []byte
- switch val.Type() {
- case KStringEscaped:
- node := ptrCast(val.cptr)
- offset := val.Position()
- len := int(node.val)
- origin = ctx.Parser.JsonBytes()[offset : offset + len]
- case KStringCommon:
- origin = rt.Str2Mem(val.StringRef(ctx))
- case KArray:
- arr := val.Array()
- size := arr.Len()
- a := make([]byte, size)
- elem := NewNode(arr.Children())
- var gerr error
- var ok bool
- for i := 0; i < size; i++ {
- a[i], ok = elem.AsByte(ctx)
- if !ok && gerr == nil {
- gerr = newUnmatched(val.Position(), rt.BytesType)
- }
- elem = NewNode(PtrOffset(elem.cptr, 1))
- }
- return a, gerr
- default:
- return nil, newUnmatched(val.Position(), rt.BytesType)
- }
-
- b64, err := rt.DecodeBase64(origin)
- if err != nil {
- return nil, newUnmatched(val.Position(), rt.BytesType)
- }
- return b64, nil
- }
- // AsEface will always ok, because we have parse in native.
- func (node *Node) AsEface(ctx *Context) (interface{}, error) {
- if ctx.efacePool != nil {
- iter := NewNodeIter(*node)
- v := AsEfaceFast(&iter, ctx)
- *node = iter.Peek()
- return v, nil
- } else {
- return node.AsEfaceFallback(ctx)
- }
- }
- func parseSingleNode(node Node, ctx *Context) interface{} {
- var v interface{}
- switch node.Type() {
- case KObject: v = map[string]interface{}{}
- case KArray: v = []interface{}{}
- case KStringCommon: v = node.StringRef(ctx)
- case KStringEscaped: v = node.StringCopyEsc(ctx)
- case KTrue: v = true
- case KFalse: v = false
- case KNull: v = nil
- case KUint: v = float64(node.U64())
- case KSint: v = float64(node.I64())
- case KReal: v = float64(node.F64())
- case KRawNumber: v = node.Number(ctx)
- default: panic("unreachable for as eface")
- }
- return v
- }
- func castU64(val float64) uint64 {
- return *((*uint64)(unsafe.Pointer((&val))))
- }
- func AsEfaceFast(iter *NodeIter, ctx *Context) interface{} {
- var mp, sp, parent unsafe.Pointer // current container pointer
- var node Node
- var size int
- var isObj bool
- var slice rt.GoSlice
- var val unsafe.Pointer
- var vt **rt.GoType
- var vp *unsafe.Pointer
- var rootM unsafe.Pointer
- var rootS rt.GoSlice
- var root interface{}
- var key string
- node = iter.Next()
- switch node.Type() {
- case KObject:
- size = node.Object().Len()
- if size != 0 {
- ctx.Stack.Push(nil, 0, true)
- mp = ctx.efacePool.GetMap(size)
- rootM = mp
- isObj = true
- goto _object_key
- } else {
- return rt.GoEface {
- Type: rt.MapEfaceType,
- Value: ctx.efacePool.GetMap(0),
- }.Pack()
- }
- case KArray:
- size = node.Array().Len()
- if size != 0 {
- ctx.Stack.Push(nil, 0, false)
- sp = ctx.efacePool.GetSlice(size)
- slice = rt.GoSlice {
- Ptr: sp,
- Len: size,
- Cap: size,
- }
- rootS = slice
- isObj = false
- val = sp
- goto _arr_val;
- } else {
- ctx.efacePool.ConvTSlice(rt.EmptySlice, rt.SliceEfaceType, unsafe.Pointer(&root))
- }
- case KStringCommon: ctx.efacePool.ConvTstring(node.StringRef(ctx), unsafe.Pointer(&root))
- case KStringEscaped: ctx.efacePool.ConvTstring(node.StringCopyEsc(ctx), unsafe.Pointer(&root))
- case KTrue: root = true
- case KFalse: root = false
- case KNull: root = nil
- case KUint: ctx.efacePool.ConvF64(float64(node.U64()), unsafe.Pointer(&root))
- case KSint: ctx.efacePool.ConvF64(float64(node.I64()), unsafe.Pointer(&root))
- case KReal: ctx.efacePool.ConvF64(node.F64(), unsafe.Pointer(&root))
- case KRawNumber: ctx.efacePool.ConvTnum(node.Number(ctx), unsafe.Pointer(&root))
- default: panic("unreachable for as eface")
- }
- return root
- _object_key:
- node = iter.Next()
- if node.Type() == KStringCommon {
- key = node.StringRef(ctx)
- } else {
- key = node.StringCopyEsc(ctx)
- }
- // interface{} slot in map bucket
- val = rt.Mapassign_faststr(rt.MapEfaceMapType, mp, key)
- vt = &(*rt.GoEface)(val).Type
- vp = &(*rt.GoEface)(val).Value
- // parse value node
- node = iter.Next()
- switch node.Type() {
- case KObject:
- newSize := node.Object().Len()
- newMp := ctx.efacePool.GetMap(newSize)
- *vt = rt.MapEfaceType
- *vp = newMp
- remain := size - 1
- isObj = true
- if newSize != 0 {
- if remain > 0 {
- ctx.Stack.Push(mp, remain, true)
- }
- mp = newMp
- size = newSize
- goto _object_key;
- }
- case KArray:
- newSize := node.Array().Len()
- if newSize == 0 {
- ctx.efacePool.ConvTSlice(rt.EmptySlice, rt.SliceEfaceType, val)
- break;
- }
- newSp := ctx.efacePool.GetSlice(newSize)
- // pack to []interface{}
- ctx.efacePool.ConvTSlice(rt.GoSlice{
- Ptr: newSp,
- Len: newSize,
- Cap: newSize,
- }, rt.SliceEfaceType, val)
- remain := size - 1
- if remain > 0 {
- ctx.Stack.Push(mp, remain, true)
- }
- val = newSp
- isObj = false
- size = newSize
- goto _arr_val;
- case KStringCommon:
- ctx.efacePool.ConvTstring(node.StringRef(ctx), val)
- case KStringEscaped:
- ctx.efacePool.ConvTstring(node.StringCopyEsc(ctx), val)
- case KTrue:
- rt.ConvTBool(true, (*interface{})(val))
- case KFalse:
- rt.ConvTBool(false, (*interface{})(val))
- case KNull: /* skip */
- case KUint:
- ctx.efacePool.ConvF64(float64(node.U64()), val)
- case KSint:
- ctx.efacePool.ConvF64(float64(node.I64()), val)
- case KReal:
- ctx.efacePool.ConvF64(node.F64(), val)
- case KRawNumber:
- ctx.efacePool.ConvTnum(node.Number(ctx), val)
- default:
- panic("unreachable for as eface")
- }
-
- // check size
- size -= 1
- if size != 0 {
- goto _object_key;
- }
- parent, size, isObj = ctx.Stack.Pop()
- // parent is empty
- if parent == nil {
- if isObj {
- return rt.GoEface {
- Type: rt.MapEfaceType,
- Value: rootM,
- }.Pack()
- } else {
- ctx.efacePool.ConvTSlice(rootS, rt.SliceEfaceType, (unsafe.Pointer)(&root))
- return root
- }
- }
- // continue to parse parent
- if isObj {
- mp = parent
- goto _object_key;
- } else {
- val = rt.PtrAdd(parent, rt.AnyType.Size)
- goto _arr_val;
- }
- _arr_val:
- // interface{} slot in slice
- vt = &(*rt.GoEface)(val).Type
- vp = &(*rt.GoEface)(val).Value
- // parse value node
- node = iter.Next()
- switch node.Type() {
- case KObject:
- newSize := node.Object().Len()
- newMp := ctx.efacePool.GetMap(newSize)
- *vt = rt.MapEfaceType
- *vp = newMp
- remain := size - 1
- if newSize != 0 {
- // push next array elem into stack
- if remain > 0 {
- ctx.Stack.Push(val, remain, false)
- }
- mp = newMp
- size = newSize
- isObj = true
- goto _object_key;
- }
- case KArray:
- newSize := node.Array().Len()
- if newSize == 0 {
- ctx.efacePool.ConvTSlice(rt.EmptySlice, rt.SliceEfaceType, val)
- break;
- }
-
- newSp := ctx.efacePool.GetSlice(newSize)
- // pack to []interface{}
- ctx.efacePool.ConvTSlice(rt.GoSlice {
- Ptr: newSp,
- Len: newSize,
- Cap: newSize,
- }, rt.SliceEfaceType, val)
- remain := size - 1
- if remain > 0 {
- ctx.Stack.Push(val, remain, false)
- }
- val = newSp
- isObj = false
- size = newSize
- goto _arr_val;
- case KStringCommon:
- ctx.efacePool.ConvTstring(node.StringRef(ctx), val)
- case KStringEscaped:
- ctx.efacePool.ConvTstring(node.StringCopyEsc(ctx), val)
- case KTrue:
- rt.ConvTBool(true, (*interface{})(val))
- case KFalse:
- rt.ConvTBool(false, (*interface{})(val))
- case KNull: /* skip */
- case KUint:
- ctx.efacePool.ConvF64(float64(node.U64()), val)
- case KSint:
- ctx.efacePool.ConvF64(float64(node.I64()), val)
- case KReal:
- ctx.efacePool.ConvF64(node.F64(), val)
- case KRawNumber:
- ctx.efacePool.ConvTnum(node.Number(ctx), val)
- default: panic("unreachable for as eface")
- }
- // check size
- size -= 1
- if size != 0 {
- val = rt.PtrAdd(val, rt.AnyType.Size)
- goto _arr_val;
- }
- parent, size, isObj = ctx.Stack.Pop()
- // parent is empty
- if parent == nil {
- if isObj {
- return rt.GoEface {
- Type: rt.MapEfaceType,
- Value: rootM,
- }.Pack()
- } else {
- ctx.efacePool.ConvTSlice(rootS, rt.SliceEfaceType, unsafe.Pointer(&root))
- return root
- }
- }
- // continue to parse parent
- if isObj {
- mp = parent
- goto _object_key;
- } else {
- val = rt.PtrAdd(parent, rt.AnyType.Size)
- goto _arr_val;
- }
- }
- func (node *Node) AsEfaceFallback(ctx *Context) (interface{}, error) {
- switch node.Type() {
- case KObject:
- obj := node.Object()
- size := obj.Len()
- m := make(map[string]interface{}, size)
- *node = NewNode(obj.Children())
- var gerr, err error
- for i := 0; i < size; i++ {
- key, _ := node.AsStr(ctx)
- *node = NewNode(PtrOffset(node.cptr, 1))
- m[key], err = node.AsEfaceFallback(ctx)
- if gerr == nil && err != nil {
- gerr = err
- }
- }
- return m, gerr
- case KArray:
- arr := node.Array()
- size := arr.Len()
- a := make([]interface{}, size)
- *node = NewNode(arr.Children())
- var gerr, err error
- for i := 0; i < size; i++ {
- a[i], err = node.AsEfaceFallback(ctx)
- if gerr == nil && err != nil {
- gerr = err
- }
- }
- return a, gerr
- case KStringCommon:
- str, _ := node.AsStr(ctx)
- *node = NewNode(PtrOffset(node.cptr, 1))
- return str, nil
- case KStringEscaped:
- str := node.StringCopyEsc(ctx)
- *node = NewNode(PtrOffset(node.cptr, 1))
- return str, nil
- case KTrue:
- *node = NewNode(PtrOffset(node.cptr, 1))
- return true, nil
- case KFalse:
- *node = NewNode(PtrOffset(node.cptr, 1))
- return false, nil
- case KNull:
- *node = NewNode(PtrOffset(node.cptr, 1))
- return nil, nil
- default:
- // use float64
- if ctx.Parser.options & (1 << _F_use_number) != 0 {
- num, ok := node.AsNumber(ctx)
- if !ok {
- // skip the unmacthed type
- *node = NewNode(node.Next())
- return nil, newUnmatched(node.Position(), rt.JsonNumberType)
- } else {
- *node = NewNode(PtrOffset(node.cptr, 1))
- return num, nil
- }
- } else if ctx.Parser.options & (1 << _F_use_int64) != 0 {
- // first try int64
- i, ok := node.AsI64(ctx)
- if ok {
- *node = NewNode(PtrOffset(node.cptr, 1))
- return i, nil
- }
- // is not integer, then use float64
- f, ok := node.AsF64(ctx)
- if ok {
- *node = NewNode(PtrOffset(node.cptr, 1))
- return f, nil
- }
-
- // skip the unmacthed type
- *node = NewNode(node.Next())
- return nil, newUnmatched(node.Position(), rt.Int64Type)
- } else {
- num, ok := node.AsF64(ctx)
- if !ok {
- // skip the unmacthed type
- *node = NewNode(node.Next())
- return nil, newUnmatched(node.Position(), rt.Float64Type)
- } else {
- *node = NewNode(PtrOffset(node.cptr, 1))
- return num, nil
- }
- }
- }
- }
- //go:nosplit
- func PtrOffset(ptr uintptr, off int64) uintptr {
- return uintptr(int64(ptr) + off * int64(unsafe.Sizeof(node{})))
- }
|