diff options
Diffstat (limited to 'vendor/github.com/goccy/go-json/internal/encoder/opcode.go')
-rw-r--r-- | vendor/github.com/goccy/go-json/internal/encoder/opcode.go | 752 |
1 files changed, 0 insertions, 752 deletions
diff --git a/vendor/github.com/goccy/go-json/internal/encoder/opcode.go b/vendor/github.com/goccy/go-json/internal/encoder/opcode.go deleted file mode 100644 index df22f5542..000000000 --- a/vendor/github.com/goccy/go-json/internal/encoder/opcode.go +++ /dev/null @@ -1,752 +0,0 @@ -package encoder - -import ( - "bytes" - "fmt" - "sort" - "strings" - "unsafe" - - "github.com/goccy/go-json/internal/runtime" -) - -const uintptrSize = 4 << (^uintptr(0) >> 63) - -type OpFlags uint16 - -const ( - AnonymousHeadFlags OpFlags = 1 << 0 - AnonymousKeyFlags OpFlags = 1 << 1 - IndirectFlags OpFlags = 1 << 2 - IsTaggedKeyFlags OpFlags = 1 << 3 - NilCheckFlags OpFlags = 1 << 4 - AddrForMarshalerFlags OpFlags = 1 << 5 - IsNextOpPtrTypeFlags OpFlags = 1 << 6 - IsNilableTypeFlags OpFlags = 1 << 7 - MarshalerContextFlags OpFlags = 1 << 8 - NonEmptyInterfaceFlags OpFlags = 1 << 9 -) - -type Opcode struct { - Op OpType // operation type - Idx uint32 // offset to access ptr - Next *Opcode // next opcode - End *Opcode // array/slice/struct/map end - NextField *Opcode // next struct field - Key string // struct field key - Offset uint32 // offset size from struct header - PtrNum uint8 // pointer number: e.g. double pointer is 2. - NumBitSize uint8 - Flags OpFlags - - Type *runtime.Type // go type - Jmp *CompiledCode // for recursive call - FieldQuery *FieldQuery // field query for Interface / MarshalJSON / MarshalText - ElemIdx uint32 // offset to access array/slice elem - Length uint32 // offset to access slice length or array length - Indent uint32 // indent number - Size uint32 // array/slice elem size - DisplayIdx uint32 // opcode index - DisplayKey string // key text to display -} - -func (c *Opcode) Validate() error { - var prevIdx uint32 - for code := c; !code.IsEnd(); { - if prevIdx != 0 { - if code.DisplayIdx != prevIdx+1 { - return fmt.Errorf( - "invalid index. previous display index is %d but next is %d. dump = %s", - prevIdx, code.DisplayIdx, c.Dump(), - ) - } - } - prevIdx = code.DisplayIdx - code = code.IterNext() - } - return nil -} - -func (c *Opcode) IterNext() *Opcode { - if c == nil { - return nil - } - switch c.Op.CodeType() { - case CodeArrayElem, CodeSliceElem, CodeMapKey: - return c.End - default: - return c.Next - } -} - -func (c *Opcode) IsEnd() bool { - if c == nil { - return true - } - return c.Op == OpEnd || c.Op == OpInterfaceEnd || c.Op == OpRecursiveEnd -} - -func (c *Opcode) MaxIdx() uint32 { - max := uint32(0) - for _, value := range []uint32{ - c.Idx, - c.ElemIdx, - c.Length, - c.Size, - } { - if max < value { - max = value - } - } - return max -} - -func (c *Opcode) ToHeaderType(isString bool) OpType { - switch c.Op { - case OpInt: - if isString { - return OpStructHeadIntString - } - return OpStructHeadInt - case OpIntPtr: - if isString { - return OpStructHeadIntPtrString - } - return OpStructHeadIntPtr - case OpUint: - if isString { - return OpStructHeadUintString - } - return OpStructHeadUint - case OpUintPtr: - if isString { - return OpStructHeadUintPtrString - } - return OpStructHeadUintPtr - case OpFloat32: - if isString { - return OpStructHeadFloat32String - } - return OpStructHeadFloat32 - case OpFloat32Ptr: - if isString { - return OpStructHeadFloat32PtrString - } - return OpStructHeadFloat32Ptr - case OpFloat64: - if isString { - return OpStructHeadFloat64String - } - return OpStructHeadFloat64 - case OpFloat64Ptr: - if isString { - return OpStructHeadFloat64PtrString - } - return OpStructHeadFloat64Ptr - case OpString: - if isString { - return OpStructHeadStringString - } - return OpStructHeadString - case OpStringPtr: - if isString { - return OpStructHeadStringPtrString - } - return OpStructHeadStringPtr - case OpNumber: - if isString { - return OpStructHeadNumberString - } - return OpStructHeadNumber - case OpNumberPtr: - if isString { - return OpStructHeadNumberPtrString - } - return OpStructHeadNumberPtr - case OpBool: - if isString { - return OpStructHeadBoolString - } - return OpStructHeadBool - case OpBoolPtr: - if isString { - return OpStructHeadBoolPtrString - } - return OpStructHeadBoolPtr - case OpBytes: - return OpStructHeadBytes - case OpBytesPtr: - return OpStructHeadBytesPtr - case OpMap: - return OpStructHeadMap - case OpMapPtr: - c.Op = OpMap - return OpStructHeadMapPtr - case OpArray: - return OpStructHeadArray - case OpArrayPtr: - c.Op = OpArray - return OpStructHeadArrayPtr - case OpSlice: - return OpStructHeadSlice - case OpSlicePtr: - c.Op = OpSlice - return OpStructHeadSlicePtr - case OpMarshalJSON: - return OpStructHeadMarshalJSON - case OpMarshalJSONPtr: - return OpStructHeadMarshalJSONPtr - case OpMarshalText: - return OpStructHeadMarshalText - case OpMarshalTextPtr: - return OpStructHeadMarshalTextPtr - } - return OpStructHead -} - -func (c *Opcode) ToFieldType(isString bool) OpType { - switch c.Op { - case OpInt: - if isString { - return OpStructFieldIntString - } - return OpStructFieldInt - case OpIntPtr: - if isString { - return OpStructFieldIntPtrString - } - return OpStructFieldIntPtr - case OpUint: - if isString { - return OpStructFieldUintString - } - return OpStructFieldUint - case OpUintPtr: - if isString { - return OpStructFieldUintPtrString - } - return OpStructFieldUintPtr - case OpFloat32: - if isString { - return OpStructFieldFloat32String - } - return OpStructFieldFloat32 - case OpFloat32Ptr: - if isString { - return OpStructFieldFloat32PtrString - } - return OpStructFieldFloat32Ptr - case OpFloat64: - if isString { - return OpStructFieldFloat64String - } - return OpStructFieldFloat64 - case OpFloat64Ptr: - if isString { - return OpStructFieldFloat64PtrString - } - return OpStructFieldFloat64Ptr - case OpString: - if isString { - return OpStructFieldStringString - } - return OpStructFieldString - case OpStringPtr: - if isString { - return OpStructFieldStringPtrString - } - return OpStructFieldStringPtr - case OpNumber: - if isString { - return OpStructFieldNumberString - } - return OpStructFieldNumber - case OpNumberPtr: - if isString { - return OpStructFieldNumberPtrString - } - return OpStructFieldNumberPtr - case OpBool: - if isString { - return OpStructFieldBoolString - } - return OpStructFieldBool - case OpBoolPtr: - if isString { - return OpStructFieldBoolPtrString - } - return OpStructFieldBoolPtr - case OpBytes: - return OpStructFieldBytes - case OpBytesPtr: - return OpStructFieldBytesPtr - case OpMap: - return OpStructFieldMap - case OpMapPtr: - c.Op = OpMap - return OpStructFieldMapPtr - case OpArray: - return OpStructFieldArray - case OpArrayPtr: - c.Op = OpArray - return OpStructFieldArrayPtr - case OpSlice: - return OpStructFieldSlice - case OpSlicePtr: - c.Op = OpSlice - return OpStructFieldSlicePtr - case OpMarshalJSON: - return OpStructFieldMarshalJSON - case OpMarshalJSONPtr: - return OpStructFieldMarshalJSONPtr - case OpMarshalText: - return OpStructFieldMarshalText - case OpMarshalTextPtr: - return OpStructFieldMarshalTextPtr - } - return OpStructField -} - -func newOpCode(ctx *compileContext, typ *runtime.Type, op OpType) *Opcode { - return newOpCodeWithNext(ctx, typ, op, newEndOp(ctx, typ)) -} - -func opcodeOffset(idx int) uint32 { - return uint32(idx) * uintptrSize -} - -func getCodeAddrByIdx(head *Opcode, idx uint32) *Opcode { - addr := uintptr(unsafe.Pointer(head)) + uintptr(idx)*unsafe.Sizeof(Opcode{}) - return *(**Opcode)(unsafe.Pointer(&addr)) -} - -func copyOpcode(code *Opcode) *Opcode { - codeNum := ToEndCode(code).DisplayIdx + 1 - codeSlice := make([]Opcode, codeNum) - head := (*Opcode)((*runtime.SliceHeader)(unsafe.Pointer(&codeSlice)).Data) - ptr := head - c := code - for { - *ptr = Opcode{ - Op: c.Op, - Key: c.Key, - PtrNum: c.PtrNum, - NumBitSize: c.NumBitSize, - Flags: c.Flags, - Idx: c.Idx, - Offset: c.Offset, - Type: c.Type, - FieldQuery: c.FieldQuery, - DisplayIdx: c.DisplayIdx, - DisplayKey: c.DisplayKey, - ElemIdx: c.ElemIdx, - Length: c.Length, - Size: c.Size, - Indent: c.Indent, - Jmp: c.Jmp, - } - if c.End != nil { - ptr.End = getCodeAddrByIdx(head, c.End.DisplayIdx) - } - if c.NextField != nil { - ptr.NextField = getCodeAddrByIdx(head, c.NextField.DisplayIdx) - } - if c.Next != nil { - ptr.Next = getCodeAddrByIdx(head, c.Next.DisplayIdx) - } - if c.IsEnd() { - break - } - ptr = getCodeAddrByIdx(head, c.DisplayIdx+1) - c = c.IterNext() - } - return head -} - -func setTotalLengthToInterfaceOp(code *Opcode) { - for c := code; !c.IsEnd(); { - if c.Op == OpInterface || c.Op == OpInterfacePtr { - c.Length = uint32(code.TotalLength()) - } - c = c.IterNext() - } -} - -func ToEndCode(code *Opcode) *Opcode { - c := code - for !c.IsEnd() { - c = c.IterNext() - } - return c -} - -func copyToInterfaceOpcode(code *Opcode) *Opcode { - copied := copyOpcode(code) - c := copied - c = ToEndCode(c) - c.Idx += uintptrSize - c.ElemIdx = c.Idx + uintptrSize - c.Length = c.Idx + 2*uintptrSize - c.Op = OpInterfaceEnd - return copied -} - -func newOpCodeWithNext(ctx *compileContext, typ *runtime.Type, op OpType, next *Opcode) *Opcode { - return &Opcode{ - Op: op, - Idx: opcodeOffset(ctx.ptrIndex), - Next: next, - Type: typ, - DisplayIdx: ctx.opcodeIndex, - Indent: ctx.indent, - } -} - -func newEndOp(ctx *compileContext, typ *runtime.Type) *Opcode { - return newOpCodeWithNext(ctx, typ, OpEnd, nil) -} - -func (c *Opcode) TotalLength() int { - var idx int - code := c - for !code.IsEnd() { - maxIdx := int(code.MaxIdx() / uintptrSize) - if idx < maxIdx { - idx = maxIdx - } - if code.Op == OpRecursiveEnd { - break - } - code = code.IterNext() - } - maxIdx := int(code.MaxIdx() / uintptrSize) - if idx < maxIdx { - idx = maxIdx - } - return idx + 1 -} - -func (c *Opcode) dumpHead(code *Opcode) string { - var length uint32 - if code.Op.CodeType() == CodeArrayHead { - length = code.Length - } else { - length = code.Length / uintptrSize - } - return fmt.Sprintf( - `[%03d]%s%s ([idx:%d][elemIdx:%d][length:%d])`, - code.DisplayIdx, - strings.Repeat("-", int(code.Indent)), - code.Op, - code.Idx/uintptrSize, - code.ElemIdx/uintptrSize, - length, - ) -} - -func (c *Opcode) dumpMapHead(code *Opcode) string { - return fmt.Sprintf( - `[%03d]%s%s ([idx:%d])`, - code.DisplayIdx, - strings.Repeat("-", int(code.Indent)), - code.Op, - code.Idx/uintptrSize, - ) -} - -func (c *Opcode) dumpMapEnd(code *Opcode) string { - return fmt.Sprintf( - `[%03d]%s%s ([idx:%d])`, - code.DisplayIdx, - strings.Repeat("-", int(code.Indent)), - code.Op, - code.Idx/uintptrSize, - ) -} - -func (c *Opcode) dumpElem(code *Opcode) string { - var length uint32 - if code.Op.CodeType() == CodeArrayElem { - length = code.Length - } else { - length = code.Length / uintptrSize - } - return fmt.Sprintf( - `[%03d]%s%s ([idx:%d][elemIdx:%d][length:%d][size:%d])`, - code.DisplayIdx, - strings.Repeat("-", int(code.Indent)), - code.Op, - code.Idx/uintptrSize, - code.ElemIdx/uintptrSize, - length, - code.Size, - ) -} - -func (c *Opcode) dumpField(code *Opcode) string { - return fmt.Sprintf( - `[%03d]%s%s ([idx:%d][key:%s][offset:%d])`, - code.DisplayIdx, - strings.Repeat("-", int(code.Indent)), - code.Op, - code.Idx/uintptrSize, - code.DisplayKey, - code.Offset, - ) -} - -func (c *Opcode) dumpKey(code *Opcode) string { - return fmt.Sprintf( - `[%03d]%s%s ([idx:%d])`, - code.DisplayIdx, - strings.Repeat("-", int(code.Indent)), - code.Op, - code.Idx/uintptrSize, - ) -} - -func (c *Opcode) dumpValue(code *Opcode) string { - return fmt.Sprintf( - `[%03d]%s%s ([idx:%d])`, - code.DisplayIdx, - strings.Repeat("-", int(code.Indent)), - code.Op, - code.Idx/uintptrSize, - ) -} - -func (c *Opcode) Dump() string { - codes := []string{} - for code := c; !code.IsEnd(); { - switch code.Op.CodeType() { - case CodeSliceHead: - codes = append(codes, c.dumpHead(code)) - code = code.Next - case CodeMapHead: - codes = append(codes, c.dumpMapHead(code)) - code = code.Next - case CodeArrayElem, CodeSliceElem: - codes = append(codes, c.dumpElem(code)) - code = code.End - case CodeMapKey: - codes = append(codes, c.dumpKey(code)) - code = code.End - case CodeMapValue: - codes = append(codes, c.dumpValue(code)) - code = code.Next - case CodeMapEnd: - codes = append(codes, c.dumpMapEnd(code)) - code = code.Next - case CodeStructField: - codes = append(codes, c.dumpField(code)) - code = code.Next - case CodeStructEnd: - codes = append(codes, c.dumpField(code)) - code = code.Next - default: - codes = append(codes, fmt.Sprintf( - "[%03d]%s%s ([idx:%d])", - code.DisplayIdx, - strings.Repeat("-", int(code.Indent)), - code.Op, - code.Idx/uintptrSize, - )) - code = code.Next - } - } - return strings.Join(codes, "\n") -} - -func (c *Opcode) DumpDOT() string { - type edge struct { - from, to *Opcode - label string - weight int - } - var edges []edge - - b := &bytes.Buffer{} - fmt.Fprintf(b, "digraph \"%p\" {\n", c.Type) - fmt.Fprintln(b, "mclimit=1.5;\nrankdir=TD;\nordering=out;\nnode[shape=box];") - for code := c; !code.IsEnd(); { - label := code.Op.String() - fmt.Fprintf(b, "\"%p\" [label=%q];\n", code, label) - if p := code.Next; p != nil { - edges = append(edges, edge{ - from: code, - to: p, - label: "Next", - weight: 10, - }) - } - if p := code.NextField; p != nil { - edges = append(edges, edge{ - from: code, - to: p, - label: "NextField", - weight: 2, - }) - } - if p := code.End; p != nil { - edges = append(edges, edge{ - from: code, - to: p, - label: "End", - weight: 1, - }) - } - if p := code.Jmp; p != nil { - edges = append(edges, edge{ - from: code, - to: p.Code, - label: "Jmp", - weight: 1, - }) - } - - switch code.Op.CodeType() { - case CodeSliceHead: - code = code.Next - case CodeMapHead: - code = code.Next - case CodeArrayElem, CodeSliceElem: - code = code.End - case CodeMapKey: - code = code.End - case CodeMapValue: - code = code.Next - case CodeMapEnd: - code = code.Next - case CodeStructField: - code = code.Next - case CodeStructEnd: - code = code.Next - default: - code = code.Next - } - if code.IsEnd() { - fmt.Fprintf(b, "\"%p\" [label=%q];\n", code, code.Op.String()) - } - } - sort.Slice(edges, func(i, j int) bool { - return edges[i].to.DisplayIdx < edges[j].to.DisplayIdx - }) - for _, e := range edges { - fmt.Fprintf(b, "\"%p\" -> \"%p\" [label=%q][weight=%d];\n", e.from, e.to, e.label, e.weight) - } - fmt.Fprint(b, "}") - return b.String() -} - -func newSliceHeaderCode(ctx *compileContext, typ *runtime.Type) *Opcode { - idx := opcodeOffset(ctx.ptrIndex) - ctx.incPtrIndex() - elemIdx := opcodeOffset(ctx.ptrIndex) - ctx.incPtrIndex() - length := opcodeOffset(ctx.ptrIndex) - return &Opcode{ - Op: OpSlice, - Type: typ, - Idx: idx, - DisplayIdx: ctx.opcodeIndex, - ElemIdx: elemIdx, - Length: length, - Indent: ctx.indent, - } -} - -func newSliceElemCode(ctx *compileContext, typ *runtime.Type, head *Opcode, size uintptr) *Opcode { - return &Opcode{ - Op: OpSliceElem, - Type: typ, - Idx: head.Idx, - DisplayIdx: ctx.opcodeIndex, - ElemIdx: head.ElemIdx, - Length: head.Length, - Indent: ctx.indent, - Size: uint32(size), - } -} - -func newArrayHeaderCode(ctx *compileContext, typ *runtime.Type, alen int) *Opcode { - idx := opcodeOffset(ctx.ptrIndex) - ctx.incPtrIndex() - elemIdx := opcodeOffset(ctx.ptrIndex) - return &Opcode{ - Op: OpArray, - Type: typ, - Idx: idx, - DisplayIdx: ctx.opcodeIndex, - ElemIdx: elemIdx, - Indent: ctx.indent, - Length: uint32(alen), - } -} - -func newArrayElemCode(ctx *compileContext, typ *runtime.Type, head *Opcode, length int, size uintptr) *Opcode { - return &Opcode{ - Op: OpArrayElem, - Type: typ, - Idx: head.Idx, - DisplayIdx: ctx.opcodeIndex, - ElemIdx: head.ElemIdx, - Length: uint32(length), - Indent: ctx.indent, - Size: uint32(size), - } -} - -func newMapHeaderCode(ctx *compileContext, typ *runtime.Type) *Opcode { - idx := opcodeOffset(ctx.ptrIndex) - ctx.incPtrIndex() - return &Opcode{ - Op: OpMap, - Type: typ, - Idx: idx, - DisplayIdx: ctx.opcodeIndex, - Indent: ctx.indent, - } -} - -func newMapKeyCode(ctx *compileContext, typ *runtime.Type, head *Opcode) *Opcode { - return &Opcode{ - Op: OpMapKey, - Type: typ, - Idx: head.Idx, - DisplayIdx: ctx.opcodeIndex, - Indent: ctx.indent, - } -} - -func newMapValueCode(ctx *compileContext, typ *runtime.Type, head *Opcode) *Opcode { - return &Opcode{ - Op: OpMapValue, - Type: typ, - Idx: head.Idx, - DisplayIdx: ctx.opcodeIndex, - Indent: ctx.indent, - } -} - -func newMapEndCode(ctx *compileContext, typ *runtime.Type, head *Opcode) *Opcode { - return &Opcode{ - Op: OpMapEnd, - Type: typ, - Idx: head.Idx, - DisplayIdx: ctx.opcodeIndex, - Indent: ctx.indent, - Next: newEndOp(ctx, typ), - } -} - -func newRecursiveCode(ctx *compileContext, typ *runtime.Type, jmp *CompiledCode) *Opcode { - return &Opcode{ - Op: OpRecursive, - Type: typ, - Idx: opcodeOffset(ctx.ptrIndex), - Next: newEndOp(ctx, typ), - DisplayIdx: ctx.opcodeIndex, - Indent: ctx.indent, - Jmp: jmp, - } -} |