go-json/encode_opcode.go

452 lines
8.9 KiB
Go

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
opInterface
opPtr
opSliceHead
opSliceElem
opSliceEnd
opArrayHead
opArrayElem
opArrayEnd
opMapHead
opMapKey
opMapValue
opMapEnd
opStructFieldHead
opStructFieldHeadInt
opStructFieldHeadInt8
opStructFieldHeadInt16
opStructFieldHeadInt32
opStructFieldHeadInt64
opStructFieldHeadUint
opStructFieldHeadUint8
opStructFieldHeadUint16
opStructFieldHeadUint32
opStructFieldHeadUint64
opStructFieldHeadFloat32
opStructFieldHeadFloat64
opStructFieldHeadString
opStructFieldHeadBool
opStructFieldPtrHead
opStructFieldPtrHeadInt
opStructFieldPtrHeadInt8
opStructFieldPtrHeadInt16
opStructFieldPtrHeadInt32
opStructFieldPtrHeadInt64
opStructFieldPtrHeadUint
opStructFieldPtrHeadUint8
opStructFieldPtrHeadUint16
opStructFieldPtrHeadUint32
opStructFieldPtrHeadUint64
opStructFieldPtrHeadFloat32
opStructFieldPtrHeadFloat64
opStructFieldPtrHeadString
opStructFieldPtrHeadBool
opStructField
opStructFieldInt
opStructFieldInt8
opStructFieldInt16
opStructFieldInt32
opStructFieldInt64
opStructFieldUint
opStructFieldUint8
opStructFieldUint16
opStructFieldUint32
opStructFieldUint64
opStructFieldFloat32
opStructFieldFloat64
opStructFieldString
opStructFieldBool
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 opInterface:
return "INTERFACE"
case opPtr:
return "PTR"
case opSliceHead:
return "SLICE_HEAD"
case opSliceElem:
return "SLICE_ELEM"
case opSliceEnd:
return "SLICE_END"
case opArrayHead:
return "ARRAY_HEAD"
case opArrayElem:
return "ARRAY_ELEM"
case opArrayEnd:
return "ARRAY_END"
case opMapHead:
return "MAP_HEAD"
case opMapKey:
return "MAP_KEY"
case opMapValue:
return "MAP_VALUE"
case opMapEnd:
return "MAP_END"
case opStructFieldHead:
return "STRUCT_FIELD_HEAD"
case opStructFieldHeadInt:
return "STRUCT_FIELD_HEAD_INT"
case opStructFieldHeadInt8:
return "STRUCT_FIELD_HEAD_INT8"
case opStructFieldHeadInt16:
return "STRUCT_FIELD_HEAD_INT16"
case opStructFieldHeadInt32:
return "STRUCT_FIELD_HEAD_INT32"
case opStructFieldHeadInt64:
return "STRUCT_FIELD_HEAD_INT64"
case opStructFieldHeadUint:
return "STRUCT_FIELD_HEAD_UINT"
case opStructFieldHeadUint8:
return "STRUCT_FIELD_HEAD_UINT8"
case opStructFieldHeadUint16:
return "STRUCT_FIELD_HEAD_UINT16"
case opStructFieldHeadUint32:
return "STRUCT_FIELD_HEAD_UINT32"
case opStructFieldHeadUint64:
return "STRUCT_FIELD_HEAD_UINT64"
case opStructFieldHeadFloat32:
return "STRUCT_FIELD_HEAD_FLOAT32"
case opStructFieldHeadFloat64:
return "STRUCT_FIELD_HEAD_FLOAT64"
case opStructFieldHeadString:
return "STRUCT_FIELD_HEAD_STRING"
case opStructFieldHeadBool:
return "STRUCT_FIELD_HEAD_BOOL"
case opStructFieldPtrHead:
return "STRUCT_FIELD_PTR_HEAD"
case opStructFieldPtrHeadInt:
return "STRUCT_FIELD_PTR_HEAD_INT"
case opStructFieldPtrHeadInt8:
return "STRUCT_FIELD_PTR_HEAD_INT8"
case opStructFieldPtrHeadInt16:
return "STRUCT_FIELD_PTR_HEAD_INT16"
case opStructFieldPtrHeadInt32:
return "STRUCT_FIELD_PTR_HEAD_INT32"
case opStructFieldPtrHeadInt64:
return "STRUCT_FIELD_PTR_HEAD_INT64"
case opStructFieldPtrHeadUint:
return "STRUCT_FIELD_PTR_HEAD_UINT"
case opStructFieldPtrHeadUint8:
return "STRUCT_FIELD_PTR_HEAD_UINT8"
case opStructFieldPtrHeadUint16:
return "STRUCT_FIELD_PTR_HEAD_UINT16"
case opStructFieldPtrHeadUint32:
return "STRUCT_FIELD_PTR_HEAD_UINT32"
case opStructFieldPtrHeadUint64:
return "STRUCT_FIELD_PTR_HEAD_UINT64"
case opStructFieldPtrHeadFloat32:
return "STRUCT_FIELD_PTR_HEAD_FLOAT32"
case opStructFieldPtrHeadFloat64:
return "STRUCT_FIELD_PTR_HEAD_FLOAT64"
case opStructFieldPtrHeadString:
return "STRUCT_FIELD_PTR_HEAD_STRING"
case opStructFieldPtrHeadBool:
return "STRUCT_FIELD_PTR_HEAD_BOOL"
case opStructField:
return "STRUCT_FIELD"
case opStructFieldInt:
return "STRUCT_FIELD_INT"
case opStructFieldInt8:
return "STRUCT_FIELD_INT8"
case opStructFieldInt16:
return "STRUCT_FIELD_INT16"
case opStructFieldInt32:
return "STRUCT_FIELD_INT32"
case opStructFieldInt64:
return "STRUCT_FIELD_INT64"
case opStructFieldUint:
return "STRUCT_FIELD_UINT"
case opStructFieldUint8:
return "STRUCT_FIELD_UINT8"
case opStructFieldUint16:
return "STRUCT_FIELD_UINT16"
case opStructFieldUint32:
return "STRUCT_FIELD_UINT32"
case opStructFieldUint64:
return "STRUCT_FIELD_UINT64"
case opStructFieldFloat32:
return "STRUCT_FIELD_FLOAT32"
case opStructFieldFloat64:
return "STRUCT_FIELD_FLOAT64"
case opStructFieldString:
return "STRUCT_FIELD_STRING"
case opStructFieldBool:
return "STRUCT_FIELD_BOOL"
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
switch code.op {
case opArrayElem:
nextCode = code.toArrayElemCode().end
case opSliceElem:
nextCode = code.toSliceElemCode().end
case opMapKey:
nextCode = code.toMapKeyCode().end
default:
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))
switch code.op {
case opArrayElem:
code = code.toArrayElemCode().end
case opSliceElem:
code = code.toSliceElemCode().end
case opMapKey:
code = code.toMapKeyCode().end
default:
code = code.next
}
}
return strings.Join(codes, "\n")
}
func (c *opcode) toSliceHeaderCode() *sliceHeaderCode {
return (*sliceHeaderCode)(unsafe.Pointer(c))
}
func (c *opcode) toSliceElemCode() *sliceElemCode {
return (*sliceElemCode)(unsafe.Pointer(c))
}
func (c *opcode) toArrayHeaderCode() *arrayHeaderCode {
return (*arrayHeaderCode)(unsafe.Pointer(c))
}
func (c *opcode) toArrayElemCode() *arrayElemCode {
return (*arrayElemCode)(unsafe.Pointer(c))
}
func (c *opcode) toStructFieldCode() *structFieldCode {
return (*structFieldCode)(unsafe.Pointer(c))
}
func (c *opcode) toMapHeadCode() *mapHeaderCode {
return (*mapHeaderCode)(unsafe.Pointer(c))
}
func (c *opcode) toMapKeyCode() *mapKeyCode {
return (*mapKeyCode)(unsafe.Pointer(c))
}
func (c *opcode) toMapValueCode() *mapValueCode {
return (*mapValueCode)(unsafe.Pointer(c))
}
type sliceHeaderCode struct {
*opcodeHeader
elem *sliceElemCode
end *opcode
}
func newSliceHeaderCode() *sliceHeaderCode {
return &sliceHeaderCode{
opcodeHeader: &opcodeHeader{
op: opSliceHead,
},
}
}
type sliceElemCode struct {
*opcodeHeader
idx uintptr
len uintptr
size uintptr
data uintptr
end *opcode
}
func (c *sliceElemCode) set(header *reflect.SliceHeader) {
c.idx = uintptr(0)
c.len = uintptr(header.Len)
c.data = header.Data
}
type arrayHeaderCode struct {
*opcodeHeader
len uintptr
elem *arrayElemCode
end *opcode
}
func newArrayHeaderCode(alen int) *arrayHeaderCode {
return &arrayHeaderCode{
opcodeHeader: &opcodeHeader{
op: opArrayHead,
},
len: uintptr(alen),
}
}
type arrayElemCode struct {
*opcodeHeader
idx uintptr
len uintptr
size uintptr
end *opcode
}
type structFieldCode struct {
*opcodeHeader
key []byte
offset uintptr
nextField *opcode
end *opcode
}
type mapHeaderCode struct {
*opcodeHeader
key *mapKeyCode
value *mapValueCode
end *opcode
}
type mapKeyCode struct {
*opcodeHeader
idx int
len int
iter unsafe.Pointer
end *opcode
}
func (c *mapKeyCode) set(len int, iter unsafe.Pointer) {
c.idx = 0
c.len = len
c.iter = iter
}
type mapValueCode struct {
*opcodeHeader
iter unsafe.Pointer
}
func (c *mapValueCode) set(iter unsafe.Pointer) {
c.iter = iter
}
func newMapHeaderCode(typ *rtype) *mapHeaderCode {
return &mapHeaderCode{
opcodeHeader: &opcodeHeader{
op: opMapHead,
typ: typ,
},
}
}
func newMapKeyCode() *mapKeyCode {
return &mapKeyCode{
opcodeHeader: &opcodeHeader{
op: opMapKey,
},
}
}
func newMapValueCode() *mapValueCode {
return &mapValueCode{
opcodeHeader: &opcodeHeader{
op: opMapValue,
},
}
}