From 3135e275a7df0376951b5a7cda0783d08983ed9e Mon Sep 17 00:00:00 2001 From: "liuqiang.06" Date: Tue, 30 Jan 2024 13:16:09 +0800 Subject: [PATCH] feat: support copy string --- dev/decoder/context.go | 2 - dev/decoder/interface.go | 4 +- dev/decoder/map.go | 20 ++++----- dev/decoder/slice.go | 4 +- dev/decoder/stringopts.go | 92 ++++++++------------------------------- dev/decoder/structs.go | 4 +- dev/dev.go | 18 -------- dev/internal/const.go | 7 +++ dev/internal/sonic_rs.go | 47 ++++++++++++++++---- 9 files changed, 80 insertions(+), 118 deletions(-) diff --git a/dev/decoder/context.go b/dev/decoder/context.go index 27d890c95..32dc7bde5 100644 --- a/dev/decoder/context.go +++ b/dev/decoder/context.go @@ -6,7 +6,6 @@ import ( type context struct { internal.Context - options Options } func newCtx(s string, opt Options) (context, error) { @@ -17,6 +16,5 @@ func newCtx(s string, opt Options) (context, error) { return context{ Context: ctx, - options: opt, }, nil } diff --git a/dev/decoder/interface.go b/dev/decoder/interface.go index 8de60cd64..8c2d37ed4 100644 --- a/dev/decoder/interface.go +++ b/dev/decoder/interface.go @@ -26,9 +26,9 @@ func (d *efaceDecoder) FromDom(vp unsafe.Pointer, node internal.Node, ctx *conte var ret interface{} var err error - if ctx.options&OptionUseNumber == 0 && ctx.options&OptionUseInt64 == 0 { + if Options(ctx.Options)&OptionUseNumber == 0 && Options(ctx.Options)&OptionUseInt64 == 0 { ret, err = node.AsEface(&ctx.Context) - } else if ctx.options&OptionUseNumber != 0 { + } else if Options(ctx.Options)&OptionUseNumber != 0 { ret, err = node.AsEfaceUseNumber(&ctx.Context) } else { ret, err = node.AsEfaceUseInt64(&ctx.Context) diff --git a/dev/decoder/map.go b/dev/decoder/map.go index 28d3a060e..540333520 100644 --- a/dev/decoder/map.go +++ b/dev/decoder/map.go @@ -22,11 +22,11 @@ func (d *mapEfaceDecoder) FromDom(vp unsafe.Pointer, node internal.Node, ctx *co return nil } - if ctx.options&OptionUseNumber == 0 && ctx.options&OptionUseInt64 == 0 { + if Options(ctx.Options)&OptionUseNumber == 0 && Options(ctx.Options)&OptionUseInt64 == 0 { return node.AsMapEface(&ctx.Context, vp) } - if ctx.options&OptionUseNumber != 0 { + if Options(ctx.Options)&OptionUseNumber != 0 { return node.AsMapEfaceUseNumber(&ctx.Context, vp) } return node.AsMapEfaceUseInt64(&ctx.Context, vp) @@ -160,7 +160,7 @@ func (d *mapI32KeyFastDecoder) FromDom(vp unsafe.Pointer, node internal.Node, ct next := obj.Children() for i := 0; i < obj.Len(); i++ { keyn := internal.NewNode(next) - k, err := keyn.AsKeyI64(&ctx.Context) + k, err := keyn.ParseI64(&ctx.Context) if k > math.MaxInt32 || k < math.MinInt32 { return error_value(keyn.AsRaw(&ctx.Context), d.mapType.Key.Pack()) } @@ -210,7 +210,7 @@ func (d *mapI32KeyStdDecoder) FromDom(vp unsafe.Pointer, node internal.Node, ctx next := obj.Children() for i := 0; i < obj.Len(); i++ { keyn := internal.NewNode(next) - k, err := keyn.AsKeyI64(&ctx.Context) + k, err := keyn.ParseI64(&ctx.Context) if k > math.MaxInt32 || k < math.MinInt32 { return error_value(keyn.AsRaw(&ctx.Context), d.mapType.Key.Pack()) } @@ -258,7 +258,7 @@ func (d *mapI64KeyFastDecoder) FromDom(vp unsafe.Pointer, node internal.Node, ct next := obj.Children() for i := 0; i < obj.Len(); i++ { keyn := internal.NewNode(next) - key, err := keyn.AsKeyI64(&ctx.Context) + key, err := keyn.ParseI64(&ctx.Context) ku64 := *(*uint64)(unsafe.Pointer(&key)) if err != nil { return err @@ -302,7 +302,7 @@ func (d *mapI64KeyStdDecoder) FromDom(vp unsafe.Pointer, node internal.Node, ctx next := obj.Children() for i := 0; i < obj.Len(); i++ { keyn := internal.NewNode(next) - key, err := keyn.AsKeyI64(&ctx.Context) + key, err := keyn.ParseI64(&ctx.Context) if err != nil { return err } @@ -347,7 +347,7 @@ func (d *mapU32KeyFastDecoder) FromDom(vp unsafe.Pointer, node internal.Node, ct next := obj.Children() for i := 0; i < obj.Len(); i++ { keyn := internal.NewNode(next) - k, err := keyn.AsKeyU64(&ctx.Context) + k, err := keyn.ParseU64(&ctx.Context) if k > math.MaxUint32 { return error_value(keyn.AsRaw(&ctx.Context), d.mapType.Key.Pack()) } @@ -394,7 +394,7 @@ func (d *mapU32KeyStdDecoder) FromDom(vp unsafe.Pointer, node internal.Node, ctx next := obj.Children() for i := 0; i < obj.Len(); i++ { keyn := internal.NewNode(next) - k, err := keyn.AsKeyU64(&ctx.Context) + k, err := keyn.ParseU64(&ctx.Context) if k > math.MaxUint32 { return error_value(keyn.AsRaw(&ctx.Context), d.mapType.Key.Pack()) } @@ -442,7 +442,7 @@ func (d *mapU64KeyFastDecoder) FromDom(vp unsafe.Pointer, node internal.Node, ct next := obj.Children() for i := 0; i < obj.Len(); i++ { - key, err := internal.NewNode(next).AsKeyU64(&ctx.Context) + key, err := internal.NewNode(next).ParseU64(&ctx.Context) if err != nil { return err } @@ -485,7 +485,7 @@ func (d *mapU64KeyStdDecoder) FromDom(vp unsafe.Pointer, node internal.Node, ctx next := obj.Children() for i := 0; i < obj.Len(); i++ { keyn := internal.NewNode(next) - key, err := keyn.AsKeyU64(&ctx.Context) + key, err := keyn.ParseU64(&ctx.Context) if err != nil { return err } diff --git a/dev/decoder/slice.go b/dev/decoder/slice.go index cca3211a7..7362f4323 100644 --- a/dev/decoder/slice.go +++ b/dev/decoder/slice.go @@ -89,11 +89,11 @@ func (d *sliceEfaceDecoder) FromDom(vp unsafe.Pointer, node internal.Node, ctx * return nil } - if ctx.options&OptionUseNumber == 0 && ctx.options&OptionUseInt64 == 0 { + if Options(ctx.Options)&OptionUseNumber == 0 && Options(ctx.Options)&OptionUseInt64 == 0 { return node.AsSliceEface(&ctx.Context, vp) } - if ctx.options&OptionUseNumber != 0 { + if Options(ctx.Options)&OptionUseNumber != 0 { return node.AsSliceEfaceUseNumber(&ctx.Context, vp) } diff --git a/dev/decoder/stringopts.go b/dev/decoder/stringopts.go index cb4a53c0b..509a2cd17 100644 --- a/dev/decoder/stringopts.go +++ b/dev/decoder/stringopts.go @@ -16,12 +16,7 @@ func (d *boolStringDecoder) FromDom(vp unsafe.Pointer, node internal.Node, ctx * return nil } - s, err := node.AsStr(&ctx.Context) - if err != nil { - return err - } - - b, err := internal.ParseBool(s) + b, err := node.ParseBool(&ctx.Context) if err != nil { return err } @@ -36,18 +31,13 @@ func (d *i8StringDecoder) FromDom(vp unsafe.Pointer, node internal.Node, ctx *co return nil } - s, err := node.AsStr(&ctx.Context) - if err != nil { - return err - } - - ret, err := internal.ParseI64(s) + ret, err := node.ParseI64(&ctx.Context) if err != nil { return err } if ret > math.MaxInt8 || ret < math.MinInt8 { - return error_value(s, int8Type) + return error_value(node.AsRaw(&ctx.Context), int8Type) } *(*int8)(vp) = int8(ret) @@ -61,18 +51,13 @@ func (d *i16StringDecoder) FromDom(vp unsafe.Pointer, node internal.Node, ctx *c return nil } - s, err := node.AsStr(&ctx.Context) - if err != nil { - return err - } - - ret, err := internal.ParseI64(s) + ret, err := node.ParseI64(&ctx.Context) if err != nil { return err } if ret > math.MaxInt16 || ret < math.MinInt16 { - return error_value(s, int16Type) + return error_value(node.AsRaw(&ctx.Context), int16Type) } *(*int16)(vp) = int16(ret) @@ -86,18 +71,13 @@ func (d *i32StringDecoder) FromDom(vp unsafe.Pointer, node internal.Node, ctx *c return nil } - s, err := node.AsStr(&ctx.Context) - if err != nil { - return err - } - - ret, err := internal.ParseI64(s) + ret, err := node.ParseI64(&ctx.Context) if err != nil { return err } if ret > math.MaxInt32 || ret < math.MinInt32 { - return error_value(s, int32Type) + return error_value(node.AsRaw(&ctx.Context), int32Type) } *(*int32)(vp) = int32(ret) @@ -111,12 +91,7 @@ func (d *i64StringDecoder) FromDom(vp unsafe.Pointer, node internal.Node, ctx *c return nil } - s, err := node.AsStr(&ctx.Context) - if err != nil { - return err - } - - ret, err := internal.ParseI64(s) + ret, err := node.ParseI64(&ctx.Context) if err != nil { return err } @@ -132,18 +107,13 @@ func (d *u8StringDecoder) FromDom(vp unsafe.Pointer, node internal.Node, ctx *co return nil } - s, err := node.AsStr(&ctx.Context) - if err != nil { - return err - } - - ret, err := internal.ParseU64(s) + ret, err := node.ParseU64(&ctx.Context) if err != nil { return err } if ret > math.MaxUint8 { - return error_value(s, uint8Type) + return error_value(node.AsRaw(&ctx.Context), uint8Type) } *(*uint8)(vp) = uint8(ret) @@ -157,18 +127,13 @@ func (d *u16StringDecoder) FromDom(vp unsafe.Pointer, node internal.Node, ctx *c return nil } - s, err := node.AsStr(&ctx.Context) - if err != nil { - return err - } - - ret, err := internal.ParseU64(s) + ret, err := node.ParseU64(&ctx.Context) if err != nil { return err } if ret > math.MaxUint16 { - return error_value(s, uint16Type) + return error_value(node.AsRaw(&ctx.Context), uint16Type) } *(*uint16)(vp) = uint16(ret) @@ -182,18 +147,13 @@ func (d *u32StringDecoder) FromDom(vp unsafe.Pointer, node internal.Node, ctx *c return nil } - s, err := node.AsStr(&ctx.Context) - if err != nil { - return err - } - - ret, err := internal.ParseU64(s) + ret, err := node.ParseU64(&ctx.Context) if err != nil { return err } if ret > math.MaxUint32 { - return error_value(s, uint32Type) + return error_value(node.AsRaw(&ctx.Context), uint32Type) } *(*uint32)(vp) = uint32(ret) @@ -207,15 +167,11 @@ func (d *u64StringDecoder) FromDom(vp unsafe.Pointer, node internal.Node, ctx *c return nil } - s, err := node.AsStr(&ctx.Context) + ret, err := node.ParseU64(&ctx.Context) if err != nil { return err } - ret, err := internal.ParseU64(s) - if err != nil { - return err - } *(*uint64)(vp) = uint64(ret) return nil } @@ -227,18 +183,13 @@ func (d *f32StringDecoder) FromDom(vp unsafe.Pointer, node internal.Node, ctx *c return nil } - s, err := node.AsStr(&ctx.Context) - if err != nil { - return err - } - - ret, err := internal.ParseF64(s) + ret, err := node.ParseF64(&ctx.Context) if err != nil { return err } if ret > math.MaxFloat32 || ret < -math.MaxFloat32 { - return error_value(s, float32Type) + return error_value(node.AsRaw(&ctx.Context), float32Type) } *(*float32)(vp) = float32(ret) @@ -252,12 +203,7 @@ func (d *f64StringDecoder) FromDom(vp unsafe.Pointer, node internal.Node, ctx *c return nil } - s, err := node.AsStr(&ctx.Context) - if err != nil { - return err - } - - ret, err := internal.ParseF64(s) + ret, err := node.ParseF64(&ctx.Context) if err != nil { return err } @@ -274,7 +220,7 @@ func (d *strStringDecoder) FromDom(vp unsafe.Pointer, node internal.Node, ctx *c return nil } - s, err := node.AsStr(&ctx.Context) + s, err := node.AsStrRef(&ctx.Context) /* deal with empty string */ if err != nil || s == "" { return err diff --git a/dev/decoder/structs.go b/dev/decoder/structs.go index 191121f39..76de85396 100644 --- a/dev/decoder/structs.go +++ b/dev/decoder/structs.go @@ -32,7 +32,7 @@ func (d *structDecoder) FromDom(vp unsafe.Pointer, node internal.Node, ctx *cont next := obj.Children() for i := 0; i < obj.Len(); i++ { - key, err := internal.NewNode(next).AsStr(&ctx.Context) + key, err := internal.NewNode(next).AsStrRef(&ctx.Context) val := internal.NewNode(internal.PtrOffset(next, 1)) next = val.Next() if err != nil { @@ -47,7 +47,7 @@ func (d *structDecoder) FromDom(vp unsafe.Pointer, node internal.Node, ctx *cont idx = d.fieldMap.GetCaseInsensitive(key) } if idx == -1 { - if ctx.options&OptionDisableUnknown != 0 { + if Options(ctx.Options)&OptionDisableUnknown != 0 { return error_field(key) } continue diff --git a/dev/dev.go b/dev/dev.go index 737bad8ab..0604164e0 100644 --- a/dev/dev.go +++ b/dev/dev.go @@ -5,24 +5,6 @@ import ( "github.com/bytedance/sonic/dev/decoder" ) -// func UnmarshalString_Bak(json string, val interface{}) error { -// ctx, err := internal.NewContext(json) -// if err != nil { -// return err -// } - -// node := ctx.Dom.Root() -// ret, err := node.AsIface(&ctx) -// if err != nil { -// return err -// } - -// rv := reflect.ValueOf(val) -// rv.Elem().Set(reflect.ValueOf(ret)) -// ctx.Delete() -// return nil -// } - func UnmarshalString(json string, val interface{}) error { dec := decoder.NewDecoder(json) err := dec.Decode(val) diff --git a/dev/internal/const.go b/dev/internal/const.go index 577b7de90..bffc4c664 100644 --- a/dev/internal/const.go +++ b/dev/internal/const.go @@ -58,3 +58,10 @@ const ( ConLenMask = uint64(math.MaxUint32) ConLenBits = 32 ) + +const ( + _F_use_int64 = 0 + _F_disable_urc = 2 + _F_disable_unknown = 3 + _F_copy_string = 4 +) diff --git a/dev/internal/sonic_rs.go b/dev/internal/sonic_rs.go index 8c71b8a75..69f636820 100644 --- a/dev/internal/sonic_rs.go +++ b/dev/internal/sonic_rs.go @@ -17,7 +17,7 @@ import ( ) type Context struct { - Cur **C.Node + Options uint64 Json string Start uintptr Dom Dom @@ -29,7 +29,7 @@ func NewContext(json string, opts uint64) (Context, error) { return Context{}, err } return Context{ - Cur: nil, + Options: opts, Json: json, Start: dom.StrStart(), Dom: dom, @@ -205,8 +205,8 @@ func (val Node) AsI64() (int64, error) { return 0, newUnmatched("expect int64") } -func (val Node) AsKeyI64(ctx *Context) (int64, error) { - s, err := val.AsStr(ctx) +func (val Node) ParseI64(ctx *Context) (int64, error) { + s, err := val.AsStrRef(ctx) if err != nil { return 0, err } @@ -218,8 +218,21 @@ func (val Node) AsKeyI64(ctx *Context) (int64, error) { return i, nil } -func (val Node) AsKeyU64(ctx *Context) (uint64, error) { - s, err := val.AsStr(ctx) +func (val Node) ParseBool(ctx *Context) (bool, error) { + s, err := val.AsStrRef(ctx) + if err != nil { + return false, err + } + + b, err := ParseBool(s) + if err != nil { + return false, err + } + return b, nil +} + +func (val Node) ParseU64(ctx *Context) (uint64, error) { + s, err := val.AsStrRef(ctx) if err != nil { return 0, err } @@ -231,8 +244,8 @@ func (val Node) AsKeyU64(ctx *Context) (uint64, error) { return i, nil } -func (val Node) AsKeyF64(ctx *Context) (float64, error) { - s, err := val.AsStr(ctx) +func (val Node) ParseF64(ctx *Context) (float64, error) { + s, err := val.AsStrRef(ctx) if err != nil { return 0, err } @@ -268,6 +281,22 @@ func (val Node) AsBool() (bool, error) { } func (val Node) AsStr(ctx *Context) (string, error) { + if ctx.Options & (1 << _F_copy_string) != 0 { + return val.StringCopy(), nil + } + + switch val.Type() { + case KStringHasEscaped: + return val.StringCopy(), nil + case KStringCommon: + return val.String(ctx), nil + default: + return "", newUnmatched("expect string") + } +} + + +func (val Node) AsStrRef(ctx *Context) (string, error) { switch val.Type() { case KStringHasEscaped: return val.StringCopy(), nil @@ -746,7 +775,7 @@ func (node *Node) AsSliceString(ctx *Context, vp unsafe.Pointer) error { } func (node *Node) AsSliceBytes(ctx *Context) ([]byte, error) { - s, err := node.AsStr(ctx) + s, err := node.AsStrRef(ctx) if err != nil { return nil, err }