Ruby 3.0.5p211 (2022-11-24 revision ba5cf0f7c52d4d35cc6a173c89eda98ceffa2dcf)
memory_view.c
Go to the documentation of this file.
1/**********************************************************************
2
3 memory_view.c - Memory View
4
5 Copyright (C) 2020 Kenta Murata <mrkn@mrkn.jp>
6
7**********************************************************************/
8
9#include "internal.h"
10#include "internal/hash.h"
11#include "internal/variable.h"
12#include "internal/util.h"
13#include "ruby/memory_view.h"
14#include "vm_sync.h"
15
16#if SIZEOF_INTPTR_T == SIZEOF_LONG_LONG
17# define INTPTR2NUM LL2NUM
18# define UINTPTR2NUM ULL2NUM
19#elif SIZEOF_INTPTR_T == SIZEOF_LONG
20# define INTPTR2NUM LONG2NUM
21# define UINTPTR2NUM ULONG2NUM
22#else
23# define INTPTR2NUM INT2NUM
24# define UINTPTR2NUM UINT2NUM
25#endif
26
27
28#define STRUCT_ALIGNOF(T, result) do { \
29 (result) = RUBY_ALIGNOF(T); \
30} while(0)
31
32// Exported Object Registry
33
34static st_table *exported_object_table = NULL;
36
37static int
38exported_object_registry_mark_key_i(st_data_t key, st_data_t value, st_data_t data)
39{
41 return ST_CONTINUE;
42}
43
44static void
45exported_object_registry_mark(void *ptr)
46{
47 // Don't use RB_VM_LOCK_ENTER here. It is unnecessary during GC.
48 st_foreach(exported_object_table, exported_object_registry_mark_key_i, 0);
49}
50
51static void
52exported_object_registry_free(void *ptr)
53{
55 st_clear(exported_object_table);
56 st_free_table(exported_object_table);
57 exported_object_table = NULL;
59}
60
62 "memory_view/exported_object_registry",
63 {
64 exported_object_registry_mark,
65 exported_object_registry_free,
66 0,
67 },
69};
70
71static int
72exported_object_add_ref(st_data_t *key, st_data_t *val, st_data_t arg, int existing)
73{
75
76 if (existing) {
77 *val += 1;
78 }
79 else {
80 *val = 1;
81 }
82 return ST_CONTINUE;
83}
84
85static int
86exported_object_dec_ref(st_data_t *key, st_data_t *val, st_data_t arg, int existing)
87{
89
90 if (existing) {
91 *val -= 1;
92 if (*val == 0) {
93 return ST_DELETE;
94 }
95 }
96 return ST_CONTINUE;
97}
98
99static void
100register_exported_object(VALUE obj)
101{
103 st_update(exported_object_table, (st_data_t)obj, exported_object_add_ref, 0);
105}
106
107static void
108unregister_exported_object(VALUE obj)
109{
111 st_update(exported_object_table, (st_data_t)obj, exported_object_dec_ref, 0);
113}
114
115// MemoryView
116
117static ID id_memory_view;
118
119static const rb_data_type_t memory_view_entry_data_type = {
120 "memory_view/entry",
121 {
122 0,
123 0,
124 0,
125 },
127};
128
129/* Register memory view functions for the given class */
130bool
132 Check_Type(klass, T_CLASS);
133 VALUE entry_obj = rb_ivar_lookup(klass, id_memory_view, Qnil);
134 if (! NIL_P(entry_obj)) {
135 rb_warning("Duplicated registration of memory view to %"PRIsVALUE, klass);
136 return false;
137 }
138 else {
139 entry_obj = TypedData_Wrap_Struct(0, &memory_view_entry_data_type, (void *)entry);
140 rb_ivar_set(klass, id_memory_view, entry_obj);
141 return true;
142 }
143}
144
145/* Examine whether the given memory view has row-major order strides. */
146bool
148{
149 const ssize_t ndim = view->ndim;
150 const ssize_t *shape = view->shape;
151 const ssize_t *strides = view->strides;
152 ssize_t n = view->item_size;
153 ssize_t i;
154 for (i = ndim - 1; i >= 0; --i) {
155 if (strides[i] != n) return false;
156 n *= shape[i];
157 }
158 return true;
159}
160
161/* Examine whether the given memory view has column-major order strides. */
162bool
164{
165 const ssize_t ndim = view->ndim;
166 const ssize_t *shape = view->shape;
167 const ssize_t *strides = view->strides;
168 ssize_t n = view->item_size;
169 ssize_t i;
170 for (i = 0; i < ndim; ++i) {
171 if (strides[i] != n) return false;
172 n *= shape[i];
173 }
174 return true;
175}
176
177/* Initialize strides array to represent the specified contiguous array. */
178void
179rb_memory_view_fill_contiguous_strides(const ssize_t ndim, const ssize_t item_size, const ssize_t *const shape, const bool row_major_p, ssize_t *const strides)
180{
181 ssize_t i, n = item_size;
182 if (row_major_p) {
183 for (i = ndim - 1; i >= 0; --i) {
184 strides[i] = n;
185 n *= shape[i];
186 }
187 }
188 else { // column-major
189 for (i = 0; i < ndim; ++i) {
190 strides[i] = n;
191 n *= shape[i];
192 }
193 }
194}
195
196/* Initialize view to expose a simple byte array */
197bool
198rb_memory_view_init_as_byte_array(rb_memory_view_t *view, VALUE obj, void *data, const ssize_t len, const bool readonly)
199{
200 view->obj = obj;
201 view->data = data;
202 view->byte_size = len;
203 view->readonly = readonly;
204 view->format = NULL;
205 view->item_size = 1;
206 view->item_desc.components = NULL;
207 view->item_desc.length = 0;
208 view->ndim = 1;
209 view->shape = NULL;
210 view->strides = NULL;
211 view->sub_offsets = NULL;
212 *((void **)&view->private) = NULL;
213
214 return true;
215}
216
217#ifdef HAVE_TRUE_LONG_LONG
218static const char native_types[] = "sSiIlLqQjJ";
219#else
220static const char native_types[] = "sSiIlLjJ";
221#endif
222static const char endianness_types[] = "sSiIlLqQjJ";
223
224typedef enum {
229
230static ssize_t
231get_format_size(const char *format, bool *native_p, ssize_t *alignment, endianness_t *endianness, ssize_t *count, const char **next_format, VALUE *error)
232{
233 RUBY_ASSERT(format != NULL);
234 RUBY_ASSERT(native_p != NULL);
235 RUBY_ASSERT(endianness != NULL);
237 RUBY_ASSERT(next_format != NULL);
238
239 *native_p = false;
240 *endianness = ENDIANNESS_NATIVE;
241 *count = 1;
242
243 const int type_char = *format;
244
245 int i = 1;
246 while (format[i]) {
247 switch (format[i]) {
248 case '!':
249 case '_':
250 if (strchr(native_types, type_char)) {
251 *native_p = true;
252 ++i;
253 }
254 else {
255 if (error) {
257 rb_sprintf("Unable to specify native size for '%c'", type_char));
258 }
259 return -1;
260 }
261 continue;
262
263 case '<':
264 case '>':
265 if (!strchr(endianness_types, type_char)) {
266 if (error) {
268 rb_sprintf("Unable to specify endianness for '%c'", type_char));
269 }
270 return -1;
271 }
272 if (*endianness != ENDIANNESS_NATIVE) {
273 *error = rb_exc_new_cstr(rb_eArgError, "Unable to use both '<' and '>' multiple times");
274 return -1;
275 }
276 *endianness = (format[i] == '<') ? ENDIANNESS_LITTLE : ENDIANNESS_BIG;
277 ++i;
278 continue;
279
280 default:
281 break;
282 }
283
284 break;
285 }
286
287 // parse count
288 int ch = format[i];
289 if ('0' <= ch && ch <= '9') {
290 ssize_t n = 0;
291 while ('0' <= (ch = format[i]) && ch <= '9') {
292 n = 10*n + ruby_digit36_to_number_table[ch];
293 ++i;
294 }
295 *count = n;
296 }
297
298 *next_format = &format[i];
299
300 switch (type_char) {
301 case 'x': // padding
302 return 1;
303
304 case 'c': // signed char
305 case 'C': // unsigned char
306 return sizeof(char);
307
308 case 's': // s for int16_t, s! for signed short
309 case 'S': // S for uint16_t, S! for unsigned short
310 if (*native_p) {
311 STRUCT_ALIGNOF(short, *alignment);
312 return sizeof(short);
313 }
314 // fall through
315
316 case 'n': // n for big-endian 16bit unsigned integer
317 case 'v': // v for little-endian 16bit unsigned integer
318 STRUCT_ALIGNOF(int16_t, *alignment);
319 return 2;
320
321 case 'i': // i and i! for signed int
322 case 'I': // I and I! for unsigned int
323 STRUCT_ALIGNOF(int, *alignment);
324 return sizeof(int);
325
326 case 'l': // l for int32_t, l! for signed long
327 case 'L': // L for uint32_t, L! for unsigned long
328 if (*native_p) {
329 STRUCT_ALIGNOF(long, *alignment);
330 return sizeof(long);
331 }
332 // fall through
333
334 case 'N': // N for big-endian 32bit unsigned integer
335 case 'V': // V for little-endian 32bit unsigned integer
336 STRUCT_ALIGNOF(int32_t, *alignment);
337 return 4;
338
339 case 'f': // f for native float
340 case 'e': // e for little-endian float
341 case 'g': // g for big-endian float
342 STRUCT_ALIGNOF(float, *alignment);
343 return sizeof(float);
344
345 case 'q': // q for int64_t, q! for signed long long
346 case 'Q': // Q for uint64_t, Q! for unsigned long long
347 if (*native_p) {
348 STRUCT_ALIGNOF(LONG_LONG, *alignment);
349 return sizeof(LONG_LONG);
350 }
351 STRUCT_ALIGNOF(int64_t, *alignment);
352 return 8;
353
354 case 'd': // d for native double
355 case 'E': // E for little-endian double
356 case 'G': // G for big-endian double
357 STRUCT_ALIGNOF(double, *alignment);
358 return sizeof(double);
359
360 case 'j': // j for intptr_t
361 case 'J': // J for uintptr_t
362 STRUCT_ALIGNOF(intptr_t, *alignment);
363 return sizeof(intptr_t);
364
365 default:
366 *alignment = -1;
367 if (error) {
368 *error = rb_exc_new_str(rb_eArgError, rb_sprintf("Invalid type character '%c'", type_char));
369 }
370 return -1;
371 }
372}
373
374static inline ssize_t
375calculate_padding(ssize_t total, ssize_t alignment_size) {
376 if (alignment_size > 1) {
377 ssize_t res = total % alignment_size;
378 if (res > 0) {
379 return alignment_size - res;
380 }
381 }
382 return 0;
383}
384
385ssize_t
388 size_t *n_members, const char **err)
389{
390 if (format == NULL) return 1;
391
392 VALUE error = Qnil;
393 ssize_t total = 0;
394 size_t len = 0;
395 bool alignment = false;
396 ssize_t max_alignment_size = 0;
397
398 const char *p = format;
399 if (*p == '|') { // alginment specifier
400 alignment = true;
401 ++format;
402 ++p;
403 }
404 while (*p) {
405 const char *q = p;
406
407 // ignore spaces
408 if (ISSPACE(*p)) {
409 while (ISSPACE(*p)) ++p;
410 continue;
411 }
412
413 bool native_size_p = false;
414 ssize_t alignment_size = 0;
415 endianness_t endianness = ENDIANNESS_NATIVE;
416 ssize_t count = 0;
417 const ssize_t size = get_format_size(p, &native_size_p, &alignment_size, &endianness, &count, &p, &error);
418 if (size < 0) {
419 if (err) *err = q;
420 return -1;
421 }
422 if (max_alignment_size < alignment_size) {
423 max_alignment_size = alignment_size;
424 }
425
426 const ssize_t padding = alignment ? calculate_padding(total, alignment_size) : 0;
427 total += padding + size * count;
428
429 if (*q != 'x') {
430 ++len;
431 }
432 }
433
434 // adjust total size with the alignment size of the largest element
435 if (alignment && max_alignment_size > 0) {
436 const ssize_t padding = calculate_padding(total, max_alignment_size);
437 total += padding;
438 }
439
440 if (members && n_members) {
442
443 ssize_t i = 0, offset = 0;
444 const char *p = format;
445 while (*p) {
446 const int type_char = *p;
447
448 bool native_size_p;
449 ssize_t alignment_size = 0;
450 endianness_t endianness = ENDIANNESS_NATIVE;
451 ssize_t count = 0;
452 const ssize_t size = get_format_size(p, &native_size_p, &alignment_size, &endianness, &count, &p, NULL);
453
454 const ssize_t padding = alignment ? calculate_padding(offset, alignment_size) : 0;
455 offset += padding;
456
457 if (type_char != 'x') {
458#ifdef WORDS_BIGENDIAN
459 bool little_endian_p = (endianness == ENDIANNESS_LITTLE);
460#else
461 bool little_endian_p = (endianness != ENDIANNESS_BIG);
462#endif
463
464 switch (type_char) {
465 case 'e':
466 case 'E':
467 case 'v':
468 case 'V':
469 little_endian_p = true;
470 break;
471 case 'g':
472 case 'G':
473 case 'n':
474 case 'N':
475 little_endian_p = false;
476 break;
477 default:
478 break;
479 }
480
482 .format = type_char,
483 .native_size_p = native_size_p,
484 .little_endian_p = little_endian_p,
485 .offset = offset,
486 .size = size,
487 .repeat = count
488 };
489 }
490
491 offset += size * count;
492 }
493
494 *members = buf;
495 *n_members = len;
496 }
497
498 return total;
499}
500
501/* Return the item size. */
502ssize_t
503rb_memory_view_item_size_from_format(const char *format, const char **err)
504{
506}
507
508/* Return the pointer to the item located by the given indices. */
509void *
511{
512 uint8_t *ptr = view->data;
513
514 if (view->ndim == 1) {
515 ssize_t stride = view->strides != NULL ? view->strides[0] : view->item_size;
516 return ptr + indices[0] * stride;
517 }
518
519 assert(view->shape != NULL);
520
521 ssize_t i;
522 if (view->strides == NULL) {
523 // row-major contiguous array
524 ssize_t stride = view->item_size;
525 for (i = 0; i < view->ndim; ++i) {
526 stride *= view->shape[i];
527 }
528 for (i = 0; i < view->ndim; ++i) {
529 stride /= view->shape[i];
530 ptr += indices[i] * stride;
531 }
532 }
533 else if (view->sub_offsets == NULL) {
534 // flat strided array
535 for (i = 0; i < view->ndim; ++i) {
536 ptr += indices[i] * view->strides[i];
537 }
538 }
539 else {
540 // indirect strided array
541 for (i = 0; i < view->ndim; ++i) {
542 ptr += indices[i] * view->strides[i];
543 if (view->sub_offsets[i] >= 0) {
544 ptr = *(uint8_t **)ptr + view->sub_offsets[i];
545 }
546 }
547 }
548
549 return ptr;
550}
551
552static void
553switch_endianness(uint8_t *buf, ssize_t len)
554{
555 RUBY_ASSERT(buf != NULL);
556 RUBY_ASSERT(len >= 0);
557
558 uint8_t *p = buf;
559 uint8_t *q = buf + len - 1;
560
561 while (q - p > 0) {
562 uint8_t t = *p;
563 *p = *q;
564 *q = t;
565 ++p;
566 --q;
567 }
568}
569
570static inline VALUE
571extract_item_member(const uint8_t *ptr, const rb_memory_view_item_component_t *member, const size_t i)
572{
573 RUBY_ASSERT(ptr != NULL);
574 RUBY_ASSERT(member != NULL);
575 RUBY_ASSERT(i < member->repeat);
576
577#ifdef WORDS_BIGENDIAN
578 const bool native_endian_p = !member->little_endian_p;
579#else
580 const bool native_endian_p = member->little_endian_p;
581#endif
582
583 const uint8_t *p = ptr + member->offset + i * member->size;
584
585 if (member->format == 'c') {
586 return INT2FIX(*(char *)p);
587 }
588 else if (member->format == 'C') {
589 return INT2FIX(*(unsigned char *)p);
590 }
591
592 union {
593 short s;
594 unsigned short us;
595 int i;
596 unsigned int ui;
597 long l;
598 unsigned long ul;
599 LONG_LONG ll;
600 unsigned LONG_LONG ull;
601 int16_t i16;
602 uint16_t u16;
603 int32_t i32;
605 int64_t i64;
607 intptr_t iptr;
608 uintptr_t uptr;
609 float f;
610 double d;
611 } val;
612
613 if (!native_endian_p) {
614 MEMCPY(&val, p, uint8_t, member->size);
615 switch_endianness((uint8_t *)&val, member->size);
616 }
617 else {
618 MEMCPY(&val, p, uint8_t, member->size);
619 }
620
621 switch (member->format) {
622 case 's':
623 if (member->native_size_p) {
624 return INT2FIX(val.s);
625 }
626 else {
627 return INT2FIX(val.i16);
628 }
629
630 case 'S':
631 case 'n':
632 case 'v':
633 if (member->native_size_p) {
634 return UINT2NUM(val.us);
635 }
636 else {
637 return INT2FIX(val.u16);
638 }
639
640 case 'i':
641 return INT2NUM(val.i);
642
643 case 'I':
644 return UINT2NUM(val.ui);
645
646 case 'l':
647 if (member->native_size_p) {
648 return LONG2NUM(val.l);
649 }
650 else {
651 return LONG2NUM(val.i32);
652 }
653
654 case 'L':
655 case 'N':
656 case 'V':
657 if (member->native_size_p) {
658 return ULONG2NUM(val.ul);
659 }
660 else {
661 return ULONG2NUM(val.u32);
662 }
663
664 case 'f':
665 case 'e':
666 case 'g':
667 return DBL2NUM(val.f);
668
669 case 'q':
670 if (member->native_size_p) {
671 return LL2NUM(val.ll);
672 }
673 else {
674#if SIZEOF_INT64_t == SIZEOF_LONG
675 return LONG2NUM(val.i64);
676#else
677 return LL2NUM(val.i64);
678#endif
679 }
680
681 case 'Q':
682 if (member->native_size_p) {
683 return ULL2NUM(val.ull);
684 }
685 else {
686#if SIZEOF_UINT64_t == SIZEOF_LONG
687 return ULONG2NUM(val.u64);
688#else
689 return ULL2NUM(val.u64);
690#endif
691 }
692
693 case 'd':
694 case 'E':
695 case 'G':
696 return DBL2NUM(val.d);
697
698 case 'j':
699 return INTPTR2NUM(val.iptr);
700
701 case 'J':
702 return UINTPTR2NUM(val.uptr);
703
704 default:
706 }
707}
708
709/* Return a value of the extracted member. */
710VALUE
712{
713 if (ptr == NULL) return Qnil;
714 if (member == NULL) return Qnil;
715 if (i >= member->repeat) return Qnil;
716
717 return extract_item_member(ptr, member, i);
718}
719
720/* Return a value that consists of item members.
721 * When an item is a single member, the return value is a single value.
722 * When an item consists of multiple members, an array will be returned. */
723VALUE
724rb_memory_view_extract_item_members(const void *ptr, const rb_memory_view_item_component_t *members, const size_t n_members)
725{
726 if (ptr == NULL) return Qnil;
727 if (members == NULL) return Qnil;
728 if (n_members == 0) return Qnil;
729
730 if (n_members == 1 && members[0].repeat == 1) {
731 return rb_memory_view_extract_item_member(ptr, members, 0);
732 }
733
734 size_t i, j;
735 VALUE item = rb_ary_new();
736 for (i = 0; i < n_members; ++i) {
737 for (j = 0; j < members[i].repeat; ++j) {
738 VALUE v = extract_item_member(ptr, &members[i], j);
739 rb_ary_push(item, v);
740 }
741 }
742
743 return item;
744}
745
746void
748{
749 if (view->item_desc.components == NULL) {
750 const char *err;
751 rb_memory_view_item_component_t **p_components =
753 ssize_t n = rb_memory_view_parse_item_format(view->format, p_components, &view->item_desc.length, &err);
754 if (n < 0) {
756 "Unable to parse item format at %"PRIdSIZE" in \"%s\"",
757 (err - view->format), view->format);
758 }
759 }
760}
761
762/* Return a value that consists of item members in the given memory view. */
763VALUE
764rb_memory_view_get_item(rb_memory_view_t *view, const ssize_t *indices)
765{
766 void *ptr = rb_memory_view_get_item_pointer(view, indices);
767
768 if (view->format == NULL) {
769 return INT2FIX(*(uint8_t *)ptr);
770 }
771
772 if (view->item_desc.components == NULL) {
774 }
775
777}
778
779static const rb_memory_view_entry_t *
780lookup_memory_view_entry(VALUE klass)
781{
782 VALUE entry_obj = rb_ivar_lookup(klass, id_memory_view, Qnil);
783 while (NIL_P(entry_obj)) {
784 klass = rb_class_get_superclass(klass);
785
786 if (klass == rb_cBasicObject || klass == rb_cObject)
787 return NULL;
788
789 entry_obj = rb_ivar_lookup(klass, id_memory_view, Qnil);
790 }
791
792 if (! rb_typeddata_is_kind_of(entry_obj, &memory_view_entry_data_type))
793 return NULL;
794
795 return (const rb_memory_view_entry_t *)RTYPEDDATA_DATA(entry_obj);
796}
797
798/* Examine whether the given object supports memory view. */
799bool
801{
802 VALUE klass = CLASS_OF(obj);
803 const rb_memory_view_entry_t *entry = lookup_memory_view_entry(klass);
804 if (entry)
805 return (* entry->available_p_func)(obj);
806 else
807 return false;
808}
809
810/* Obtain a memory view from obj, and substitute the information to view. */
811bool
813{
814 VALUE klass = CLASS_OF(obj);
815 const rb_memory_view_entry_t *entry = lookup_memory_view_entry(klass);
816 if (entry) {
817 if (!(*entry->available_p_func)(obj)) {
818 return false;
819 }
820
821 bool rv = (*entry->get_func)(obj, view, flags);
822 if (rv) {
823 register_exported_object(view->obj);
824 }
825 return rv;
826 }
827 else
828 return false;
829}
830
831/* Release the memory view obtained from obj. */
832bool
834{
835 VALUE klass = CLASS_OF(view->obj);
836 const rb_memory_view_entry_t *entry = lookup_memory_view_entry(klass);
837 if (entry) {
838 bool rv = true;
839 if (entry->release_func) {
840 rv = (*entry->release_func)(view->obj, view);
841 }
842 if (rv) {
843 unregister_exported_object(view->obj);
844 view->obj = Qnil;
845 if (view->item_desc.components) {
846 xfree((void *)view->item_desc.components);
847 }
848 }
849 return rv;
850 }
851 else
852 return false;
853}
854
855void
857{
858 exported_object_table = rb_init_identtable();
859
860 // exported_object_table is referred through rb_memory_view_exported_object_registry
861 // in -test-/memory_view extension.
864 exported_object_table);
867
868 id_memory_view = rb_intern_const("__memory_view__");
869}
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:1301
VALUE rb_ary_new(void)
Definition: array.c:749
#define RUBY_ASSERT(expr)
Asserts that the given expression is truthy iff RUBY_DEBUG is truthy.
Definition: assert.h:177
#define UNREACHABLE_RETURN
Definition: assume.h:31
#define ISSPACE
Definition: ctype.h:38
struct RIMemo * ptr
Definition: debug.c:88
char * strchr(char *, char)
#define assert(x)
Definition: dlmalloc.c:1176
#define DBL2NUM
Definition: double.h:29
uint8_t len
Definition: escape.c:17
const signed char ruby_digit36_to_number_table[]
Definition: util.c:79
#define PRIsVALUE
Definition: function.c:10
void rb_gc_mark(VALUE ptr)
Definition: gc.c:6112
void rb_gc_register_mark_object(VALUE obj)
Inform the garbage collector that object is a live Ruby object that should not be moved.
Definition: gc.c:8022
#define CLASS_OF
Definition: globals.h:153
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2917
int rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type)
Definition: error.c:1007
VALUE rb_eRuntimeError
Definition: error.c:1055
VALUE rb_exc_new_str(VALUE etype, VALUE str)
Definition: error.c:1107
VALUE rb_eArgError
Definition: error.c:1058
void rb_warning(const char *fmt,...)
Definition: error.c:439
VALUE rb_class_get_superclass(VALUE)
Returns the superclass of klass The return value might be an iclass of a module, unlike rb_class_supe...
Definition: object.c:1999
VALUE rb_cObject
Object class.
Definition: object.c:49
VALUE rb_cBasicObject
BasicObject class.
Definition: object.c:47
st_table * rb_init_identtable(void)
Definition: hash.c:4451
#define rb_exc_new_cstr(exc, str)
Definition: string.h:271
VALUE rb_ivar_set(VALUE, ID, VALUE)
Definition: variable.c:1493
#define INT2NUM
Definition: int.h:43
#define UINT2NUM
Definition: int.h:46
#define LL2NUM
Definition: long_long.h:30
#define ULL2NUM
Definition: long_long.h:31
Internal header for Hash.
Internal header corresponding util.c.
VALUE rb_ivar_lookup(VALUE obj, ID id, VALUE undef)
Definition: variable.c:1192
#define PRIdSIZE
Definition: inttypes.h:124
voidpf void uLong size
Definition: ioapi.h:138
typedef long(ZCALLBACK *tell_file_func) OF((voidpf opaque
voidpf uLong offset
Definition: ioapi.h:144
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
voidpf void * buf
Definition: ioapi.h:138
#define INT2FIX
Definition: long.h:48
#define ULONG2NUM
Definition: long.h:60
#define LONG2NUM
Definition: long.h:50
#define MEMCPY(p1, p2, type, n)
Definition: memory.h:129
#define ALLOC_N
Definition: memory.h:133
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_is_row_major_contiguous(const rb_memory_view_t *view)
Definition: memory_view.c:147
bool rb_memory_view_release(rb_memory_view_t *view)
Definition: memory_view.c:833
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
ssize_t rb_memory_view_item_size_from_format(const char *format, const char **err)
Definition: memory_view.c:503
#define UINTPTR2NUM
Definition: memory_view.c:18
bool rb_memory_view_get(VALUE obj, rb_memory_view_t *view, int flags)
Definition: memory_view.c:812
void Init_MemoryView(void)
Definition: memory_view.c:856
void rb_memory_view_fill_contiguous_strides(const ssize_t ndim, const ssize_t item_size, const ssize_t *const shape, const bool row_major_p, ssize_t *const strides)
Definition: memory_view.c:179
#define INTPTR2NUM
Definition: memory_view.c:17
endianness_t
Definition: memory_view.c:224
@ ENDIANNESS_LITTLE
Definition: memory_view.c:226
@ ENDIANNESS_NATIVE
Definition: memory_view.c:225
@ ENDIANNESS_BIG
Definition: memory_view.c:227
bool rb_memory_view_available_p(VALUE obj)
Definition: memory_view.c:800
bool rb_memory_view_is_column_major_contiguous(const rb_memory_view_t *view)
Definition: memory_view.c:163
VALUE rb_memory_view_exported_object_registry
Definition: memory_view.c:35
bool rb_memory_view_register(VALUE klass, const rb_memory_view_entry_t *entry)
Definition: memory_view.c:131
VALUE rb_memory_view_extract_item_member(const void *ptr, const rb_memory_view_item_component_t *member, const size_t i)
Definition: memory_view.c:711
bool rb_memory_view_init_as_byte_array(rb_memory_view_t *view, VALUE obj, void *data, const ssize_t len, const bool readonly)
Definition: memory_view.c:198
VALUE rb_memory_view_get_item(rb_memory_view_t *view, const ssize_t *indices)
Definition: memory_view.c:764
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 STRUCT_ALIGNOF(T, result)
Definition: memory_view.c:28
void rb_memory_view_prepare_item_desc(rb_memory_view_t *view)
Definition: memory_view.c:747
const rb_data_type_t rb_memory_view_exported_object_registry_data_type
Definition: memory_view.c:61
Memory View.
int count
Definition: nkf.c:5055
uint32_t u32[type_roomof(hash_salt_t, uint32_t)]
Definition: random.c:1609
#define NULL
Definition: regenc.h:69
#define RTYPEDDATA_DATA(v)
Definition: rtypeddata.h:47
#define TypedData_Wrap_Struct(klass, data_type, sval)
Definition: rtypeddata.h:101
@ RUBY_TYPED_FREE_IMMEDIATELY
Definition: rtypeddata.h:62
unsigned int uint32_t
Definition: sha2.h:101
unsigned long long uint64_t
Definition: sha2.h:102
unsigned char uint8_t
Definition: sha2.h:100
uint64_t u64[4]
Definition: siphash.c:136
#define Qundef
#define Qnil
#define NIL_P
#define f
VALUE rb_sprintf(const char *,...)
Definition: sprintf.c:1203
@ ST_DELETE
Definition: st.h:99
@ ST_CONTINUE
Definition: st.h:99
unsigned long st_data_t
Definition: st.h:22
#define st_foreach
Definition: st.h:142
#define st_clear
Definition: st.h:160
#define st_free_table
Definition: st.h:156
#define st_update
Definition: st.h:136
Definition: memory_view.h:112
rb_memory_view_release_func_t release_func
Definition: memory_view.h:114
rb_memory_view_available_p_func_t available_p_func
Definition: memory_view.h:115
rb_memory_view_get_func_t get_func
Definition: memory_view.h:113
const rb_memory_view_item_component_t * components
Definition: memory_view.h:83
ssize_t item_size
Definition: memory_view.h:76
const ssize_t * strides
Definition: memory_view.h:98
void *const private
Definition: memory_view.h:105
const ssize_t * sub_offsets
Definition: memory_view.h:102
const ssize_t * shape
Definition: memory_view.h:94
const char * format
Definition: memory_view.h:72
ssize_t byte_size
Definition: memory_view.h:49
struct rb_memory_view_t::@106 item_desc
Definition: st.h:79
#define t
Definition: symbol.c:253
void error(const char *msg)
Definition: untgz.c:593
unsigned long VALUE
Definition: value.h:38
unsigned long ID
Definition: value.h:39
#define T_CLASS
Definition: value_type.h:57
#define ASSERT_vm_locking()
Definition: vm_sync.h:134
#define RB_VM_LOCK_ENTER()
Definition: vm_sync.h:121
#define RB_VM_LOCK_LEAVE()
Definition: vm_sync.h:122
int err
Definition: win32.c:142
int intptr_t
Definition: win32.h:90
unsigned int uintptr_t
Definition: win32.h:106
#define xfree
Definition: xmalloc.h:49