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.c73
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