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

     1  package vm_color
     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  	errUnsupportedValue = encoder.ErrUnsupportedValue
    16  	errUnsupportedFloat = encoder.ErrUnsupportedFloat
    17  	mapiterinit         = encoder.MapIterInit
    18  	mapiterkey          = encoder.MapIterKey
    19  	mapitervalue        = encoder.MapIterValue
    20  	mapiternext         = encoder.MapIterNext
    21  	maplen              = encoder.MapLen
    22  )
    23  
    24  type emptyInterface struct {
    25  	typ *runtime.Type
    26  	ptr unsafe.Pointer
    27  }
    28  
    29  type nonEmptyInterface struct {
    30  	itab *struct {
    31  		ityp *runtime.Type // static interface type
    32  		typ  *runtime.Type // dynamic concrete type
    33  		// unused fields...
    34  	}
    35  	ptr unsafe.Pointer
    36  }
    37  
    38  func errUnimplementedOp(op encoder.OpType) error {
    39  	return fmt.Errorf("encoder: opcode %s has not been implemented", op)
    40  }
    41  
    42  func load(base uintptr, idx uint32) uintptr {
    43  	addr := base + uintptr(idx)
    44  	return **(**uintptr)(unsafe.Pointer(&addr))
    45  }
    46  
    47  func store(base uintptr, idx uint32, p uintptr) {
    48  	addr := base + uintptr(idx)
    49  	**(**uintptr)(unsafe.Pointer(&addr)) = p
    50  }
    51  
    52  func loadNPtr(base uintptr, idx uint32, ptrNum uint8) uintptr {
    53  	addr := base + uintptr(idx)
    54  	p := **(**uintptr)(unsafe.Pointer(&addr))
    55  	for i := uint8(0); i < ptrNum; i++ {
    56  		if p == 0 {
    57  			return 0
    58  		}
    59  		p = ptrToPtr(p)
    60  	}
    61  	return p
    62  }
    63  
    64  func ptrToUint64(p uintptr, bitSize uint8) uint64 {
    65  	switch bitSize {
    66  	case 8:
    67  		return (uint64)(**(**uint8)(unsafe.Pointer(&p)))
    68  	case 16:
    69  		return (uint64)(**(**uint16)(unsafe.Pointer(&p)))
    70  	case 32:
    71  		return (uint64)(**(**uint32)(unsafe.Pointer(&p)))
    72  	case 64:
    73  		return **(**uint64)(unsafe.Pointer(&p))
    74  	}
    75  	return 0
    76  }
    77  func ptrToFloat32(p uintptr) float32            { return **(**float32)(unsafe.Pointer(&p)) }
    78  func ptrToFloat64(p uintptr) float64            { return **(**float64)(unsafe.Pointer(&p)) }
    79  func ptrToBool(p uintptr) bool                  { return **(**bool)(unsafe.Pointer(&p)) }
    80  func ptrToBytes(p uintptr) []byte               { return **(**[]byte)(unsafe.Pointer(&p)) }
    81  func ptrToNumber(p uintptr) json.Number         { return **(**json.Number)(unsafe.Pointer(&p)) }
    82  func ptrToString(p uintptr) string              { return **(**string)(unsafe.Pointer(&p)) }
    83  func ptrToSlice(p uintptr) *runtime.SliceHeader { return *(**runtime.SliceHeader)(unsafe.Pointer(&p)) }
    84  func ptrToPtr(p uintptr) uintptr {
    85  	return uintptr(**(**unsafe.Pointer)(unsafe.Pointer(&p)))
    86  }
    87  func ptrToNPtr(p uintptr, ptrNum uint8) uintptr {
    88  	for i := uint8(0); i < ptrNum; i++ {
    89  		if p == 0 {
    90  			return 0
    91  		}
    92  		p = ptrToPtr(p)
    93  	}
    94  	return p
    95  }
    96  
    97  func ptrToUnsafePtr(p uintptr) unsafe.Pointer {
    98  	return *(*unsafe.Pointer)(unsafe.Pointer(&p))
    99  }
   100  func ptrToInterface(code *encoder.Opcode, p uintptr) interface{} {
   101  	return *(*interface{})(unsafe.Pointer(&emptyInterface{
   102  		typ: code.Type,
   103  		ptr: *(*unsafe.Pointer)(unsafe.Pointer(&p)),
   104  	}))
   105  }
   106  
   107  func appendInt(ctx *encoder.RuntimeContext, b []byte, p uintptr, code *encoder.Opcode) []byte {
   108  	format := ctx.Option.ColorScheme.Int
   109  	b = append(b, format.Header...)
   110  	b = encoder.AppendInt(ctx, b, p, code)
   111  	return append(b, format.Footer...)
   112  }
   113  
   114  func appendUint(ctx *encoder.RuntimeContext, b []byte, p uintptr, code *encoder.Opcode) []byte {
   115  	format := ctx.Option.ColorScheme.Uint
   116  	b = append(b, format.Header...)
   117  	b = encoder.AppendUint(ctx, b, p, code)
   118  	return append(b, format.Footer...)
   119  }
   120  
   121  func appendFloat32(ctx *encoder.RuntimeContext, b []byte, v float32) []byte {
   122  	format := ctx.Option.ColorScheme.Float
   123  	b = append(b, format.Header...)
   124  	b = encoder.AppendFloat32(ctx, b, v)
   125  	return append(b, format.Footer...)
   126  }
   127  
   128  func appendFloat64(ctx *encoder.RuntimeContext, b []byte, v float64) []byte {
   129  	format := ctx.Option.ColorScheme.Float
   130  	b = append(b, format.Header...)
   131  	b = encoder.AppendFloat64(ctx, b, v)
   132  	return append(b, format.Footer...)
   133  }
   134  
   135  func appendString(ctx *encoder.RuntimeContext, b []byte, v string) []byte {
   136  	format := ctx.Option.ColorScheme.String
   137  	b = append(b, format.Header...)
   138  	b = encoder.AppendString(ctx, b, v)
   139  	return append(b, format.Footer...)
   140  }
   141  
   142  func appendByteSlice(ctx *encoder.RuntimeContext, b []byte, src []byte) []byte {
   143  	format := ctx.Option.ColorScheme.Binary
   144  	b = append(b, format.Header...)
   145  	b = encoder.AppendByteSlice(ctx, b, src)
   146  	return append(b, format.Footer...)
   147  }
   148  
   149  func appendNumber(ctx *encoder.RuntimeContext, b []byte, n json.Number) ([]byte, error) {
   150  	format := ctx.Option.ColorScheme.Int
   151  	b = append(b, format.Header...)
   152  	bb, err := encoder.AppendNumber(ctx, b, n)
   153  	if err != nil {
   154  		return nil, err
   155  	}
   156  	return append(bb, format.Footer...), nil
   157  }
   158  
   159  func appendBool(ctx *encoder.RuntimeContext, b []byte, v bool) []byte {
   160  	format := ctx.Option.ColorScheme.Bool
   161  	b = append(b, format.Header...)
   162  	if v {
   163  		b = append(b, "true"...)
   164  	} else {
   165  		b = append(b, "false"...)
   166  	}
   167  	return append(b, format.Footer...)
   168  }
   169  
   170  func appendNull(ctx *encoder.RuntimeContext, b []byte) []byte {
   171  	format := ctx.Option.ColorScheme.Null
   172  	b = append(b, format.Header...)
   173  	b = append(b, "null"...)
   174  	return append(b, format.Footer...)
   175  }
   176  
   177  func appendComma(_ *encoder.RuntimeContext, b []byte) []byte {
   178  	return append(b, ',')
   179  }
   180  
   181  func appendNullComma(ctx *encoder.RuntimeContext, b []byte) []byte {
   182  	format := ctx.Option.ColorScheme.Null
   183  	b = append(b, format.Header...)
   184  	b = append(b, "null"...)
   185  	return append(append(b, format.Footer...), ',')
   186  }
   187  
   188  func appendColon(_ *encoder.RuntimeContext, b []byte) []byte {
   189  	last := len(b) - 1
   190  	b[last] = ':'
   191  	return b
   192  }
   193  
   194  func appendMapKeyValue(_ *encoder.RuntimeContext, _ *encoder.Opcode, b, key, value []byte) []byte {
   195  	b = append(b, key[:len(key)-1]...)
   196  	b = append(b, ':')
   197  	return append(b, value...)
   198  }
   199  
   200  func appendMapEnd(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte {
   201  	last := len(b) - 1
   202  	b[last] = '}'
   203  	b = append(b, ',')
   204  	return b
   205  }
   206  
   207  func appendMarshalJSON(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte, v interface{}) ([]byte, error) {
   208  	return encoder.AppendMarshalJSON(ctx, code, b, v)
   209  }
   210  
   211  func appendMarshalText(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte, v interface{}) ([]byte, error) {
   212  	format := ctx.Option.ColorScheme.String
   213  	b = append(b, format.Header...)
   214  	bb, err := encoder.AppendMarshalText(ctx, code, b, v)
   215  	if err != nil {
   216  		return nil, err
   217  	}
   218  	return append(bb, format.Footer...), nil
   219  }
   220  
   221  func appendArrayHead(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte {
   222  	return append(b, '[')
   223  }
   224  
   225  func appendArrayEnd(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte {
   226  	last := len(b) - 1
   227  	b[last] = ']'
   228  	return append(b, ',')
   229  }
   230  
   231  func appendEmptyArray(_ *encoder.RuntimeContext, b []byte) []byte {
   232  	return append(b, '[', ']', ',')
   233  }
   234  
   235  func appendEmptyObject(_ *encoder.RuntimeContext, b []byte) []byte {
   236  	return append(b, '{', '}', ',')
   237  }
   238  
   239  func appendObjectEnd(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte {
   240  	last := len(b) - 1
   241  	b[last] = '}'
   242  	return append(b, ',')
   243  }
   244  
   245  func appendStructHead(_ *encoder.RuntimeContext, b []byte) []byte {
   246  	return append(b, '{')
   247  }
   248  
   249  func appendStructKey(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte {
   250  	format := ctx.Option.ColorScheme.ObjectKey
   251  	b = append(b, format.Header...)
   252  	b = append(b, code.Key[:len(code.Key)-1]...)
   253  	b = append(b, format.Footer...)
   254  
   255  	return append(b, ':')
   256  }
   257  
   258  func appendStructEnd(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte {
   259  	return append(b, '}', ',')
   260  }
   261  
   262  func appendStructEndSkipLast(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte {
   263  	last := len(b) - 1
   264  	if b[last] == ',' {
   265  		b[last] = '}'
   266  		return appendComma(ctx, b)
   267  	}
   268  	return appendStructEnd(ctx, code, b)
   269  }
   270  
   271  func restoreIndent(_ *encoder.RuntimeContext, _ *encoder.Opcode, _ uintptr)               {}
   272  func storeIndent(_ uintptr, _ *encoder.Opcode, _ uintptr)                                 {}
   273  func appendMapKeyIndent(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte    { return b }
   274  func appendArrayElemIndent(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte { return b }