上传codec 编码系统代码

This commit is contained in:
liwei1dao 2022-07-11 15:54:54 +08:00
parent 83dd0f905f
commit 906afe87d0
19 changed files with 4364 additions and 0 deletions

180
lego/sys/codec/codec.go Normal file
View File

@ -0,0 +1,180 @@
package codec
import (
"sync"
"go_dreamfactory/lego/sys/codec/core"
"go_dreamfactory/lego/sys/codec/extractor"
"go_dreamfactory/lego/sys/codec/factory"
"go_dreamfactory/lego/sys/codec/stream"
"github.com/modern-go/reflect2"
)
func newSys(options core.Options) (sys *codec, err error) {
sys = &codec{
options: &options,
decoderCache: new(sync.Map),
encoderCache: new(sync.Map),
streamPool: &sync.Pool{
New: func() interface{} {
return stream.NewStream(sys, 512)
},
},
extraPool: &sync.Pool{
New: func() interface{} {
return extractor.NewExtractor(sys)
},
},
}
return
}
type codec struct {
options *core.Options
decoderCache *sync.Map
encoderCache *sync.Map
streamPool *sync.Pool
extraPool *sync.Pool
}
func (this *codec) Options() *core.Options {
return this.options
}
//序列化Josn
func (this *codec) MarshalJson(val interface{}, option ...core.ExecuteOption) (buf []byte, err error) {
stream := this.BorrowStream()
defer this.ReturnStream(stream)
stream.WriteVal(val)
if stream.Error() != nil {
return nil, stream.Error()
}
result := stream.Buffer()
copied := make([]byte, len(result))
copy(copied, result)
return copied, nil
}
func (this *codec) UnmarshalJson(data []byte, v interface{}) error {
extra := this.BorrowExtractor(data)
defer this.ReturnExtractor(extra)
extra.ReadVal(v)
return extra.Error()
}
func (this *codec) addDecoderToCache(cacheKey uintptr, decoder core.IDecoder) {
this.decoderCache.Store(cacheKey, decoder)
}
func (this *codec) addEncoderToCache(cacheKey uintptr, encoder core.IEncoder) {
this.encoderCache.Store(cacheKey, encoder)
}
func (this *codec) GetEncoderFromCache(cacheKey uintptr) core.IEncoder {
encoder, found := this.encoderCache.Load(cacheKey)
if found {
return encoder.(core.IEncoder)
}
return nil
}
func (this *codec) GetDecoderFromCache(cacheKey uintptr) core.IDecoder {
decoder, found := this.decoderCache.Load(cacheKey)
if found {
return decoder.(core.IDecoder)
}
return nil
}
func (this *codec) EncoderOf(typ reflect2.Type) core.IEncoder {
cacheKey := typ.RType()
encoder := this.GetEncoderFromCache(cacheKey)
if encoder != nil {
return encoder
}
ctx := &core.Ctx{
ICodec: this,
Prefix: "",
Decoders: map[reflect2.Type]core.IDecoder{},
Encoders: map[reflect2.Type]core.IEncoder{},
}
encoder = factory.EncoderOfType(ctx, typ)
if typ.LikePtr() {
encoder = factory.NewonePtrEncoder(encoder)
}
this.addEncoderToCache(cacheKey, encoder)
return encoder
}
func (this *codec) DecoderOf(typ reflect2.Type) core.IDecoder {
cacheKey := typ.RType()
decoder := this.GetDecoderFromCache(cacheKey)
if decoder != nil {
return decoder
}
ctx := &core.Ctx{
ICodec: this,
Prefix: "",
Decoders: map[reflect2.Type]core.IDecoder{},
Encoders: map[reflect2.Type]core.IEncoder{},
}
ptrType := typ.(*reflect2.UnsafePtrType)
decoder = factory.DecoderOfType(ctx, ptrType.Elem())
this.addDecoderToCache(cacheKey, decoder)
return decoder
}
func (this *codec) BorrowStream() core.IStream {
stream := this.streamPool.Get().(core.IStream)
return stream
}
func (this *codec) ReturnStream(stream core.IStream) {
this.streamPool.Put(stream)
}
func (this *codec) BorrowExtractor(buf []byte) core.IExtractor {
extra := this.extraPool.Get().(core.IExtractor)
extra.ResetBytes(buf)
return extra
}
func (this *codec) ReturnExtractor(extra core.IExtractor) {
this.extraPool.Put(extra)
}
///日志***********************************************************************
func (this *codec) Debug() bool {
return this.options.Debug
}
func (this *codec) Debugf(format string, a ...interface{}) {
if this.options.Debug {
this.options.Log.Debugf("[SYS Gin] "+format, a...)
}
}
func (this *codec) Infof(format string, a ...interface{}) {
if this.options.Debug {
this.options.Log.Infof("[SYS Gin] "+format, a...)
}
}
func (this *codec) Warnf(format string, a ...interface{}) {
if this.options.Debug {
this.options.Log.Warnf("[SYS Gin] "+format, a...)
}
}
func (this *codec) Errorf(format string, a ...interface{}) {
if this.options.Debug {
this.options.Log.Errorf("[SYS Gin] "+format, a...)
}
}
func (this *codec) Panicf(format string, a ...interface{}) {
if this.options.Debug {
this.options.Log.Panicf("[SYS Gin] "+format, a...)
}
}
func (this *codec) Fatalf(format string, a ...interface{}) {
if this.options.Debug {
this.options.Log.Fatalf("[SYS Gin] "+format, a...)
}
}

24
lego/sys/codec/core.go Normal file
View File

@ -0,0 +1,24 @@
package codec
import (
"go_dreamfactory/lego/sys/codec/core"
)
type (
ISys interface {
MarshalJson(v interface{}, option ...core.ExecuteOption) ([]byte, error)
UnmarshalJson(data []byte, v interface{}) error
}
)
var defsys ISys
func OnInit(config map[string]interface{}, option ...core.Option) (err error) {
defsys, err = newSys(newOptions(config, option...))
return
}
func NewSys(option ...core.Option) (sys ISys, err error) {
sys, err = newSys(newOptionsByOption(option...))
return
}

146
lego/sys/codec/core/core.go Normal file
View File

@ -0,0 +1,146 @@
package core
import (
"unsafe"
"github.com/modern-go/reflect2"
)
//数据类型
type CodecType int8
const (
Json CodecType = iota //json 格式数据
Bytes //byte 字节流数据
Proto //proto google protobuff 数据
)
//结构值类型
type ValueType int
const (
// InvalidValue invalid JSON element
InvalidValue ValueType = iota
// StringValue JSON element "string"
StringValue
// NumberValue JSON element 100 or 0.10
NumberValue
// NilValue JSON element null
NilValue
// BoolValue JSON element true or false
BoolValue
// ArrayValue JSON element []
ArrayValue
// ObjectValue JSON element {}
ObjectValue
)
type (
ICodec interface {
Options() *Options
GetEncoderFromCache(cacheKey uintptr) IEncoder
GetDecoderFromCache(cacheKey uintptr) IDecoder
EncoderOf(typ reflect2.Type) IEncoder
DecoderOf(typ reflect2.Type) IDecoder
BorrowExtractor(buf []byte) IExtractor //借 提取器
ReturnExtractor(extra IExtractor) //还 提取器
BorrowStream() IStream //借 输出对象
ReturnStream(stream IStream) //换 输出对象
}
IExtractor interface {
ReadVal(obj interface{}) //读取指定类型对象
WhatIsNext() ValueType
Read() interface{}
ReadNil() (ret bool) //读取空 null
ReadArrayStart() (ret bool) //读数组开始 [
CheckNextIsArrayEnd() (ret bool) //下一个是否是数组结束符 不影响数据游标位置
ReadArrayEnd() (ret bool) //读数组结束 ]
ReadObjectStart() (ret bool) //读对象或Map开始 {
CheckNextIsObjectEnd() (ret bool) //下一个是否是数对象结束符 不影响数据游标位置
ReadObjectEnd() (ret bool) //读对象或Map结束 }
ReadMemberSplit() (ret bool) //读成员分割符 ,
ReadKVSplit() (ret bool) //读取key value 分割符 :
ReadKeyStart() (ret bool) //读取字段名 开始
ReadKeyEnd() (ret bool) //读取字段名 结束
Skip() //跳过一个数据单元 容错处理
ReadBool() (ret bool)
ReadInt8() (ret int8)
ReadInt16() (ret int16)
ReadInt32() (ret int32)
ReadInt64() (ret int64)
ReadUint8() (ret uint8)
ReadUint16() (ret uint16)
ReadUint32() (ret uint32)
ReadUint64() (ret uint64)
ReadFloat32() (ret float32)
ReadFloat64() (ret float64)
ReadString() (ret string)
ResetBytes(d []byte)
Error() error
SetErr(err error)
}
IStream interface {
WriteVal(val interface{}) //写入一个对象
WriteNil() //写空 null
WriteEmptyArray() //写空数组 []
WriteArrayStart() //写数组开始 [
WriteArrayEnd() //写数组结束 ]
WriteEmptyObject() //写空对象 {}
WriteObjectStart() //写对象或Map开始 {
WriteObjectEnd() //写对象或Map结束 }
WriteMemberSplit() //写成员分割符 ,
WriteKVSplit() //写key value 分割符 :
WriteKeyStart() //写入字段名 开始
WriteKeyEnd() //写入字段名 结束
WriteObjectFieldName(val string) //写入对象字段名
WriteBool(val bool)
WriteInt8(val int8)
WriteInt16(val int16)
WriteInt32(val int32)
WriteInt64(val int64)
WriteUint8(val uint8)
WriteUint16(val uint16)
WriteUint32(val uint32)
WriteUint64(val uint64)
WriteFloat32(val float32)
WriteFloat64(val float64)
WriteString(val string)
WriteBytes(val []byte)
Buffer() []byte //返回缓存区数据
Error() error
SetErr(err error)
}
//编码器
IEncoder interface {
IsEmpty(ptr unsafe.Pointer) bool
Encode(ptr unsafe.Pointer, stream IStream)
}
//解码器
IDecoder interface {
Decode(ptr unsafe.Pointer, extra IExtractor)
}
//空校验
CheckIsEmpty interface {
IsEmpty(ptr unsafe.Pointer) bool
}
//内嵌指针是否是空
IsEmbeddedPtrNil interface {
IsEmbeddedPtrNil(ptr unsafe.Pointer) bool
}
)
type Ctx struct {
ICodec
Prefix string
Encoders map[reflect2.Type]IEncoder
Decoders map[reflect2.Type]IDecoder
}
func (this *Ctx) Append(prefix string) *Ctx {
return &Ctx{
ICodec: this.ICodec,
Prefix: this.Prefix + " " + prefix,
Encoders: this.Encoders,
Decoders: this.Decoders,
}
}

View File

@ -0,0 +1,30 @@
package core
import (
"go_dreamfactory/lego/sys/log"
)
type Option func(*Options)
type Options struct {
IndentionStep int //缩进步骤
ObjectFieldMustBeSimpleString bool //对象字段必须是简单字符串
OnlyTaggedField bool //仅仅处理标签字段
DisallowUnknownFields bool //禁止未知字段
CaseSensitive bool //是否区分大小写
TagKey string //标签
Debug bool //日志是否开启
Log log.ILog
}
//执行选项
type ExecuteOption func(*ExecuteOptions)
type ExecuteOptions struct {
}
func NewExecuteOptions(opts ...ExecuteOption) ExecuteOptions {
options := ExecuteOptions{}
for _, o := range opts {
o(&options)
}
return options
}

View File

