diff options
Diffstat (limited to 'ext/fiddle/memory_view.c')
-rw-r--r-- | ext/fiddle/memory_view.c | 89 |
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 */ |