github.com/3JoB/go-json@v0.10.4/internal/encoder/vm_indent/util.go (about) 1 package vm_indent 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "unsafe" 7 8 "github.com/3JoB/go-json/internal/encoder" 9 "github.com/3JoB/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 // static interface type 41 typ *runtime.Type // dynamic concrete type 42 // unused fields... 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 87 func ptrToFloat32(p uintptr) float32 { return **(**float32)(unsafe.Pointer(&p)) } 88 89 func ptrToFloat64(p uintptr) float64 { return **(**float64)(unsafe.Pointer(&p)) } 90 91 func ptrToBool(p uintptr) bool { return **(**bool)(unsafe.Pointer(&p)) } 92 93 func ptrToBytes(p uintptr) []byte { return **(**[]byte)(unsafe.Pointer(&p)) } 94 95 func ptrToNumber(p uintptr) json.Number { return **(**json.Number)(unsafe.Pointer(&p)) } 96 97 func ptrToString(p uintptr) string { return **(**string)(unsafe.Pointer(&p)) } 98 99 func ptrToSlice(p uintptr) *runtime.SliceHeader { return *(**runtime.SliceHeader)(unsafe.Pointer(&p)) } 100 101 func ptrToPtr(p uintptr) uintptr { 102 return uintptr(**(**unsafe.Pointer)(unsafe.Pointer(&p))) 103 } 104 105 func ptrToNPtr(p uintptr, ptrNum uint8) uintptr { 106 for i := uint8(0); i < ptrNum; i++ { 107 if p == 0 { 108 return 0 109 } 110 p = ptrToPtr(p) 111 } 112 return p 113 } 114 115 func ptrToUnsafePtr(p uintptr) unsafe.Pointer { 116 return *(*unsafe.Pointer)(unsafe.Pointer(&p)) 117 } 118 119 func ptrToInterface(code *encoder.Opcode, p uintptr) any { 120 return *(*any)(unsafe.Pointer(&emptyInterface{ 121 typ: code.Type, 122 ptr: *(*unsafe.Pointer)(unsafe.Pointer(&p)), 123 })) 124 } 125 126 func appendBool(_ *encoder.RuntimeContext, b []byte, v bool) []byte { 127 if v { 128 return append(b, "true"...) 129 } 130 return append(b, "false"...) 131 } 132 133 func appendNull(_ *encoder.RuntimeContext, b []byte) []byte { 134 return append(b, "null"...) 135 } 136 137 func appendComma(_ *encoder.RuntimeContext, b []byte) []byte { 138 return append(b, ',', '\n') 139 } 140 141 func appendNullComma(_ *encoder.RuntimeContext, b []byte) []byte { 142 return append(b, "null,\n"...) 143 } 144 145 func appendColon(_ *encoder.RuntimeContext, b []byte) []byte { 146 return append(b[:len(b)-2], ':', ' ') 147 } 148 149 func appendMapKeyValue(ctx *encoder.RuntimeContext, code *encoder.Opcode, b, key, value []byte) []byte { 150 b = appendIndent(ctx, b, code.Indent+1) 151 b = append(b, key...) 152 b[len(b)-2] = ':' 153 b[len(b)-1] = ' ' 154 return append(b, value...) 155 } 156 157 func appendMapEnd(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte { 158 b = b[:len(b)-2] 159 b = append(b, '\n') 160 b = appendIndent(ctx, b, code.Indent) 161 return append(b, '}', ',', '\n') 162 } 163 164 func appendArrayHead(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte { 165 b = append(b, '[', '\n') 166 return appendIndent(ctx, b, code.Indent+1) 167 } 168 169 func appendArrayEnd(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte { 170 b = b[:len(b)-2] 171 b = append(b, '\n') 172 b = appendIndent(ctx, b, code.Indent) 173 return append(b, ']', ',', '\n') 174 } 175 176 func appendEmptyArray(_ *encoder.RuntimeContext, b []byte) []byte { 177 return append(b, '[', ']', ',', '\n') 178 } 179 180 func appendEmptyObject(_ *encoder.RuntimeContext, b []byte) []byte { 181 return append(b, '{', '}', ',', '\n') 182 } 183 184 func appendObjectEnd(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte { 185 last := len(b) - 1 186 // replace comma to newline 187 b[last-1] = '\n' 188 b = appendIndent(ctx, b[:last], code.Indent) 189 return append(b, '}', ',', '\n') 190 } 191 192 func appendMarshalJSON(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte, v any) ([]byte, error) { 193 return encoder.AppendMarshalJSONIndent(ctx, code, b, v) 194 } 195 196 func appendMarshalText(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte, v any) ([]byte, error) { 197 return encoder.AppendMarshalTextIndent(ctx, code, b, v) 198 } 199 200 func appendStructHead(_ *encoder.RuntimeContext, b []byte) []byte { 201 return append(b, '{', '\n') 202 } 203 204 func appendStructKey(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte { 205 b = appendIndent(ctx, b, code.Indent) 206 b = append(b, code.Key...) 207 return append(b, ' ') 208 } 209 210 func appendStructEndSkipLast(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte { 211 last := len(b) - 1 212 if b[last-1] == '{' { 213 b[last] = '}' 214 } else { 215 if b[last] == '\n' { 216 // to remove ',' and '\n' characters 217 b = b[:len(b)-2] 218 } 219 b = append(b, '\n') 220 b = appendIndent(ctx, b, code.Indent-1) 221 b = append(b, '}') 222 } 223 return appendComma(ctx, b) 224 } 225 226 func restoreIndent(ctx *encoder.RuntimeContext, code *encoder.Opcode, ctxptr uintptr) { 227 ctx.BaseIndent = uint32(load(ctxptr, code.Length)) 228 } 229 230 func storeIndent(ctxptr uintptr, code *encoder.Opcode, indent uintptr) { 231 store(ctxptr, code.Length, indent) 232 } 233 234 func appendArrayElemIndent(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte { 235 return appendIndent(ctx, b, code.Indent+1) 236 } 237 238 func appendMapKeyIndent(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte { 239 return appendIndent(ctx, b, code.Indent) 240 }