1 package vm
2
3 import (
4 "encoding/json"
5 "fmt"
6 "unsafe"
7
8 "github.com/goccy/go-json/internal/encoder"
9 "github.com/goccy/go-json/internal/runtime"
10 )
11
12 const uintptrSize = 4 << (^uintptr(0) >> 63)
13
14 var (
15 appendInt = encoder.AppendInt
16 appendUint = encoder.AppendUint
17 appendFloat32 = encoder.AppendFloat32
18 appendFloat64 = encoder.AppendFloat64
19 appendString = encoder.AppendString
20 appendByteSlice = encoder.AppendByteSlice
21 appendNumber = encoder.AppendNumber
22 errUnsupportedValue = encoder.ErrUnsupportedValue
23 errUnsupportedFloat = encoder.ErrUnsupportedFloat
24 mapiterinit = encoder.MapIterInit
25 mapiterkey = encoder.MapIterKey
26 mapitervalue = encoder.MapIterValue
27 mapiternext = encoder.MapIterNext
28 maplen = encoder.MapLen
29 )
30
31 type emptyInterface struct {
32 typ *runtime.Type
33 ptr unsafe.Pointer
34 }
35
36 type nonEmptyInterface struct {
37 itab *struct {
38 ityp *runtime.Type
39 typ *runtime.Type
40
41 }
42 ptr unsafe.Pointer
43 }
44
45 func errUnimplementedOp(op encoder.OpType) error {
46 return fmt.Errorf("encoder: opcode %s has not been implemented", op)
47 }
48
49 func load(base uintptr, idx uint32) uintptr {
50 addr := base + uintptr(idx)
51 return **(**uintptr)(unsafe.Pointer(&addr))
52 }
53
54 func store(base uintptr, idx uint32, p uintptr) {
55 addr := base + uintptr(idx)
56 **(**uintptr)(unsafe.Pointer(&addr)) = p
57 }
58
59 func loadNPtr(base uintptr, idx uint32, ptrNum uint8) uintptr {
60 addr := base + uintptr(idx)
61 p := **(**uintptr)(unsafe.Pointer(&addr))
62 for i := uint8(0); i < ptrNum; i++ {
63 if p == 0 {
64 return 0
65 }
66 p = ptrToPtr(p)
67 }
68 return p
69 }
70
71 func ptrToUint64(p uintptr, bitSize uint8) uint64 {
72 switch bitSize {
73 case 8:
74 return (uint64)(**(**uint8)(unsafe.Pointer(&p)))
75 case 16:
76 return (uint64)(**(**uint16)(unsafe.Pointer(&p)))
77 case 32:
78 return (uint64)(**(**uint32)(unsafe.Pointer(&p)))
79 case 64:
80 return **(**uint64)(unsafe.Pointer(&p))
81 }
82 return 0
83 }
84 func ptrToFloat32(p uintptr) float32 { return **(**float32)(unsafe.Pointer(&p)) }
85 func ptrToFloat64(p uintptr) float64 { return **(**float64)(unsafe.Pointer(&p)) }
86 func ptrToBool(p uintptr) bool { return **(**bool)(unsafe.Pointer(&p)) }
87 func ptrToBytes(p uintptr) []byte { return **(**[]byte)(unsafe.Pointer(&p)) }
88 func ptrToNumber(p uintptr) json.Number { return **(**json.Number)(unsafe.Pointer(&p)) }
89 func ptrToString(p uintptr) string { return **(**string)(unsafe.Pointer(&p)) }
90 func ptrToSlice(p uintptr) *runtime.SliceHeader { return *(**runtime.SliceHeader)(unsafe.Pointer(&p)) }
91 func ptrToPtr(p uintptr) uintptr {
92 return uintptr(**(**unsafe.Pointer)(unsafe.Pointer(&p)))
93 }
94 func ptrToNPtr(p uintptr, ptrNum uint8) uintptr {
95 for i := uint8(0); i < ptrNum; i++ {
96 if p == 0 {
97 return 0
98 }
99 p = ptrToPtr(p)
100 }
101 return p
102 }
103
104 func ptrToUnsafePtr(p uintptr) unsafe.Pointer {
105 return *(*unsafe.Pointer)(unsafe.Pointer(&p))
106 }
107 func ptrToInterface(code *encoder.Opcode, p uintptr) interface{} {
108 return *(*interface{})(unsafe.Pointer(&emptyInterface{
109 typ: code.Type,
110 ptr: *(*unsafe.Pointer)(unsafe.Pointer(&p)),
111 }))
112 }
113
114 func appendBool(_ *encoder.RuntimeContext, b []byte, v bool) []byte {
115 if v {
116 return append(b, "true"...)
117 }
118 return append(b, "false"...)
119 }
120
121 func appendNull(_ *encoder.RuntimeContext, b []byte) []byte {
122 return append(b, "null"...)
123 }
124
125 func appendComma(_ *encoder.RuntimeContext, b []byte) []byte {
126 return append(b, ',')
127 }
128
129 func appendNullComma(_ *encoder.RuntimeContext, b []byte) []byte {
130 return append(b, "null,"...)
131 }
132
133 func appendColon(_ *encoder.RuntimeContext, b []byte) []byte {
134 last := len(b) - 1
135 b[last] = ':'
136 return b
137 }
138
139 func appendMapKeyValue(_ *encoder.RuntimeContext, _ *encoder.Opcode, b, key, value []byte) []byte {
140 b = append(b, key...)
141 b[len(b)-1] = ':'
142 return append(b, value...)
143 }
144
145 func appendMapEnd(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte {
146 b[len(b)-1] = '}'
147 b = append(b, ',')
148 return b
149 }
150
151 func appendMarshalJSON(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte, v interface{}) ([]byte, error) {
152 return encoder.AppendMarshalJSON(ctx, code, b, v)
153 }
154
155 func appendMarshalText(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte, v interface{}) ([]byte, error) {
156 return encoder.AppendMarshalText(ctx, code, b, v)
157 }
158
159 func appendArrayHead(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte {
160 return append(b, '[')
161 }
162
163 func appendArrayEnd(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte {
164 last := len(b) - 1
165 b[last] = ']'
166 return append(b, ',')
167 }
168
169 func appendEmptyArray(_ *encoder.RuntimeContext, b []byte) []byte {
170 return append(b, '[', ']', ',')
171 }
172
173 func appendEmptyObject(_ *encoder.RuntimeContext, b []byte) []byte {
174 return append(b, '{', '}', ',')
175 }
176
177 func appendObjectEnd(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte {
178 last := len(b) - 1
179 b[last] = '}'
180 return append(b, ',')
181 }
182
183 func appendStructHead(_ *encoder.RuntimeContext, b []byte) []byte {
184 return append(b, '{')
185 }
186
187 func appendStructKey(_ *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte {
188 return append(b, code.Key...)
189 }
190
191 func appendStructEnd(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte {
192 return append(b, '}', ',')
193 }
194
195 func appendStructEndSkipLast(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte {
196 last := len(b) - 1
197 if b[last] == ',' {
198 b[last] = '}'
199 return appendComma(ctx, b)
200 }
201 return appendStructEnd(ctx, code, b)
202 }
203
204 func restoreIndent(_ *encoder.RuntimeContext, _ *encoder.Opcode, _ uintptr) {}
205 func storeIndent(_ uintptr, _ *encoder.Opcode, _ uintptr) {}
206 func appendMapKeyIndent(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte { return b }
207 func appendArrayElemIndent(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte { return b }
208
View as plain text