github.com/night-codes/go-json@v0.9.15/internal/encoder/vm/util.go (about)

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