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 }