summaryrefslogtreecommitdiff
path: root/ext/ffi_c/AbstractMemory.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/ffi_c/AbstractMemory.c')
-rw-r--r--ext/ffi_c/AbstractMemory.c90
1 files changed, 56 insertions, 34 deletions
diff --git a/ext/ffi_c/AbstractMemory.c b/ext/ffi_c/AbstractMemory.c
index 1a7fcde..49da32e 100644
--- a/ext/ffi_c/AbstractMemory.c
+++ b/ext/ffi_c/AbstractMemory.c
@@ -55,21 +55,30 @@
# define RB_OBJ_STRING(obj) StringValueCStr(obj)
#endif
+static size_t memsize(const void *data);
static inline char* memory_address(VALUE self);
VALUE rbffi_AbstractMemoryClass = Qnil;
static VALUE NullPointerErrorClass = Qnil;
static ID id_to_ptr = 0, id_plus = 0, id_call = 0;
-static VALUE
-memory_allocate(VALUE klass)
-{
- AbstractMemory* memory;
- VALUE obj;
- obj = Data_Make_Struct(klass, AbstractMemory, NULL, -1, memory);
- memory->flags = MEM_RD | MEM_WR;
+const rb_data_type_t rbffi_abstract_memory_data_type = { /* extern */
+ .wrap_struct_name = "FFI::AbstractMemory",
+ .function = {
+ .dmark = NULL,
+ .dfree = RUBY_TYPED_DEFAULT_FREE,
+ .dsize = memsize,
+ },
+ // IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE()
+ // macro to update VALUE references, as to trigger write barriers.
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | FFI_RUBY_TYPED_FROZEN_SHAREABLE
+};
- return obj;
+static size_t
+memsize(const void *data)
+{
+ return sizeof(AbstractMemory);
}
+
#define VAL(x, swap) (unlikely(((memory->flags & MEM_SWAP) != 0)) ? swap((x)) : (x))
#define NUM_OP(name, type, toNative, fromNative, swap) \
@@ -87,7 +96,7 @@ static VALUE \
memory_put_##name(VALUE self, VALUE offset, VALUE value) \
{ \
AbstractMemory* memory; \
- Data_Get_Struct(self, AbstractMemory, memory); \
+ TypedData_Get_Struct(self, AbstractMemory, &rbffi_abstract_memory_data_type, memory); \
memory_op_put_##name(memory, NUM2LONG(offset), value); \
return self; \
} \
@@ -96,7 +105,7 @@ static VALUE \
memory_write_##name(VALUE self, VALUE value) \
{ \
AbstractMemory* memory; \
- Data_Get_Struct(self, AbstractMemory, memory); \
+ TypedData_Get_Struct(self, AbstractMemory, &rbffi_abstract_memory_data_type, memory); \
memory_op_put_##name(memory, 0, value); \
return self; \
} \
@@ -115,7 +124,7 @@ static VALUE \
memory_get_##name(VALUE self, VALUE offset) \
{ \
AbstractMemory* memory; \
- Data_Get_Struct(self, AbstractMemory, memory); \
+ TypedData_Get_Struct(self, AbstractMemory, &rbffi_abstract_memory_data_type, memory); \
return memory_op_get_##name(memory, NUM2LONG(offset)); \
} \
static VALUE memory_read_##name(VALUE self); \
@@ -123,7 +132,7 @@ static VALUE \
memory_read_##name(VALUE self) \
{ \
AbstractMemory* memory; \
- Data_Get_Struct(self, AbstractMemory, memory); \
+ TypedData_Get_Struct(self, AbstractMemory, &rbffi_abstract_memory_data_type, memory); \
return memory_op_get_##name(memory, 0); \
} \
static MemoryOp memory_op_##name = { memory_op_get_##name, memory_op_put_##name }; \
@@ -141,7 +150,7 @@ memory_put_array_of_##name(VALUE self, VALUE offset, VALUE ary) \
if (likely(count > 0)) checkWrite(memory); \
checkBounds(memory, off, count * sizeof(type)); \
for (i = 0; i < count; i++) { \
- type tmp = (type) VAL(toNative(RARRAY_PTR(ary)[i]), swap); \
+ type tmp = (type) VAL(toNative(RARRAY_AREF(ary, i)), swap); \
memcpy(memory->address + off + (i * sizeof(type)), &tmp, sizeof(tmp)); \
} \
return self; \
@@ -307,6 +316,7 @@ static VALUE
memory_clear(VALUE self)
{
AbstractMemory* ptr = MEMORY(self);
+ checkWrite(ptr);
memset(ptr->address, 0, ptr->size);
return self;
}
@@ -321,7 +331,7 @@ memory_size(VALUE self)
{
AbstractMemory* ptr;
- Data_Get_Struct(self, AbstractMemory, ptr);
+ TypedData_Get_Struct(self, AbstractMemory, &rbffi_abstract_memory_data_type, ptr);
return LONG2NUM(ptr->size);
}
@@ -344,8 +354,8 @@ memory_get(VALUE self, VALUE type_name, VALUE offset)
nType = rbffi_Type_Lookup(type_name);
if(NIL_P(nType)) goto undefined_type;
- Data_Get_Struct(self, AbstractMemory, ptr);
- Data_Get_Struct(nType, Type, type);
+ TypedData_Get_Struct(self, AbstractMemory, &rbffi_abstract_memory_data_type, ptr);
+ TypedData_Get_Struct(nType, Type, &rbffi_type_data_type, type);
MemoryOp *op = get_memory_op(type);
if(op == NULL) goto undefined_type;
@@ -376,8 +386,8 @@ memory_put(VALUE self, VALUE type_name, VALUE offset, VALUE value)
nType = rbffi_Type_Lookup(type_name);
if(NIL_P(nType)) goto undefined_type;
- Data_Get_Struct(self, AbstractMemory, ptr);
- Data_Get_Struct(nType, Type, type);
+ TypedData_Get_Struct(self, AbstractMemory, &rbffi_abstract_memory_data_type, ptr);
+ TypedData_Get_Struct(nType, Type, &rbffi_type_data_type, type);
MemoryOp *op = get_memory_op(type);
if(op == NULL) goto undefined_type;
@@ -442,7 +452,7 @@ memory_get_array_of_string(int argc, VALUE* argv, VALUE self)
count = (countnum == Qnil ? 0 : NUM2INT(countnum));
retVal = rb_ary_new2(count);
- Data_Get_Struct(self, AbstractMemory, ptr);
+ TypedData_Get_Struct(self, AbstractMemory, &rbffi_abstract_memory_data_type, ptr);
checkRead(ptr);
if (countnum != Qnil) {
@@ -633,7 +643,7 @@ memory_type_size(VALUE self)
{
AbstractMemory* ptr;
- Data_Get_Struct(self, AbstractMemory, ptr);
+ TypedData_Get_Struct(self, AbstractMemory, &rbffi_abstract_memory_data_type, ptr);
return INT2NUM(ptr->typeSize);
}
@@ -651,7 +661,7 @@ memory_aref(VALUE self, VALUE idx)
AbstractMemory* ptr;
VALUE rbOffset = Qnil;
- Data_Get_Struct(self, AbstractMemory, ptr);
+ TypedData_Get_Struct(self, AbstractMemory, &rbffi_abstract_memory_data_type, ptr);
rbOffset = ULONG2NUM(NUM2ULONG(idx) * ptr->typeSize);
@@ -661,7 +671,9 @@ memory_aref(VALUE self, VALUE idx)
static inline char*
memory_address(VALUE obj)
{
- return ((AbstractMemory *) DATA_PTR(obj))->address;
+ AbstractMemory *mem;
+ TypedData_Get_Struct(obj, AbstractMemory, &rbffi_abstract_memory_data_type, mem);
+ return mem->address;
}
static VALUE
@@ -669,24 +681,33 @@ memory_copy_from(VALUE self, VALUE rbsrc, VALUE rblen)
{
AbstractMemory* dst;
- Data_Get_Struct(self, AbstractMemory, dst);
+ TypedData_Get_Struct(self, AbstractMemory, &rbffi_abstract_memory_data_type, dst);
- memcpy(dst->address, rbffi_AbstractMemory_Cast(rbsrc, rbffi_AbstractMemoryClass)->address, NUM2INT(rblen));
+ memcpy(dst->address, rbffi_AbstractMemory_Cast(rbsrc, &rbffi_abstract_memory_data_type)->address, NUM2INT(rblen));
return self;
}
-AbstractMemory*
-rbffi_AbstractMemory_Cast(VALUE obj, VALUE klass)
+/*
+ * call-seq:
+ * res.freeze
+ *
+ * Freeze the AbstractMemory object and unset the writable flag.
+ */
+static VALUE
+memory_freeze(VALUE self)
{
- if (rb_obj_is_kind_of(obj, klass)) {
- AbstractMemory* memory;
- Data_Get_Struct(obj, AbstractMemory, memory);
- return memory;
- }
+ AbstractMemory* ptr = MEMORY(self);
+ ptr->flags &= ~MEM_WR;
+ return rb_call_super(0, NULL);
+}
- rb_raise(rb_eArgError, "Invalid Memory object");
- return NULL;
+AbstractMemory*
+rbffi_AbstractMemory_Cast(VALUE obj, const rb_data_type_t *data_type)
+{
+ AbstractMemory* memory;
+ TypedData_Get_Struct(obj, AbstractMemory, data_type, memory);
+ return memory;
}
void
@@ -781,7 +802,7 @@ rbffi_AbstractMemory_Init(VALUE moduleFFI)
* Document-variable: FFI::AbstractMemory
*/
rb_global_variable(&rbffi_AbstractMemoryClass);
- rb_define_alloc_func(classMemory, memory_allocate);
+ rb_undef_alloc_func(classMemory);
NullPointerErrorClass = rb_define_class_under(moduleFFI, "NullPointerError", rb_eRuntimeError);
/* Document-variable: NullPointerError */
@@ -1096,6 +1117,7 @@ rbffi_AbstractMemory_Init(VALUE moduleFFI)
rb_define_method(classMemory, "type_size", memory_type_size, 0);
rb_define_method(classMemory, "[]", memory_aref, 1);
rb_define_method(classMemory, "__copy_from__", memory_copy_from, 2);
+ rb_define_method(classMemory, "freeze", memory_freeze, 0 );
id_to_ptr = rb_intern("to_ptr");
id_call = rb_intern("call");