summaryrefslogtreecommitdiff
path: root/ext/fiddle/memory_view.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/fiddle/memory_view.c')
-rw-r--r--ext/fiddle/memory_view.c89
1 files changed, 78 insertions, 11 deletions
diff --git a/ext/fiddle/memory_view.c b/ext/fiddle/memory_view.c
index 172b1f18fc..fa66fc2c7b 100644
--- a/ext/fiddle/memory_view.c
+++ b/ext/fiddle/memory_view.c
@@ -1,9 +1,11 @@
-#include <stdbool.h>
-#include <ruby/ruby.h>
+#include <fiddle.h>
#ifdef HAVE_RUBY_MEMORY_VIEW_H
-# include <ruby/memory_view.h>
-#endif
+
+#include <stdbool.h>
+#include <ruby/ruby.h>
+#include <ruby/encoding.h>
+#include <ruby/memory_view.h>
#if SIZEOF_INTPTR_T == SIZEOF_LONG_LONG
# define INTPTR2NUM LL2NUM
@@ -16,9 +18,6 @@
# define UINTPTR2NUM UINT2NUM
#endif
-#include <fiddle.h>
-
-#ifdef FIDDLE_MEMORY_VIEW
VALUE rb_cMemoryView = Qnil;
struct memview_data {
@@ -35,12 +34,25 @@ fiddle_memview_mark(void *ptr)
}
static void
-fiddle_memview_free(void *ptr)
+fiddle_memview_release(struct memview_data *data)
{
- struct memview_data *data = ptr;
+ if (NIL_P(data->view.obj)) return;
+
rb_memory_view_release(&data->view);
- if (data->members)
+ data->view.obj = Qnil;
+ data->view.byte_size = 0;
+ if (data->members) {
xfree(data->members);
+ data->members = NULL;
+ data->n_members = 0;
+ }
+}
+
+static void
+fiddle_memview_free(void *ptr)
+{
+ struct memview_data *data = ptr;
+ fiddle_memview_release(data);
xfree(ptr);
}
@@ -62,18 +74,40 @@ rb_fiddle_memview_s_allocate(VALUE klass)
struct memview_data *data;
VALUE obj = TypedData_Make_Struct(klass, struct memview_data, &fiddle_memview_data_type, data);
data->view.obj = Qnil;
+ data->view.byte_size = 0;
data->members = NULL;
data->n_members = 0;
return obj;
}
static VALUE
+rb_fiddle_memview_release(VALUE obj)
+{
+ struct memview_data *data;
+ TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data);
+
+ if (NIL_P(data->view.obj)) return Qnil;
+ fiddle_memview_release(data);
+ return Qnil;
+}
+
+static VALUE
+rb_fiddle_memview_s_export(VALUE klass, VALUE target)
+{
+ ID id_new;
+ CONST_ID(id_new, "new");
+ VALUE memview = rb_funcall(klass, id_new, 1, target);
+ return rb_ensure(rb_yield, memview, rb_fiddle_memview_release, memview);
+}
+
+static VALUE
rb_fiddle_memview_initialize(VALUE obj, VALUE target)
{
struct memview_data *data;
TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data);
if (!rb_memory_view_get(target, &data->view, 0)) {
+ data->view.obj = Qnil;
rb_raise(rb_eArgError, "Unable to get a memory view from %+"PRIsVALUE, target);
}
@@ -233,12 +267,44 @@ rb_fiddle_memview_aref(int argc, VALUE *argv, VALUE obj)
return rb_memory_view_extract_item_members(ptr, data->members, data->n_members);
}
+static VALUE
+rb_fiddle_memview_to_s(VALUE self)
+{
+ struct memview_data *data;
+ const char *raw_data;
+ long byte_size;
+ VALUE string;
+
+ TypedData_Get_Struct(self,
+ struct memview_data,
+ &fiddle_memview_data_type,
+ data);
+
+ if (NIL_P(data->view.obj)) {
+ raw_data = NULL;
+ byte_size = 0;
+ } else {
+ raw_data = data->view.data;
+ byte_size = data->view.byte_size;
+ }
+
+ string = rb_enc_str_new_static(raw_data, byte_size, rb_ascii8bit_encoding());
+ {
+ ID id_memory_view;
+ CONST_ID(id_memory_view, "memory_view");
+ rb_ivar_set(string, id_memory_view, self);
+ }
+ return rb_obj_freeze(string);
+}
+
void
Init_fiddle_memory_view(void)
{
rb_cMemoryView = rb_define_class_under(mFiddle, "MemoryView", rb_cObject);
rb_define_alloc_func(rb_cMemoryView, rb_fiddle_memview_s_allocate);
+ rb_define_singleton_method(rb_cMemoryView, "export", rb_fiddle_memview_s_export, 1);
rb_define_method(rb_cMemoryView, "initialize", rb_fiddle_memview_initialize, 1);
+ rb_define_method(rb_cMemoryView, "release", rb_fiddle_memview_release, 0);
rb_define_method(rb_cMemoryView, "obj", rb_fiddle_memview_get_obj, 0);
rb_define_method(rb_cMemoryView, "byte_size", rb_fiddle_memview_get_byte_size, 0);
rb_define_method(rb_cMemoryView, "readonly?", rb_fiddle_memview_get_readonly, 0);
@@ -249,6 +315,7 @@ Init_fiddle_memory_view(void)
rb_define_method(rb_cMemoryView, "strides", rb_fiddle_memview_get_strides, 0);
rb_define_method(rb_cMemoryView, "sub_offsets", rb_fiddle_memview_get_sub_offsets, 0);
rb_define_method(rb_cMemoryView, "[]", rb_fiddle_memview_aref, -1);
+ rb_define_method(rb_cMemoryView, "to_s", rb_fiddle_memview_to_s, 0);
}
-#endif /* FIDDLE_MEMORY_VIEW */
+#endif /* HAVE_RUBY_MEMORY_VIEW_H */