| OLD | NEW |
| (Empty) |
| 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) ReadInt32() int32 { | |
| 64 offset := align(b.Offset, 4) | |
| 65 if len(b.Data)-offset < 4 { | |
| 66 b.panic(4) | |
| 67 } | |
| 68 v := *(*int32)(unsafe.Pointer(&b.Data[offset])) | |
| 69 b.Offset = offset + 4 | |
| 70 return v | |
| 71 } | |
| 72 | |
| 73 func (b *Buffer) ReadInt64() int64 { | |
| 74 offset := align(b.Offset, 8) | |
| 75 if len(b.Data)-offset < 8 { | |
| 76 b.panic(8) | |
| 77 } | |
| 78 v := *(*int64)(unsafe.Pointer(&b.Data[offset])) | |
| 79 b.Offset = offset + 8 | |
| 80 return v | |
| 81 } | |
| 82 | |
| 83 // TODO(hyangah): int8, int16? | |
| 84 | |
| 85 func (b *Buffer) ReadInt() int { | |
| 86 return int(b.ReadInt64()) | |
| 87 } | |
| 88 | |
| 89 func (b *Buffer) ReadFloat32() float32 { | |
| 90 offset := align(b.Offset, 4) | |
| 91 if len(b.Data)-offset < 4 { | |
| 92 b.panic(4) | |
| 93 } | |
| 94 v := *(*float32)(unsafe.Pointer(&b.Data[offset])) | |
| 95 b.Offset = offset + 4 | |
| 96 return v | |
| 97 } | |
| 98 | |
| 99 func (b *Buffer) ReadFloat64() float64 { | |
| 100 offset := align(b.Offset, 8) | |
| 101 if len(b.Data)-offset < 8 { | |
| 102 b.panic(8) | |
| 103 } | |
| 104 v := *(*float64)(unsafe.Pointer(&b.Data[offset])) | |
| 105 b.Offset = offset + 8 | |
| 106 return v | |
| 107 } | |
| 108 | |
| 109 func (b *Buffer) ReadByteArray() []byte { | |
| 110 sz := b.ReadInt64() | |
| 111 if sz == 0 { | |
| 112 return nil | |
| 113 } | |
| 114 | |
| 115 ptr := b.ReadInt64() | |
| 116 org := (*[1 << 30]byte)(unsafe.Pointer(uintptr(ptr)))[:sz] | |
| 117 | |
| 118 // Make a copy managed by Go, so the returned byte array can be | |
| 119 // used safely in Go. | |
| 120 slice := make([]byte, sz) | |
| 121 copy(slice, org) | |
| 122 return slice | |
| 123 } | |
| 124 | |
| 125 func (b *Buffer) ReadRef() *Ref { | |
| 126 ref := &Ref{b.ReadInt32()} | |
| 127 if ref.Num > 0 { | |
| 128 // This is a foreign object reference. | |
| 129 // Track its lifetime with a finalizer. | |
| 130 runtime.SetFinalizer(ref, FinalizeRef) | |
| 131 } | |
| 132 return ref | |
| 133 } | |
| 134 | |
| 135 func (b *Buffer) WriteInt32(v int32) { | |
| 136 offset := align(b.Offset, 4) | |
| 137 if len(b.Data)-offset < 4 { | |
| 138 b.grow(offset + 4 - len(b.Data)) | |
| 139 } | |
| 140 *(*int32)(unsafe.Pointer(&b.Data[offset])) = v | |
| 141 b.Offset = offset + 4 | |
| 142 } | |
| 143 | |
| 144 func (b *Buffer) WriteInt64(v int64) { | |
| 145 offset := align(b.Offset, 8) | |
| 146 if len(b.Data)-offset < 8 { | |
| 147 b.grow(offset + 8 - len(b.Data)) | |
| 148 } | |
| 149 *(*int64)(unsafe.Pointer(&b.Data[offset])) = v | |
| 150 b.Offset = offset + 8 | |
| 151 } | |
| 152 | |
| 153 func (b *Buffer) WriteInt(v int) { | |
| 154 b.WriteInt64(int64(v)) | |
| 155 } | |
| 156 | |
| 157 func (b *Buffer) WriteFloat32(v float32) { | |
| 158 offset := align(b.Offset, 4) | |
| 159 if len(b.Data)-offset < 4 { | |
| 160 b.grow(offset + 4 - len(b.Data)) | |
| 161 } | |
| 162 *(*float32)(unsafe.Pointer(&b.Data[offset])) = v | |
| 163 b.Offset = offset + 4 | |
| 164 } | |
| 165 | |
| 166 func (b *Buffer) WriteFloat64(v float64) { | |
| 167 offset := align(b.Offset, 8) | |
| 168 if len(b.Data)-offset < 8 { | |
| 169 b.grow(offset + 8 - len(b.Data)) | |
| 170 } | |
| 171 *(*float64)(unsafe.Pointer(&b.Data[offset])) = v | |
| 172 b.Offset = offset + 8 | |
| 173 } | |
| 174 | |
| 175 func (b *Buffer) WriteByteArray(byt []byte) { | |
| 176 sz := len(byt) | |
| 177 if sz == 0 { | |
| 178 b.WriteInt64(int64(sz)) | |
| 179 return | |
| 180 } | |
| 181 | |
| 182 ptr := uintptr(unsafe.Pointer(&byt[0])) | |
| 183 b.WriteInt64(int64(sz)) | |
| 184 b.WriteInt64(int64(ptr)) | |
| 185 return | |
| 186 } | |
| 187 | |
| 188 func (b *Buffer) WriteGoRef(obj interface{}) { | |
| 189 refs.Lock() | |
| 190 num := refs.refs[obj] | |
| 191 if num == 0 { | |
| 192 num = refs.next | |
| 193 refs.next-- | |
| 194 if refs.next > 0 { | |
| 195 panic("refs.next underflow") | |
| 196 } | |
| 197 refs.refs[obj] = num | |
| 198 refs.objs[num] = obj | |
| 199 } | |
| 200 refs.Unlock() | |
| 201 | |
| 202 b.WriteInt32(int32(num)) | |
| 203 } | |
| 204 | |
| 205 /* TODO: Will we need it? | |
| 206 func (b *Buffer) WriteRef(ref *Ref) { | |
| 207 b.WriteInt32(ref.Num) | |
| 208 } | |
| 209 */ | |
| OLD | NEW |