diff options
Diffstat (limited to 'stream.go')
-rw-r--r-- | stream.go | 138 |
1 files changed, 104 insertions, 34 deletions
@@ -2,19 +2,45 @@ package salticidae // #include <stdlib.h> // #include "salticidae/stream.h" +// uint16_t _salti_htole16(uint16_t x) { return htole16(x); } +// uint32_t _salti_htole32(uint32_t x) { return htole32(x); } +// uint64_t _salti_htole64(uint64_t x) { return htole64(x); } +// +// uint16_t _salti_letoh16(uint16_t x) { return le16toh(x); } +// uint32_t _salti_letoh32(uint32_t x) { return le32toh(x); } +// uint64_t _salti_letoh64(uint64_t x) { return le64toh(x); } +// +// uint16_t _salti_htobe16(uint16_t x) { return htobe16(x); } +// uint32_t _salti_htobe32(uint32_t x) { return htobe32(x); } +// uint64_t _salti_htobe64(uint64_t x) { return htobe64(x); } +// +// uint16_t _salti_betoh16(uint16_t x) { return be16toh(x); } +// uint32_t _salti_betoh32(uint32_t x) { return be32toh(x); } +// uint64_t _salti_betoh64(uint64_t x) { return be64toh(x); } +// import "C" import "runtime" -type byteArray struct { - inner *C.bytearray_t -} +type CByteArray = *C.bytearray_t +// The C pointer to a ByteArray object. +type byteArray struct { inner CByteArray } // Array of binary data. type ByteArray = *byteArray +func ByteArrayFromC(ptr CByteArray) ByteArray { + return &byteArray{ inner: ptr } +} + +func byteArraySetFinalizer(res ByteArray) { + if res != nil { + runtime.SetFinalizer(res, func(self ByteArray) { self.free() }) + } +} + // Create an empty byte array (with zero contained bytes). func NewByteArray() ByteArray { - res := &byteArray{ inner: C.bytearray_new() } - runtime.SetFinalizer(res, func(self ByteArray) { self.free() }) + res := ByteArrayFromC(C.bytearray_new()) + byteArraySetFinalizer(res) return res } @@ -23,19 +49,39 @@ func (self ByteArray) free() { C.bytearray_free(self.inner) } // Create a byte array by taking out all data from src. Notice this is a // zero-copy operation that consumes and invalidates the data in src ("move" // semantics) so that no more operation should be done to src after this -// function call. -func NewByteArrayMovedFromDataStream(src DataStream) ByteArray { - res := &byteArray{ inner: C.bytearray_new_moved_from_datastream(src.inner) } - runtime.SetFinalizer(res, func(self ByteArray) { self.free() }) - return res +// function call. Also notice unlike copying, the entire DataStream buffer is +// moved (including the possibily consumed part). +func NewByteArrayMovedFromDataStream(src DataStream) (res ByteArray) { + res = ByteArrayFromC(C.bytearray_new_moved_from_datastream(src.inner)) + byteArraySetFinalizer(res) + return +} + +// Create a byte array by copying the remaining data from src. +func NewByteArrayCopiedFromDataStream(src DataStream) (res ByteArray) { + res = ByteArrayFromC(C.bytearray_new_copied_from_datastream(src.inner)) + byteArraySetFinalizer(res) + return } -func NewByteArrayFromHex(hex string) ByteArray { +func NewByteArrayFromHex(hex string) (res ByteArray) { c_str := C.CString(hex) - res := &byteArray{ inner: C.bytearray_new_from_hex(c_str) } + res = ByteArrayFromC(C.bytearray_new_from_hex(c_str)) C.free(rawptr_t(c_str)) - runtime.SetFinalizer(res, func(self ByteArray) { self.free() }) - return res + byteArraySetFinalizer(res) + return +} + +func NewByteArrayFromBytes(bytes []byte) (res ByteArray) { + size := len(bytes) + if size > 0 { + base := (*C.uint8_t)(&bytes[0]) + res = ByteArrayFromC(C.bytearray_new_from_bytes(base, C.size_t(size))) + } else { + res = ByteArrayFromC(C.bytearray_new()) + } + byteArraySetFinalizer(res) + return } // The C pointer to a DataStream object. @@ -55,17 +101,17 @@ func DataStreamFromC(ptr CDataStream) DataStream { } } -func dataStreamSetFinalizer(res DataStream) DataStream { +func dataStreamSetFinalizer(res DataStream) { if res != nil { runtime.SetFinalizer(res, func(self DataStream) { self.free() }) } - return res } // Create an empty DataStream. func NewDataStream() DataStream { res := DataStreamFromC(C.datastream_new()) - return dataStreamSetFinalizer(res) + dataStreamSetFinalizer(res) + return res } // Create a DataStream with data copied from bytes. @@ -77,7 +123,8 @@ func NewDataStreamFromBytes(bytes []byte) (res DataStream) { } else { res = DataStreamFromC(C.datastream_new()) } - return dataStreamSetFinalizer(res) + dataStreamSetFinalizer(res) + return } // Create a DataStream with content moved from a ByteArray. @@ -100,9 +147,10 @@ func (self DataStream) attach(ptr rawptr_t, obj interface{}) { self.attached[uin func (self DataStream) detach(ptr rawptr_t) { delete(self.attached, uintptr(ptr)) } // Make a copy of the object. -func (self DataStream) Copy() DataStream { - res := DataStreamFromC(C.datastream_copy(self.inner)) - return dataStreamSetFinalizer(res) +func (self DataStream) Copy() (res DataStream) { + res = DataStreamFromC(C.datastream_copy(self.inner)) + dataStreamSetFinalizer(res) + return } // TODO: datastream_data @@ -157,6 +205,23 @@ func (self DataStream) GetI32(succ *bool) int32 { return int32(C.datastream_get_ // Parse an int64 integer by consuming the stream (no byte order conversion). func (self DataStream) GetI64(succ *bool) int64 { return int64(C.datastream_get_i64(self.inner, (*C.bool)(succ))) } +func ToLittleEndianU16(x uint16) uint16 { return uint16(C._salti_htole16(C.uint16_t(x))); } +func ToLittleEndianU32(x uint32) uint32 { return uint32(C._salti_htole32(C.uint32_t(x))); } +func ToLittleEndianU64(x uint64) uint64 { return uint64(C._salti_htole64(C.uint64_t(x))); } + +func FromLittleEndianU16(x uint16) uint16 { return uint16(C._salti_letoh16(C.uint16_t(x))); } +func FromLittleEndianU32(x uint32) uint32 { return uint32(C._salti_letoh32(C.uint32_t(x))); } +func FromLittleEndianU64(x uint64) uint64 { return uint64(C._salti_letoh64(C.uint64_t(x))); } + +func ToBigEndianU16(x uint16) uint16 { return uint16(C._salti_htobe16(C.uint16_t(x))); } +func ToBigEndianU32(x uint32) uint32 { return uint32(C._salti_htobe32(C.uint32_t(x))); } +func ToBigEndianU64(x uint64) uint64 { return uint64(C._salti_htobe64(C.uint64_t(x))); } + +func FromBigEndianU16(x uint16) uint16 { return uint16(C._salti_betoh16(C.uint16_t(x))); } +func FromBigEndianU32(x uint32) uint32 { return uint32(C._salti_betoh32(C.uint32_t(x))); } +func FromBigEndianU64(x uint64) uint64 { return uint64(C._salti_betoh64(C.uint64_t(x))); } + + // The handle returned by GetDataInPlace. The Go slice returned by Get() is // valid only during the lifetime of the handle. type dataStreamBytes struct { @@ -182,30 +247,35 @@ func (self DataStream) GetDataInPlace(length int) DataStreamBytes { return res } -type uint256 struct { - inner *C.uint256_t -} - +// The C pointer to a UInt256 object. +type CUInt256 = *C.uint256_t +type uint256 struct { inner CUInt256 } // 256-bit integer. type UInt256 = *uint256 -// Create a 256-bit integer. -func NewUInt256() UInt256 { - res := &uint256{ inner: C.uint256_new() } - if res != nil { - runtime.SetFinalizer(res, func(self UInt256) { self.free() }) - } - return res +func UInt256FromC(ptr CUInt256) UInt256 { + return &uint256{ inner: ptr } } -func NewUInt256FromByteArray(bytes ByteArray) UInt256 { - res := &uint256{ inner: C.uint256_new_from_bytearray(bytes.inner) } +func uint256SetFinalizer(res UInt256) { if res != nil { runtime.SetFinalizer(res, func(self UInt256) { self.free() }) } +} + +// Create a 256-bit integer. +func NewUInt256() UInt256 { + res := &uint256{ inner: C.uint256_new() } + uint256SetFinalizer(res) return res } +func NewUInt256FromByteArray(bytes ByteArray) (res UInt256) { + res = &uint256{ inner: C.uint256_new_from_bytearray(bytes.inner) } + uint256SetFinalizer(res) + return +} + func (self UInt256) free() { C.uint256_free(self.inner) } func (self UInt256) IsNull() bool { return bool(C.uint256_is_null(self.inner)) } |