github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/mobile/bind/seq/buffer.go (about)

     1  // Copyright 2014 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package seq
     6  
     7  import (
     8  	"bytes"
     9  	"fmt"
    10  	"runtime"
    11  	"unsafe"
    12  )
    13  
    14  // Buffer is a set of arguments or return values from a function call
    15  // across the language boundary. Encoding is machine-dependent.
    16  type Buffer struct {
    17  	Data   []byte
    18  	Offset int // position of next read/write from Data
    19  }
    20  
    21  func (b *Buffer) String() string {
    22  	// Debugging.
    23  	var buf bytes.Buffer
    24  	fmt.Fprintf(&buf, "seq{Off=%d, Len=%d Data=", b.Offset, len(b.Data))
    25  	const hextable = "0123456789abcdef"
    26  	for i, v := range b.Data {
    27  		if i > 0 {
    28  			buf.WriteByte(':')
    29  		}
    30  		buf.WriteByte(hextable[v>>4])
    31  		buf.WriteByte(hextable[v&0x0f])
    32  	}
    33  	buf.WriteByte('}')
    34  	return buf.String()
    35  }
    36  
    37  func (b *Buffer) panic(need int) {
    38  	panic(fmt.Sprintf("need %d bytes: %s", need, b))
    39  }
    40  
    41  func (b *Buffer) grow(need int) {
    42  	size := len(b.Data)
    43  	if size == 0 {
    44  		size = 2
    45  	}
    46  	for size < need {
    47  		size *= 2
    48  	}
    49  	data := make([]byte, size+len(b.Data))
    50  	copy(data, b.Data[:b.Offset])
    51  	b.Data = data
    52  }
    53  
    54  // align returns the aligned offset.
    55  func align(offset, alignment int) int {
    56  	pad := offset % alignment
    57  	if pad > 0 {
    58  		pad = alignment - pad
    59  	}
    60  	return pad + offset
    61  }
    62  
    63  func (b *Buffer) ReadInt8() int8 {
    64  	offset := b.Offset
    65  	if len(b.Data)-offset < 1 {
    66  		b.panic(1)
    67  	}
    68  	v := *(*int8)(unsafe.Pointer(&b.Data[offset]))
    69  	b.Offset++
    70  	return v
    71  }
    72  
    73  func (b *Buffer) ReadInt16() int16 {
    74  	offset := align(b.Offset, 2)
    75  	if len(b.Data)-offset < 2 {
    76  		b.panic(2)
    77  	}
    78  	v := *(*int16)(unsafe.Pointer(&b.Data[offset]))
    79  	b.Offset = offset + 2
    80  	return v
    81  }
    82  
    83  func (b *Buffer) ReadInt32() int32 {
    84  	offset := align(b.Offset, 4)
    85  	if len(b.Data)-offset < 4 {
    86  		b.panic(4)
    87  	}
    88  	v := *(*int32)(unsafe.Pointer(&b.Data[offset]))
    89  	b.Offset = offset + 4
    90  	return v
    91  }
    92  
    93  func (b *Buffer) ReadInt64() int64 {
    94  	offset := align(b.Offset, 8)
    95  	if len(b.Data)-offset < 8 {
    96  		b.panic(8)
    97  	}
    98  	v := *(*int64)(unsafe.Pointer(&b.Data[offset]))
    99  	b.Offset = offset + 8
   100  	return v
   101  }
   102  
   103  func (b *Buffer) ReadBool() bool {
   104  	return b.ReadInt8() != 0
   105  }
   106  
   107  func (b *Buffer) ReadInt() int {
   108  	return int(b.ReadInt64())
   109  }
   110  
   111  func (b *Buffer) ReadFloat32() float32 {
   112  	offset := align(b.Offset, 4)
   113  	if len(b.Data)-offset < 4 {
   114  		b.panic(4)
   115  	}
   116  	v := *(*float32)(unsafe.Pointer(&b.Data[offset]))
   117  	b.Offset = offset + 4
   118  	return v
   119  }
   120  
   121  func (b *Buffer) ReadFloat64() float64 {
   122  	offset := align(b.Offset, 8)
   123  	if len(b.Data)-offset < 8 {
   124  		b.panic(8)
   125  	}
   126  	v := *(*float64)(unsafe.Pointer(&b.Data[offset]))
   127  	b.Offset = offset + 8
   128  	return v
   129  }
   130  
   131  func (b *Buffer) ReadByteArray() []byte {
   132  	sz := b.ReadInt64()
   133  	if sz == 0 {
   134  		return nil
   135  	}
   136  
   137  	ptr := b.ReadInt64()
   138  	org := (*[1 << 30]byte)(unsafe.Pointer(uintptr(ptr)))[:sz]
   139  
   140  	// Make a copy managed by Go, so the returned byte array can be
   141  	// used safely in Go.
   142  	slice := make([]byte, sz)
   143  	copy(slice, org)
   144  	return slice
   145  }
   146  
   147  func (b *Buffer) ReadRef() *Ref {
   148  	ref := &Ref{b.ReadInt32()}
   149  	if ref.Num > 0 {
   150  		// This is a foreign object reference.
   151  		// Track its lifetime with a finalizer.
   152  		runtime.SetFinalizer(ref, FinalizeRef)
   153  	}
   154  	return ref
   155  }
   156  
   157  func (b *Buffer) ReadString() string {
   158  	return DecString(b)
   159  }
   160  
   161  func (b *Buffer) WriteInt8(v int8) {
   162  	offset := b.Offset
   163  	if len(b.Data)-offset < 1 {
   164  		b.grow(offset + 1 - len(b.Data))
   165  	}
   166  	*(*int8)(unsafe.Pointer(&b.Data[offset])) = v
   167  	b.Offset++
   168  }
   169  
   170  func (b *Buffer) WriteInt16(v int16) {
   171  	offset := align(b.Offset, 2)
   172  	if len(b.Data)-offset < 2 {
   173  		b.grow(offset + 2 - len(b.Data))
   174  	}
   175  	*(*int16)(unsafe.Pointer(&b.Data[offset])) = v
   176  	b.Offset = offset + 2
   177  }
   178  
   179  func (b *Buffer) WriteInt32(v int32) {
   180  	offset := align(b.Offset, 4)
   181  	if len(b.Data)-offset < 4 {
   182  		b.grow(offset + 4 - len(b.Data))
   183  	}
   184  	*(*int32)(unsafe.Pointer(&b.Data[offset])) = v
   185  	b.Offset = offset + 4
   186  }
   187  
   188  func (b *Buffer) WriteInt64(v int64) {
   189  	offset := align(b.Offset, 8)
   190  	if len(b.Data)-offset < 8 {
   191  		b.grow(offset + 8 - len(b.Data))
   192  	}
   193  	*(*int64)(unsafe.Pointer(&b.Data[offset])) = v
   194  	b.Offset = offset + 8
   195  }
   196  
   197  func (b *Buffer) WriteBool(v bool) {
   198  	if v {
   199  		b.WriteInt8(1)
   200  	} else {
   201  		b.WriteInt8(0)
   202  	}
   203  }
   204  
   205  func (b *Buffer) WriteInt(v int) {
   206  	b.WriteInt64(int64(v))
   207  }
   208  
   209  func (b *Buffer) WriteFloat32(v float32) {
   210  	offset := align(b.Offset, 4)
   211  	if len(b.Data)-offset < 4 {
   212  		b.grow(offset + 4 - len(b.Data))
   213  	}
   214  	*(*float32)(unsafe.Pointer(&b.Data[offset])) = v
   215  	b.Offset = offset + 4
   216  }
   217  
   218  func (b *Buffer) WriteFloat64(v float64) {
   219  	offset := align(b.Offset, 8)
   220  	if len(b.Data)-offset < 8 {
   221  		b.grow(offset + 8 - len(b.Data))
   222  	}
   223  	*(*float64)(unsafe.Pointer(&b.Data[offset])) = v
   224  	b.Offset = offset + 8
   225  }
   226  
   227  func (b *Buffer) WriteByteArray(byt []byte) {
   228  	sz := len(byt)
   229  	if sz == 0 {
   230  		b.WriteInt64(int64(sz))
   231  		return
   232  	}
   233  
   234  	ptr := uintptr(unsafe.Pointer(&byt[0]))
   235  	b.WriteInt64(int64(sz))
   236  	b.WriteInt64(int64(ptr))
   237  	return
   238  }
   239  
   240  func (b *Buffer) WriteString(v string) {
   241  	EncString(b, v)
   242  }
   243  
   244  func (b *Buffer) WriteGoRef(obj interface{}) {
   245  	refs.Lock()
   246  	num := refs.refs[obj]
   247  	if num != 0 {
   248  		s := refs.objs[num]
   249  		refs.objs[num] = countedObj{s.obj, s.cnt + 1}
   250  	} else {
   251  		num = refs.next
   252  		refs.next--
   253  		if refs.next > 0 {
   254  			panic("refs.next underflow")
   255  		}
   256  		refs.refs[obj] = num
   257  		refs.objs[num] = countedObj{obj, 1}
   258  	}
   259  	refs.Unlock()
   260  
   261  	b.WriteInt32(int32(num))
   262  }
   263  
   264  /*  TODO: Will we need it?
   265  func (b *Buffer) WriteRef(ref *Ref) {
   266  	b.WriteInt32(ref.Num)
   267  }
   268  */