@ -0,0 +1,866 @@
package extractor
import (
"fmt"
"go_dreamfactory/lego/sys/codec/core"
"go_dreamfactory/lego/sys/codec/utils"
"io"
"math/big"
"reflect"
"unicode/utf16"
"github.com/modern-go/reflect2"
)
const maxDepth = 10000
var hexDigits []byte
var valueTypes []core.ValueType
func init() {
hexDigits = make([]byte, 256)
for i := 0; i < len(hexDigits); i++ {
hexDigits[i] = 255
}
for i := '0'; i <= '9'; i++ {
hexDigits[i] = byte(i - '0')
}
for i := 'a'; i <= 'f'; i++ {
hexDigits[i] = byte((i - 'a') + 10)
}
for i := 'A'; i <= 'F'; i++ {
hexDigits[i] = byte((i - 'A') + 10)
}
valueTypes = make([]core.ValueType, 256)
for i := 0; i < len(valueTypes); i++ {
valueTypes[i] = core.InvalidValue
}
valueTypes['"'] = core.StringValue
valueTypes['-'] = core.NumberValue
valueTypes['0'] = core.NumberValue
valueTypes['1'] = core.NumberValue
valueTypes['2'] = core.NumberValue
valueTypes['3'] = core.NumberValue
valueTypes['4'] = core.NumberValue
valueTypes['5'] = core.NumberValue
valueTypes['6'] = core.NumberValue
valueTypes['7'] = core.NumberValue
valueTypes['8'] = core.NumberValue
valueTypes['9'] = core.NumberValue
valueTypes['t'] = core.BoolValue
valueTypes['f'] = core.BoolValue
valueTypes['n'] = core.NilValue
valueTypes['['] = core.ArrayValue
valueTypes['{'] = core.ObjectValue
}
func NewExtractor(codec core.ICodec) *JsonExtractor {
return &JsonExtractor{
codec: codec,
buf: nil,
head: 0,
tail: 0,
depth: 0,
err: nil,
}
}
type JsonExtractor struct {
codec core.ICodec
buf []byte
head int
tail int
depth int
err error
}
func (this *JsonExtractor) ReadVal(obj interface{}) {
depth := this.depth
cacheKey := reflect2.RTypeOf(obj)
decoder := this.codec.GetDecoderFromCache(cacheKey)
if decoder == nil {
typ := reflect2.TypeOf(obj)
if typ == nil || typ.Kind() != reflect.Ptr {
this.reportError("ReadVal", "can only unmarshal into pointer")
return
}
decoder = this.codec.DecoderOf(typ)
}
ptr := reflect2.PtrOf(obj)
if ptr == nil {
this.reportError("ReadVal", "can not read into nil pointer")
return
}
decoder.Decode(ptr, this)
if this.depth != depth {
this.reportError("ReadVal", "unexpected mismatched nesting")
return
}
}
func (this *JsonExtractor) WhatIsNext() core.ValueType {
valueType := valueTypes[this.nextToken()]
this.unreadByte()
return valueType
}
func (this *JsonExtractor) Read() interface{} {
valueType := this.WhatIsNext()
switch valueType {
case core.StringValue:
return this.ReadString()
case core.NumberValue:
return this.ReadFloat64()
case core.NilValue:
this.skipFourBytes('n', 'u', 'l', 'l')
return nil
case core.BoolValue:
return this.ReadBool()
case core.ArrayValue:
arr := []interface{}{}
this.ReadArrayCB(func(extra core.IExtractor) bool {
var elem interface{}
extra.ReadVal(&elem)
arr = append(arr, elem)
return true
})
return arr
case core.ObjectValue:
obj := map[string]interface{}{}
this.ReadMapCB(func(extra core.IExtractor, field string) bool {
var elem interface{}
this.ReadVal(&elem)
obj[field] = elem
return true
})
return obj
default:
this.reportError("Read", fmt.Sprintf("unexpected value type: %v", valueType))
return nil
}
}
func (this *JsonExtractor) ReadNil() (ret bool) {
c := this.nextToken()
if c == 'n' {
this.skipThreeBytes('u', 'l', 'l') // null
return true
}
this.unreadByte()
return false
}
func (this *JsonExtractor) ReadArrayStart() (ret bool) {
c := this.nextToken()
if c == '[' {
return true
}
this.reportError("ReadArrayStart", `expect [ but found `+string([]byte{c}))
return
}
func (this *JsonExtractor) CheckNextIsArrayEnd() (ret bool) {
c := this.nextToken()
this.unreadByte()
if c == ']' {
return true
}
return
}
func (this *JsonExtractor) ReadArrayEnd() (ret bool) {
c := this.nextToken()
if c == ']' {
return true
}
this.reportError("ReadArrayEnd", `expect ] but found `+string([]byte{c}))
return
}
func (this *JsonExtractor) ReadObjectStart() (ret bool) {
c := this.nextToken()
if c == '{' {
return this.incrementDepth()
}
this.reportError("ReadObjectStart", `expect { but found `+string([]byte{c}))
return
}
func (this *JsonExtractor) CheckNextIsObjectEnd() (ret bool) {
c := this.nextToken()
this.unreadByte()
if c == '}' {
return true
}
return
}
func (this *JsonExtractor) ReadObjectEnd() (ret bool) {
c := this.nextToken()
if c == '}' {
return this.decrementDepth()
}
this.reportError("ReadObjectEnd", `expect } but found `+string([]byte{c}))
return
}
func (this *JsonExtractor) ReadMemberSplit() (ret bool) {
c := this.nextToken()
if c == ',' {
return true
}
this.unreadByte()
return
}
func (this *JsonExtractor) ReadKVSplit() (ret bool) {
c := this.nextToken()
if c == ':' {
return true
}
this.reportError("ReadKVSplit", `expect : but found `+string([]byte{c}))
return
}
func (this *JsonExtractor) ReadKeyStart() (ret bool) {
c := this.nextToken()
if c == '"' {
return true
}
this.reportError("ReadKeyStart", `expect " but found `+string([]byte{c}))
return
}
func (this *JsonExtractor) ReadKeyEnd() (ret bool) {
c := this.nextToken()
if c == '"' {
return true
}
this.reportError("ReadKeyEnd", `expect " but found `+string([]byte{c}))
return
}
func (this *JsonExtractor) Skip() {
c := this.nextToken()
switch c {
case '"':
this.skipString()
case 'n':
this.skipThreeBytes('u', 'l', 'l') // null
case 't':
this.skipThreeBytes('r', 'u', 'e') // true
case 'f':
this.skipFourBytes('a', 'l', 's', 'e') // false
case '0':
this.unreadByte()
this.ReadFloat32()
case '-', '1', '2', '3', '4', '5', '6', '7', '8', '9':
this.skipNumber()
case '[':
this.skipArray()
case '{':
this.skipObject()
default:
this.reportError("Skip", fmt.Sprintf("do not know how to skip: %v", c))
return
}
}
func (this *JsonExtractor) ReadBool() (ret bool) {
c := this.nextToken()
if c == 't' {
this.skipThreeBytes('r', 'u', 'e')
return true
}
if c == 'f' {
this.skipFourBytes('a', 'l', 's', 'e')
return false
}
this.reportError("ReadBool", "expect t or f, but found "+string([]byte{c}))
return
}
func (this *JsonExtractor) ReadInt8() (ret int8) {
var (
n int
err error
)
if ret, n, err = utils.ReadInt8ForString(this.buf[this.head:]); err != nil {
this.reportError("ReadInt8", err.Error())
return
}
this.head += n
return
}
func (this *JsonExtractor) ReadInt16() (ret int16) {
var (
n int
err error
)
if ret, n, err = utils.ReadInt16ForString(this.buf[this.head:]); err != nil {
this.reportError("ReadInt32", err.Error())
return
}
this.head += n
return
}
func (this *JsonExtractor) ReadInt32() (ret int32) {
var (
n int
err error
)
if ret, n, err = utils.ReadInt32ForString(this.buf[this.head:]); err != nil {
this.reportError("ReadInt32", err.Error())
return
}
this.head += n
return
}
func (this *JsonExtractor) ReadInt64() (ret int64) {
var (
n int
err error
)
if ret, n, err = utils.ReadInt64ForString(this.buf[this.head:]); err != nil {
this.reportError("ReadInt64", err.Error())
return
}
this.head += n
return
}
func (this *JsonExtractor) ReadUint8() (ret uint8) {
var (
n int
err error
)
if ret, n, err = utils.ReadUint8ForString(this.buf[this.head:]); err != nil {
this.reportError("ReadUint8", err.Error())
return
}
this.head += n
return
}
func (this *JsonExtractor) ReadUint16() (ret uint16) {
var (
n int
err error
)
if ret, n, err = utils.ReadUint16ForString(this.buf[this.head:]); err != nil {
this.reportError("ReadUint16", err.Error())
return
}
this.head += n
return
}
func (this *JsonExtractor) ReadUint32() (ret uint32) {
var (
n int
err error
)
if ret, n, err = utils.ReadUint32ForString(this.buf[this.head:]); err != nil {
this.reportError("ReadUint32", err.Error())
return
}
this.head += n
return
}
func (this *JsonExtractor) ReadUint64() (ret uint64) {
var (
n int
err error
)
if ret, n, err = utils.ReadUint64ForString(this.buf[this.head:]); err != nil {
this.reportError("ReadUint64", err.Error())
return
}
this.head += n
return
}
func (this *JsonExtractor) ReadFloat32() (ret float32) {
var (
n int
err error
)
if ret, n, err = utils.ReadFloat32ForString(this.buf[this.head:]); err != nil {
this.reportError("ReadFloat32", err.Error())
return
}
this.head += n
return
}
func (this *JsonExtractor) ReadFloat64() (ret float64) {
var (
n int
err error
)
if ret, n, err = utils.ReadFloat64ForString(this.buf[this.head:]); err != nil {
this.reportError("ReadFloat64", err.Error())
return
}
this.head += n
return
}
func (this *JsonExtractor) ReadString() (ret string) {
c := this.nextToken()
if c == '"' {
for i := this.head; i < this.tail; i++ {
c := this.buf[i]
if c == '"' {
ret = string(this.buf[this.head:i])
this.head = i + 1
return ret
} else if c == '\\' {
break
} else if c < ' ' {
this.reportError("ReadString",
fmt.Sprintf(`invalid control character found: %d`, c))
return
}
}
return this.readStringSlowPath()
} else if c == 'n' {
this.skipThreeBytes('u', 'l', 'l')
return ""
}
this.reportError("ReadString", `expects " or n, but found `+string([]byte{c}))
return
}
func (this *JsonExtractor) ResetBytes(d []byte) {
this.buf = d
this.head = 0
this.tail = len(d)
}
func (this *JsonExtractor) Error() error {
return this.err
}
func (this *JsonExtractor) SetErr(err error) {
this.err = err
}
//-----------------------------------------------------------------------------------------------------------------------------------
func (this *JsonExtractor) readByte() (ret byte) {
if this.head == this.tail {
return 0
}
ret = this.buf[this.head]
this.head++
return ret
}
func (this *JsonExtractor) readStringSlowPath() (ret string) {
var str []byte
var c byte
for this.err == nil {
c = this.readByte()
if c == '"' {
return string(str)
}
if c == '\\' {
c = this.readByte()
str = this.readEscapedChar(c, str)
} else {
str = append(str, c)
}
}
this.reportError("readStringSlowPath", "unexpected end of input")
return
}
func (this *JsonExtractor) readEscapedChar(c byte, str []byte) []byte {
switch c {
case 'u':
r := this.readU4()
if utf16.IsSurrogate(r) {
c = this.readByte()
if this.err != nil {
return nil
}
if c != '\\' {
this.unreadByte()
str = utils.AppendRune(str, r)
return str
}
c = this.readByte()
if this.err != nil {
return nil
}
if c != 'u' {
str = utils.AppendRune(str, r)
return this.readEscapedChar(c, str)
}
r2 := this.readU4()
if this.err != nil {
return nil
}
combined := utf16.DecodeRune(r, r2)
if combined == '\uFFFD' {
str = utils.AppendRune(str, r)
str = utils.AppendRune(str, r2)
} else {
str = utils.AppendRune(str, combined)
}
} else {
str = utils.AppendRune(str, r)
}
case '"':
str = append(str, '"')
case '\\':
str = append(str, '\\')
case '/':
str = append(str, '/')
case 'b':
str = append(str, '\b')
case 'f':
str = append(str, '\f')
case 'n':
str = append(str, '\n')
case 'r':
str = append(str, '\r')
case 't':
str = append(str, '\t')
default:
this.reportError("readEscapedChar",
`invalid escape char after \`)
return nil
}
return str
}
func (this *JsonExtractor) readU4() (ret rune) {
for i := 0; i < 4; i++ {
c := this.readByte()
if this.err != nil {
return
}
if c >= '0' && c <= '9' {
ret = ret*16 + rune(c-'0')
} else if c >= 'a' && c <= 'f' {
ret = ret*16 + rune(c-'a'+10)
} else if c >= 'A' && c <= 'F' {
ret = ret*16 + rune(c-'A'+10)
} else {
this.reportError("readU4", "expects 0~9 or a~f, but found "+string([]byte{c}))
return
}
}
return ret
}
func (this *JsonExtractor) nextToken() byte {
for i := this.head; i < this.tail; i++ {
c := this.buf[i]
switch c {
case ' ', '\n', '\t', '\r':
continue
}
this.head = i + 1
return c
}
return 0
}
func (this *JsonExtractor) unreadByte() {
if this.err != nil {
return
}
this.head--
return
}
func (this *JsonExtractor) skipNumber() {
if !this.trySkipNumber() {
this.unreadByte()
if this.err != nil && this.err != io.EOF {
return
}
this.ReadFloat64()
if this.err != nil && this.err != io.EOF {
this.err = nil
this.ReadBigFloat()
}
}
}
func (this *JsonExtractor) ReadBigFloat() (ret *big.Float) {
var (
n int
err error
)
if ret, n, err = utils.ReadBigFloatForString(this.buf[this.head:]); err != nil {
this.reportError("ReadBigFloat", err.Error())
return
}
this.head += n
return
}
func (iter *JsonExtractor) trySkipNumber() bool {
dotFound := false
for i := iter.head; i < iter.tail; i++ {
c := iter.buf[i]
switch c {
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
case '.':
if dotFound {
iter.reportError("validateNumber", `more than one dot found in number`)
return true // already failed
}
if i+1 == iter.tail {
return false
}
c = iter.buf[i+1]
switch c {
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
default:
iter.reportError("validateNumber", `missing digit after dot`)
return true // already failed
}
dotFound = true
default:
switch c {
case ',', ']', '}', ' ', '\t', '\n', '\r':
if iter.head == i {
return false // if - without following digits
}
iter.head = i
return true // must be valid
}
return false // may be invalid
}
}
return false
}
func (this *JsonExtractor) skipString() {
if !this.trySkipString() {
this.unreadByte()
this.ReadString()
}
}
func (this *JsonExtractor) trySkipString() bool {
for i := this.head; i < this.tail; i++ {
c := this.buf[i]
if c == '"' {
this.head = i + 1
return true // valid
} else if c == '\\' {
return false
} else if c < ' ' {
this.reportError("trySkipString",
fmt.Sprintf(`invalid control character found: %d`, c))
return true // already failed
}
}
return false
}
func (this *JsonExtractor) skipObject() {
this.unreadByte()
this.ReadObjectCB(func(extra core.IExtractor, field string) bool {
extra.Skip()
return true
})
}
func (this *JsonExtractor) skipArray() {
this.unreadByte()
this.ReadArrayCB(func(extra core.IExtractor) bool {
extra.Skip()
return true
})
}
func (this *JsonExtractor) skipThreeBytes(b1, b2, b3 byte) {
if this.readByte() != b1 {
this.reportError("skipThreeBytes", fmt.Sprintf("expect %s", string([]byte{b1, b2, b3})))
return
}
if this.readByte() != b2 {
this.reportError("skipThreeBytes", fmt.Sprintf("expect %s", string([]byte{b1, b2, b3})))
return
}
if this.readByte() != b3 {
this.reportError("skipThreeBytes", fmt.Sprintf("expect %s", string([]byte{b1, b2, b3})))
return
}
}
func (this *JsonExtractor) skipFourBytes(b1, b2, b3, b4 byte) {
if this.readByte() != b1 {
this.reportError("skipFourBytes", fmt.Sprintf("expect %s", string([]byte{b1, b2, b3, b4})))
return
}
if this.readByte() != b2 {
this.reportError("skipFourBytes", fmt.Sprintf("expect %s", string([]byte{b1, b2, b3, b4})))
return
}
if this.readByte() != b3 {
this.reportError("skipFourBytes", fmt.Sprintf("expect %s", string([]byte{b1, b2, b3, b4})))
return
}
if this.readByte() != b4 {
this.reportError("skipFourBytes", fmt.Sprintf("expect %s", string([]byte{b1, b2, b3, b4})))
return
}
}
func (this *JsonExtractor) reportError(operation string, msg string) {
if this.err != nil {
if this.err != io.EOF {
return
}
}
peekStart := this.head - 10
if peekStart < 0 {
peekStart = 0
}
peekEnd := this.head + 10
if peekEnd > this.tail {
peekEnd = this.tail
}
parsing := string(this.buf[peekStart:peekEnd])
contextStart := this.head - 50
if contextStart < 0 {
contextStart = 0
}
contextEnd := this.head + 50
if contextEnd > this.tail {
contextEnd = this.tail
}
context := string(this.buf[contextStart:contextEnd])
this.err = fmt.Errorf("%s: %s, error found in #%v byte of ...|%s|..., bigger context ...|%s|...",
operation, msg, this.head-peekStart, parsing, context)
}
func (this *JsonExtractor) incrementDepth() (success bool) {
this.depth++
if this.depth <= maxDepth {
return true
}
this.reportError("incrementDepth", "exceeded max depth")
return false
}
func (this *JsonExtractor) decrementDepth() (success bool) {
this.depth--
if this.depth >= 0 {
return true
}
this.reportError("decrementDepth", "unexpected negative nesting")
return false
}
func (iter *JsonExtractor) ReadObjectCB(callback func(core.IExtractor, string) bool) bool {
c := iter.nextToken()
var field string
if c == '{' {
if !iter.incrementDepth() {
return false
}
c = iter.nextToken()
if c == '"' {
iter.unreadByte()
field = iter.ReadString()
c = iter.nextToken()
if c != ':' {
iter.reportError("ReadObject", "expect : after object field, but found "+string([]byte{c}))
}
if !callback(iter, field) {
iter.decrementDepth()
return false
}
c = iter.nextToken()
for c == ',' {
field = iter.ReadString()
c = iter.nextToken()
if c != ':' {
iter.reportError("ReadObject", "expect : after object field, but found "+string([]byte{c}))
}
if !callback(iter, field) {
iter.decrementDepth()
return false
}
c = iter.nextToken()
}
if c != '}' {
iter.reportError("ReadObjectCB", `object not ended with }`)
iter.decrementDepth()
return false
}
return iter.decrementDepth()
}
if c == '}' {
return iter.decrementDepth()
}
iter.reportError("ReadObjectCB", `expect " after {, but found `+string([]byte{c}))
iter.decrementDepth()
return false
}
if c == 'n' {
iter.skipThreeBytes('u', 'l', 'l')
return true // null
}
iter.reportError("ReadObjectCB", `expect { or n, but found `+string([]byte{c}))
return false
}
func (iter *JsonExtractor) ReadMapCB(callback func(core.IExtractor, string) bool) bool {
c := iter.nextToken()
if c == '{' {
if !iter.incrementDepth() {
return false
}
c = iter.nextToken()
if c == '"' {
iter.unreadByte()
field := iter.ReadString()
if iter.nextToken() != ':' {
iter.reportError("ReadMapCB", "expect : after object field, but found "+string([]byte{c}))
iter.decrementDepth()
return false
}
if !callback(iter, field) {
iter.decrementDepth()
return false
}
c = iter.nextToken()
for c == ',' {
field = iter.ReadString()
if iter.nextToken() != ':' {
iter.reportError("ReadMapCB", "expect : after object field, but found "+string([]byte{c}))
iter.decrementDepth()
return false
}
if !callback(iter, field) {
iter.decrementDepth()
return false
}
c = iter.nextToken()
}
if c != '}' {
iter.reportError("ReadMapCB", `object not ended with }`)
iter.decrementDepth()
return false
}
return iter.decrementDepth()
}
if c == '}' {
return iter.decrementDepth()
}
iter.reportError("ReadMapCB", `expect " after {, but found `+string([]byte{c}))
iter.decrementDepth()
return false
}
if c == 'n' {
iter.skipThreeBytes('u', 'l', 'l')
return true // null
}
iter.reportError("ReadMapCB", `expect { or n, but found `+string([]byte{c}))
return false
}
func (iter *JsonExtractor) ReadArrayCB(callback func(core.IExtractor) bool) (ret bool) {
c := iter.nextToken()
if c == '[' {
if !iter.incrementDepth() {
return false
}
c = iter.nextToken()
if c != ']' {
iter.unreadByte()
if !callback(iter) {
iter.decrementDepth()
return false
}
c = iter.nextToken()
for c == ',' {
if !callback(iter) {
iter.decrementDepth()
return false
}
c = iter.nextToken()
}
if c != ']' {
iter.reportError("ReadArrayCB", "expect ] in the end, but found "+string([]byte{c}))
iter.decrementDepth()
return false
}
return iter.decrementDepth()
}
return iter.decrementDepth()
}
if c == 'n' {
iter.skipThreeBytes('u', 'l', 'l')
return true // null
}
iter.reportError("ReadArrayCB", "expect [ or n, but found "+string([]byte{c}))
return false
}

