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 */