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