View File

@ -0,0 +1,179 @@
package factory
import (
"fmt"
"reflect"
"unsafe"
"go_dreamfactory/lego/sys/codec/core"
"github.com/modern-go/reflect2"
)
type sortableBindings []*Binding
func (this sortableBindings) Len() int {
return len(this)
}
func (this sortableBindings) Less(i, j int) bool {
left := this[i].levels
right := this[j].levels
k := 0
for {
if left[k] < right[k] {
return true
} else if left[k] > right[k] {
return false
}
k++
}
}
func (this sortableBindings) Swap(i, j int) {
this[i], this[j] = this[j], this[i]
}
//----------------------------------------------------------------------------------------------------------------------------------------------------------------
func EncoderOfType(ctx *core.Ctx, typ reflect2.Type) core.IEncoder {
encoder := ctx.Encoders[typ]
if encoder != nil {
return encoder
}
root := &rootEncoder{}
ctx.Encoders[typ] = root
encoder = _createEncoderOfType(ctx, typ)
root.encoder = encoder
return encoder
}
func _createEncoderOfType(ctx *core.Ctx, typ reflect2.Type) core.IEncoder {
var encoder core.IEncoder
encoder = createEncoderOfNative(ctx, typ)
if encoder != nil {
return encoder
}
kind := typ.Kind()
switch kind {
case reflect.Interface:
return &dynamicEncoder{typ}
case reflect.Struct:
return encoderOfStruct(ctx, typ)
case reflect.Array:
return encoderOfArray(ctx, typ)
case reflect.Slice:
return encoderOfSlice(ctx, typ)
case reflect.Map:
return encoderOfMap(ctx, typ)
case reflect.Ptr:
return encoderOfOptional(ctx, typ)
default:
return &lazyErrorEncoder{err: fmt.Errorf("%s %s is unsupported type", ctx.Prefix, typ.String())}
}
}
func DecoderOfType(ctx *core.Ctx, typ reflect2.Type) core.IDecoder {
decoder := ctx.Decoders[typ]
if decoder != nil {
return decoder
}
root := &rootDecoder{}
ctx.Decoders[typ] = root
decoder = _createDecoderOfType(ctx, typ)
root.decoder = decoder
return decoder
}
func _createDecoderOfType(ctx *core.Ctx, typ reflect2.Type) core.IDecoder {
var decoder core.IDecoder
decoder = createDecoderOfNative(ctx, typ)
if decoder != nil {
return decoder
}
switch typ.Kind() {
case reflect.Interface:
ifaceType, isIFace := typ.(*reflect2.UnsafeIFaceType)
if isIFace {
return &ifaceDecoder{valType: ifaceType}
}
return &efaceDecoder{}
case reflect.Struct:
return decoderOfStruct(ctx, typ)
case reflect.Array:
return decoderOfArray(ctx, typ)
case reflect.Slice:
return decoderOfSlice(ctx, typ)
case reflect.Map:
return decoderOfMap(ctx, typ)
case reflect.Ptr:
return decoderOfOptional(ctx, typ)
default:
return &lazyErrorDecoder{err: fmt.Errorf("%s %s is unsupported type", ctx.Prefix, typ.String())}
}
}
//根节点 -------------------------------------------------------------------
type rootDecoder struct {
decoder core.IDecoder
}
func (this *rootDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
this.decoder.Decode(ptr, extra)
}
type rootEncoder struct {
encoder core.IEncoder
}
func (this *rootEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) {
this.encoder.Encode(ptr, stream)
}
func (this *rootEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return this.encoder.IsEmpty(ptr)
}
//onePtrEncoder---------------------------------------------------------------
func NewonePtrEncoder(encoder core.IEncoder) core.IEncoder {
return &onePtrEncoder{encoder}
}
type onePtrEncoder struct {
encoder core.IEncoder
}
func (encoder *onePtrEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return encoder.encoder.IsEmpty(unsafe.Pointer(&ptr))
}
func (encoder *onePtrEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) {
encoder.encoder.Encode(unsafe.Pointer(&ptr), stream)
}
//错误节点 ------------------------------------------------------------------
type lazyErrorDecoder struct {
err error
}
func (this *lazyErrorDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
if extra.Error() == nil {
extra.SetErr(this.err)
}
}
type lazyErrorEncoder struct {
err error
}
func (this *lazyErrorEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) {
if ptr == nil {
stream.WriteNil()
} else if stream.Error() == nil {
stream.SetErr(this.err)
}
}
func (this *lazyErrorEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return false
}

View File

@ -0,0 +1,94 @@
package factory
import (
"fmt"
"io"
"unsafe"
"go_dreamfactory/lego/sys/codec/core"
"github.com/modern-go/reflect2"
)
func decoderOfArray(ctx *core.Ctx, typ reflect2.Type) core.IDecoder {
arrayType := typ.(*reflect2.UnsafeArrayType)
decoder := DecoderOfType(ctx.Append("[arrayElem]"), arrayType.Elem())
return &arrayDecoder{arrayType, decoder}
}
func encoderOfArray(ctx *core.Ctx, typ reflect2.Type) core.IEncoder {
arrayType := typ.(*reflect2.UnsafeArrayType)
if arrayType.Len() == 0 {
return emptyArrayEncoder{}
}
encoder := EncoderOfType(ctx.Append("[arrayElem]"), arrayType.Elem())
return &arrayEncoder{arrayType, encoder}
}
//array-------------------------------------------------------------------------------------------------------------------------------
type arrayEncoder struct {
arrayType *reflect2.UnsafeArrayType
elemEncoder core.IEncoder
}
func (encoder *arrayEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) {
stream.WriteArrayStart()
elemPtr := unsafe.Pointer(ptr)
encoder.elemEncoder.Encode(elemPtr, stream)
for i := 1; i < encoder.arrayType.Len(); i++ {
stream.WriteMemberSplit()
elemPtr = encoder.arrayType.UnsafeGetIndex(ptr, i)
encoder.elemEncoder.Encode(elemPtr, stream)
}
stream.WriteArrayEnd()
if stream.Error() != nil && stream.Error() != io.EOF {
stream.SetErr(fmt.Errorf("%v: %s", encoder.arrayType, stream.Error().Error()))
}
}
func (encoder *arrayEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return false
}
type arrayDecoder struct {
arrayType *reflect2.UnsafeArrayType
elemDecoder core.IDecoder
}
func (this *arrayDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
arrayType := this.arrayType
if extra.ReadNil() {
return
}
if extra.ReadArrayStart() {
return
}
if extra.CheckNextIsArrayEnd() {
return
}
elemPtr := arrayType.UnsafeGetIndex(ptr, 0)
this.elemDecoder.Decode(elemPtr, extra)
length := 1
for extra.ReadMemberSplit() {
idx := length
length += 1
elemPtr = arrayType.UnsafeGetIndex(ptr, idx)
this.elemDecoder.Decode(elemPtr, extra)
}
if extra.ReadArrayEnd() {
return
}
if extra.Error() != nil && extra.Error() != io.EOF {
extra.SetErr(fmt.Errorf("%v: %s", this.arrayType, extra.Error().Error()))
}
}
type emptyArrayEncoder struct{}
func (this emptyArrayEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) {
stream.WriteEmptyArray()
}
func (this emptyArrayEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return true
}

View File

@ -0,0 +1,74 @@
package factory
import (
"errors"
"reflect"
"unsafe"
"go_dreamfactory/lego/sys/codec/core"
"github.com/modern-go/reflect2"
)
type dynamicEncoder struct {
valType reflect2.Type
}
func (encoder *dynamicEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) {
obj := encoder.valType.UnsafeIndirect(ptr)
stream.WriteVal(obj)
}
func (encoder *dynamicEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return encoder.valType.UnsafeIndirect(ptr) == nil
}
type efaceDecoder struct {
}
func (decoder *efaceDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
pObj := (*interface{})(ptr)
obj := *pObj
if obj == nil {
*pObj = extra.Read()
return
}
typ := reflect2.TypeOf(obj)
if typ.Kind() != reflect.Ptr {
*pObj = extra.Read()
return
}
ptrType := typ.(*reflect2.UnsafePtrType)
ptrElemType := ptrType.Elem()
if extra.WhatIsNext() == core.NilValue {
if ptrElemType.Kind() != reflect.Ptr {
extra.ReadNil()
*pObj = nil
return
}
}
if reflect2.IsNil(obj) {
obj := ptrElemType.New()
extra.ReadVal(obj)
*pObj = obj
return
}
extra.ReadVal(obj)
}
type ifaceDecoder struct {
valType *reflect2.UnsafeIFaceType
}
func (decoder *ifaceDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
if extra.ReadNil() {
decoder.valType.UnsafeSet(ptr, decoder.valType.UnsafeNew())
return
}
obj := decoder.valType.UnsafeIndirect(ptr)
if reflect2.IsNil(obj) {
extra.SetErr(errors.New("decode non empty interface can not unmarshal into nil"))
return
}
extra.ReadVal(obj)
}

View File

