Ruby 3.0.5p211 (2022-11-24 revision ba5cf0f7c52d4d35cc6a173c89eda98ceffa2dcf)
memory_view.c
Go to the documentation of this file.
1#include <stdbool.h>
2#include <ruby/ruby.h>
3
4#ifdef HAVE_RUBY_MEMORY_VIEW_H
5# include <ruby/memory_view.h>
6#endif
7
8#if SIZEOF_INTPTR_T == SIZEOF_LONG_LONG
9# define INTPTR2NUM LL2NUM
10# define UINTPTR2NUM ULL2NUM
11#elif SIZEOF_INTPTR_T == SIZEOF_LONG
12# define INTPTR2NUM LONG2NUM
13# define UINTPTR2NUM ULONG2NUM
14#else
15# define INTPTR2NUM INT2NUM
16# define UINTPTR2NUM UINT2NUM
17#endif
18
19#include <fiddle.h>
20
21#ifdef FIDDLE_MEMORY_VIEW
22VALUE rb_cMemoryView = Qnil;
23
24struct memview_data {
27 size_t n_members;
28};
29
30static void
31fiddle_memview_mark(void *ptr)
32{
33 const struct memview_data *data = ptr;
34 rb_gc_mark(data->view.obj);
35}
36
37static void
38fiddle_memview_free(void *ptr)
39{
40 struct memview_data *data = ptr;
41 rb_memory_view_release(&data->view);
42 if (data->members)
43 xfree(data->members);
44 xfree(ptr);
45}
46
47static size_t
48fiddle_memview_memsize(const void *ptr)
49{
50 const struct memview_data *data = ptr;
51 return sizeof(*data) + sizeof(rb_memory_view_item_component_t)*data->n_members + (size_t)data->view.byte_size;
52}
53
54static const rb_data_type_t fiddle_memview_data_type = {
55 "fiddle/memory_view",
56 {fiddle_memview_mark, fiddle_memview_free, fiddle_memview_memsize,},
57};
58
59static VALUE
60rb_fiddle_memview_s_allocate(VALUE klass)
61{
62 struct memview_data *data;
63 VALUE obj = TypedData_Make_Struct(klass, struct memview_data, &fiddle_memview_data_type, data);
64 data->view.obj = Qnil;
65 data->members = NULL;
66 data->n_members = 0;
67 return obj;
68}
69
70static VALUE
71rb_fiddle_memview_initialize(VALUE obj, VALUE target)
72{
73 struct memview_data *data;
74 TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data);
75
76 if (!rb_memory_view_get(target, &data->view, 0)) {
77 rb_raise(rb_eArgError, "Unable to get a memory view from %+"PRIsVALUE, target);
78 }
79
80 return Qnil;
81}
82
83static VALUE
84rb_fiddle_memview_get_obj(VALUE obj)
85{
86 struct memview_data *data;
87 TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data);
88
89 return data->view.obj;
90}
91
92static VALUE
93rb_fiddle_memview_get_byte_size(VALUE obj)
94{
95 struct memview_data *data;
96 TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data);
97
98 if (NIL_P(data->view.obj)) return Qnil;
99 return SSIZET2NUM(data->view.byte_size);
100}
101
102static VALUE
103rb_fiddle_memview_get_readonly(VALUE obj)
104{
105 struct memview_data *data;
106 TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data);
107
108 if (NIL_P(data->view.obj)) return Qnil;
109 return data->view.readonly ? Qtrue : Qfalse;
110}
111
112static VALUE
113rb_fiddle_memview_get_format(VALUE obj)
114{
115 struct memview_data *data;
116 TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data);
117
118 if (NIL_P(data->view.obj)) return Qnil;
119 return data->view.format == NULL ? Qnil : rb_str_new_cstr(data->view.format);
120}
121
122static VALUE
123rb_fiddle_memview_get_item_size(VALUE obj)
124{
125 struct memview_data *data;
126 TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data);
127
128 if (NIL_P(data->view.obj)) return Qnil;
129 return SSIZET2NUM(data->view.item_size);
130}
131
132static VALUE
133rb_fiddle_memview_get_ndim(VALUE obj)
134{
135 struct memview_data *data;
136 TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data);
137
138 if (NIL_P(data->view.obj)) return Qnil;
139 return SSIZET2NUM(data->view.ndim);
140}
141
142static VALUE
143rb_fiddle_memview_get_shape(VALUE obj)
144{
145 struct memview_data *data;
146 TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data);
147
148 if (NIL_P(data->view.obj)) return Qnil;
149 if (data->view.shape == NULL) return Qnil;
150
151 const ssize_t ndim = data->view.ndim;
152 VALUE shape = rb_ary_new_capa(ndim);
153 ssize_t i;
154 for (i = 0; i < ndim; ++i) {
155 rb_ary_push(shape, SSIZET2NUM(data->view.shape[i]));
156 }
157 return shape;
158}
159
160static VALUE
161rb_fiddle_memview_get_strides(VALUE obj)
162{
163 struct memview_data *data;
164 TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data);
165
166 if (NIL_P(data->view.obj)) return Qnil;
167 if (data->view.strides == NULL) return Qnil;
168
169 const ssize_t ndim = data->view.ndim;
170 VALUE strides = rb_ary_new_capa(ndim);
171 ssize_t i;
172 for (i = 0; i < ndim; ++i) {
173 rb_ary_push(strides, SSIZET2NUM(data->view.strides[i]));
174 }
175 return strides;
176}
177
178static VALUE
179rb_fiddle_memview_get_sub_offsets(VALUE obj)
180{
181 struct memview_data *data;
182 TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data);
183
184 if (NIL_P(data->view.obj)) return Qnil;
185 if (data->view.sub_offsets == NULL) return Qnil;
186
187 const ssize_t ndim = data->view.ndim;
188 VALUE sub_offsets = rb_ary_new_capa(ndim);
189 ssize_t i;
190 for (i = 0; i < ndim; ++i) {
191 rb_ary_push(sub_offsets, SSIZET2NUM(data->view.sub_offsets[i]));
192 }
193 return sub_offsets;
194}
195
196static VALUE
197rb_fiddle_memview_aref(int argc, VALUE *argv, VALUE obj)
198{
199 struct memview_data *data;
200 TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data);
201
202 if (NIL_P(data->view.obj)) return Qnil;
203
204 const ssize_t ndim = data->view.ndim;
205 if (argc != ndim) {
206 rb_raise(rb_eIndexError, "wrong number of index (%d for %"PRIdSIZE")", argc, ndim);
207 }
208
209 VALUE indices_v = 0;
210 ssize_t *indices = ALLOCV_N(ssize_t, indices_v, ndim);
211
212 ssize_t i;
213 for (i = 0; i < ndim; ++i) {
214 ssize_t x = NUM2SSIZET(argv[i]);
215 indices[i] = x;
216 }
217
218 uint8_t *ptr = rb_memory_view_get_item_pointer(&data->view, indices);
219 ALLOCV_END(indices_v);
220
221 if (data->view.format == NULL) {
222 return INT2FIX(*ptr);
223 }
224
225 if (!data->members) {
226 const char *err;
227 if (rb_memory_view_parse_item_format(data->view.format, &data->members, &data->n_members, &err) < 0) {
228 rb_raise(rb_eRuntimeError, "Unable to recognize item format at %"PRIdSIZE" in \"%s\"",
229 err - data->view.format, data->view.format);
230 }
231 }
232
233 return rb_memory_view_extract_item_members(ptr, data->members, data->n_members);
234}
235
236void
237Init_fiddle_memory_view(void)
238{
239 rb_cMemoryView = rb_define_class_under(mFiddle, "MemoryView", rb_cObject);
240 rb_define_alloc_func(rb_cMemoryView, rb_fiddle_memview_s_allocate);
241 rb_define_method(rb_cMemoryView, "initialize", rb_fiddle_memview_initialize, 1);
242 rb_define_method(rb_cMemoryView, "obj", rb_fiddle_memview_get_obj, 0);
243 rb_define_method(rb_cMemoryView, "byte_size", rb_fiddle_memview_get_byte_size, 0);
244 rb_define_method(rb_cMemoryView, "readonly?", rb_fiddle_memview_get_readonly, 0);
245 rb_define_method(rb_cMemoryView, "format", rb_fiddle_memview_get_format, 0);
246 rb_define_method(rb_cMemoryView, "item_size", rb_fiddle_memview_get_item_size, 0);
247 rb_define_method(rb_cMemoryView, "ndim", rb_fiddle_memview_get_ndim, 0);
248 rb_define_method(rb_cMemoryView, "shape", rb_fiddle_memview_get_shape, 0);
249 rb_define_method(rb_cMemoryView, "strides", rb_fiddle_memview_get_strides, 0);
250 rb_define_method(rb_cMemoryView, "sub_offsets", rb_fiddle_memview_get_sub_offsets, 0);
251 rb_define_method(rb_cMemoryView, "[]", rb_fiddle_memview_aref, -1);
252}
253
254#endif /* FIDDLE_MEMORY_VIEW */
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:1301
VALUE rb_ary_new_capa(long capa)
Definition: array.c:743
#define rb_define_method(klass, mid, func, arity)
Defines klass#mid.
Definition: cxxanyargs.hpp:653
struct RIMemo * ptr
Definition: debug.c:88
VALUE mFiddle
Definition: fiddle.c:3
#define PRIsVALUE
Definition: function.c:10
void rb_gc_mark(VALUE ptr)
Definition: gc.c:6112
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:797
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2917
VALUE rb_eRuntimeError
Definition: error.c:1055
VALUE rb_eArgError
Definition: error.c:1058
VALUE rb_eIndexError
Definition: error.c:1059
VALUE rb_cObject
Object class.
Definition: object.c:49
#define rb_str_new_cstr(str)
Definition: string.h:219
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
#define PRIdSIZE
Definition: inttypes.h:124
#define INT2FIX
Definition: long.h:48
#define ALLOCV_N
Definition: memory.h:139
#define ALLOCV_END
Definition: memory.h:140
Memory View.
void * rb_memory_view_get_item_pointer(rb_memory_view_t *view, const ssize_t *indices)
Definition: memory_view.c:510
bool rb_memory_view_get(VALUE obj, rb_memory_view_t *memory_view, int flags)
Definition: memory_view.c:812
VALUE rb_memory_view_extract_item_members(const void *ptr, const rb_memory_view_item_component_t *members, const size_t n_members)
Definition: memory_view.c:724
bool rb_memory_view_release(rb_memory_view_t *memory_view)
Definition: memory_view.c:833
ssize_t rb_memory_view_parse_item_format(const char *format, rb_memory_view_item_component_t **members, size_t *n_members, const char **err)
Definition: memory_view.c:386
#define NULL
Definition: regenc.h:69
#define TypedData_Get_Struct(obj, type, data_type, sval)
Definition: rtypeddata.h:130
#define TypedData_Make_Struct(klass, type, data_type, sval)
Definition: rtypeddata.h:122
int argc
Definition: ruby.c:240
char ** argv
Definition: ruby.c:241
unsigned char uint8_t
Definition: sha2.h:100
#define NUM2SSIZET
Definition: size_t.h:53
#define SSIZET2NUM
Definition: size_t.h:54
#define Qtrue
#define Qnil
#define Qfalse
#define NIL_P
C99 shim for <stdbool.h>
unsigned long VALUE
Definition: value.h:38
int err
Definition: win32.c:142
#define xfree
Definition: xmalloc.h:49