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  }