@ -0,0 +1,196 @@
package factory
import (
"fmt"
"reflect"
"unsafe"
"go_dreamfactory/lego/sys/codec/core"
"github.com/modern-go/reflect2"
)
func decoderOfMap(ctx *core.Ctx, typ reflect2.Type) core.IDecoder {
mapType := typ.(*reflect2.UnsafeMapType)
keyDecoder := decoderOfMapKey(ctx.Append("[mapKey]"), mapType.Key())
elemDecoder := DecoderOfType(ctx.Append("[mapElem]"), mapType.Elem())
return &mapDecoder{
mapType: mapType,
keyType: mapType.Key(),
elemType: mapType.Elem(),
keyDecoder: keyDecoder,
elemDecoder: elemDecoder,
}
}
func encoderOfMap(ctx *core.Ctx, typ reflect2.Type) core.IEncoder {
mapType := typ.(*reflect2.UnsafeMapType)
return &mapEncoder{
mapType: mapType,
keyEncoder: encoderOfMapKey(ctx.Append("[mapKey]"), mapType.Key()),
elemEncoder: EncoderOfType(ctx.Append("[mapElem]"), mapType.Elem()),
}
}
func decoderOfMapKey(ctx *core.Ctx, typ reflect2.Type) core.IDecoder {
switch typ.Kind() {
case reflect.String:
return DecoderOfType(ctx, reflect2.DefaultTypeOfKind(reflect.String))
case reflect.Bool,
reflect.Uint8, reflect.Int8,
reflect.Uint16, reflect.Int16,
reflect.Uint32, reflect.Int32,
reflect.Uint64, reflect.Int64,
reflect.Uint, reflect.Int,
reflect.Float32, reflect.Float64,
reflect.Uintptr:
typ = reflect2.DefaultTypeOfKind(typ.Kind())
return &numericMapKeyDecoder{DecoderOfType(ctx, typ)}
default:
return &lazyErrorDecoder{err: fmt.Errorf("unsupported map key type: %v", typ)}
}
}
func encoderOfMapKey(ctx *core.Ctx, typ reflect2.Type) core.IEncoder {
switch typ.Kind() {
case reflect.String:
return EncoderOfType(ctx, reflect2.DefaultTypeOfKind(reflect.String))
case reflect.Bool,
reflect.Uint8, reflect.Int8,
reflect.Uint16, reflect.Int16,
reflect.Uint32, reflect.Int32,
reflect.Uint64, reflect.Int64,
reflect.Uint, reflect.Int,
reflect.Float32, reflect.Float64,
reflect.Uintptr:
typ = reflect2.DefaultTypeOfKind(typ.Kind())
return &numericMapKeyEncoder{EncoderOfType(ctx, typ)}
default:
if typ.Kind() == reflect.Interface {
return &dynamicMapKeyEncoder{ctx, typ}
}
return &lazyErrorEncoder{err: fmt.Errorf("unsupported map key type: %v", typ)}
}
}
//Map--------------------------------------------------------------------------------------------------------------------------------------
type mapEncoder struct {
mapType *reflect2.UnsafeMapType
keyEncoder core.IEncoder
elemEncoder core.IEncoder
}
func (this *mapEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) {
if *(*unsafe.Pointer)(ptr) == nil {
stream.WriteNil()
return
}
stream.WriteObjectStart()
iter := this.mapType.UnsafeIterate(ptr)
for i := 0; iter.HasNext(); i++ {
if i != 0 {
stream.WriteMemberSplit()
}
key, elem := iter.UnsafeNext()
this.keyEncoder.Encode(key, stream)
stream.WriteKVSplit()
this.elemEncoder.Encode(elem, stream)
}
stream.WriteObjectEnd()
}
func (this *mapEncoder) IsEmpty(ptr unsafe.Pointer) bool {
iter := this.mapType.UnsafeIterate(ptr)
return !iter.HasNext()
}
type mapDecoder struct {
mapType *reflect2.UnsafeMapType
keyType reflect2.Type
elemType reflect2.Type
keyDecoder core.IDecoder
elemDecoder core.IDecoder
}
func (this *mapDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
mapType := this.mapType
if extra.ReadNil() {
*(*unsafe.Pointer)(ptr) = nil
mapType.UnsafeSet(ptr, mapType.UnsafeNew())
return
}
if mapType.UnsafeIsNil(ptr) {
mapType.UnsafeSet(ptr, mapType.UnsafeMakeMap(0))
}
if !extra.ReadObjectStart() {
return
}
if extra.CheckNextIsObjectEnd() {
extra.ReadObjectEnd()
return
}
key := this.keyType.UnsafeNew()
this.keyDecoder.Decode(key, extra)
if !extra.ReadKVSplit() {
return
}
elem := this.elemType.UnsafeNew()
this.elemDecoder.Decode(elem, extra)
this.mapType.UnsafeSetIndex(ptr, key, elem)
for extra.ReadMemberSplit() {
key := this.keyType.UnsafeNew()
this.keyDecoder.Decode(key, extra)
if !extra.ReadKVSplit() {
return
}
elem := this.elemType.UnsafeNew()
this.elemDecoder.Decode(elem, extra)
this.mapType.UnsafeSetIndex(ptr, key, elem)
}
extra.ReadObjectEnd()
}
//NumericMap-------------------------------------------------------------------------------------------------------------------------------
type numericMapKeyDecoder struct {
decoder core.IDecoder
}
func (this *numericMapKeyDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
if extra.ReadKeyStart() {
return
}
this.decoder.Decode(ptr, extra)
if extra.ReadKeyEnd() {
return
}
}
type numericMapKeyEncoder struct {
encoder core.IEncoder
}
func (this *numericMapKeyEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) {
stream.WriteKeyStart()
this.encoder.Encode(ptr, stream)
stream.WriteKeyEnd()
}
func (encoder *numericMapKeyEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return false
}
//------------------------------------------------------------------------------------------------------------------
type dynamicMapKeyEncoder struct {
ctx *core.Ctx
valType reflect2.Type
}
func (this *dynamicMapKeyEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) {
obj := this.valType.UnsafeIndirect(ptr)
encoderOfMapKey(this.ctx, reflect2.TypeOf(obj)).Encode(reflect2.PtrOf(obj), stream)
}
func (this *dynamicMapKeyEncoder) IsEmpty(ptr unsafe.Pointer) bool {
obj := this.valType.UnsafeIndirect(ptr)
return encoderOfMapKey(this.ctx, reflect2.TypeOf(obj)).IsEmpty(reflect2.PtrOf(obj))
}

View File

@ -0,0 +1,397 @@
package factory
import (
"reflect"
"strconv"
"unsafe"
"go_dreamfactory/lego/sys/codec/core"
"github.com/modern-go/reflect2"
)
const ptrSize = 32 << uintptr(^uintptr(0)>>63) //计算int的大小 是32 还是64
func createDecoderOfNative(ctx *core.Ctx, typ reflect2.Type) core.IDecoder {
typeName := typ.String()
switch typ.Kind() {
case reflect.String:
if typeName != "string" {
return DecoderOfType(ctx, reflect2.TypeOfPtr((*string)(nil)).Elem())
}
return &stringCodec{}
case reflect.Int:
if typeName != "int" {
return DecoderOfType(ctx, reflect2.TypeOfPtr((*int)(nil)).Elem())
}
if strconv.IntSize == 32 {
return &int32Codec{}
}
return &int64Codec{}
case reflect.Int8:
if typeName != "int8" {
return DecoderOfType(ctx, reflect2.TypeOfPtr((*int8)(nil)).Elem())
}
return &int8Codec{}
case reflect.Int16:
if typeName != "int16" {
return DecoderOfType(ctx, reflect2.TypeOfPtr((*int16)(nil)).Elem())
}
return &int16Codec{}
case reflect.Int32:
if typeName != "int32" {
return DecoderOfType(ctx, reflect2.TypeOfPtr((*int32)(nil)).Elem())
}
return &int32Codec{}
case reflect.Int64:
if typeName != "int64" {
return DecoderOfType(ctx, reflect2.TypeOfPtr((*int64)(nil)).Elem())
}
return &int64Codec{}
case reflect.Uint:
if typeName != "uint" {
return DecoderOfType(ctx, reflect2.TypeOfPtr((*uint)(nil)).Elem())
}
if strconv.IntSize == 32 {
return &uint32Codec{}
}
return &uint64Codec{}
case reflect.Uint8:
if typeName != "uint8" {
return DecoderOfType(ctx, reflect2.TypeOfPtr((*uint8)(nil)).Elem())
}
return &uint8Codec{}
case reflect.Uint16:
if typeName != "uint16" {
return DecoderOfType(ctx, reflect2.TypeOfPtr((*uint16)(nil)).Elem())
}
return &uint16Codec{}
case reflect.Uint32:
if typeName != "uint32" {
return DecoderOfType(ctx, reflect2.TypeOfPtr((*uint32)(nil)).Elem())
}
return &uint32Codec{}
case reflect.Uintptr:
if typeName != "uintptr" {
return DecoderOfType(ctx, reflect2.TypeOfPtr((*uintptr)(nil)).Elem())
}
if ptrSize == 32 {
return &uint32Codec{}
}
return &uint64Codec{}
case reflect.Uint64:
if typeName != "uint64" {
return DecoderOfType(ctx, reflect2.TypeOfPtr((*uint64)(nil)).Elem())
}
return &uint64Codec{}
case reflect.Float32:
if typeName != "float32" {
return DecoderOfType(ctx, reflect2.TypeOfPtr((*float32)(nil)).Elem())
}
return &float32Codec{}
case reflect.Float64:
if typeName != "float64" {
return DecoderOfType(ctx, reflect2.TypeOfPtr((*float64)(nil)).Elem())
}
return &float64Codec{}
case reflect.Bool:
if typeName != "bool" {
return DecoderOfType(ctx, reflect2.TypeOfPtr((*bool)(nil)).Elem())
}
return &boolCodec{}
}
return nil
}
func createEncoderOfNative(ctx *core.Ctx, typ reflect2.Type) core.IEncoder {
typeName := typ.String()
kind := typ.Kind()
switch kind {
case reflect.String:
if typeName != "string" {
return EncoderOfType(ctx, reflect2.TypeOfPtr((*string)(nil)).Elem())
}
return &stringCodec{}
case reflect.Int:
if typeName != "int" {
return EncoderOfType(ctx, reflect2.TypeOfPtr((*int)(nil)).Elem())
}
if strconv.IntSize == 32 {
return &int32Codec{}
}
return &int64Codec{}
case reflect.Int8:
if typeName != "int8" {
return EncoderOfType(ctx, reflect2.TypeOfPtr((*int8)(nil)).Elem())
}
return &int8Codec{}
case reflect.Int16:
if typeName != "int16" {
return EncoderOfType(ctx, reflect2.TypeOfPtr((*int16)(nil)).Elem())
}
return &int16Codec{}
case reflect.Int32:
if typeName != "int32" {
return EncoderOfType(ctx, reflect2.TypeOfPtr((*int32)(nil)).Elem())
}
return &int32Codec{}
case reflect.Int64:
if typeName != "int64" {
return EncoderOfType(ctx, reflect2.TypeOfPtr((*int64)(nil)).Elem())
}
return &int64Codec{}
case reflect.Uint:
if typeName != "uint" {
return EncoderOfType(ctx, reflect2.TypeOfPtr((*uint)(nil)).Elem())
}
if strconv.IntSize == 32 {
return &uint32Codec{}
}
return &uint64Codec{}
case reflect.Uint8:
if typeName != "uint8" {
return EncoderOfType(ctx, reflect2.TypeOfPtr((*uint8)(nil)).Elem())
}
return &uint8Codec{}
case reflect.Uint16:
if typeName != "uint16" {
return EncoderOfType(ctx, reflect2.TypeOfPtr((*uint16)(nil)).Elem())
}
return &uint16Codec{}
case reflect.Uint32:
if typeName != "uint32" {
return EncoderOfType(ctx, reflect2.TypeOfPtr((*uint32)(nil)).Elem())
}
return &uint32Codec{}
case reflect.Uintptr:
if typeName != "uintptr" {
return EncoderOfType(ctx, reflect2.TypeOfPtr((*uintptr)(nil)).Elem())
}
if ptrSize == 32 {
return &uint32Codec{}
}
return &uint64Codec{}
case reflect.Uint64:
if typeName != "uint64" {
return EncoderOfType(ctx, reflect2.TypeOfPtr((*uint64)(nil)).Elem())
}
return &uint64Codec{}
case reflect.Float32:
if typeName != "float32" {
return EncoderOfType(ctx, reflect2.TypeOfPtr((*float32)(nil)).Elem())
}
return &float32Codec{}
case reflect.Float64:
if typeName != "float64" {
return EncoderOfType(ctx, reflect2.TypeOfPtr((*float64)(nil)).Elem())
}
return &float64Codec{}
case reflect.Bool:
if typeName != "bool" {
return EncoderOfType(ctx, reflect2.TypeOfPtr((*bool)(nil)).Elem())
}
return &boolCodec{}
}
return nil
}
type stringCodec struct {
}
func (codec *stringCodec) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
*((*string)(ptr)) = extra.ReadString()
}
func (codec *stringCodec) Encode(ptr unsafe.Pointer, stream core.IStream) {
str := *((*string)(ptr))
stream.WriteString(str)
}
func (codec *stringCodec) IsEmpty(ptr unsafe.Pointer) bool {
return *((*string)(ptr)) == ""
}
type int8Codec struct {
}
func (codec *int8Codec) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
if !extra.ReadNil() {
*((*int8)(ptr)) = extra.ReadInt8()
}
}
func (codec *int8Codec) Encode(ptr unsafe.Pointer, stream core.IStream) {
stream.WriteInt8(*((*int8)(ptr)))
}
func (codec *int8Codec) IsEmpty(ptr unsafe.Pointer) bool {
return *((*int8)(ptr)) == 0
}
type int16Codec struct {
}
func (codec *int16Codec) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
if !extra.ReadNil() {
*((*int16)(ptr)) = extra.ReadInt16()
}
}
func (codec *int16Codec) Encode(ptr unsafe.Pointer, stream core.IStream) {
stream.WriteInt16(*((*int16)(ptr)))
}
func (codec *int16Codec) IsEmpty(ptr unsafe.Pointer) bool {
return *((*int16)(ptr)) == 0
}
type int32Codec struct {
}
func (codec *int32Codec) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
if !extra.ReadNil() {
*((*int32)(ptr)) = extra.ReadInt32()
}
}
func (codec *int32Codec) Encode(ptr unsafe.Pointer, stream core.IStream) {
stream.WriteInt32(*((*int32)(ptr)))
}
func (codec *int32Codec) IsEmpty(ptr unsafe.Pointer) bool {
return *((*int32)(ptr)) == 0
}
type int64Codec struct {
}
func (codec *int64Codec) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
if !extra.ReadNil() {
*((*int64)(ptr)) = extra.ReadInt64()
}
}
func (codec *int64Codec) Encode(ptr unsafe.Pointer, stream core.IStream) {
stream.WriteInt64(*((*int64)(ptr)))
}
func (codec *int64Codec) IsEmpty(ptr unsafe.Pointer) bool {
return *((*int64)(ptr)) == 0
}
type uint8Codec struct {
}
func (codec *uint8Codec) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
if !extra.ReadNil() {
*((*uint8)(ptr)) = extra.ReadUint8()
}
}
func (codec *uint8Codec) Encode(ptr unsafe.Pointer, stream core.IStream) {
stream.WriteUint8(*((*uint8)(ptr)))
}
func (codec *uint8Codec) IsEmpty(ptr unsafe.Pointer) bool {
return *((*uint8)(ptr)) == 0
}
type uint16Codec struct {
}
func (codec *uint16Codec) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
if !extra.ReadNil() {
*((*uint16)(ptr)) = extra.ReadUint16()
}
}
func (codec *uint16Codec) Encode(ptr unsafe.Pointer, stream core.IStream) {
stream.WriteUint16(*((*uint16)(ptr)))
}
func (codec *uint16Codec) IsEmpty(ptr unsafe.Pointer) bool {
return *((*uint16)(ptr)) == 0
}
type uint32Codec struct {
}
func (codec *uint32Codec) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
if !extra.ReadNil() {
*((*uint32)(ptr)) = extra.ReadUint32()
}
}
func (codec *uint32Codec) Encode(ptr unsafe.Pointer, stream core.IStream) {
stream.WriteUint32(*((*uint32)(ptr)))
}
func (codec *uint32Codec) IsEmpty(ptr unsafe.Pointer) bool {
return *((*uint32)(ptr)) == 0
}
type uint64Codec struct {
}
func (codec *uint64Codec) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
if !extra.ReadNil() {
*((*uint64)(ptr)) = extra.ReadUint64()
}
}
func (codec *uint64Codec) Encode(ptr unsafe.Pointer, stream core.IStream) {
stream.WriteUint64(*((*uint64)(ptr)))
}
func (codec *uint64Codec) IsEmpty(ptr unsafe.Pointer) bool {
return *((*uint64)(ptr)) == 0
}
type float32Codec struct {
}
func (codec *float32Codec) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
if !extra.ReadNil() {
*((*float32)(ptr)) = extra.ReadFloat32()
}
}
func (codec *float32Codec) Encode(ptr unsafe.Pointer, stream core.IStream) {
stream.WriteFloat32(*((*float32)(ptr)))
}
func (codec *float32Codec) IsEmpty(ptr unsafe.Pointer) bool {
return *((*float32)(ptr)) == 0
}
type float64Codec struct {
}
func (codec *float64Codec) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
if !extra.ReadNil() {
*((*float64)(ptr)) = extra.ReadFloat64()
}
}
func (codec *float64Codec) Encode(ptr unsafe.Pointer, stream core.IStream) {
stream.WriteFloat64(*((*float64)(ptr)))
}
func (codec *float64Codec) IsEmpty(ptr unsafe.Pointer) bool {
return *((*float64)(ptr)) == 0
}
type boolCodec struct {
}
func (codec *boolCodec) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
if !extra.ReadNil() {
*((*bool)(ptr)) = extra.ReadBool()
}
}
func (codec *boolCodec) Encode(ptr unsafe.Pointer, stream core.IStream) {
stream.WriteBool(*((*bool)(ptr)))
}
func (codec *boolCodec) IsEmpty(ptr unsafe.Pointer) bool {
return !(*((*bool)(ptr)))
}

