1 package vm_indent
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 appendStructEnd = encoder.AppendStructEndIndent
23 appendIndent = encoder.AppendIndent
24 errUnsupportedValue = encoder.ErrUnsupportedValue
25 errUnsupportedFloat = encoder.ErrUnsupportedFloat
26 mapiterinit = encoder.MapIterInit
27 mapiterkey = encoder.MapIterKey
28 mapitervalue = encoder.MapIterValue
29 mapiternext = encoder.MapIterNext
30 maplen = encoder.MapLen
31 )
32
33 type emptyInterface struct {
34 typ *runtime.Type
35 ptr unsafe.Pointer
36 }
37
38 type nonEmptyInterface struct {
39 itab *struct {
40 ityp *runtime.Type
41 typ *runtime.Type
42
43 }
44 ptr unsafe.Pointer
45 }
46
47 func errUnimplementedOp(op encoder.OpType) error {
48 return fmt.Errorf("encoder (indent): opcode %s has not been implemented", op)
49 }
50
51 func load(base uintptr, idx uint32) uintptr {
52 addr := base + uintptr(idx)
53 return **(**uintptr)(unsafe.Pointer(&addr))
54 }
55
56 func store(base uintptr, idx uint32, p uintptr) {
57 addr := base + uintptr(idx)
58 **(**uintptr)(unsafe.Pointer(&addr)) = p
59 }
60
61 func loadNPtr(base uintptr, idx uint32, ptrNum uint8) uintptr {
62 addr := base + uintptr(idx)
63 p := **(**uintptr)(unsafe.Pointer(&addr))
64 for i := uint8(0); i < ptrNum; i++ {
65 if p == 0 {
66 return 0
67 }
68 p = ptrToPtr(p)
69 }
70 return p
71 }
72
73 func ptrToUint64(p uintptr, bitSize uint8) uint64 {
74 switch bitSize {
75 case 8:
76 return (uint64)(**(**uint8)(unsafe.Pointer(&p)))
77 case 16:
78 return (uint64)(**(**uint16)(unsafe.Pointer(&p)))
79 case 32:
80 return (uint64)(**(**uint32)(unsafe.Pointer(&p)))
81 case 64:
82 return **(**uint64)(unsafe.Pointer(&p))
83 }
84 return 0
85 }
86 func ptrToFloat32(p uintptr) float32 { return **(**float32)(unsafe.Pointer(&p)) }
87 func ptrToFloat64(p uintptr) float64 { return **(**float64)(unsafe.Pointer(&p)) }
88 func ptrToBool(p uintptr) bool { return **(**bool)(unsafe.Pointer(&p)) }
89 func ptrToBytes(p uintptr) []byte { return **(**[]byte)(unsafe.Pointer(&p)) }
90 func ptrToNumber(p uintptr) json.Number { return **(**json.Number)(unsafe.Pointer(&p)) }
91 func ptrToString(p uintptr) string { return **(**string)(unsafe.Pointer(&p)) }
92 func ptrToSlice(p uintptr) *runtime.SliceHeader { return *(**runtime.SliceHeader)(unsafe.Pointer(&p)) }
93 func ptrToPtr(p uintptr) uintptr {
94 return uintptr(**(**unsafe.Pointer)(unsafe.Pointer(&p)))
95 }
96 func ptrToNPtr(p uintptr, ptrNum uint8) uintptr {
97 for i := uint8(0); i < ptrNum; i++ {
98 if p == 0 {
99 return 0
100 }
101 p = ptrToPtr(p)
102 }
103 return p
104 }
105
106 func ptrToUnsafePtr(p uintptr) unsafe.Pointer {
107 return *(*unsafe.Pointer)(unsafe.Pointer(&p))
108 }
109 func ptrToInterface(code *encoder.Opcode, p uintptr) interface{} {
110 return *(*interface{})(unsafe.Pointer(&emptyInterface{
111 typ: code.Type,
112 ptr: *(*unsafe.Pointer)(unsafe.Pointer(&p)),
113 }))
114 }
115
116 func appendBool(_ *encoder.RuntimeContext, b []byte, v bool) []byte {
117 if v {
118 return append(b, "true"...)
119 }
120 return append(b, "false"...)
121 }
122
123 func appendNull(_ *encoder.RuntimeContext, b []byte) []byte {
124 return append(b, "null"...)
125 }
126
127 func appendComma(_ *encoder.RuntimeContext, b []byte) []byte {
128 return append(b, ',', '\n')
129 }
130
131 func appendNullComma(_ *encoder.RuntimeContext, b []byte) []byte {
132 return append(b, "null,\n"...)
133 }
134
135 func appendColon(_ *encoder.RuntimeContext, b []byte) []byte {
136 return append(b[:len(b)-2], ':', ' ')
137 }
138
139 func appendMapKeyValue(ctx *encoder.RuntimeContext, code *encoder.Opcode, b, key, value []byte) []byte {
140 b = appendIndent(ctx, b, code.Indent+1)
141 b = append(b, key...)
142 b[len(b)-2] = ':'
143 b[len(b)-1] = ' '
144 return append(b, value...)
145 }
146
147 func appendMapEnd(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte {
148 b = b[:len(b)-2]
149 b = append(b, '\n')
150 b = appendIndent(ctx, b, code.Indent)
151 return append(b, '}', ',', '\n')
152 }
153
154 func appendArrayHead(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte {
155 b = append(b, '[', '\n')
156 return appendIndent(ctx, b, code.Indent+1)
157 }
158
159 func appendArrayEnd(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte {
160 b = b[:len(b)-2]
161 b = append(b, '\n')
162 b = appendIndent(ctx, b, code.Indent)
163 return append(b, ']', ',', '\n')
164 }
165
166 func appendEmptyArray(_ *encoder.RuntimeContext, b []byte) []byte {
167 return append(b, '[', ']', ',', '\n')
168 }
169
170 func appendEmptyObject(_ *encoder.RuntimeContext, b []byte) []byte {
171 return append(b, '{', '}', ',', '\n')
172 }
173
174 func appendObjectEnd(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte {
175 last := len(b) - 1
176
177 b[last-1] = '\n'
178 b = appendIndent(ctx, b[:last], code.Indent)
179 return append(b, '}', ',', '\n')
180 }
181
182 func appendMarshalJSON(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte, v interface{}) ([]byte, error) {
183 return encoder.AppendMarshalJSONIndent(ctx, code, b, v)
184 }
185
186 func appendMarshalText(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte, v interface{}) ([]byte, error) {
187 return encoder.AppendMarshalTextIndent(ctx, code, b, v)
188 }
189
190 func appendStructHead(_ *encoder.RuntimeContext, b []byte) []byte {
191 return append(b, '{', '\n')
192 }
193
194 func appendStructKey(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte {
195 b = appendIndent(ctx, b, code.Indent)
196 b = append(b, code.Key...)
197 return append(b, ' ')
198 }
199
200 func appendStructEndSkipLast(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte {
201 last := len(b) - 1
202 if b[last-1] == '{' {
203 b[last] = '}'
204 } else {
205 if b[last] == '\n' {
206
207 b = b[:len(b)-2]
208 }
209 b = append(b, '\n')
210 b = appendIndent(ctx, b, code.Indent-1)
211 b = append(b, '}')
212 }
213 return appendComma(ctx, b)
214 }
215
216 func restoreIndent(ctx *encoder.RuntimeContext, code *encoder.Opcode, ctxptr uintptr) {
217 ctx.BaseIndent = uint32(load(ctxptr, code.Length))
218 }
219
220 func storeIndent(ctxptr uintptr, code *encoder.Opcode, indent uintptr) {
221 store(ctxptr, code.Length, indent)
222 }
223
224 func appendArrayElemIndent(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte {
225 return appendIndent(ctx, b, code.Indent+1)
226 }
227
228 func appendMapKeyIndent(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte {
229 return appendIndent(ctx, b, code.Indent)
230 }
231
View as plain text