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