View File

@ -0,0 +1,130 @@
package factory
import (
"unsafe"
"go_dreamfactory/lego/sys/codec/core"
"github.com/modern-go/reflect2"
)
func decoderOfOptional(ctx *core.Ctx, typ reflect2.Type) core.IDecoder {
ptrType := typ.(*reflect2.UnsafePtrType)
elemType := ptrType.Elem()
decoder := DecoderOfType(ctx, elemType)
return &OptionalDecoder{elemType, decoder}
}
func encoderOfOptional(ctx *core.Ctx, typ reflect2.Type) core.IEncoder {
ptrType := typ.(*reflect2.UnsafePtrType)
elemType := ptrType.Elem()
elemEncoder := EncoderOfType(ctx, elemType)
encoder := &OptionalEncoder{elemEncoder}
return encoder
}
//Optional--------------------------------------------------------------------------------------------------------------------
type OptionalDecoder struct {
ValueType reflect2.Type
ValueDecoder core.IDecoder
}
func (decoder *OptionalDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
if extra.ReadNil() {
*((*unsafe.Pointer)(ptr)) = nil
} else {
if *((*unsafe.Pointer)(ptr)) == nil {
newPtr := decoder.ValueType.UnsafeNew()
decoder.ValueDecoder.Decode(newPtr, extra)
*((*unsafe.Pointer)(ptr)) = newPtr
} else {
decoder.ValueDecoder.Decode(*((*unsafe.Pointer)(ptr)), extra)
}
}
}
type OptionalEncoder struct {
ValueEncoder core.IEncoder
}
func (encoder *OptionalEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) {
if *((*unsafe.Pointer)(ptr)) == nil {
stream.WriteNil()
} else {
encoder.ValueEncoder.Encode(*((*unsafe.Pointer)(ptr)), stream)
}
}
func (encoder *OptionalEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return *((*unsafe.Pointer)(ptr)) == nil
}
//reference--------------------------------------------------------------------------------------------------------------------
type referenceEncoder struct {
encoder core.IEncoder
}
func (encoder *referenceEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) {
encoder.encoder.Encode(unsafe.Pointer(&ptr), stream)
}
func (encoder *referenceEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return encoder.encoder.IsEmpty(unsafe.Pointer(&ptr))
}
type referenceDecoder struct {
decoder core.IDecoder
}
func (decoder *referenceDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
decoder.decoder.Decode(unsafe.Pointer(&ptr), extra)
}
//dereference--------------------------------------------------------------------------------------------------------------------
type dereferenceDecoder struct {
valueType reflect2.Type
valueDecoder core.IDecoder
}
func (this *dereferenceDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
if *((*unsafe.Pointer)(ptr)) == nil {
newPtr := this.valueType.UnsafeNew()
this.valueDecoder.Decode(newPtr, extra)
*((*unsafe.Pointer)(ptr)) = newPtr
} else {
this.valueDecoder.Decode(*((*unsafe.Pointer)(ptr)), extra)
}
}
type dereferenceEncoder struct {
ValueEncoder core.IEncoder
}
func (encoder *dereferenceEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) {
if *((*unsafe.Pointer)(ptr)) == nil {
stream.WriteNil()
} else {
encoder.ValueEncoder.Encode(*((*unsafe.Pointer)(ptr)), stream)
}
}
func (encoder *dereferenceEncoder) IsEmpty(ptr unsafe.Pointer) bool {
dePtr := *((*unsafe.Pointer)(ptr))
if dePtr == nil {
return true
}
return encoder.ValueEncoder.IsEmpty(dePtr)
}
func (encoder *dereferenceEncoder) IsEmbeddedPtrNil(ptr unsafe.Pointer) bool {
deReferenced := *((*unsafe.Pointer)(ptr))
if deReferenced == nil {
return true
}
isEmbeddedPtrNil, converted := encoder.ValueEncoder.(core.IsEmbeddedPtrNil)
if !converted {
return false
}
fieldPtr := unsafe.Pointer(deReferenced)
return isEmbeddedPtrNil.IsEmbeddedPtrNil(fieldPtr)
}

View File

@ -0,0 +1,91 @@
package factory
import (
"fmt"
"io"
"unsafe"
"go_dreamfactory/lego/sys/codec/core"
"github.com/modern-go/reflect2"
)
func decoderOfSlice(ctx *core.Ctx, typ reflect2.Type) core.IDecoder {
sliceType := typ.(*reflect2.UnsafeSliceType)
decoder := DecoderOfType(ctx.Append("[sliceElem]"), sliceType.Elem())
return &sliceDecoder{sliceType, decoder}
}
func encoderOfSlice(ctx *core.Ctx, typ reflect2.Type) core.IEncoder {
sliceType := typ.(*reflect2.UnsafeSliceType)
encoder := EncoderOfType(ctx.Append("[sliceElem]"), sliceType.Elem())
return &sliceEncoder{sliceType, encoder}
}
type sliceEncoder struct {
sliceType *reflect2.UnsafeSliceType
elemEncoder core.IEncoder
}
func (encoder *sliceEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) {
if encoder.sliceType.UnsafeIsNil(ptr) {
stream.WriteNil()
return
}
length := encoder.sliceType.UnsafeLengthOf(ptr)
if length == 0 {
stream.WriteEmptyArray()
return
}
stream.WriteArrayStart()
encoder.elemEncoder.Encode(encoder.sliceType.UnsafeGetIndex(ptr, 0), stream)
for i := 1; i < length; i++ {
stream.WriteMemberSplit()
elemPtr := encoder.sliceType.UnsafeGetIndex(ptr, i)
encoder.elemEncoder.Encode(elemPtr, stream)
}
stream.WriteArrayEnd()
if stream.Error() != nil && stream.Error() != io.EOF {
stream.SetErr(fmt.Errorf("%v: %s", encoder.sliceType, stream.Error().Error()))
}
}
func (encoder *sliceEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return encoder.sliceType.UnsafeLengthOf(ptr) == 0
}
type sliceDecoder struct {
sliceType *reflect2.UnsafeSliceType
elemDecoder core.IDecoder
}
func (decoder *sliceDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
sliceType := decoder.sliceType
if extra.ReadNil() {
sliceType.UnsafeSetNil(ptr)
return
}
if !extra.ReadArrayStart() {
return
}
if extra.CheckNextIsArrayEnd() {
sliceType.UnsafeSet(ptr, sliceType.UnsafeMakeSlice(0, 0))
return
}
sliceType.UnsafeGrow(ptr, 1)
elemPtr := sliceType.UnsafeGetIndex(ptr, 0)
decoder.elemDecoder.Decode(elemPtr, extra)
length := 1
for extra.ReadMemberSplit() {
idx := length
length += 1
sliceType.UnsafeGrow(ptr, length)
elemPtr = sliceType.UnsafeGetIndex(ptr, idx)
decoder.elemDecoder.Decode(elemPtr, extra)
}
if extra.ReadArrayEnd() {
return
}
if extra.Error() != nil && extra.Error() != io.EOF {
extra.SetErr(fmt.Errorf("%v: %s", decoder.sliceType, extra.Error().Error()))
}
}

View File

@ -0,0 +1,383 @@
package factory
import (
"fmt"
"io"
"reflect"
"sort"
"strings"
"unicode"
"unsafe"
"go_dreamfactory/lego/sys/codec/core"
"github.com/modern-go/reflect2"
)
type StructDescriptor struct {
Type reflect2.Type
Fields []*Binding
}
type Binding struct {
levels []int
Field reflect2.StructField
FromNames []string
ToNames []string
Encoder core.IEncoder
Decoder core.IDecoder
}
func encoderOfStruct(ctx *core.Ctx, typ reflect2.Type) core.IEncoder {
type bindingTo struct {
binding *Binding
toName string
ignored bool
}
orderedBindings := []*bindingTo{}
structDescriptor := describeStruct(ctx, typ)
for _, binding := range structDescriptor.Fields {
for _, toName := range binding.ToNames {
new := &bindingTo{
binding: binding,
toName: toName,
}
for _, old := range orderedBindings {
if old.toName != toName {
continue
}
old.ignored, new.ignored = resolveConflictBinding(ctx.Options(), old.binding, new.binding)
}
orderedBindings = append(orderedBindings, new)
}
}
if len(orderedBindings) == 0 {
return &emptyStructEncoder{}
}
finalOrderedFields := []structFieldTo{}
for _, bindingTo := range orderedBindings {
if !bindingTo.ignored {
finalOrderedFields = append(finalOrderedFields, structFieldTo{
encoder: bindingTo.binding.Encoder.(*structFieldEncoder),
toName: bindingTo.toName,
})
}
}
return &structEncoder{typ, finalOrderedFields}
}
func decoderOfStruct(ctx *core.Ctx, typ reflect2.Type) core.IDecoder {
bindings := map[string]*Binding{}
structDescriptor := describeStruct(ctx, typ)
for _, binding := range structDescriptor.Fields {
for _, fromName := range binding.FromNames {
old := bindings[fromName]
if old == nil {
bindings[fromName] = binding
continue
}
ignoreOld, ignoreNew := resolveConflictBinding(ctx.Options(), old, binding)
if ignoreOld {
delete(bindings, fromName)
}
if !ignoreNew {
bindings[fromName] = binding
}
}
}
fields := map[string]*structFieldDecoder{}
for k, binding := range bindings {
fields[k] = binding.Decoder.(*structFieldDecoder)
}
if !ctx.Options().CaseSensitive {
for k, binding := range bindings {
if _, found := fields[strings.ToLower(k)]; !found {
fields[strings.ToLower(k)] = binding.Decoder.(*structFieldDecoder)
}
}
}
return createStructDecoder(ctx.Options(), typ, fields)
}
//结构第编辑码构建
func describeStruct(ctx *core.Ctx, typ reflect2.Type) *StructDescriptor {
structType := typ.(*reflect2.UnsafeStructType)
embeddedBindings := []*Binding{}
bindings := []*Binding{}
for i := 0; i < structType.NumField(); i++ {
field := structType.Field(i)
tag, hastag := field.Tag().Lookup(ctx.Options().TagKey)
if ctx.Options().OnlyTaggedField && !hastag && !field.Anonymous() {
continue
}
if tag == "-" || field.Name() == "_" {
continue
}
tagParts := strings.Split(tag, ",")
if field.Anonymous() && (tag == "" || tagParts[0] == "") {
if field.Type().Kind() == reflect.Struct {
structDescriptor := describeStruct(ctx, field.Type())
for _, binding := range structDescriptor.Fields {
binding.levels = append([]int{i}, binding.levels...)
omitempty := binding.Encoder.(*structFieldEncoder).omitempty
binding.Encoder = &structFieldEncoder{field, binding.Encoder, omitempty}
binding.Decoder = &structFieldDecoder{field, binding.Decoder}
embeddedBindings = append(embeddedBindings, binding)
}
continue
} else if field.Type().Kind() == reflect.Ptr {
ptrType := field.Type().(*reflect2.UnsafePtrType)
if ptrType.Elem().Kind() == reflect.Struct {
structDescriptor := describeStruct(ctx, ptrType.Elem())
for _, binding := range structDescriptor.Fields {
binding.levels = append([]int{i}, binding.levels...)
omitempty := binding.Encoder.(*structFieldEncoder).omitempty
binding.Encoder = &dereferenceEncoder{binding.Encoder}
binding.Encoder = &structFieldEncoder{field, binding.Encoder, omitempty}
binding.Decoder = &dereferenceDecoder{ptrType.Elem(), binding.Decoder}
binding.Decoder = &structFieldDecoder{field, binding.Decoder}
embeddedBindings = append(embeddedBindings, binding)
}
continue
}
}
}
fieldNames := calcFieldNames(field.Name(), tagParts[0], tag)
decoder := DecoderOfType(ctx.Append(field.Name()), field.Type())
encoder := EncoderOfType(ctx.Append(field.Name()), field.Type())
binding := &Binding{
Field: field,
FromNames: fieldNames,
ToNames: fieldNames,
Decoder: decoder,
Encoder: encoder,
}
binding.levels = []int{i}
bindings = append(bindings, binding)
}
return createStructDescriptor(ctx, typ, bindings, embeddedBindings)
}
func createStructDescriptor(ctx *core.Ctx, typ reflect2.Type, bindings []*Binding, embeddedBindings []*Binding) *StructDescriptor {
structDescriptor := &StructDescriptor{
Type: typ,
Fields: bindings,
}
processTags(structDescriptor, ctx.ICodec)
allBindings := sortableBindings(append(embeddedBindings, structDescriptor.Fields...))
sort.Sort(allBindings)
structDescriptor.Fields = allBindings
return structDescriptor
}
func processTags(structDescriptor *StructDescriptor, codec core.ICodec) {
for _, binding := range structDescriptor.Fields {
shouldOmitEmpty := false
tagParts := strings.Split(binding.Field.Tag().Get(codec.Options().TagKey), ",")
for _, tagPart := range tagParts[1:] {
if tagPart == "omitempty" {
shouldOmitEmpty = true
}
}
binding.Decoder = &structFieldDecoder{binding.Field, binding.Decoder}
binding.Encoder = &structFieldEncoder{binding.Field, binding.Encoder, shouldOmitEmpty}
}
}
func calcFieldNames(originalFieldName string, tagProvidedFieldName string, wholeTag string) []string {
// ignore?
if wholeTag == "-" {
return []string{}
}
// rename?
var fieldNames []string
if tagProvidedFieldName == "" {
fieldNames = []string{originalFieldName}
} else {
fieldNames = []string{tagProvidedFieldName}
}
// private?
isNotExported := unicode.IsLower(rune(originalFieldName[0])) || originalFieldName[0] == '_'
if isNotExported {
fieldNames = []string{}
}
return fieldNames
}
func createStructDecoder(opt *core.Options, typ reflect2.Type, fields map[string]*structFieldDecoder) core.IDecoder {
if opt.DisallowUnknownFields {
return &structDecoder{typ: typ, fields: fields, disallowUnknownFields: true}
} else {
return &structDecoder{opt, typ, fields, false}
}
}
func resolveConflictBinding(opt *core.Options, old, new *Binding) (ignoreOld, ignoreNew bool) {
newTagged := new.Field.Tag().Get(opt.TagKey) != ""
oldTagged := old.Field.Tag().Get(opt.TagKey) != ""
if newTagged {
if oldTagged {
if len(old.levels) > len(new.levels) {
return true, false
} else if len(new.levels) > len(old.levels) {
return false, true
} else {
return true, true
}
} else {
return true, false
}
} else {
if oldTagged {
return true, false
}
if len(old.levels) > len(new.levels) {
return true, false
} else if len(new.levels) > len(old.levels) {
return false, true
} else {
return true, true
}
}
}
//结构对象 编解码-----------------------------------------------------------------------------------------------------------------------
type structEncoder struct {
typ reflect2.Type
fields []structFieldTo
}
func (this *structEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) {
stream.WriteObjectStart()
isNotFirst := false
for _, field := range this.fields {
if field.encoder.omitempty && field.encoder.IsEmpty(ptr) {
continue
}
if field.encoder.IsEmbeddedPtrNil(ptr) {
continue
}
if isNotFirst {
stream.WriteMemberSplit()
}
stream.WriteObjectFieldName(field.toName)
field.encoder.Encode(ptr, stream)
isNotFirst = true
}
stream.WriteObjectEnd()
if stream.Error() != nil && stream.Error() != io.EOF {
stream.SetErr(fmt.Errorf("%v.%s", this.typ, stream.Error().Error()))
}
}
func (this *structEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return false
}
type structDecoder struct {
opt *core.Options
typ reflect2.Type
fields map[string]*structFieldDecoder
disallowUnknownFields bool
}
func (this *structDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
if !extra.ReadObjectStart() {
return
}
this.decodeField(ptr, extra)
for extra.ReadMemberSplit() {
this.decodeField(ptr, extra)
}
if extra.Error() != nil && extra.Error() != io.EOF && len(this.typ.Type1().Name()) != 0 {
extra.SetErr(fmt.Errorf("%v.%s", this.typ, extra.Error().Error()))
}
extra.ReadObjectEnd()
}
func (this *structDecoder) decodeField(ptr unsafe.Pointer, extra core.IExtractor) {
var field string
var fieldDecoder *structFieldDecoder
field = extra.ReadString()
fieldDecoder = this.fields[field]
if fieldDecoder == nil && !this.opt.CaseSensitive {
fieldDecoder = this.fields[strings.ToLower(field)]
}
if fieldDecoder == nil {
if this.disallowUnknownFields {
msg := "found unknown field: " + field
extra.SetErr(fmt.Errorf("decodeField %s", msg))
return
}
if !extra.ReadKVSplit() {
return
}
extra.Skip() //跳过一个数据单元
return
}
if !extra.ReadKVSplit() {
return
}
fieldDecoder.Decode(ptr, extra)
}
//结构对象字段 编解码-----------------------------------------------------------------------------------------------------------------------
type structFieldTo struct {
encoder *structFieldEncoder
toName string
}
type structFieldEncoder struct {
field reflect2.StructField
fieldEncoder core.IEncoder
omitempty bool
}
func (encoder *structFieldEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) {
fieldPtr := encoder.field.UnsafeGet(ptr)
encoder.fieldEncoder.Encode(fieldPtr, stream)
if stream.Error() != nil && stream.Error() != io.EOF {
stream.SetErr(fmt.Errorf("%s: %s", encoder.field.Name(), stream.Error().Error()))
}
}
func (encoder *structFieldEncoder) IsEmpty(ptr unsafe.Pointer) bool {
fieldPtr := encoder.field.UnsafeGet(ptr)
return encoder.fieldEncoder.IsEmpty(fieldPtr)
}
func (encoder *structFieldEncoder) IsEmbeddedPtrNil(ptr unsafe.Pointer) bool {
isEmbeddedPtrNil, converted := encoder.fieldEncoder.(core.IsEmbeddedPtrNil)
if !converted {
return false
}
fieldPtr := encoder.field.UnsafeGet(ptr)
return isEmbeddedPtrNil.IsEmbeddedPtrNil(fieldPtr)
}
type structFieldDecoder struct {
field reflect2.StructField
fieldDecoder core.IDecoder
}
func (decoder *structFieldDecoder) Decode(ptr unsafe.Pointer, extra core.IExtractor) {
fieldPtr := decoder.field.UnsafeGet(ptr)
decoder.fieldDecoder.Decode(fieldPtr, extra)
if extra.Error() != nil && extra.Error() != io.EOF {
extra.SetErr(fmt.Errorf("%s: %s", decoder.field.Name(), extra.Error().Error()))
}
}
//Empty-----------------------------------------------------------------------------------------------------------------------
type emptyStructEncoder struct {
}
func (encoder *emptyStructEncoder) Encode(ptr unsafe.Pointer, stream core.IStream) {
stream.WriteEmptyObject()
}
func (encoder *emptyStructEncoder) IsEmpty(ptr unsafe.Pointer) bool {
return false
}

