forked from mirror/go-json
Add VirtualMachine for Encoder
This commit is contained in:
parent
3b27b5f267
commit
4f3b1262b2
20
encode.go
20
encode.go
|
@ -29,14 +29,14 @@ type EncodeOpMap struct {
|
||||||
sync.Map
|
sync.Map
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *EncodeOpMap) Get(k string) EncodeOp {
|
func (m *EncodeOpMap) Get(k string) *opcode { //EncodeOp {
|
||||||
if v, ok := m.Load(k); ok {
|
if v, ok := m.Load(k); ok {
|
||||||
return v.(EncodeOp)
|
return v.(*opcode) //(EncodeOp)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *EncodeOpMap) Set(k string, op EncodeOp) {
|
func (m *EncodeOpMap) Set(k string, op *opcode) { // EncodeOp) {
|
||||||
m.Store(k, op)
|
m.Store(k, op)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,17 +181,23 @@ func (e *Encoder) encode(v interface{}) error {
|
||||||
name := typ.String()
|
name := typ.String()
|
||||||
if op := cachedEncodeOp.Get(name); op != nil {
|
if op := cachedEncodeOp.Get(name); op != nil {
|
||||||
p := uintptr(header.ptr)
|
p := uintptr(header.ptr)
|
||||||
op(e, typ, p)
|
op.ptr = p
|
||||||
|
if err := e.run(op); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
//op(e, typ, p)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
op, err := e.compile(typ)
|
op, err := e.compileOp(typ)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == errCompileSlowPath {
|
if err == errCompileSlowPath {
|
||||||
|
/*
|
||||||
slowOp, err := e.compileSlowPath(typ)
|
slowOp, err := e.compileSlowPath(typ)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
op = slowOp
|
op = slowOp
|
||||||
|
*/
|
||||||
} else {
|
} else {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -200,7 +206,9 @@ func (e *Encoder) encode(v interface{}) error {
|
||||||
cachedEncodeOp.Set(name, op)
|
cachedEncodeOp.Set(name, op)
|
||||||
}
|
}
|
||||||
p := uintptr(header.ptr)
|
p := uintptr(header.ptr)
|
||||||
op(e, typ, p)
|
op.ptr = p
|
||||||
|
e.run(op)
|
||||||
|
//op(e, typ, p)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,233 @@
|
||||||
|
package json
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/xerrors"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (e *Encoder) compileOp(typ *rtype) (*opcode, error) {
|
||||||
|
switch typ.Kind() {
|
||||||
|
case reflect.Ptr:
|
||||||
|
return e.compilePtrOp(typ)
|
||||||
|
case reflect.Slice:
|
||||||
|
return e.compileSliceOp(typ)
|
||||||
|
case reflect.Struct:
|
||||||
|
return e.compileStructOp(typ)
|
||||||
|
case reflect.Int:
|
||||||
|
return e.compileIntOp(typ)
|
||||||
|
case reflect.Int8:
|
||||||
|
return e.compileInt8Op(typ)
|
||||||
|
case reflect.Int16:
|
||||||
|
return e.compileInt16Op(typ)
|
||||||
|
case reflect.Int32:
|
||||||
|
return e.compileInt32Op(typ)
|
||||||
|
case reflect.Int64:
|
||||||
|
return e.compileInt64Op(typ)
|
||||||
|
case reflect.Uint:
|
||||||
|
return e.compileUintOp(typ)
|
||||||
|
case reflect.Uint8:
|
||||||
|
return e.compileUint8Op(typ)
|
||||||
|
case reflect.Uint16:
|
||||||
|
return e.compileUint16Op(typ)
|
||||||
|
case reflect.Uint32:
|
||||||
|
return e.compileUint32Op(typ)
|
||||||
|
case reflect.Uint64:
|
||||||
|
return e.compileUint64Op(typ)
|
||||||
|
case reflect.Uintptr:
|
||||||
|
return e.compileUintOp(typ)
|
||||||
|
case reflect.Float32:
|
||||||
|
return e.compileFloat32Op(typ)
|
||||||
|
case reflect.Float64:
|
||||||
|
return e.compileFloat64Op(typ)
|
||||||
|
case reflect.String:
|
||||||
|
return e.compileStringOp(typ)
|
||||||
|
case reflect.Bool:
|
||||||
|
return e.compileBoolOp(typ)
|
||||||
|
case reflect.Interface:
|
||||||
|
return nil, errCompileSlowPath
|
||||||
|
}
|
||||||
|
return nil, xerrors.Errorf("failed to encode type %s: %w", typ.String(), ErrUnsupportedType)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Encoder) compilePtrOp(typ *rtype) (*opcode, error) {
|
||||||
|
elem := typ.Elem()
|
||||||
|
code, err := e.compileOp(elem)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &opcode{
|
||||||
|
opcodeHeader: &opcodeHeader{
|
||||||
|
op: opPtr,
|
||||||
|
typ: typ,
|
||||||
|
next: code,
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Encoder) compileIntOp(typ *rtype) (*opcode, error) {
|
||||||
|
return newOpCode(opInt, typ, newEndOp()), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Encoder) compileInt8Op(typ *rtype) (*opcode, error) {
|
||||||
|
return newOpCode(opInt8, typ, newEndOp()), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Encoder) compileInt16Op(typ *rtype) (*opcode, error) {
|
||||||
|
return newOpCode(opInt16, typ, newEndOp()), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Encoder) compileInt32Op(typ *rtype) (*opcode, error) {
|
||||||
|
return newOpCode(opInt32, typ, newEndOp()), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Encoder) compileInt64Op(typ *rtype) (*opcode, error) {
|
||||||
|
return newOpCode(opInt64, typ, newEndOp()), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Encoder) compileUintOp(typ *rtype) (*opcode, error) {
|
||||||
|
return newOpCode(opUint, typ, newEndOp()), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Encoder) compileUint8Op(typ *rtype) (*opcode, error) {
|
||||||
|
return newOpCode(opUint8, typ, newEndOp()), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Encoder) compileUint16Op(typ *rtype) (*opcode, error) {
|
||||||
|
return newOpCode(opUint16, typ, newEndOp()), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Encoder) compileUint32Op(typ *rtype) (*opcode, error) {
|
||||||
|
return newOpCode(opUint32, typ, newEndOp()), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Encoder) compileUint64Op(typ *rtype) (*opcode, error) {
|
||||||
|
return newOpCode(opUint64, typ, newEndOp()), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Encoder) compileFloat32Op(typ *rtype) (*opcode, error) {
|
||||||
|
return newOpCode(opFloat32, typ, newEndOp()), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Encoder) compileFloat64Op(typ *rtype) (*opcode, error) {
|
||||||
|
return newOpCode(opFloat64, typ, newEndOp()), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Encoder) compileStringOp(typ *rtype) (*opcode, error) {
|
||||||
|
return newOpCode(opString, typ, newEndOp()), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Encoder) compileBoolOp(typ *rtype) (*opcode, error) {
|
||||||
|
return newOpCode(opBool, typ, newEndOp()), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Encoder) compileSliceOp(typ *rtype) (*opcode, error) {
|
||||||
|
elem := typ.Elem()
|
||||||
|
size := elem.Size()
|
||||||
|
code, err := e.compileOp(elem)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// header => firstElem => opcode => elem => end
|
||||||
|
// ^ |
|
||||||
|
// |________|
|
||||||
|
|
||||||
|
header := &opcode{opcodeHeader: &opcodeHeader{op: opSliceHead}}
|
||||||
|
firstElem := &sliceElemCode{opcodeHeader: &opcodeHeader{op: opSliceElemFirst}}
|
||||||
|
elemCode := &sliceElemCode{opcodeHeader: &opcodeHeader{op: opSliceElem}, size: size}
|
||||||
|
end := &opcode{opcodeHeader: &opcodeHeader{op: opSliceEnd}}
|
||||||
|
|
||||||
|
header.next = (*opcode)(unsafe.Pointer(firstElem))
|
||||||
|
firstElem.next = code
|
||||||
|
firstElem.elem = elemCode
|
||||||
|
code.beforeLastCode().next = (*opcode)(unsafe.Pointer(elemCode))
|
||||||
|
elemCode.next = code
|
||||||
|
elemCode.end = end
|
||||||
|
end.next = &opcode{opcodeHeader: &opcodeHeader{op: opEnd}}
|
||||||
|
return (*opcode)(unsafe.Pointer(header)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Encoder) compileStructOp(typ *rtype) (*opcode, error) {
|
||||||
|
// header => firstField => structField => end
|
||||||
|
// ^ |
|
||||||
|
// |________|
|
||||||
|
fieldNum := typ.NumField()
|
||||||
|
fieldIdx := 0
|
||||||
|
header := &opcode{opcodeHeader: &opcodeHeader{op: opStructHead}}
|
||||||
|
code := header
|
||||||
|
var prevField *structFieldCode
|
||||||
|
for i := 0; i < fieldNum; i++ {
|
||||||
|
field := typ.Field(i)
|
||||||
|
if e.isIgnoredStructField(field) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
keyName := field.Name
|
||||||
|
tag := e.getTag(field)
|
||||||
|
opts := strings.Split(tag, ",")
|
||||||
|
if len(opts) > 0 {
|
||||||
|
if opts[0] != "" {
|
||||||
|
keyName = opts[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fieldType := type2rtype(field.Type)
|
||||||
|
valueCode, err := e.compileOp(fieldType)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
key := fmt.Sprintf(`"%s":`, keyName)
|
||||||
|
if fieldIdx == 0 {
|
||||||
|
fieldCode := &structFieldCode{
|
||||||
|
opcodeHeader: &opcodeHeader{
|
||||||
|
op: opStructFieldFirst,
|
||||||
|
typ: fieldType,
|
||||||
|
next: valueCode,
|
||||||
|
},
|
||||||
|
key: key,
|
||||||
|
offset: field.Offset,
|
||||||
|
}
|
||||||
|
code.next = (*opcode)(unsafe.Pointer(fieldCode))
|
||||||
|
prevField = fieldCode
|
||||||
|
if valueCode.op == opInt {
|
||||||
|
fieldCode.op = opStructFieldFirstInt
|
||||||
|
code = (*opcode)(unsafe.Pointer(fieldCode))
|
||||||
|
} else if valueCode.op == opString {
|
||||||
|
fieldCode.op = opStructFieldFirstString
|
||||||
|
code = (*opcode)(unsafe.Pointer(fieldCode))
|
||||||
|
} else {
|
||||||
|
code = valueCode.beforeLastCode()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fieldCode := &structFieldCode{
|
||||||
|
opcodeHeader: &opcodeHeader{
|
||||||
|
op: opStructField,
|
||||||
|
typ: fieldType,
|
||||||
|
next: valueCode,
|
||||||
|
},
|
||||||
|
key: key,
|
||||||
|
offset: field.Offset,
|
||||||
|
}
|
||||||
|
code.next = (*opcode)(unsafe.Pointer(fieldCode))
|
||||||
|
prevField.nextField = (*opcode)(unsafe.Pointer(fieldCode))
|
||||||
|
prevField = fieldCode
|
||||||
|
if valueCode.op == opInt {
|
||||||
|
fieldCode.op = opStructFieldInt
|
||||||
|
code = (*opcode)(unsafe.Pointer(fieldCode))
|
||||||
|
} else if valueCode.op == opString {
|
||||||
|
fieldCode.op = opStructFieldString
|
||||||
|
code = (*opcode)(unsafe.Pointer(fieldCode))
|
||||||
|
} else {
|
||||||
|
code = valueCode.beforeLastCode()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
prevField.nextField = &opcode{opcodeHeader: &opcodeHeader{op: opEnd}}
|
||||||
|
fieldIdx++
|
||||||
|
}
|
||||||
|
structEndCode := &opcode{opcodeHeader: &opcodeHeader{op: opStructEnd}}
|
||||||
|
code.next = structEndCode
|
||||||
|
structEndCode.next = &opcode{opcodeHeader: &opcodeHeader{op: opEnd}}
|
||||||
|
return header, nil
|
||||||
|
}
|
|
@ -0,0 +1,198 @@
|
||||||
|
package json
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
type opType int
|
||||||
|
|
||||||
|
const (
|
||||||
|
opEnd opType = iota
|
||||||
|
opInt
|
||||||
|
opInt8
|
||||||
|
opInt16
|
||||||
|
opInt32
|
||||||
|
opInt64
|
||||||
|
opUint
|
||||||
|
opUint8
|
||||||
|
opUint16
|
||||||
|
opUint32
|
||||||
|
opUint64
|
||||||
|
opFloat32
|
||||||
|
opFloat64
|
||||||
|
opString
|
||||||
|
opBool
|
||||||
|
opPtr
|
||||||
|
opSliceHead
|
||||||
|
opSliceElemFirst
|
||||||
|
opSliceElem
|
||||||
|
opSliceEnd
|
||||||
|
opStructHead
|
||||||
|
opStructFieldFirst
|
||||||
|
opStructField
|
||||||
|
opStructFieldFirstInt
|
||||||
|
opStructFieldInt
|
||||||
|
opStructFieldFirstString
|
||||||
|
opStructFieldString
|
||||||
|
opStructEnd
|
||||||
|
)
|
||||||
|
|
||||||
|
func (t opType) String() string {
|
||||||
|
switch t {
|
||||||
|
case opEnd:
|
||||||
|
return "END"
|
||||||
|
case opInt:
|
||||||
|
return "INT"
|
||||||
|
case opInt8:
|
||||||
|
return "INT8"
|
||||||
|
case opInt16:
|
||||||
|
return "INT16"
|
||||||
|
case opInt32:
|
||||||
|
return "INT32"
|
||||||
|
case opInt64:
|
||||||
|
return "INT64"
|
||||||
|
case opUint:
|
||||||
|
return "UINT"
|
||||||
|
case opUint8:
|
||||||
|
return "UINT8"
|
||||||
|
case opUint16:
|
||||||
|
return "UINT16"
|
||||||
|
case opUint32:
|
||||||
|
return "UINT32"
|
||||||
|
case opUint64:
|
||||||
|
return "UINT64"
|
||||||
|
case opFloat32:
|
||||||
|
return "FLOAT32"
|
||||||
|
case opFloat64:
|
||||||
|
return "FLOAT64"
|
||||||
|
case opString:
|
||||||
|
return "STRING"
|
||||||
|
case opBool:
|
||||||
|
return "BOOL"
|
||||||
|
case opPtr:
|
||||||
|
return "PTR"
|
||||||
|
case opSliceHead:
|
||||||
|
return "SLICE_HEAD"
|
||||||
|
case opSliceElemFirst:
|
||||||
|
return "SLICE_ELEM_FIRST"
|
||||||
|
case opSliceElem:
|
||||||
|
return "SLICE_ELEM"
|
||||||
|
case opSliceEnd:
|
||||||
|
return "SLICE_END"
|
||||||
|
case opStructHead:
|
||||||
|
return "STRUCT_HEAD"
|
||||||
|
case opStructFieldFirst:
|
||||||
|
return "STRUCT_FIELD_FIRST"
|
||||||
|
case opStructField:
|
||||||
|
return "STRUCT_FIELD"
|
||||||
|
case opStructFieldFirstInt:
|
||||||
|
return "STRUCT_FIELD_FIRST_INT"
|
||||||
|
case opStructFieldInt:
|
||||||
|
return "STRUCT_FIELD_INT"
|
||||||
|
case opStructFieldFirstString:
|
||||||
|
return "STRUCT_FIELD_FIRST_STRING"
|
||||||
|
case opStructFieldString:
|
||||||
|
return "STRUCT_FIELD_STRING"
|
||||||
|
case opStructEnd:
|
||||||
|
return "STRUCT_END"
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
type opcodeHeader struct {
|
||||||
|
op opType
|
||||||
|
typ *rtype
|
||||||
|
ptr uintptr
|
||||||
|
next *opcode
|
||||||
|
}
|
||||||
|
|
||||||
|
type opcode struct {
|
||||||
|
*opcodeHeader
|
||||||
|
}
|
||||||
|
|
||||||
|
func newOpCode(op opType, typ *rtype, next *opcode) *opcode {
|
||||||
|
return &opcode{
|
||||||
|
opcodeHeader: &opcodeHeader{
|
||||||
|
op: op,
|
||||||
|
typ: typ,
|
||||||
|
next: next,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func newEndOp() *opcode {
|
||||||
|
return newOpCode(opEnd, nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *opcode) beforeLastCode() *opcode {
|
||||||
|
code := c
|
||||||
|
for {
|
||||||
|
var nextCode *opcode
|
||||||
|
if code.op == opSliceElem {
|
||||||
|
nextCode = code.toSliceElemCode().end
|
||||||
|
} else {
|
||||||
|
nextCode = code.next
|
||||||
|
}
|
||||||
|
if nextCode.op == opEnd {
|
||||||
|
return code
|
||||||
|
}
|
||||||
|
code = nextCode
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *opcode) dump() string {
|
||||||
|
codes := []string{}
|
||||||
|
for code := c; code.op != opEnd; {
|
||||||
|
codes = append(codes, fmt.Sprintf("%s", code.op))
|
||||||
|
if code.op == opSliceElem {
|
||||||
|
code = code.toSliceElemCode().end
|
||||||
|
} else {
|
||||||
|
code = code.next
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return strings.Join(codes, "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *opcode) toSliceElemCode() *sliceElemCode {
|
||||||
|
return (*sliceElemCode)(unsafe.Pointer(c))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *opcode) toStructHeaderCode() *structHeaderCode {
|
||||||
|
return (*structHeaderCode)(unsafe.Pointer(c))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *opcode) toStructFieldCode() *structFieldCode {
|
||||||
|
return (*structFieldCode)(unsafe.Pointer(c))
|
||||||
|
}
|
||||||
|
|
||||||
|
type sliceElemCode struct {
|
||||||
|
*opcodeHeader
|
||||||
|
idx uintptr
|
||||||
|
len uintptr
|
||||||
|
size uintptr
|
||||||
|
data uintptr
|
||||||
|
elem *sliceElemCode // first => elem
|
||||||
|
end *opcode
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *sliceElemCode) set(header *reflect.SliceHeader) {
|
||||||
|
c.idx = uintptr(0)
|
||||||
|
c.len = uintptr(header.Len)
|
||||||
|
c.data = header.Data
|
||||||
|
}
|
||||||
|
|
||||||
|
type structHeaderCode struct {
|
||||||
|
*opcodeHeader
|
||||||
|
end *opcode
|
||||||
|
}
|
||||||
|
|
||||||
|
type structFieldCode struct {
|
||||||
|
*opcodeHeader
|
||||||
|
key string
|
||||||
|
offset uintptr
|
||||||
|
nextField *opcode
|
||||||
|
}
|
|
@ -0,0 +1,152 @@
|
||||||
|
package json
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (e *Encoder) run(code *opcode) error {
|
||||||
|
//fmt.Println("================")
|
||||||
|
//fmt.Println(code.dump())
|
||||||
|
//fmt.Println("================")
|
||||||
|
for {
|
||||||
|
switch code.op {
|
||||||
|
case opPtr:
|
||||||
|
ptr := code.ptr
|
||||||
|
code = code.next
|
||||||
|
code.ptr = e.ptrToPtr(ptr)
|
||||||
|
case opInt:
|
||||||
|
e.encodeInt(e.ptrToInt(code.ptr))
|
||||||
|
code = code.next
|
||||||
|
case opInt8:
|
||||||
|
e.encodeInt8(e.ptrToInt8(code.ptr))
|
||||||
|
code = code.next
|
||||||
|
case opInt16:
|
||||||
|
e.encodeInt16(e.ptrToInt16(code.ptr))
|
||||||
|
code = code.next
|
||||||
|
case opInt32:
|
||||||
|
e.encodeInt32(e.ptrToInt32(code.ptr))
|
||||||
|
code = code.next
|
||||||
|
case opInt64:
|
||||||
|
e.encodeInt64(e.ptrToInt64(code.ptr))
|
||||||
|
code = code.next
|
||||||
|
case opUint:
|
||||||
|
e.encodeUint(e.ptrToUint(code.ptr))
|
||||||
|
code = code.next
|
||||||
|
case opUint8:
|
||||||
|
e.encodeUint8(e.ptrToUint8(code.ptr))
|
||||||
|
code = code.next
|
||||||
|
case opUint16:
|
||||||
|
e.encodeUint16(e.ptrToUint16(code.ptr))
|
||||||
|
code = code.next
|
||||||
|
case opUint32:
|
||||||
|
e.encodeUint32(e.ptrToUint32(code.ptr))
|
||||||
|
code = code.next
|
||||||
|
case opUint64:
|
||||||
|
e.encodeUint64(e.ptrToUint64(code.ptr))
|
||||||
|
code = code.next
|
||||||
|
case opFloat32:
|
||||||
|
e.encodeFloat32(e.ptrToFloat32(code.ptr))
|
||||||
|
code = code.next
|
||||||
|
case opFloat64:
|
||||||
|
e.encodeFloat64(e.ptrToFloat64(code.ptr))
|
||||||
|
code = code.next
|
||||||
|
case opString:
|
||||||
|
e.encodeEscapedString(e.ptrToString(code.ptr))
|
||||||
|
code = code.next
|
||||||
|
case opBool:
|
||||||
|
e.encodeBool(e.ptrToBool(code.ptr))
|
||||||
|
code = code.next
|
||||||
|
case opSliceHead:
|
||||||
|
p := code.ptr
|
||||||
|
if p == 0 {
|
||||||
|
e.encodeString("null")
|
||||||
|
code = code.next.toSliceElemCode().end
|
||||||
|
} else {
|
||||||
|
e.encodeByte('[')
|
||||||
|
header := (*reflect.SliceHeader)(unsafe.Pointer(p))
|
||||||
|
firstElem := code.next.toSliceElemCode()
|
||||||
|
firstElem.set(header)
|
||||||
|
firstElem.elem.set(header)
|
||||||
|
code = code.next
|
||||||
|
}
|
||||||
|
case opSliceElemFirst:
|
||||||
|
c := code.toSliceElemCode()
|
||||||
|
if c.len > 0 {
|
||||||
|
code = code.next
|
||||||
|
code.ptr = c.data
|
||||||
|
} else {
|
||||||
|
code = c.end
|
||||||
|
}
|
||||||
|
case opSliceElem:
|
||||||
|
c := code.toSliceElemCode()
|
||||||
|
c.idx++
|
||||||
|
if c.idx < c.len {
|
||||||
|
e.encodeByte(',')
|
||||||
|
code = code.next
|
||||||
|
code.ptr = c.data + c.idx*c.size
|
||||||
|
} else {
|
||||||
|
code = c.end
|
||||||
|
}
|
||||||
|
case opSliceEnd:
|
||||||
|
e.encodeByte(']')
|
||||||
|
code = code.next
|
||||||
|
case opStructHead:
|
||||||
|
ptr := code.ptr
|
||||||
|
if ptr == 0 {
|
||||||
|
e.encodeString("null")
|
||||||
|
code = code.toStructHeaderCode().end
|
||||||
|
} else {
|
||||||
|
e.encodeByte('{')
|
||||||
|
code = code.next
|
||||||
|
code.ptr = ptr
|
||||||
|
}
|
||||||
|
case opStructFieldFirst:
|
||||||
|
c := code.toStructFieldCode()
|
||||||
|
e.encodeString(c.key)
|
||||||
|
code = code.next
|
||||||
|
code.ptr = c.ptr + c.offset
|
||||||
|
c.nextField.ptr = c.ptr
|
||||||
|
case opStructFieldFirstInt:
|
||||||
|
c := code.toStructFieldCode()
|
||||||
|
e.encodeString(c.key)
|
||||||
|
c.nextField.ptr = c.ptr
|
||||||
|
e.encodeInt(e.ptrToInt(c.ptr + c.offset))
|
||||||
|
code = code.next
|
||||||
|
case opStructFieldFirstString:
|
||||||
|
c := code.toStructFieldCode()
|
||||||
|
e.encodeString(c.key)
|
||||||
|
c.nextField.ptr = c.ptr
|
||||||
|
e.encodeEscapedString(e.ptrToString(c.ptr + c.offset))
|
||||||
|
code = code.next
|
||||||
|
case opStructField:
|
||||||
|
e.encodeByte(',')
|
||||||
|
c := code.toStructFieldCode()
|
||||||
|
e.encodeString(c.key)
|
||||||
|
code = code.next
|
||||||
|
code.ptr = c.ptr + c.offset
|
||||||
|
c.nextField.ptr = c.ptr
|
||||||
|
case opStructFieldInt:
|
||||||
|
e.encodeByte(',')
|
||||||
|
c := code.toStructFieldCode()
|
||||||
|
c.nextField.ptr = c.ptr
|
||||||
|
e.encodeString(c.key)
|
||||||
|
e.encodeInt(e.ptrToInt(c.ptr + c.offset))
|
||||||
|
code = code.next
|
||||||
|
case opStructFieldString:
|
||||||
|
e.encodeByte(',')
|
||||||
|
c := code.toStructFieldCode()
|
||||||
|
c.nextField.ptr = c.ptr
|
||||||
|
e.encodeString(c.key)
|
||||||
|
e.encodeEscapedString(e.ptrToString(c.ptr + c.offset))
|
||||||
|
code = code.next
|
||||||
|
case opStructEnd:
|
||||||
|
e.encodeByte('}')
|
||||||
|
code = code.next
|
||||||
|
case opEnd:
|
||||||
|
goto END
|
||||||
|
}
|
||||||
|
}
|
||||||
|
END:
|
||||||
|
return nil
|
||||||
|
}
|
Loading…
Reference in New Issue