Skip to content

Commit bb489ac

Browse files
authored
memory_view.c: Add rb_memory_view_get_item and rb_memory_view_prepare_item_desc (ruby#3871)
1 parent 549118b commit bb489ac

File tree

4 files changed

+69
-20
lines changed

4 files changed

+69
-20
lines changed

ext/-test-/memory_view/memory_view.c

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -264,9 +264,17 @@ static int
264264
mdview_get_memory_view(VALUE obj, rb_memory_view_t *view, int flags)
265265
{
266266
VALUE buf_v = rb_ivar_get(obj, id_str);
267+
VALUE format_v = rb_ivar_get(obj, SYM2ID(sym_format));
267268
VALUE shape_v = rb_ivar_get(obj, SYM2ID(sym_shape));
268269
VALUE strides_v = rb_ivar_get(obj, SYM2ID(sym_strides));
269270

271+
const char *format = RSTRING_PTR(format_v);
272+
const char *err;
273+
const ssize_t item_size = rb_memory_view_item_size_from_format(format, &err);
274+
if (item_size < 0) {
275+
return 0;
276+
}
277+
270278
ssize_t i, ndim = RARRAY_LEN(shape_v);
271279
ssize_t *shape = ALLOC_N(ssize_t, ndim);
272280
ssize_t *strides = NULL;
@@ -288,8 +296,8 @@ mdview_get_memory_view(VALUE obj, rb_memory_view_t *view, int flags)
288296
}
289297

290298
rb_memory_view_init_as_byte_array(view, obj, RSTRING_PTR(buf_v), RSTRING_LEN(buf_v), true);
291-
view->format = "l";
292-
view->item_size = sizeof(long);
299+
view->format = StringValueCStr(format_v);
300+
view->item_size = item_size;
293301
view->ndim = ndim;
294302
view->shape = shape;
295303
view->strides = strides;
@@ -310,13 +318,15 @@ static const rb_memory_view_entry_t mdview_memory_view_entry = {
310318
};
311319

312320
static VALUE
313-
mdview_initialize(VALUE obj, VALUE buf, VALUE shape, VALUE strides)
321+
mdview_initialize(VALUE obj, VALUE buf, VALUE format, VALUE shape, VALUE strides)
314322
{
315323
Check_Type(buf, T_STRING);
324+
StringValue(format);
316325
Check_Type(shape, T_ARRAY);
317326
if (!NIL_P(strides)) Check_Type(strides, T_ARRAY);
318327

319328
rb_ivar_set(obj, id_str, buf);
329+
rb_ivar_set(obj, SYM2ID(sym_format), format);
320330
rb_ivar_set(obj, SYM2ID(sym_shape), shape);
321331
rb_ivar_set(obj, SYM2ID(sym_strides), strides);
322332
return Qnil;
@@ -344,11 +354,8 @@ mdview_aref(VALUE obj, VALUE indices_v)
344354
indices[i] = NUM2SSIZET(RARRAY_AREF(indices_v, i));
345355
}
346356

347-
char *ptr = rb_memory_view_get_item_pointer(&view, indices);
357+
VALUE result = rb_memory_view_get_item(&view, indices);
348358
ALLOCV_END(buf_indices);
349-
350-
long x = *(long *)ptr;
351-
VALUE result = LONG2FIX(x);
352359
rb_memory_view_release(&view);
353360

354361
return result;
@@ -373,7 +380,7 @@ Init_memory_view(void)
373380
rb_memory_view_register(cExportableString, &exportable_string_memory_view_entry);
374381

375382
VALUE cMDView = rb_define_class_under(mMemoryViewTestUtils, "MultiDimensionalView", rb_cObject);
376-
rb_define_method(cMDView, "initialize", mdview_initialize, 3);
383+
rb_define_method(cMDView, "initialize", mdview_initialize, 4);
377384
rb_define_method(cMDView, "[]", mdview_aref, 1);
378385
rb_memory_view_register(cMDView, &mdview_memory_view_entry);
379386

include/ruby/memory_view.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,11 +77,13 @@ typedef struct {
7777

7878
struct {
7979
/* The array of rb_memory_view_item_component_t that describes the
80-
* item structure. */
80+
* item structure. rb_memory_view_prepare_item_desc and
81+
* rb_memory_view_get_item allocate this memory if needed,
82+
* and rb_memory_view_release frees it. */
8183
rb_memory_view_item_component_t *components;
8284

8385
/* The number of components in an item. */
84-
ssize_t length;
86+
size_t length;
8587
} item_desc;
8688

8789
/* The number of dimension. */
@@ -132,6 +134,8 @@ ssize_t rb_memory_view_parse_item_format(const char *format,
132134
ssize_t rb_memory_view_item_size_from_format(const char *format, const char **err);
133135
void *rb_memory_view_get_item_pointer(rb_memory_view_t *view, const ssize_t *indices);
134136
VALUE rb_memory_view_extract_item_members(const void *ptr, const rb_memory_view_item_component_t *members, const size_t n_members);
137+
VALUE rb_memory_view_prepare_item_dexc(rb_memory_view_t *view);
138+
VALUE rb_memory_view_get_item(rb_memory_view_t *view, const ssize_t *indices);
135139

136140
int rb_memory_view_available_p(VALUE obj);
137141
int rb_memory_view_get(VALUE obj, rb_memory_view_t* memory_view, int flags);

memory_view.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,8 @@ rb_memory_view_init_as_byte_array(rb_memory_view_t *view, VALUE obj, void *data,
226226
view->readonly = readonly;
227227
view->format = NULL;
228228
view->item_size = 1;
229+
view->item_desc.components = NULL;
230+
view->item_desc.length = 0;
229231
view->ndim = 1;
230232
view->shape = NULL;
231233
view->strides = NULL;
@@ -764,6 +766,37 @@ rb_memory_view_extract_item_members(const void *ptr, const rb_memory_view_item_c
764766
return item;
765767
}
766768

769+
void
770+
rb_memory_view_prepare_item_desc(rb_memory_view_t *view)
771+
{
772+
if (view->item_desc.components == NULL) {
773+
const char *err;
774+
ssize_t n = rb_memory_view_parse_item_format(view->format, &view->item_desc.components, &view->item_desc.length, &err);
775+
if (n < 0) {
776+
rb_raise(rb_eRuntimeError,
777+
"Unable to parse item format at %"PRIdSIZE" in \"%s\"",
778+
(err - view->format), view->format);
779+
}
780+
}
781+
}
782+
783+
/* Return a value that consists of item members in the given memory view. */
784+
VALUE
785+
rb_memory_view_get_item(rb_memory_view_t *view, const ssize_t *indices)
786+
{
787+
void *ptr = rb_memory_view_get_item_pointer(view, indices);
788+
789+
if (view->format == NULL) {
790+
return INT2FIX(*(uint8_t *)ptr);
791+
}
792+
793+
if (view->item_desc.components == NULL) {
794+
rb_memory_view_prepare_item_desc(view);
795+
}
796+
797+
return rb_memory_view_extract_item_members(ptr, view->item_desc.components, view->item_desc.length);
798+
}
799+
767800
static const rb_memory_view_entry_t *
768801
lookup_memory_view_entry(VALUE klass)
769802
{
@@ -830,6 +863,9 @@ rb_memory_view_release(rb_memory_view_t* view)
830863
if (rv) {
831864
unregister_exported_object(view->obj);
832865
view->obj = Qnil;
866+
if (view->item_desc.components) {
867+
xfree(view->item_desc.components);
868+
}
833869
}
834870
return rv;
835871
}

test/ruby/test_memory_view.rb

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -297,25 +297,27 @@ def test_rb_memory_view_fill_contiguous_strides
297297
column_major_strides)
298298
end
299299

300-
def test_rb_memory_view_get_item_pointer
300+
def test_rb_memory_view_get_item_pointer_single_member
301301
buf = [ 1, 2, 3, 4,
302302
5, 6, 7, 8,
303303
9, 10, 11, 12 ].pack("l!*")
304304
shape = [3, 4]
305-
mv = MemoryViewTestUtils::MultiDimensionalView.new(buf, shape, nil)
305+
mv = MemoryViewTestUtils::MultiDimensionalView.new(buf, "l!", shape, nil)
306306
assert_equal(1, mv[[0, 0]])
307307
assert_equal(4, mv[[0, 3]])
308308
assert_equal(6, mv[[1, 1]])
309309
assert_equal(10, mv[[2, 1]])
310+
end
310311

312+
def test_rb_memory_view_get_item_pointer_multiple_members
311313
buf = [ 1, 2, 3, 4, 5, 6, 7, 8,
312-
9, 10, 11, 12, 13, 14, 15, 16 ].pack("l!*")
313-
shape = [2, 8]
314-
strides = [4*sizeof(:long)*2, sizeof(:long)*2]
315-
mv = MemoryViewTestUtils::MultiDimensionalView.new(buf, shape, strides)
316-
assert_equal(1, mv[[0, 0]])
317-
assert_equal(5, mv[[0, 2]])
318-
assert_equal(9, mv[[1, 0]])
319-
assert_equal(15, mv[[1, 3]])
314+
-1, -2, -3, -4, -5, -6, -7, -8].pack("s*")
315+
shape = [2, 4]
316+
strides = [4*sizeof(:short)*2, sizeof(:short)*2]
317+
mv = MemoryViewTestUtils::MultiDimensionalView.new(buf, "ss", shape, strides)
318+
assert_equal([1, 2], mv[[0, 0]])
319+
assert_equal([5, 6], mv[[0, 2]])
320+
assert_equal([-1, -2], mv[[1, 0]])
321+
assert_equal([-7, -8], mv[[1, 3]])
320322
end
321323
end

0 commit comments

Comments
 (0)