mirror of https://github.com/goccy/go-json.git
452 lines
8.9 KiB
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,
|
|
},
|
|
}
|
|
}
|