github.com/goccy/go-json@v0.10.3-0.20240509105655-5e2ae3f23c1d/internal/encoder/vm_color/util.go (about) 1 package vm_color 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 errUnsupportedValue = encoder.ErrUnsupportedValue 16 errUnsupportedFloat = encoder.ErrUnsupportedFloat 17 mapiterinit = encoder.MapIterInit 18 mapiterkey = encoder.MapIterKey 19 mapitervalue = encoder.MapIterValue 20 mapiternext = encoder.MapIterNext 21 maplen = encoder.MapLen 22 ) 23 24 type emptyInterface struct { 25 typ *runtime.Type 26 ptr unsafe.Pointer 27 } 28 29 type nonEmptyInterface struct { 30 itab *struct { 31 ityp *runtime.Type // static interface type 32 typ *runtime.Type // dynamic concrete type 33 // unused fields... 34 } 35 ptr unsafe.Pointer 36 } 37 38 func errUnimplementedOp(op encoder.OpType) error { 39 return fmt.Errorf("encoder: opcode %s has not been implemented", op) 40 } 41 42 func load(base uintptr, idx uint32) uintptr { 43 addr := base + uintptr(idx) 44 return **(**uintptr)(unsafe.Pointer(&addr)) 45 } 46 47 func store(base uintptr, idx uint32, p uintptr) { 48 addr := base + uintptr(idx) 49 **(**uintptr)(unsafe.Pointer(&addr)) = p 50 } 51 52 func loadNPtr(base uintptr, idx uint32, ptrNum uint8) uintptr { 53 addr := base + uintptr(idx) 54 p := **(**uintptr)(unsafe.Pointer(&addr)) 55 for i := uint8(0); i < ptrNum; i++ { 56 if p == 0 { 57 return 0 58 } 59 p = ptrToPtr(p) 60 } 61 return p 62 } 63 64 func ptrToUint64(p uintptr, bitSize uint8) uint64 { 65 switch bitSize { 66 case 8: 67 return (uint64)(**(**uint8)(unsafe.Pointer(&p))) 68 case 16: 69 return (uint64)(**(**uint16)(unsafe.Pointer(&p))) 70 case 32: 71 return (uint64)(**(**uint32)(unsafe.Pointer(&p))) 72 case 64: 73 return **(**uint64)(unsafe.Pointer(&p)) 74 } 75 return 0 76 } 77 func ptrToFloat32(p uintptr) float32 { return **(**float32)(unsafe.Pointer(&p)) } 78 func ptrToFloat64(p uintptr) float64 { return **(**float64)(unsafe.Pointer(&p)) } 79 func ptrToBool(p uintptr) bool { return **(**bool)(unsafe.Pointer(&p)) } 80 func ptrToBytes(p uintptr) []byte { return **(**[]byte)(unsafe.Pointer(&p)) } 81 func ptrToNumber(p uintptr) json.Number { return **(**json.Number)(unsafe.Pointer(&p)) } 82 func ptrToString(p uintptr) string { return **(**string)(unsafe.Pointer(&p)) } 83 func ptrToSlice(p uintptr) *runtime.SliceHeader { return *(**runtime.SliceHeader)(unsafe.Pointer(&p)) } 84 func ptrToPtr(p uintptr) uintptr { 85 return uintptr(**(**unsafe.Pointer)(unsafe.Pointer(&p))) 86 } 87 func ptrToNPtr(p uintptr, ptrNum uint8) uintptr { 88 for i := uint8(0); i < ptrNum; i++ { 89 if p == 0 { 90 return 0 91 } 92 p = ptrToPtr(p) 93 } 94 return p 95 } 96 97 func ptrToUnsafePtr(p uintptr) unsafe.Pointer { 98 return *(*unsafe.Pointer)(unsafe.Pointer(&p)) 99 } 100 func ptrToInterface(code *encoder.Opcode, p uintptr) interface{} { 101 return *(*interface{})(unsafe.Pointer(&emptyInterface{ 102 typ: code.Type, 103 ptr: *(*unsafe.Pointer)(unsafe.Pointer(&p)), 104 })) 105 } 106 107 func appendInt(ctx *encoder.RuntimeContext, b []byte, p uintptr, code *encoder.Opcode) []byte { 108 format := ctx.Option.ColorScheme.Int 109 b = append(b, format.Header...) 110 b = encoder.AppendInt(ctx, b, p, code) 111 return append(b, format.Footer...) 112 } 113 114 func appendUint(ctx *encoder.RuntimeContext, b []byte, p uintptr, code *encoder.Opcode) []byte { 115 format := ctx.Option.ColorScheme.Uint 116 b = append(b, format.Header...) 117 b = encoder.AppendUint(ctx, b, p, code) 118 return append(b, format.Footer...) 119 } 120 121 func appendFloat32(ctx *encoder.RuntimeContext, b []byte, v float32) []byte { 122 format := ctx.Option.ColorScheme.Float 123 b = append(b, format.Header...) 124 b = encoder.AppendFloat32(ctx, b, v) 125 return append(b, format.Footer...) 126 } 127 128 func appendFloat64(ctx *encoder.RuntimeContext, b []byte, v float64) []byte { 129 format := ctx.Option.ColorScheme.Float 130 b = append(b, format.Header...) 131 b = encoder.AppendFloat64(ctx, b, v) 132 return append(b, format.Footer...) 133 } 134 135 func appendString(ctx *encoder.RuntimeContext, b []byte, v string) []byte { 136 format := ctx.Option.ColorScheme.String 137 b = append(b, format.Header...) 138 b = encoder.AppendString(ctx, b, v) 139 return append(b, format.Footer...) 140 } 141 142 func appendByteSlice(ctx *encoder.RuntimeContext, b []byte, src []byte) []byte { 143 format := ctx.Option.ColorScheme.Binary 144 b = append(b, format.Header...) 145 b = encoder.AppendByteSlice(ctx, b, src) 146 return append(b, format.Footer...) 147 } 148 149 func appendNumber(ctx *encoder.RuntimeContext, b []byte, n json.Number) ([]byte, error) { 150 format := ctx.Option.ColorScheme.Int 151 b = append(b, format.Header...) 152 bb, err := encoder.AppendNumber(ctx, b, n) 153 if err != nil { 154 return nil, err 155 } 156 return append(bb, format.Footer...), nil 157 } 158 159 func appendBool(ctx *encoder.RuntimeContext, b []byte, v bool) []byte { 160 format := ctx.Option.ColorScheme.Bool 161 b = append(b, format.Header...) 162 if v { 163 b = append(b, "true"...) 164 } else { 165 b = append(b, "false"...) 166 } 167 return append(b, format.Footer...) 168 } 169 170 func appendNull(ctx *encoder.RuntimeContext, b []byte) []byte { 171 format := ctx.Option.ColorScheme.Null 172 b = append(b, format.Header...) 173 b = append(b, "null"...) 174 return append(b, format.Footer...) 175 } 176 177 func appendComma(_ *encoder.RuntimeContext, b []byte) []byte { 178 return append(b, ',') 179 } 180 181 func appendNullComma(ctx *encoder.RuntimeContext, b []byte) []byte { 182 format := ctx.Option.ColorScheme.Null 183 b = append(b, format.Header...) 184 b = append(b, "null"...) 185 return append(append(b, format.Footer...), ',') 186 } 187 188 func appendColon(_ *encoder.RuntimeContext, b []byte) []byte { 189 last := len(b) - 1 190 b[last] = ':' 191 return b 192 } 193 194 func appendMapKeyValue(_ *encoder.RuntimeContext, _ *encoder.Opcode, b, key, value []byte) []byte { 195 b = append(b, key[:len(key)-1]...) 196 b = append(b, ':') 197 return append(b, value...) 198 } 199 200 func appendMapEnd(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte { 201 last := len(b) - 1 202 b[last] = '}' 203 b = append(b, ',') 204 return b 205 } 206 207 func appendMarshalJSON(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte, v interface{}) ([]byte, error) { 208 return encoder.AppendMarshalJSON(ctx, code, b, v) 209 } 210 211 func appendMarshalText(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte, v interface{}) ([]byte, error) { 212 format := ctx.Option.ColorScheme.String 213 b = append(b, format.Header...) 214 bb, err := encoder.AppendMarshalText(ctx, code, b, v) 215 if err != nil { 216 return nil, err 217 } 218 return append(bb, format.Footer...), nil 219 } 220 221 func appendArrayHead(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte { 222 return append(b, '[') 223 } 224 225 func appendArrayEnd(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte { 226 last := len(b) - 1 227 b[last] = ']' 228 return append(b, ',') 229 } 230 231 func appendEmptyArray(_ *encoder.RuntimeContext, b []byte) []byte { 232 return append(b, '[', ']', ',') 233 } 234 235 func appendEmptyObject(_ *encoder.RuntimeContext, b []byte) []byte { 236 return append(b, '{', '}', ',') 237 } 238 239 func appendObjectEnd(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte { 240 last := len(b) - 1 241 b[last] = '}' 242 return append(b, ',') 243 } 244 245 func appendStructHead(_ *encoder.RuntimeContext, b []byte) []byte { 246 return append(b, '{') 247 } 248 249 func appendStructKey(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte { 250 format := ctx.Option.ColorScheme.ObjectKey 251 b = append(b, format.Header...) 252 b = append(b, code.Key[:len(code.Key)-1]...) 253 b = append(b, format.Footer...) 254 255 return append(b, ':') 256 } 257 258 func appendStructEnd(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte { 259 return append(b, '}', ',') 260 } 261 262 func appendStructEndSkipLast(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte { 263 last := len(b) - 1 264 if b[last] == ',' { 265 b[last] = '}' 266 return appendComma(ctx, b) 267 } 268 return appendStructEnd(ctx, code, b) 269 } 270 271 func restoreIndent(_ *encoder.RuntimeContext, _ *encoder.Opcode, _ uintptr) {} 272 func storeIndent(_ uintptr, _ *encoder.Opcode, _ uintptr) {} 273 func appendMapKeyIndent(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte { return b } 274 func appendArrayElemIndent(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte { return b }