29
lego/sys/codec/options.go Normal file
View File

@ -0,0 +1,29 @@
package codec
import (
"go_dreamfactory/lego/sys/codec/core"
"go_dreamfactory/lego/utils/mapstructure"
)
func newOptions(config map[string]interface{}, opts ...core.Option) core.Options {
options := core.Options{
IndentionStep: 2,
}
if config != nil {
mapstructure.Decode(config, &options)
}
for _, o := range opts {
o(&options)
}
return options
}
func newOptionsByOption(opts ...core.Option) core.Options {
options := core.Options{
IndentionStep: 2,
}
for _, o := range opts {
o(&options)
}
return options
}

View File

@ -0,0 +1,201 @@
package stream
import (
"go_dreamfactory/lego/sys/codec/core"
"go_dreamfactory/lego/sys/codec/utils"
"github.com/modern-go/reflect2"
)
func NewStream(codec core.ICodec, bufSize int) *JsonStream {
return &JsonStream{
codec: codec,
buf: make([]byte, 0, bufSize),
err: nil,
indention: 0,
}
}
type JsonStream struct {
codec core.ICodec
err error
buf []byte
indention int
}
//写入对象
func (this *JsonStream) WriteVal(val interface{}) {
if nil == val {
this.WriteNil()
return
}
cacheKey := reflect2.RTypeOf(val)
encoder := this.codec.GetEncoderFromCache(cacheKey)
if encoder == nil {
typ := reflect2.TypeOf(val)
encoder = this.codec.EncoderOf(typ)
}
encoder.Encode(reflect2.PtrOf(val), this)
}
func (this *JsonStream) WriteNil() {
this.writeFourBytes('n', 'u', 'l', 'l')
}
func (this *JsonStream) WriteEmptyArray() {
this.writeTwoBytes('[', ']')
}
func (this *JsonStream) WriteArrayStart() {
this.indention += this.codec.Options().IndentionStep
this.writeByte('[')
this.writeIndention(0)
}
func (this *JsonStream) WriteArrayEnd() {
this.writeIndention(this.codec.Options().IndentionStep)
this.indention -= this.codec.Options().IndentionStep
this.writeByte(']')
}
func (this *JsonStream) WriteEmptyObject() {
this.writeTwoBytes('{', '}')
}
func (this *JsonStream) WriteObjectStart() {
this.indention += this.codec.Options().IndentionStep
this.writeByte('{')
this.writeIndention(0)
}
func (this *JsonStream) WriteObjectEnd() {
this.writeIndention(this.codec.Options().IndentionStep)
this.indention -= this.codec.Options().IndentionStep
this.writeByte('}')
}
func (this *JsonStream) WriteMemberSplit() {
this.writeByte(',')
this.writeIndention(0)
}
func (this *JsonStream) WriteKVSplit() {
this.writeByte(':')
}
func (this *JsonStream) WriteKeyStart() {
this.writeByte('"')
}
func (this *JsonStream) WriteKeyEnd() {
this.writeByte('"')
}
func (this *JsonStream) WriteObjectFieldName(val string) {
this.WriteString(val)
if this.indention > 0 {
this.writeTwoBytes(':', ' ')
} else {
this.writeByte(':')
}
}
func (this *JsonStream) WriteBool(val bool) {
if val {
this.writeTrue()
} else {
this.writeFalse()
}
}
func (this *JsonStream) WriteInt8(val int8) {
utils.WriteInt8ToString(&this.buf, val)
}
func (this *JsonStream) WriteInt16(val int16) {
utils.WriteInt16ToString(&this.buf, val)
}
func (this *JsonStream) WriteInt32(val int32) {
utils.WriteInt32ToString(&this.buf, val)
}
func (this *JsonStream) WriteInt64(val int64) {
utils.WriteInt64ToString(&this.buf, val)
}
func (this *JsonStream) WriteUint8(val uint8) {
utils.WriteUint8ToString(&this.buf, val)
}
func (this *JsonStream) WriteUint16(val uint16) {
utils.WriteUint16ToString(&this.buf, val)
}
func (this *JsonStream) WriteUint32(val uint32) {
utils.WriteUint32ToString(&this.buf, val)
}
func (this *JsonStream) WriteUint64(val uint64) {
utils.WriteUint64ToString(&this.buf, val)
}
func (this *JsonStream) WriteFloat32(val float32) {
utils.WriteFloat32ToString(&this.buf, val)
}
func (this *JsonStream) WriteFloat64(val float64) {
utils.WriteFloat64ToString(&this.buf, val)
}
func (this *JsonStream) WriteString(val string) {
valLen := len(val)
this.buf = append(this.buf, '"')
i := 0
for ; i < valLen; i++ {
c := val[i]
if c > 31 && c != '"' && c != '\\' {
this.buf = append(this.buf, c)
} else {
break
}
}
if i == valLen {
this.buf = append(this.buf, '"')
return
}
utils.WriteStringSlowPath(&this.buf, i, val, valLen)
}
func (this *JsonStream) WriteBytes(val []byte) {
this.buf = append(this.buf, val...)
}
func (this *JsonStream) Buffer() []byte {
return this.buf
}
func (this *JsonStream) Error() error {
return this.err
}
func (this *JsonStream) SetErr(err error) {
this.err = err
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------
// WriteTrue write true to stream
func (stream *JsonStream) writeTrue() {
stream.writeFourBytes('t', 'r', 'u', 'e')
}
// WriteFalse write false to stream
func (stream *JsonStream) writeFalse() {
stream.writeFiveBytes('f', 'a', 'l', 's', 'e')
}
func (this *JsonStream) writeByte(c byte) {
this.buf = append(this.buf, c)
}
func (this *JsonStream) writeTwoBytes(c1 byte, c2 byte) {
this.buf = append(this.buf, c1, c2)
}
func (this *JsonStream) writeThreeBytes(c1 byte, c2 byte, c3 byte) {
this.buf = append(this.buf, c1, c2, c3)
}
func (this *JsonStream) writeFourBytes(c1 byte, c2 byte, c3 byte, c4 byte) {
this.buf = append(this.buf, c1, c2, c3, c4)
}
func (this *JsonStream) writeFiveBytes(c1 byte, c2 byte, c3 byte, c4 byte, c5 byte) {
this.buf = append(this.buf, c1, c2, c3, c4, c5)
}
func (stream *JsonStream) writeIndention(delta int) {
if stream.indention == 0 {
return
}
stream.writeByte('\n')
toWrite := stream.indention - delta
for i := 0; i < toWrite; i++ {
stream.buf = append(stream.buf, ' ')
}
}

View File

@ -0,0 +1,36 @@
package codec_test
import (
"fmt"
"testing"
"go_dreamfactory/lego/sys/codec"
"go_dreamfactory/lego/sys/log"
)
type TestData struct {
Name string
Value int
Array []interface{}
Data map[string]interface{}
}
type Test1Data struct {
Name string
Value int
}
func Test_sys(t *testing.T) {
if err := log.OnInit(nil); err != nil {
fmt.Printf("log init err:%v", err)
return
}
if sys, err := codec.NewSys(); err != nil {
fmt.Printf("gin init err:%v", err)
} else {
d, err := sys.MarshalJson(&TestData{Name: "liwe1idao", Value: 10, Array: []interface{}{1, "dajiahao", &Test1Data{Name: "liwe1dao", Value: 123}}, Data: map[string]interface{}{"hah": 1, "asd": 999}})
fmt.Printf("codec Marshal d:%s err:%v", d, err)
data := &TestData{}
err = sys.UnmarshalJson(d, data)
fmt.Printf("codec UnmarshalJson data:%v err:%v", data, err)
}
}

View File

@ -0,0 +1,416 @@
package utils
import (
"errors"
"fmt"
"math"
"math/big"
"strconv"
"strings"
"unsafe"
)
var pow10 []uint64
var floatDigits []int8
const invalidCharForNumber = int8(-1)
const endOfNumber = int8(-2)
const dotInNumber = int8(-3)
func init() {
pow10 = []uint64{1, 10, 100, 1000, 10000, 100000, 1000000}
floatDigits = make([]int8, 256)
for i := 0; i < len(floatDigits); i++ {
floatDigits[i] = invalidCharForNumber
}
for i := int8('0'); i <= int8('9'); i++ {
floatDigits[i] = i - int8('0')
}
floatDigits[','] = endOfNumber
floatDigits[']'] = endOfNumber
floatDigits['}'] = endOfNumber
floatDigits[' '] = endOfNumber
floatDigits['\t'] = endOfNumber
floatDigits['\n'] = endOfNumber
floatDigits['.'] = dotInNumber
}
//Read Float For String-------------------------------------------------------------------------------------------------------------------------------------------------------------
//从字符串中读取float 对象
func ReadBigFloatForString(buf []byte) (ret *big.Float, n int, err error) {
var str string
if str, n, err = readNumberAsString(buf); err == nil {
return
}
prec := 64
if len(str) > prec {
prec = len(str)
}
ret, _, err = big.ParseFloat(str, 10, uint(prec), big.ToZero)
return
}
func ReadFloat32ForString(buf []byte) (ret float32, n int, err error) {
if buf[0] == '-' {
ret, n, err = readPositiveFloat32(buf[1:])
ret = -ret
return
}
return readPositiveFloat32(buf)
}
func ReadFloat64ForString(buf []byte) (ret float64, n int, err error) {
if buf[0] == '-' {
ret, n, err = readPositiveFloat64(buf[1:])
ret = -ret
return
}
return readPositiveFloat64(buf)
}
//读取float32
func readPositiveFloat32(buf []byte) (ret float32, n int, err error) {
i := 0
// first char
if len(buf) == 0 {
return readFloat32SlowPath(buf)
}
c := buf[i]
i++
ind := floatDigits[c]
switch ind {
case invalidCharForNumber:
return readFloat32SlowPath(buf)
case endOfNumber:
err = errors.New("readFloat32 empty number")
return
case dotInNumber:
err = errors.New("readFloat32 leading dot is invalid")
return
case 0:
if i == len(buf) {
return readFloat32SlowPath(buf)
}
c = buf[i]
switch c {
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
err = errors.New("readFloat32 leading zero is invalid")
return
}
}
value := uint64(ind)
// chars before dot
non_decimal_loop:
for ; i < len(buf); i++ {
c = buf[i]
ind := floatDigits[c]
switch ind {
case invalidCharForNumber:
return readFloat32SlowPath(buf)
case endOfNumber:
n = i
ret = float32(value)
return
case dotInNumber:
break non_decimal_loop
}
if value > uint64SafeToMultiple10 {
return readFloat32SlowPath(buf)
}
value = (value << 3) + (value << 1) + uint64(ind) // value = value * 10 + ind;
}
// chars after dot
if c == '.' {
i++
decimalPlaces := 0
if i == len(buf) {
return readFloat32SlowPath(buf)
}
for ; i < len(buf); i++ {
c = buf[i]
ind := floatDigits[c]
switch ind {
case endOfNumber:
if decimalPlaces > 0 && decimalPlaces < len(pow10) {
n = i
ret = float32(float64(value) / float64(pow10[decimalPlaces]))
return
}
// too many decimal places
return readFloat32SlowPath(buf)
case invalidCharForNumber, dotInNumber:
return readFloat32SlowPath(buf)
}
decimalPlaces++
if value > uint64SafeToMultiple10 {
return readFloat32SlowPath(buf)
}
value = (value << 3) + (value << 1) + uint64(ind)
}
}
return readFloat32SlowPath(buf)
}
func readFloat32SlowPath(buf []byte) (ret float32, n int, err error) {
var str string
if str, n, err = readNumberAsString(buf); err != nil {
return
}
errMsg := validateFloat(str)
if errMsg != "" {
err = errors.New(errMsg)
return
}
var val float64
if val, err = strconv.ParseFloat(str, 32); err != nil {
return
}
ret = float32(val)
return
}
//读取float64
func readPositiveFloat64(buf []byte) (ret float64, n int, err error) {
i := 0
// first char
if i == len(buf) {
return readFloat64SlowPath(buf)
}
c := buf[i]
i++
ind := floatDigits[c]
switch ind {
case invalidCharForNumber:
return readFloat64SlowPath(buf)
case endOfNumber:
err = errors.New("readFloat64 empty number")
return
case dotInNumber:
err = errors.New("readFloat64 leading dot is invalid")
return
case 0:
if i == len(buf) {
return readFloat64SlowPath(buf)
}
c = buf[i]
switch c {
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
err = errors.New("readFloat64 leading zero is invalid")
return
}
}
value := uint64(ind)
// chars before dot
non_decimal_loop:
for ; i < len(buf); i++ {
c = buf[i]
ind := floatDigits[c]
switch ind {
case invalidCharForNumber:
return readFloat64SlowPath(buf)
case endOfNumber:
n = i
ret = float64(value)
return
case dotInNumber:
break non_decimal_loop
}
if value > uint64SafeToMultiple10 {
return readFloat64SlowPath(buf)
}
value = (value << 3) + (value << 1) + uint64(ind) // value = value * 10 + ind;
}
// chars after dot
if c == '.' {
i++
decimalPlaces := 0
if i == len(buf) {
return readFloat64SlowPath(buf)
}
for ; i < len(buf); i++ {
c = buf[i]
ind := floatDigits[c]
switch ind {
case endOfNumber:
if decimalPlaces > 0 && decimalPlaces < len(pow10) {
n = i
ret = float64(value) / float64(pow10[decimalPlaces])
return
}
// too many decimal places
return readFloat64SlowPath(buf)
case invalidCharForNumber, dotInNumber:
return readFloat64SlowPath(buf)
}
decimalPlaces++
if value > uint64SafeToMultiple10 {
return readFloat64SlowPath(buf)
}
value = (value << 3) + (value << 1) + uint64(ind)
if value > maxFloat64 {
return readFloat64SlowPath(buf)
}
}
}
return readFloat64SlowPath(buf)
}
func readFloat64SlowPath(buf []byte) (ret float64, n int, err error) {
var str string
if str, n, err = readNumberAsString(buf); err != nil {
return
}
errMsg := validateFloat(str)
if errMsg != "" {
err = fmt.Errorf("readFloat64SlowPath:%v", errMsg)
return
}
ret, err = strconv.ParseFloat(str, 64)
return
}
//读取字符串数字
func readNumberAsString(buf []byte) (ret string, n int, err error) {
strBuf := [16]byte{}
str := strBuf[0:0]
load_loop:
for i := 0; i < len(buf); i++ {
c := buf[i]
switch c {
case '+', '-', '.', 'e', 'E', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
str = append(str, c)
continue
default:
n = i
break load_loop
}
}
if len(str) == 0 {
err = errors.New("readNumberAsString invalid number")
}
ret = *(*string)(unsafe.Pointer(&str))
return
}
//字符串float 错误检验
func validateFloat(str string) string {
if len(str) == 0 {
return "empty number"
}
if str[0] == '-' {
return "-- is not valid"
}
dotPos := strings.IndexByte(str, '.')
if dotPos != -1 {
if dotPos == len(str)-1 {
return "dot can not be last character"
}
switch str[dotPos+1] {
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
default:
return "missing digit after dot"
}
}
return ""
}
//Write Float To String-------------------------------------------------------------------------------------------------------------------------------------------------------------
func WriteFloat32ToString(buff *[]byte, val float32) (err error) {
if math.IsInf(float64(val), 0) || math.IsNaN(float64(val)) {
err = fmt.Errorf("unsupported value: %f", val)
return
}
abs := math.Abs(float64(val))
fmt := byte('f')
if abs != 0 {
if float32(abs) < 1e-6 || float32(abs) >= 1e21 {
fmt = 'e'
}
}
*buff = strconv.AppendFloat(*buff, float64(val), fmt, -1, 32)
return
}
//float32 写入只有 6 位精度的流,但速度要快得多
func WriteFloat32LossyToString(buf *[]byte, val float32) (err error) {
if math.IsInf(float64(val), 0) || math.IsNaN(float64(val)) {
err = fmt.Errorf("unsupported value: %f", val)
return
}
if val < 0 {
WriteChar(buf, '-')
val = -val
}
if val > 0x4ffffff {
WriteFloat32ToString(buf, val)
return
}
precision := 6
exp := uint64(1000000) // 6
lval := uint64(float64(val)*float64(exp) + 0.5)
WriteUint64ToString(buf, lval/exp)
fval := lval % exp
if fval == 0 {
return
}
WriteChar(buf, '.')
for p := precision - 1; p > 0 && fval < pow10[p]; p-- {
WriteChar(buf, '0')
}
WriteUint64ToString(buf, fval)
temp := *buf
for temp[len(temp)-1] == '0' {
temp = temp[:len(temp)-1]
}
buf = &temp
return
}
func WriteFloat64ToString(buf *[]byte, val float64) (err error) {
if math.IsInf(val, 0) || math.IsNaN(val) {
err = fmt.Errorf("unsupported value: %f", val)
return
}
abs := math.Abs(val)
fmt := byte('f')
// Note: Must use float32 comparisons for underlying float32 value to get precise cutoffs right.
if abs != 0 {
if abs < 1e-6 || abs >= 1e21 {
fmt = 'e'
}
}
*buf = strconv.AppendFloat(*buf, float64(val), fmt, -1, 64)
return
}
//将 float64 写入只有 6 位精度的流,但速度要快得多
func WriteFloat64LossyToString(buf *[]byte, val float64) (err error) {
if math.IsInf(val, 0) || math.IsNaN(val) {
err = fmt.Errorf("unsupported value: %f", val)
return
}
if val < 0 {
WriteChar(buf, '-')
val = -val
}
if val > 0x4ffffff {
WriteFloat64ToString(buf, val)
return
}
precision := 6
exp := uint64(1000000) // 6
lval := uint64(val*float64(exp) + 0.5)
WriteUint64ToString(buf, lval/exp)
fval := lval % exp
if fval == 0 {
return
}
WriteChar(buf, '.')
for p := precision - 1; p > 0 && fval < pow10[p]; p-- {
WriteChar(buf, '0')
}
WriteUint64ToString(buf, fval)
temp := *buf
for temp[len(temp)-1] == '0' {
temp = temp[:len(temp)-1]
}
buf = &temp
return
}

543
lego/sys/codec/utils/int.go Normal file
View File

@ -0,0 +1,543 @@
package utils
import (
"errors"
"math"
"strconv"
)
var digits []uint32
var intDigits []int8
const uint32SafeToMultiply10 = uint32(0xffffffff)/10 - 1
const uint64SafeToMultiple10 = uint64(0xffffffffffffffff)/10 - 1
const maxFloat64 = 1<<53 - 1
func init() {
digits = make([]uint32, 1000)
for i := uint32(0); i < 1000; i++ {
digits[i] = (((i / 100) + '0') << 16) + ((((i / 10) % 10) + '0') << 8) + i%10 + '0'
if i < 10 {
digits[i] += 2 << 24
} else if i < 100 {
digits[i] += 1 << 24
}
}
intDigits = make([]int8, 256)
for i := 0; i < len(intDigits); i++ {
intDigits[i] = invalidCharForNumber
}
for i := int8('0'); i <= int8('9'); i++ {
intDigits[i] = i - int8('0')
}
}
//Read Int For String--------------------------------------------------------------------------------------------------------------------------------
func ReadInt8ForString(buf []byte) (ret int8, n int, err error) {
var (
val uint32
)
c := buf[0]
if c == '-' {
val, n, err = ReadUint32ForString(buf[1:])
if val > math.MaxInt8+1 {
err = errors.New("ReadInt8ForString overflow: " + strconv.FormatInt(int64(val), 10))
return
}
ret = -int8(val)
return
}
val, n, err = ReadUint32ForString(buf)
if val > math.MaxInt8 {
err = errors.New("ReadInt8ForString overflow: " + strconv.FormatInt(int64(val), 10))
return
}
ret = int8(val)
return
}
func ReadInt16ForString(buf []byte) (ret int16, n int, err error) {
var (
val uint32
)
c := buf[0]
if c == '-' {
val, n, err = ReadUint32ForString(buf[1:])
if val > math.MaxInt16+1 {
err = errors.New("ReadInt16ForString overflow: " + strconv.FormatInt(int64(val), 10))
return
}
ret = -int16(val)
return
}
val, n, err = ReadUint32ForString(buf)
if val > math.MaxInt16 {
err = errors.New("ReadInt16ForString overflow: " + strconv.FormatInt(int64(val), 10))
return
}
ret = int16(val)
return
}
func ReadInt32ForString(buf []byte) (ret int32, n int, err error) {
var (
val uint32
)
c := buf[0]
if c == '-' {
val, n, err = ReadUint32ForString(buf[1:])
if val > math.MaxInt32+1 {
err = errors.New("ReadInt32ForString overflow: " + strconv.FormatInt(int64(val), 10))
return
}
ret = -int32(val)
return
}
val, n, err = ReadUint32ForString(buf)
if val > math.MaxInt32 {
err = errors.New("ReadInt32ForString overflow: " + strconv.FormatInt(int64(val), 10))
return
}
ret = int32(val)
return
}
func ReadInt64ForString(buf []byte) (ret int64, n int, err error) {
var (
val uint64
)
c := buf[0]
if c == '-' {
val, n, err = ReadUint64ForString(buf[1:])
if val > math.MaxInt64+1 {
err = errors.New("ReadInt64ForString overflow: " + strconv.FormatInt(int64(val), 10))
return
}
ret = -int64(val)
return
}
val, n, err = ReadUint64ForString(buf)
if val > math.MaxInt64 {
err = errors.New("ReadInt64ForString overflow: " + strconv.FormatInt(int64(val), 10))
return
}
ret = int64(val)
return
}
func ReadUint8ForString(buf []byte) (ret uint8, n int, err error) {
var (
val uint32
)
val, n, err = ReadUint32ForString(buf)
if val > math.MaxUint8 {
err = errors.New("ReadUInt8ForString overflow: " + strconv.FormatInt(int64(val), 10))
return
}
ret = uint8(val)
return
}
func ReadUint16ForString(buf []byte) (ret uint16, n int, err error) {
var (
val uint32
)
val, n, err = ReadUint32ForString(buf)
if val > math.MaxUint16 {
err = errors.New("ReadUInt16ForString overflow: " + strconv.FormatInt(int64(val), 10))
return
}
ret = uint16(val)
return
}
func ReadUint32ForString(buf []byte) (ret uint32, n int, err error) {
ind := intDigits[buf[0]]
if ind == 0 {
err = assertInteger(buf[1:])
return
}
if ind == invalidCharForNumber {
err = errors.New("ReadUint32ForString unexpected character: " + string([]byte{byte(ind)}))
return
}
ret = uint32(ind)
if len(buf) > 10 {
i := 0
ind2 := intDigits[buf[i]]
if ind2 == invalidCharForNumber {
n = i
err = assertInteger(buf[i:])
return
}
i++
ind3 := intDigits[buf[i]]
if ind3 == invalidCharForNumber {
n = i
err = assertInteger(buf[i:])
ret = ret*10 + uint32(ind2)
return
}
i++
ind4 := intDigits[buf[i]]
if ind4 == invalidCharForNumber {
n = i
err = assertInteger(buf[i:])
ret = ret*100 + uint32(ind2)*10 + uint32(ind3)
return
}
i++
ind5 := intDigits[buf[i]]
if ind5 == invalidCharForNumber {
n = i
err = assertInteger(buf[i:])
ret = ret*1000 + uint32(ind2)*100 + uint32(ind3)*10 + uint32(ind4)
return
}
i++
ind6 := intDigits[buf[i]]
if ind6 == invalidCharForNumber {
n = i
err = assertInteger(buf[i:])
ret = ret*10000 + uint32(ind2)*1000 + uint32(ind3)*100 + uint32(ind4)*10 + uint32(ind5)
return
}
i++
ind7 := intDigits[buf[i]]
if ind7 == invalidCharForNumber {
n = i
err = assertInteger(buf[i:])
ret = ret*100000 + uint32(ind2)*10000 + uint32(ind3)*1000 + uint32(ind4)*100 + uint32(ind5)*10 + uint32(ind6)
return
}
i++
ind8 := intDigits[buf[i]]
if ind8 == invalidCharForNumber {
n = i
err = assertInteger(buf[i:])
ret = ret*1000000 + uint32(ind2)*100000 + uint32(ind3)*10000 + uint32(ind4)*1000 + uint32(ind5)*100 + uint32(ind6)*10 + uint32(ind7)
return
}
i++
ind9 := intDigits[buf[i]]
ret = ret*10000000 + uint32(ind2)*1000000 + uint32(ind3)*100000 + uint32(ind4)*10000 + uint32(ind5)*1000 + uint32(ind6)*100 + uint32(ind7)*10 + uint32(ind8)
n = i
if ind9 == invalidCharForNumber {
err = assertInteger(buf[i:])
return
}
}
for i := 1; i < len(buf); i++ {
ind = intDigits[buf[i]]
if ind == invalidCharForNumber {
n = i
err = assertInteger(buf[i:])
return
}
if ret > uint32SafeToMultiply10 {
value2 := (ret << 3) + (ret << 1) + uint32(ind)
if value2 < ret {
err = errors.New("ReadUint32ForString overflow")
return
}
ret = value2
continue
}
ret = (ret << 3) + (ret << 1) + uint32(ind)
}
return
}
func ReadUint64ForString(buf []byte) (ret uint64, n int, err error) {
ind := intDigits[buf[0]]
if ind == 0 {
err = assertInteger(buf[1:])
return
}
if ind == invalidCharForNumber {
err = errors.New("ReadUint64ForString unexpected character: " + string([]byte{byte(ind)}))
return
}
ret = uint64(ind)
if len(buf) > 10 {
i := 0
ind2 := intDigits[buf[i]]
if ind2 == invalidCharForNumber {
n = i
err = assertInteger(buf[i:])
return
}
i++
ind3 := intDigits[buf[i]]
if ind3 == invalidCharForNumber {
n = i
err = assertInteger(buf[i:])
ret = ret*10 + uint64(ind2)
return
}
i++
ind4 := intDigits[buf[i]]
if ind4 == invalidCharForNumber {
n = i
err = assertInteger(buf[i:])
ret = ret*100 + uint64(ind2)*10 + uint64(ind3)
return
}
i++
ind5 := intDigits[buf[i]]
if ind5 == invalidCharForNumber {
n = i
err = assertInteger(buf[i:])
ret = ret*1000 + uint64(ind2)*100 + uint64(ind3)*10 + uint64(ind4)
return
}
i++
ind6 := intDigits[buf[i]]
if ind6 == invalidCharForNumber {
n = i
err = assertInteger(buf[i:])
ret = ret*10000 + uint64(ind2)*1000 + uint64(ind3)*100 + uint64(ind4)*10 + uint64(ind5)
return
}
i++
ind7 := intDigits[buf[i]]
if ind7 == invalidCharForNumber {
n = i
err = assertInteger(buf[i:])
ret = ret*100000 + uint64(ind2)*10000 + uint64(ind3)*1000 + uint64(ind4)*100 + uint64(ind5)*10 + uint64(ind6)
return
}
i++
ind8 := intDigits[buf[i]]
if ind8 == invalidCharForNumber {
n = i
err = assertInteger(buf[i:])
ret = ret*1000000 + uint64(ind2)*100000 + uint64(ind3)*10000 + uint64(ind4)*1000 + uint64(ind5)*100 + uint64(ind6)*10 + uint64(ind7)
return
}
i++
ind9 := intDigits[buf[i]]
ret = ret*10000000 + uint64(ind2)*1000000 + uint64(ind3)*100000 + uint64(ind4)*10000 + uint64(ind5)*1000 + uint64(ind6)*100 + uint64(ind7)*10 + uint64(ind8)
n = i
if ind9 == invalidCharForNumber {
err = assertInteger(buf[i:])
return
}
}
for i := 1; i < len(buf); i++ {
ind = intDigits[buf[i]]
if ind == invalidCharForNumber {
n = i
err = assertInteger(buf[i:])
return
}
if ret > uint64SafeToMultiple10 {
value2 := (ret << 3) + (ret << 1) + uint64(ind)
if value2 < ret {
err = errors.New("ReadUint64ForString overflow")
return
}
ret = value2
continue
}
ret = (ret << 3) + (ret << 1) + uint64(ind)
}
return
}
func assertInteger(buf []byte) (err error) {
if len(buf) > 0 && buf[0] == '.' {
err = errors.New("assertInteger can not decode float as int")
}
return
}
//Write Int To String--------------------------------------------------------------------------------------------------------------------------------
func WriteChar(buff *[]byte, c byte) {
*buff = append(*buff, c)
}
// WriteUint8 write uint8 to stream
func WriteUint8ToString(buf *[]byte, val uint8) {
*buf = writeFirstBuf(*buf, digits[val])
return
}
// WriteInt8 write int8 to stream
func WriteInt8ToString(buf *[]byte, nval int8) {
var val uint8
if nval < 0 {
val = uint8(-nval)
*buf = append(*buf, '-')
} else {
val = uint8(nval)
}
*buf = writeFirstBuf(*buf, digits[val])
return
}
// WriteUint16 write uint16 to stream
func WriteUint16ToString(buf *[]byte, val uint16) {
q1 := val / 1000
if q1 == 0 {
*buf = writeFirstBuf(*buf, digits[val])
return
}
r1 := val - q1*1000
*buf = writeFirstBuf(*buf, digits[q1])
*buf = writeBuf(*buf, digits[r1])
return
}
// WriteInt16 write int16 to stream
func WriteInt16ToString(buf *[]byte, nval int16) {
var val uint16
if nval < 0 {
val = uint16(-nval)
*buf = append(*buf, '-')
} else {
val = uint16(nval)
}
WriteUint16ToString(buf, val)
return
}
// WriteUint32 write uint32 to stream
func WriteUint32ToString(buf *[]byte, val uint32) {
q1 := val / 1000
if q1 == 0 {
*buf = writeFirstBuf(*buf, digits[val])
return
}
r1 := val - q1*1000
q2 := q1 / 1000
if q2 == 0 {
*buf = writeFirstBuf(*buf, digits[q1])
*buf = writeBuf(*buf, digits[r1])
return
}
r2 := q1 - q2*1000
q3 := q2 / 1000
if q3 == 0 {
*buf = writeFirstBuf(*buf, digits[q2])
} else {
r3 := q2 - q3*1000
*buf = append(*buf, byte(q3+'0'))
*buf = writeBuf(*buf, digits[r3])
}
*buf = writeBuf(*buf, digits[r2])
*buf = writeBuf(*buf, digits[r1])
return
}
// WriteInt32 write int32 to stream
func WriteInt32ToString(buf *[]byte, nval int32) {
var val uint32
if nval < 0 {
val = uint32(-nval)
*buf = append(*buf, '-')
} else {
val = uint32(nval)
}
WriteUint32ToString(buf, val)
return
}
// WriteUint64 write uint64 to stream
func WriteUint64ToString(buf *[]byte, val uint64) {
q1 := val / 1000
if q1 == 0 {
*buf = writeFirstBuf(*buf, digits[val])
return
}
r1 := val - q1*1000
q2 := q1 / 1000
if q2 == 0 {
*buf = writeFirstBuf(*buf, digits[q1])
*buf = writeBuf(*buf, digits[r1])
return
}
r2 := q1 - q2*1000
q3 := q2 / 1000
if q3 == 0 {
*buf = writeFirstBuf(*buf, digits[q2])
*buf = writeBuf(*buf, digits[r2])
*buf = writeBuf(*buf, digits[r1])
return
}
r3 := q2 - q3*1000
q4 := q3 / 1000
if q4 == 0 {
*buf = writeFirstBuf(*buf, digits[q3])
*buf = writeBuf(*buf, digits[r3])
*buf = writeBuf(*buf, digits[r2])
*buf = writeBuf(*buf, digits[r1])
return
}
r4 := q3 - q4*1000
q5 := q4 / 1000
if q5 == 0 {
*buf = writeFirstBuf(*buf, digits[q4])
*buf = writeBuf(*buf, digits[r4])
*buf = writeBuf(*buf, digits[r3])
*buf = writeBuf(*buf, digits[r2])
*buf = writeBuf(*buf, digits[r1])
return
}
r5 := q4 - q5*1000
q6 := q5 / 1000
if q6 == 0 {
*buf = writeFirstBuf(*buf, digits[q5])
} else {
*buf = writeFirstBuf(*buf, digits[q6])
r6 := q5 - q6*1000
*buf = writeBuf(*buf, digits[r6])
}
*buf = writeBuf(*buf, digits[r5])
*buf = writeBuf(*buf, digits[r4])
*buf = writeBuf(*buf, digits[r3])
*buf = writeBuf(*buf, digits[r2])
*buf = writeBuf(*buf, digits[r1])
return
}
// WriteInt64 write int64 to stream
func WriteInt64ToString(buf *[]byte, nval int64) {
var val uint64
if nval < 0 {
val = uint64(-nval)
*buf = append(*buf, '-')
} else {
val = uint64(nval)
}
WriteUint64ToString(buf, val)
return
}
// WriteInt write int to stream
func WriteIntToString(buf *[]byte, val int) {
WriteInt64ToString(buf, int64(val))
return
}
// WriteUint write uint to stream
func WriteUint(buf *[]byte, val uint) {
WriteUint64ToString(buf, uint64(val))
return
}
func writeFirstBuf(space []byte, v uint32) []byte {
start := v >> 24
if start == 0 {
space = append(space, byte(v>>16), byte(v>>8))
} else if start == 1 {
space = append(space, byte(v>>8))
}
space = append(space, byte(v))
return space
}
func writeBuf(buf []byte, v uint32) []byte {
return append(buf, byte(v>>16), byte(v>>8), byte(v))
}

View File

@ -0,0 +1,349 @@
package utils
import "unicode/utf8"
var htmlSafeSet = [utf8.RuneSelf]bool{
' ': true,
'!': true,
'"': false,
'#': true,
'$': true,
'%': true,
'&': false,
'\'': true,
'(': true,
')': true,
'*': true,
'+': true,
',': true,
'-': true,
'.': true,
'/': true,
'0': true,
'1': true,
'2': true,
'3': true,
'4': true,
'5': true,
'6': true,
'7': true,
'8': true,
'9': true,
':': true,
';': true,
'<': false,
'=': true,
'>': false,
'?': true,
'@': true,
'A': true,
'B': true,
'C': true,
'D': true,
'E': true,
'F': true,
'G': true,
'H': true,
'I': true,
'J': true,
'K': true,
'L': true,
'M': true,
'N': true,
'O': true,
'P': true,
'Q': true,
'R': true,
'S': true,
'T': true,
'U': true,
'V': true,
'W': true,
'X': true,
'Y': true,
'Z': true,
'[': true,
'\\': false,
']': true,
'^': true,
'_': true,
'`': true,
'a': true,
'b': true,
'c': true,
'd': true,
'e': true,
'f': true,
'g': true,
'h': true,
'i': true,
'j': true,
'k': true,
'l': true,
'm': true,
'n': true,
'o': true,
'p': true,
'q': true,
'r': true,
's': true,
't': true,
'u': true,
'v': true,
'w': true,
'x': true,
'y': true,
'z': true,
'{': true,
'|': true,
'}': true,
'~': true,
'\u007f': true,
}
var safeSet = [utf8.RuneSelf]bool{
' ': true,
'!': true,
'"': false,
'#': true,
'$': true,
'%': true,
'&': true,
'\'': true,
'(': true,
')': true,
'*': true,
'+': true,
',': true,
'-': true,
'.': true,
'/': true,
'0': true,
'1': true,
'2': true,
'3': true,
'4': true,
'5': true,
'6': true,
'7': true,
'8': true,
'9': true,
':': true,
';': true,
'<': true,
'=': true,
'>': true,
'?': true,
'@': true,
'A': true,
'B': true,
'C': true,
'D': true,
'E': true,
'F': true,
'G': true,
'H': true,
'I': true,
'J': true,
'K': true,
'L': true,
'M': true,
'N': true,
'O': true,
'P': true,
'Q': true,
'R': true,
'S': true,
'T': true,
'U': true,
'V': true,
'W': true,
'X': true,
'Y': true,
'Z': true,
'[': true,
'\\': false,
']': true,
'^': true,
'_': true,
'`': true,
'a': true,
'b': true,
'c': true,
'd': true,
'e': true,
'f': true,
'g': true,
'h': true,
'i': true,
'j': true,
'k': true,
'l': true,
'm': true,
'n': true,
'o': true,
'p': true,
'q': true,
'r': true,
's': true,
't': true,
'u': true,
'v': true,
'w': true,
'x': true,
'y': true,
'z': true,
'{': true,
'|': true,
'}': true,
'~': true,
'\u007f': true,
}
var hex = "0123456789abcdef"
func WriteStringSlowPathWithHTMLEscaped(buf *[]byte, i int, s string, valLen int) {
start := i
// for the remaining parts, we process them char by char
for i < valLen {
if b := s[i]; b < utf8.RuneSelf {
if htmlSafeSet[b] {
i++
continue
}
if start < i {
*buf = append(*buf, s[start:i]...)
}
switch b {
case '\\', '"':
*buf = append(*buf, '\\', b)
case '\n':
*buf = append(*buf, '\\', 'n')
case '\r':
*buf = append(*buf, '\\', 'r')
case '\t':
*buf = append(*buf, '\\', 't')
default:
*buf = append(*buf, `\u00`...)
*buf = append(*buf, hex[b>>4], hex[b&0xF])
}
i++
start = i
continue
}
c, size := utf8.DecodeRuneInString(s[i:])
if c == utf8.RuneError && size == 1 {
if start < i {
*buf = append(*buf, s[start:i]...)
}
*buf = append(*buf, `\ufffd`...)
i++
start = i
continue
}
if c == '\u2028' || c == '\u2029' {
if start < i {
*buf = append(*buf, s[start:i]...)
}
*buf = append(*buf, `\u202`...)
*buf = append(*buf, hex[c&0xF])
i += size
start = i
continue
}
i += size
}
if start < len(s) {
*buf = append(*buf, s[start:]...)
}
*buf = append(*buf, '"')
}
func WriteStringSlowPath(buf *[]byte, i int, s string, valLen int) {
start := i
for i < valLen {
if b := s[i]; b < utf8.RuneSelf {
if safeSet[b] {
i++
continue
}
if start < i {
*buf = append(*buf, s[start:i]...)
}
switch b {
case '\\', '"':
*buf = append(*buf, '\\', b)
case '\n':
*buf = append(*buf, '\\', 'n')
case '\r':
*buf = append(*buf, '\\', 'r')
case '\t':
*buf = append(*buf, '\\', 't')
default:
*buf = append(*buf, `\u00`...)
*buf = append(*buf, hex[b>>4], hex[b&0xF])
}
i++
start = i
continue
}
i++
continue
}
if start < len(s) {
*buf = append(*buf, s[start:]...)
}
*buf = append(*buf, '"')
}
const (
t1 = 0x00 // 0000 0000
tx = 0x80 // 1000 0000
t2 = 0xC0 // 1100 0000
t3 = 0xE0 // 1110 0000
t4 = 0xF0 // 1111 0000
t5 = 0xF8 // 1111 1000
maskx = 0x3F // 0011 1111
mask2 = 0x1F // 0001 1111
mask3 = 0x0F // 0000 1111
mask4 = 0x07 // 0000 0111
rune1Max = 1<<7 - 1
rune2Max = 1<<11 - 1
rune3Max = 1<<16 - 1
surrogateMin = 0xD800
surrogateMax = 0xDFFF
maxRune = '\U0010FFFF' // Maximum valid Unicode code point.
runeError = '\uFFFD' // the "error" Rune or "Unicode replacement character"
)
func AppendRune(p []byte, r rune) []byte {
// Negative values are erroneous. Making it unsigned addresses the problem.
switch i := uint32(r); {
case i <= rune1Max:
p = append(p, byte(r))
return p
case i <= rune2Max:
p = append(p, t2|byte(r>>6))
p = append(p, tx|byte(r)&maskx)
return p
case i > maxRune, surrogateMin <= i && i <= surrogateMax:
r = runeError
fallthrough
case i <= rune3Max:
p = append(p, t3|byte(r>>12))
p = append(p, tx|byte(r>>6)&maskx)
p = append(p, tx|byte(r)&maskx)
return p
default:
p = append(p, t4|byte(r>>18))
p = append(p, tx|byte(r>>12)&maskx)
p = append(p, tx|byte(r>>6)&maskx)
p = append(p, tx|byte(r)&maskx)
return p
}
}