Class: FFI::Buffer
| Relationships & Source Files | |
| Super Chains via Extension / Inclusion / Inheritance | |
|
Class Chain:
self,
AbstractMemory
|
|
|
Instance Chain:
self,
AbstractMemory
|
|
| Inherits: |
FFI::AbstractMemory
|
| Defined in: | ext/ffi_c/Buffer.c |
Overview
A Buffer is a function argument type. It should be use with functions playing with C arrays.
Constant Summary
AbstractMemory - Inherited
Class Method Summary
- .alloc_inout(*args) (also: .alloc_inout, .alloc_out)
-
.alloc_inout(*args)
Alias for .alloc_in.
-
.alloc_inout(*args)
Alias for .alloc_in.
- .new(size, count = 1, clear = false) constructor
Instance Attribute Summary
AbstractMemory - Inherited
| #size_limit? | Return |
Instance Method Summary
- #+(offset)
- #initialize_copy(other)
- #inspect
-
#length
Alias for
total. -
#order ⇒ :big, :little
Set or get endianness of
Buffer. - #slice(offset, length)
AbstractMemory - Inherited
Constructor Details
.new(size, count = 1, clear = false)
.new(instance)
# File 'ext/ffi_c/Buffer.c', line 123
static VALUE
buffer_initialize(int argc, VALUE* argv, VALUE self)
{
VALUE rbSize = Qnil, rbCount = Qnil, rbClear = Qnil;
Buffer* p;
int nargs;
TypedData_Get_Struct(self, Buffer, &buffer_data_type, p);
nargs = rb_scan_args(argc, argv, "12", &rbSize, &rbCount, &rbClear);
p->memory.typeSize = rbffi_type_size(rbSize);
p->memory.size = p->memory.typeSize * (nargs > 1 ? NUM2LONG(rbCount) : 1);
if (p->memory.size > BUFFER_EMBED_MAXLEN) {
p->data.storage = xmalloc(p->memory.size + 7);
if (p->data.storage == NULL) {
rb_raise(rb_eNoMemError, "Failed to allocate memory size=%lu bytes", p->memory.size);
return Qnil;
}
/* ensure the memory is aligned on at least a 8 byte boundary */
p->memory.address = (void *) (((uintptr_t) p->data.storage + 0x7) & (uintptr_t) ~0x7ULL);
if (p->memory.size > 0 && (nargs < 3 || RTEST(rbClear))) {
memset(p->memory.address, 0, p->memory.size);
}
} else {
p->memory.flags |= MEM_EMBED;
p->memory.address = (void *) &p->data.embed[0];
}
if (rb_block_given_p()) {
return rb_ensure(rb_yield, self, buffer_free, self);
}
return self;
}
Class Method Details
.alloc_inout(*args)
.a(new)
Also known as: .alloc_inout, .alloc_out
# File 'ext/ffi_c/Buffer.c', line 194
static VALUE
buffer_alloc_inout(int argc, VALUE* argv, VALUE klass)
{
return buffer_initialize(argc, argv, buffer_allocate(klass));
}
.alloc_inout(*args)
.a(new)
Alias for .alloc_in.
.alloc_inout(*args)
.a(new)
Alias for .alloc_in.
Instance Method Details
#+(offset)
#a(Buffer)
# File 'ext/ffi_c/Buffer.c', line 226
static VALUE
buffer_plus(VALUE self, VALUE rbOffset)
{
Buffer* ptr;
long offset = NUM2LONG(rbOffset);
TypedData_Get_Struct(self, Buffer, &buffer_data_type, ptr);
return slice(self, offset, ptr->memory.size - offset);
}
#initialize_copy(other)
NOT(CALL)
# File 'ext/ffi_c/Buffer.c', line 167
static VALUE
buffer_initialize_copy(VALUE self, VALUE other)
{
AbstractMemory* src;
Buffer* dst;
TypedData_Get_Struct(self, Buffer, &buffer_data_type, dst);
src = rbffi_AbstractMemory_Cast(other, &buffer_data_type);
if ((dst->memory.flags & MEM_EMBED) == 0 && dst->data.storage != NULL) {
xfree(dst->data.storage);
}
dst->data.storage = xmalloc(src->size + 7);
if (dst->data.storage == NULL) {
rb_raise(rb_eNoMemError, "failed to allocate memory size=%lu bytes", src->size);
return Qnil;
}
dst->memory.address = (void *) (((uintptr_t) dst->data.storage + 0x7) & (uintptr_t) ~0x7ULL);
dst->memory.size = src->size;
dst->memory.typeSize = src->typeSize;
/* finally, copy the actual buffer contents */
memcpy(dst->memory.address, src->address, src->size);
return self;
}
#inspect
#a(Buffer)
# File 'ext/ffi_c/Buffer.c', line 255
static VALUE
buffer_inspect(VALUE self)
{
char tmp[100];
Buffer* ptr;
TypedData_Get_Struct(self, Buffer, &buffer_data_type, ptr);
snprintf(tmp, sizeof(tmp), "#<FFI:Buffer:%p address=%p size=%ld>", ptr, ptr->memory.address, ptr->memory.size);
return rb_str_new2(tmp);
}
#length
Alias for total.
#order ⇒ :big, :little
#order(order) ⇒ self
:big, :little
#order(order) ⇒ self
Set or get endianness of Buffer.
# File 'ext/ffi_c/Buffer.c', line 285
static VALUE
buffer_order(int argc, VALUE* argv, VALUE self)
{
Buffer* ptr;
TypedData_Get_Struct(self, Buffer, &buffer_data_type, ptr);
if (argc == 0) {
int order = (ptr->memory.flags & MEM_SWAP) == 0 ? BYTE_ORDER : SWAPPED_ORDER;
return order == BIG_ENDIAN ? ID2SYM(rb_intern("big")) : ID2SYM(rb_intern("little"));
} else {
VALUE rbOrder = Qnil;
int order = BYTE_ORDER;
if (rb_scan_args(argc, argv, "1", &rbOrder) < 1) {
rb_raise(rb_eArgError, "need byte order");
}
if (SYMBOL_P(rbOrder)) {
ID id = SYM2ID(rbOrder);
if (id == rb_intern("little")) {
order = LITTLE_ENDIAN;
} else if (id == rb_intern("big") || id == rb_intern("network")) {
order = BIG_ENDIAN;
}
}
if (order != BYTE_ORDER) {
Buffer* p2;
VALUE retval = slice(self, 0, ptr->memory.size);
TypedData_Get_Struct(retval, Buffer, &buffer_data_type, p2);
p2->memory.flags |= MEM_SWAP;
return retval;
}
return self;
}
}
#slice(offset, length)
#an(existing)
# File 'ext/ffi_c/Buffer.c', line 244
static VALUE
buffer_slice(VALUE self, VALUE rbOffset, VALUE rbLength)
{
return slice(self, NUM2LONG(rbOffset), NUM2LONG(rbLength));
}