diff options
Diffstat (limited to 'ext/fiddle/pointer.c')
-rw-r--r-- | ext/fiddle/pointer.c | 73 |
1 files changed, 58 insertions, 15 deletions
diff --git a/ext/fiddle/pointer.c b/ext/fiddle/pointer.c index c5fb442aec..1b7d7a69f6 100644 --- a/ext/fiddle/pointer.c +++ b/ext/fiddle/pointer.c @@ -6,13 +6,13 @@ #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 -#include <ctype.h> -#include <fiddle.h> - #ifdef PRIsVALUE # define RB_OBJ_CLASSNAME(obj) rb_obj_class(obj) # define RB_OBJ_STRING(obj) (obj) @@ -24,7 +24,7 @@ VALUE rb_cPointer; -typedef void (*freefunc_t)(void*); +typedef rb_fiddle_freefunc_t freefunc_t; struct ptr_data { void *ptr; @@ -88,11 +88,16 @@ fiddle_ptr_memsize(const void *ptr) } static const rb_data_type_t fiddle_ptr_data_type = { - "fiddle/pointer", - {fiddle_ptr_mark, fiddle_ptr_free, fiddle_ptr_memsize,}, + .wrap_struct_name = "fiddle/pointer", + .function = { + .dmark = fiddle_ptr_mark, + .dfree = fiddle_ptr_free, + .dsize = fiddle_ptr_memsize, + }, + .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED }; -#ifdef FIDDLE_MEMORY_VIEW +#ifdef HAVE_RUBY_MEMORY_VIEW_H static struct ptr_data * fiddle_ptr_check_memory_view(VALUE obj) { @@ -125,7 +130,7 @@ static const rb_memory_view_entry_t fiddle_ptr_memory_view_entry = { #endif static VALUE -rb_fiddle_ptr_new2(VALUE klass, void *ptr, long size, freefunc_t func) +rb_fiddle_ptr_new2(VALUE klass, void *ptr, long size, freefunc_t func, VALUE wrap0, VALUE wrap1) { struct ptr_data *data; VALUE val; @@ -135,14 +140,22 @@ rb_fiddle_ptr_new2(VALUE klass, void *ptr, long size, freefunc_t func) 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); 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); + return rb_fiddle_ptr_new2(rb_cPointer, ptr, size, func, 0, 0); } static VALUE @@ -152,7 +165,7 @@ rb_fiddle_ptr_malloc(VALUE klass, long size, freefunc_t func) ptr = ruby_xmalloc((size_t)size); memset(ptr,0,(size_t)size); - return rb_fiddle_ptr_new2(klass, ptr, size, func); + return rb_fiddle_ptr_new2(klass, ptr, size, func, 0, 0); } static void * @@ -227,8 +240,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); } - data->wrap[0] = wrap; - data->wrap[1] = funcwrap; + RB_OBJ_WRITE(self, &data->wrap[0], wrap); + RB_OBJ_WRITE(self, &data->wrap[1], funcwrap); data->ptr = p; data->size = s; data->free = f; @@ -306,7 +319,7 @@ rb_fiddle_ptr_s_malloc(int argc, VALUE argv[], VALUE klass) } obj = rb_fiddle_ptr_malloc(klass, s,f); - if (wrap) RPTR_DATA(obj)->wrap[1] = wrap; + if (wrap) RB_OBJ_WRITE(obj, &RPTR_DATA(obj)->wrap[1], wrap); if (rb_block_given_p()) { if (!f) { @@ -770,6 +783,7 @@ 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){ @@ -786,10 +800,37 @@ 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) RPTR_DATA(ptr)->wrap[0] = wrap; + if (wrap) RB_OBJ_WRITE(ptr, &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) +{ + memcpy(NUM2PTR(addr), StringValuePtr(str), RSTRING_LEN(str)); + return str; +} + void Init_fiddle_pointer(void) { @@ -806,6 +847,8 @@ 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); @@ -832,7 +875,7 @@ 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 FIDDLE_MEMORY_VIEW +#ifdef HAVE_RUBY_MEMORY_VIEW_H rb_memory_view_register(rb_cPointer, &fiddle_ptr_memory_view_entry); #endif |