上传codec 编码系统代码
This commit is contained in:
parent
83dd0f905f
commit
906afe87d0
180
lego/sys/codec/codec.go
Normal file
180
lego/sys/codec/codec.go
Normal 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
24
lego/sys/codec/core.go
Normal 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
146
lego/sys/codec/core/core.go
Normal 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,
|
||||
}
|
||||
}
|
30
lego/sys/codec/core/options.go
Normal file
30
lego/sys/codec/core/options.go
Normal 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
|
||||
}
|
866
lego/sys/codec/extractor/json.go
Normal file
866
lego/sys/codec/extractor/json.go
Normal 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
|
||||
}
|
179
lego/sys/codec/factory/factory.go
Normal file
179
lego/sys/codec/factory/factory.go
Normal 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
|
||||
}
|
94
lego/sys/codec/factory/factory_array.go
Normal file
94
lego/sys/codec/factory/factory_array.go
Normal 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
|
||||
}
|
74
lego/sys/codec/factory/factory_interface.go
Normal file
74
lego/sys/codec/factory/factory_interface.go
Normal 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)
|
||||
}
|
196
lego/sys/codec/factory/factory_map.go
Normal file
196
lego/sys/codec/factory/factory_map.go
Normal 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))
|
||||
}
|
397
lego/sys/codec/factory/factory_native.go
Normal file
397
lego/sys/codec/factory/factory_native.go
Normal 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)))
|
||||
}
|
130
lego/sys/codec/factory/factory_optional.go
Normal file
130
lego/sys/codec/factory/factory_optional.go
Normal 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)
|
||||
}
|
91
lego/sys/codec/factory/factory_slice.go
Normal file
91
lego/sys/codec/factory/factory_slice.go
Normal 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()))
|
||||
}
|
||||
}
|
383
lego/sys/codec/factory/factory_struct.go
Normal file
383
lego/sys/codec/factory/factory_struct.go
Normal 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
29
lego/sys/codec/options.go
Normal 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
|
||||
}
|
201
lego/sys/codec/stream/json.go
Normal file
201
lego/sys/codec/stream/json.go
Normal 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, ' ')
|
||||
}
|
||||
}
|
36
lego/sys/codec/sys_test.go
Normal file
36
lego/sys/codec/sys_test.go
Normal 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)
|
||||
}
|
||||
}
|
416
lego/sys/codec/utils/float.go
Normal file
416
lego/sys/codec/utils/float.go
Normal 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
543
lego/sys/codec/utils/int.go
Normal 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))
|
||||
}
|
349
lego/sys/codec/utils/string.go
Normal file
349
lego/sys/codec/utils/string.go
Normal 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
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user