summaryrefslogtreecommitdiff
path: root/ext/fiddle/pointer.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/fiddle/pointer.c')
-rw-r--r--ext/fiddle/pointer.c233
1 files changed, 33 insertions, 200 deletions
diff --git a/ext/fiddle/pointer.c b/ext/fiddle/pointer.c
index 10a6cc70ae..932bc576c5 100644
--- a/ext/fiddle/pointer.c
+++ b/ext/fiddle/pointer.c
@@ -2,17 +2,11 @@
* $Id$
*/
-#include <stdbool.h>
#include <ruby/ruby.h>
#include <ruby/io.h>
-
#include <ctype.h>
#include <fiddle.h>
-#ifdef HAVE_RUBY_MEMORY_VIEW_H
-# include <ruby/memory_view.h>
-#endif
-
#ifdef PRIsVALUE
# define RB_OBJ_CLASSNAME(obj) rb_obj_class(obj)
# define RB_OBJ_STRING(obj) (obj)
@@ -24,13 +18,12 @@
VALUE rb_cPointer;
-typedef rb_fiddle_freefunc_t freefunc_t;
+typedef void (*freefunc_t)(void*);
struct ptr_data {
void *ptr;
long size;
freefunc_t free;
- bool freed;
VALUE wrap[2];
};
@@ -64,19 +57,14 @@ fiddle_ptr_mark(void *ptr)
}
static void
-fiddle_ptr_free_ptr(void *ptr)
+fiddle_ptr_free(void *ptr)
{
struct ptr_data *data = ptr;
- if (data->ptr && data->free && !data->freed) {
- data->freed = true;
- (*(data->free))(data->ptr);
+ if (data->ptr) {
+ if (data->free) {
+ (*(data->free))(data->ptr);
+ }
}
-}
-
-static void
-fiddle_ptr_free(void *ptr)
-{
- fiddle_ptr_free_ptr(ptr);
xfree(ptr);
}
@@ -88,49 +76,12 @@ fiddle_ptr_memsize(const void *ptr)
}
static const rb_data_type_t fiddle_ptr_data_type = {
- .wrap_struct_name = "fiddle/pointer",
- .function = {
- .dmark = fiddle_ptr_mark,
- .dfree = fiddle_ptr_free,
- .dsize = fiddle_ptr_memsize,
- },
- .flags = FIDDLE_DEFAULT_TYPED_DATA_FLAGS,
+ "fiddle/pointer",
+ {fiddle_ptr_mark, fiddle_ptr_free, fiddle_ptr_memsize,},
};
-#ifdef HAVE_RUBY_MEMORY_VIEW_H
-static struct ptr_data *
-fiddle_ptr_check_memory_view(VALUE obj)
-{
- struct ptr_data *data;
- TypedData_Get_Struct(obj, struct ptr_data, &fiddle_ptr_data_type, data);
- if (data->ptr == NULL || data->size == 0) return NULL;
- return data;
-}
-
-static bool
-fiddle_ptr_memory_view_available_p(VALUE obj)
-{
- return fiddle_ptr_check_memory_view(obj) != NULL;
-}
-
-static bool
-fiddle_ptr_get_memory_view(VALUE obj, rb_memory_view_t *view, int flags)
-{
- struct ptr_data *data = fiddle_ptr_check_memory_view(obj);
- rb_memory_view_init_as_byte_array(view, obj, data->ptr, data->size, true);
-
- return true;
-}
-
-static const rb_memory_view_entry_t fiddle_ptr_memory_view_entry = {
- fiddle_ptr_get_memory_view,
- NULL,
- fiddle_ptr_memory_view_available_p
-};
-#endif
-
static VALUE
-rb_fiddle_ptr_new2(VALUE klass, void *ptr, long size, freefunc_t func, VALUE wrap0, VALUE wrap1)
+rb_fiddle_ptr_new2(VALUE klass, void *ptr, long size, freefunc_t func)
{
struct ptr_data *data;
VALUE val;
@@ -138,34 +89,26 @@ rb_fiddle_ptr_new2(VALUE klass, void *ptr, long size, freefunc_t func, VALUE wra
val = TypedData_Make_Struct(klass, struct ptr_data, &fiddle_ptr_data_type, data);
data->ptr = ptr;
data->free = func;
- data->freed = false;
data->size = size;
- RB_OBJ_WRITE(val, &data->wrap[0], wrap0);
- RB_OBJ_WRITE(val, &data->wrap[1], wrap1);
+ OBJ_TAINT(val);
return val;
}
-VALUE
-rb_fiddle_ptr_new_wrap(void *ptr, long size, freefunc_t func, VALUE wrap0, VALUE wrap1)
-{
- return rb_fiddle_ptr_new2(rb_cPointer, ptr, size, func, wrap0, wrap1);
-}
-
static VALUE
rb_fiddle_ptr_new(void *ptr, long size, freefunc_t func)
{
- return rb_fiddle_ptr_new2(rb_cPointer, ptr, size, func, 0, 0);
+ return rb_fiddle_ptr_new2(rb_cPointer, ptr, size, func);
}
static VALUE
-rb_fiddle_ptr_malloc(VALUE klass, long size, freefunc_t func)
+rb_fiddle_ptr_malloc(long size, freefunc_t func)
{
void *ptr;
ptr = ruby_xmalloc((size_t)size);
memset(ptr,0,(size_t)size);
- return rb_fiddle_ptr_new2(klass, ptr, size, func, 0, 0);
+ return rb_fiddle_ptr_new(ptr, size, func);
}
static void *
@@ -198,7 +141,6 @@ rb_fiddle_ptr_s_allocate(VALUE klass)
data->ptr = 0;
data->size = 0;
data->free = 0;
- data->freed = false;
return obj;
}
@@ -240,8 +182,8 @@ rb_fiddle_ptr_initialize(int argc, VALUE argv[], VALUE self)
/* Free previous memory. Use of inappropriate initialize may cause SEGV. */
(*(data->free))(data->ptr);
}
- RB_OBJ_WRITE(self, &data->wrap[0], wrap);
- RB_OBJ_WRITE(self, &data->wrap[1], funcwrap);
+ data->wrap[0] = wrap;
+ data->wrap[1] = funcwrap;
data->ptr = p;
data->size = s;
data->free = f;
@@ -250,53 +192,16 @@ rb_fiddle_ptr_initialize(int argc, VALUE argv[], VALUE self)
return Qnil;
}
-static VALUE
-rb_fiddle_ptr_call_free(VALUE self);
-
/*
* call-seq:
- * Fiddle::Pointer.malloc(size, freefunc = nil) => fiddle pointer instance
- * Fiddle::Pointer.malloc(size, freefunc) { |pointer| ... } => ...
- *
- * == Examples
- *
- * # Automatically freeing the pointer when the block is exited - recommended
- * Fiddle::Pointer.malloc(size, Fiddle::RUBY_FREE) do |pointer|
- * ...
- * end
- *
- * # Manually freeing but relying on the garbage collector otherwise
- * pointer = Fiddle::Pointer.malloc(size, Fiddle::RUBY_FREE)
- * ...
- * pointer.call_free
- *
- * # Relying on the garbage collector - may lead to unlimited memory allocated before freeing any, but safe
- * pointer = Fiddle::Pointer.malloc(size, Fiddle::RUBY_FREE)
- * ...
*
- * # Only manually freeing
- * pointer = Fiddle::Pointer.malloc(size)
- * begin
- * ...
- * ensure
- * Fiddle.free pointer
- * end
- *
- * # No free function and no call to free - the native memory will leak if the pointer is garbage collected
- * pointer = Fiddle::Pointer.malloc(size)
- * ...
+ * Fiddle::Pointer.malloc(size, freefunc = nil) => fiddle pointer instance
*
* Allocate +size+ bytes of memory and associate it with an optional
- * +freefunc+.
+ * +freefunc+ that will be called when the pointer is garbage collected.
*
- * If a block is supplied, the pointer will be yielded to the block instead of
- * being returned, and the return value of the block will be returned. A
- * +freefunc+ must be supplied if a block is.
- *
- * If a +freefunc+ is supplied it will be called once, when the pointer is
- * garbage collected or when the block is left if a block is supplied or
- * when the user calls +call_free+, whichever happens first. +freefunc+ must be
- * an address pointing to a function or an instance of +Fiddle::Function+.
+ * +freefunc+ must be an address pointing to a function or an instance of
+ * Fiddle::Function
*/
static VALUE
rb_fiddle_ptr_s_malloc(int argc, VALUE argv[], VALUE klass)
@@ -318,17 +223,10 @@ rb_fiddle_ptr_s_malloc(int argc, VALUE argv[], VALUE klass)
rb_bug("rb_fiddle_ptr_s_malloc");
}
- obj = rb_fiddle_ptr_malloc(klass, s,f);
- if (wrap) RB_OBJ_WRITE(obj, &RPTR_DATA(obj)->wrap[1], wrap);
+ obj = rb_fiddle_ptr_malloc(s,f);
+ if (wrap) RPTR_DATA(obj)->wrap[1] = wrap;
- if (rb_block_given_p()) {
- if (!f) {
- rb_raise(rb_eArgError, "a free function must be supplied to Fiddle::Pointer.malloc when it is called with a block");
- }
- return rb_ensure(rb_yield, obj, rb_fiddle_ptr_call_free, obj);
- } else {
- return obj;
- }
+ return obj;
}
/*
@@ -454,34 +352,6 @@ rb_fiddle_ptr_free_get(VALUE self)
}
/*
- * call-seq: call_free => nil
- *
- * Call the free function for this pointer. Calling more than once will do
- * nothing. Does nothing if there is no free function attached.
- */
-static VALUE
-rb_fiddle_ptr_call_free(VALUE self)
-{
- struct ptr_data *pdata;
- TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, pdata);
- fiddle_ptr_free_ptr(pdata);
- return Qnil;
-}
-
-/*
- * call-seq: freed? => bool
- *
- * Returns if the free function for this pointer has been called.
- */
-static VALUE
-rb_fiddle_ptr_freed_p(VALUE self)
-{
- struct ptr_data *pdata;
- TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, pdata);
- return pdata->freed ? Qtrue : Qfalse;
-}
-
-/*
* call-seq:
*
* ptr.to_s => string
@@ -506,11 +376,11 @@ rb_fiddle_ptr_to_s(int argc, VALUE argv[], VALUE self)
TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
switch (rb_scan_args(argc, argv, "01", &arg1)) {
case 0:
- val = rb_str_new2((char*)(data->ptr));
+ val = rb_tainted_str_new2((char*)(data->ptr));
break;
case 1:
len = NUM2INT(arg1);
- val = rb_str_new((char*)(data->ptr), len);
+ val = rb_tainted_str_new((char*)(data->ptr), len);
break;
default:
rb_bug("rb_fiddle_ptr_to_s");
@@ -544,11 +414,11 @@ rb_fiddle_ptr_to_str(int argc, VALUE argv[], VALUE self)
TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
switch (rb_scan_args(argc, argv, "01", &arg1)) {
case 0:
- val = rb_str_new((char*)(data->ptr),data->size);
+ val = rb_tainted_str_new((char*)(data->ptr),data->size);
break;
case 1:
len = NUM2INT(arg1);
- val = rb_str_new((char*)(data->ptr), len);
+ val = rb_tainted_str_new((char*)(data->ptr), len);
break;
default:
rb_bug("rb_fiddle_ptr_to_str");
@@ -570,7 +440,7 @@ rb_fiddle_ptr_inspect(VALUE self)
TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
return rb_sprintf("#<%"PRIsVALUE":%p ptr=%p size=%ld free=%p>",
- RB_OBJ_CLASSNAME(self), (void *)data, data->ptr, data->size, (void *)(VALUE)data->free);
+ RB_OBJ_CLASSNAME(self), data, data->ptr, data->size, data->free);
}
/*
@@ -672,7 +542,7 @@ rb_fiddle_ptr_aref(int argc, VALUE argv[], VALUE self)
struct ptr_data *data;
TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
- if (!data->ptr) rb_raise(rb_eFiddleDLError, "NULL pointer dereference");
+ if (!data->ptr) rb_raise(rb_eFiddleError, "NULL pointer dereference");
switch( rb_scan_args(argc, argv, "11", &arg0, &arg1) ){
case 1:
offset = NUM2ULONG(arg0);
@@ -681,7 +551,7 @@ rb_fiddle_ptr_aref(int argc, VALUE argv[], VALUE self)
case 2:
offset = NUM2ULONG(arg0);
len = NUM2ULONG(arg1);
- retval = rb_str_new((char *)data->ptr + offset, len);
+ retval = rb_tainted_str_new((char *)data->ptr + offset, len);
break;
default:
rb_bug("rb_fiddle_ptr_aref()");
@@ -710,7 +580,7 @@ rb_fiddle_ptr_aset(int argc, VALUE argv[], VALUE self)
struct ptr_data *data;
TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
- if (!data->ptr) rb_raise(rb_eFiddleDLError, "NULL pointer dereference");
+ if (!data->ptr) rb_raise(rb_eFiddleError, "NULL pointer dereference");
switch( rb_scan_args(argc, argv, "21", &arg0, &arg1, &arg2) ){
case 2:
offset = NUM2ULONG(arg0);
@@ -783,7 +653,6 @@ rb_fiddle_ptr_s_to_ptr(VALUE self, VALUE val)
}
else if (RTEST(rb_obj_is_kind_of(val, rb_cString))){
char *str = StringValuePtr(val);
- wrap = val;
ptr = rb_fiddle_ptr_new(str, RSTRING_LEN(val), NULL);
}
else if ((vptr = rb_check_funcall(val, id_to_ptr, 0, 0)) != Qundef){
@@ -792,7 +661,7 @@ rb_fiddle_ptr_s_to_ptr(VALUE self, VALUE val)
wrap = 0;
}
else{
- rb_raise(rb_eFiddleDLError, "to_ptr should return a Fiddle::Pointer object");
+ rb_raise(rb_eFiddleError, "to_ptr should return a Fiddle::Pointer object");
}
}
else{
@@ -800,42 +669,14 @@ rb_fiddle_ptr_s_to_ptr(VALUE self, VALUE val)
if (num == val) wrap = 0;
ptr = rb_fiddle_ptr_new(NUM2PTR(num), 0, NULL);
}
- if (wrap) RB_OBJ_WRITE(ptr, &RPTR_DATA(ptr)->wrap[0], wrap);
+ OBJ_INFECT(ptr, val);
+ if (wrap) RPTR_DATA(ptr)->wrap[0] = wrap;
return ptr;
}
-/*
- * call-seq:
- * Fiddle::Pointer.read(address, len) => string
- *
- * Or read the memory at address +address+ with length +len+ and return a
- * string with that memory
- */
-
-static VALUE
-rb_fiddle_ptr_read_mem(VALUE klass, VALUE address, VALUE len)
-{
- return rb_str_new((char *)NUM2PTR(address), NUM2ULONG(len));
-}
-
-/*
- * call-seq:
- * Fiddle::Pointer.write(address, str)
- *
- * Write bytes in +str+ to the location pointed to by +address+.
- */
-static VALUE
-rb_fiddle_ptr_write_mem(VALUE klass, VALUE addr, VALUE str)
-{
- const char *ptr = StringValuePtr(str);
- memcpy(NUM2PTR(addr), ptr, RSTRING_LEN(str));
- return str;
-}
-
void
Init_fiddle_pointer(void)
{
-#undef rb_intern
id_to_ptr = rb_intern("to_ptr");
/* Document-class: Fiddle::Pointer
@@ -848,13 +689,9 @@ Init_fiddle_pointer(void)
rb_define_singleton_method(rb_cPointer, "malloc", rb_fiddle_ptr_s_malloc, -1);
rb_define_singleton_method(rb_cPointer, "to_ptr", rb_fiddle_ptr_s_to_ptr, 1);
rb_define_singleton_method(rb_cPointer, "[]", rb_fiddle_ptr_s_to_ptr, 1);
- rb_define_singleton_method(rb_cPointer, "read", rb_fiddle_ptr_read_mem, 2);
- rb_define_singleton_method(rb_cPointer, "write", rb_fiddle_ptr_write_mem, 2);
rb_define_method(rb_cPointer, "initialize", rb_fiddle_ptr_initialize, -1);
rb_define_method(rb_cPointer, "free=", rb_fiddle_ptr_free_set, 1);
rb_define_method(rb_cPointer, "free", rb_fiddle_ptr_free_get, 0);
- rb_define_method(rb_cPointer, "call_free", rb_fiddle_ptr_call_free, 0);
- rb_define_method(rb_cPointer, "freed?", rb_fiddle_ptr_freed_p, 0);
rb_define_method(rb_cPointer, "to_i", rb_fiddle_ptr_to_i, 0);
rb_define_method(rb_cPointer, "to_int", rb_fiddle_ptr_to_i, 0);
rb_define_method(rb_cPointer, "to_value", rb_fiddle_ptr_to_value, 0);
@@ -876,10 +713,6 @@ Init_fiddle_pointer(void)
rb_define_method(rb_cPointer, "size", rb_fiddle_ptr_size_get, 0);
rb_define_method(rb_cPointer, "size=", rb_fiddle_ptr_size_set, 1);
-#ifdef HAVE_RUBY_MEMORY_VIEW_H
- rb_memory_view_register(rb_cPointer, &fiddle_ptr_memory_view_entry);
-#endif
-
/* Document-const: NULL
*
* A NULL pointer