14 #include "debug_counter.h"
17 #include "internal/array.h"
18 #include "internal/compar.h"
19 #include "internal/enum.h"
20 #include "internal/gc.h"
21 #include "internal/hash.h"
22 #include "internal/numeric.h"
23 #include "internal/object.h"
24 #include "internal/proc.h"
25 #include "internal/rational.h"
26 #include "internal/vm.h"
31 #include "transient_heap.h"
38 #include "ruby_assert.h"
45 #define ARY_DEFAULT_SIZE 16
46 #define ARY_MAX_SIZE (LONG_MAX / (int)sizeof(VALUE))
47 #define SMALL_ARRAY_LEN 16
51 should_be_T_ARRAY(
VALUE ary)
58 should_not_be_shared_and_embedded(
VALUE ary)
63 #define ARY_SHARED_P(ary) \
64 (assert(should_be_T_ARRAY((VALUE)(ary))), \
65 assert(should_not_be_shared_and_embedded((VALUE)ary)), \
66 FL_TEST_RAW((ary),ELTS_SHARED)!=0)
68 #define ARY_EMBED_P(ary) \
69 (assert(should_be_T_ARRAY((VALUE)(ary))), \
70 assert(should_not_be_shared_and_embedded((VALUE)ary)), \
71 FL_TEST_RAW((ary), RARRAY_EMBED_FLAG) != 0)
73 #define ARY_HEAP_PTR(a) (assert(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.ptr)
74 #define ARY_HEAP_LEN(a) (assert(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.len)
75 #define ARY_HEAP_CAPA(a) (assert(!ARY_EMBED_P(a)), assert(!ARY_SHARED_ROOT_P(a)), \
76 RARRAY(a)->as.heap.aux.capa)
78 #define ARY_EMBED_PTR(a) (assert(ARY_EMBED_P(a)), RARRAY(a)->as.ary)
79 #define ARY_EMBED_LEN(a) \
80 (assert(ARY_EMBED_P(a)), \
81 (long)((RBASIC(a)->flags >> RARRAY_EMBED_LEN_SHIFT) & \
82 (RARRAY_EMBED_LEN_MASK >> RARRAY_EMBED_LEN_SHIFT)))
83 #define ARY_HEAP_SIZE(a) (assert(!ARY_EMBED_P(a)), assert(ARY_OWNS_HEAP_P(a)), ARY_CAPA(a) * sizeof(VALUE))
85 #define ARY_OWNS_HEAP_P(a) (assert(should_be_T_ARRAY((VALUE)(a))), \
86 !FL_TEST_RAW((a), ELTS_SHARED|RARRAY_EMBED_FLAG))
88 #define FL_SET_EMBED(a) do { \
89 assert(!ARY_SHARED_P(a)); \
90 FL_SET((a), RARRAY_EMBED_FLAG); \
91 RARY_TRANSIENT_UNSET(a); \
95 #define FL_UNSET_EMBED(ary) FL_UNSET((ary), RARRAY_EMBED_FLAG|RARRAY_EMBED_LEN_MASK)
96 #define FL_SET_SHARED(ary) do { \
97 assert(!ARY_EMBED_P(ary)); \
98 FL_SET((ary), ELTS_SHARED); \
100 #define FL_UNSET_SHARED(ary) FL_UNSET((ary), ELTS_SHARED)
102 #define ARY_SET_PTR(ary, p) do { \
103 assert(!ARY_EMBED_P(ary)); \
104 assert(!OBJ_FROZEN(ary)); \
105 RARRAY(ary)->as.heap.ptr = (p); \
107 #define ARY_SET_EMBED_LEN(ary, n) do { \
109 assert(ARY_EMBED_P(ary)); \
110 assert(!OBJ_FROZEN(ary)); \
111 RBASIC(ary)->flags &= ~RARRAY_EMBED_LEN_MASK; \
112 RBASIC(ary)->flags |= (tmp_n) << RARRAY_EMBED_LEN_SHIFT; \
114 #define ARY_SET_HEAP_LEN(ary, n) do { \
115 assert(!ARY_EMBED_P(ary)); \
116 RARRAY(ary)->as.heap.len = (n); \
118 #define ARY_SET_LEN(ary, n) do { \
119 if (ARY_EMBED_P(ary)) { \
120 ARY_SET_EMBED_LEN((ary), (n)); \
123 ARY_SET_HEAP_LEN((ary), (n)); \
125 assert(RARRAY_LEN(ary) == (n)); \
127 #define ARY_INCREASE_PTR(ary, n) do { \
128 assert(!ARY_EMBED_P(ary)); \
129 assert(!OBJ_FROZEN(ary)); \
130 RARRAY(ary)->as.heap.ptr += (n); \
132 #define ARY_INCREASE_LEN(ary, n) do { \
133 assert(!OBJ_FROZEN(ary)); \
134 if (ARY_EMBED_P(ary)) { \
135 ARY_SET_EMBED_LEN((ary), RARRAY_LEN(ary)+(n)); \
138 RARRAY(ary)->as.heap.len += (n); \
142 #define ARY_CAPA(ary) (ARY_EMBED_P(ary) ? RARRAY_EMBED_LEN_MAX : \
143 ARY_SHARED_ROOT_P(ary) ? RARRAY_LEN(ary) : ARY_HEAP_CAPA(ary))
144 #define ARY_SET_CAPA(ary, n) do { \
145 assert(!ARY_EMBED_P(ary)); \
146 assert(!ARY_SHARED_P(ary)); \
147 assert(!OBJ_FROZEN(ary)); \
148 RARRAY(ary)->as.heap.aux.capa = (n); \
151 #define ARY_SHARED_ROOT(ary) (assert(ARY_SHARED_P(ary)), RARRAY(ary)->as.heap.aux.shared_root)
152 #define ARY_SET_SHARED(ary, value) do { \
153 const VALUE _ary_ = (ary); \
154 const VALUE _value_ = (value); \
155 assert(!ARY_EMBED_P(_ary_)); \
156 assert(ARY_SHARED_P(_ary_)); \
157 assert(ARY_SHARED_ROOT_P(_value_)); \
158 RB_OBJ_WRITE(_ary_, &RARRAY(_ary_)->as.heap.aux.shared_root, _value_); \
160 #define RARRAY_SHARED_ROOT_FLAG FL_USER5
161 #define ARY_SHARED_ROOT_P(ary) (assert(should_be_T_ARRAY((VALUE)(ary))), \
162 FL_TEST_RAW((ary), RARRAY_SHARED_ROOT_FLAG))
163 #define ARY_SHARED_ROOT_REFCNT(ary) \
164 (assert(ARY_SHARED_ROOT_P(ary)), RARRAY(ary)->as.heap.aux.capa)
165 #define ARY_SHARED_ROOT_OCCUPIED(ary) (ARY_SHARED_ROOT_REFCNT(ary) == 1)
166 #define ARY_SET_SHARED_ROOT_REFCNT(ary, value) do { \
167 assert(ARY_SHARED_ROOT_P(ary)); \
168 RARRAY(ary)->as.heap.aux.capa = (value); \
170 #define FL_SET_SHARED_ROOT(ary) do { \
171 assert(!ARY_EMBED_P(ary)); \
172 assert(!RARRAY_TRANSIENT_P(ary)); \
173 FL_SET((ary), RARRAY_SHARED_ROOT_FLAG); \
179 assert(!ARY_SHARED_P(a));
188 #define ary_verify(ary) ary_verify_(ary, __FILE__, __LINE__)
191 ary_verify_(
VALUE ary,
const char *file,
int line)
197 const VALUE *ptr = ARY_HEAP_PTR(ary);
199 long len = ARY_HEAP_LEN(ary), root_len =
RARRAY_LEN(root);
200 assert(
FL_TEST(root, RARRAY_SHARED_ROOT_FLAG));
201 assert(root_ptr <= ptr && ptr + len <= root_ptr + root_len);
204 else if (ARY_EMBED_P(ary)) {
206 assert(!ARY_SHARED_P(ary));
214 if (len > 1) len = 1;
215 for (i=0; i<len; i++) {
222 #if USE_TRANSIENT_HEAP
228 rb_transient_heap_verify();
234 rb_ary_verify(
VALUE ary)
239 #define ary_verify(ary) ((void)0)
243 rb_ary_ptr_use_start(
VALUE ary)
252 rb_ary_ptr_use_end(
VALUE ary)
268 ary_mem_clear(
VALUE ary,
long beg,
long size)
276 memfill(
register VALUE *mem,
register long size,
register VALUE val)
284 ary_memfill(
VALUE ary,
long beg,
long size,
VALUE val)
287 memfill(ptr + beg, size, val);
293 ary_memcpy0(
VALUE ary,
long beg,
long argc,
const VALUE *argv,
VALUE buff_owner_ary)
295 assert(!ARY_SHARED_P(buff_owner_ary));
297 if (argc > (
int)(128/
sizeof(
VALUE)) ) {
298 rb_gc_writebarrier_remember(buff_owner_ary);
306 for (i=0; i<argc; i++) {
314 ary_memcpy(
VALUE ary,
long beg,
long argc,
const VALUE *argv)
316 ary_memcpy0(ary, beg, argc, argv, ary);
320 ary_heap_alloc(
VALUE ary,
size_t capa)
322 VALUE *ptr = rb_transient_heap_alloc(ary,
sizeof(
VALUE) * capa);
325 RARY_TRANSIENT_SET(ary);
328 RARY_TRANSIENT_UNSET(ary);
336 ary_heap_free_ptr(
VALUE ary,
const VALUE *ptr,
long size)
342 ruby_sized_xfree((
void *)ptr, size);
347 ary_heap_free(
VALUE ary)
350 RARY_TRANSIENT_UNSET(ary);
353 ary_heap_free_ptr(ary, ARY_HEAP_PTR(ary), ARY_HEAP_SIZE(ary));
358 ary_heap_realloc(
VALUE ary,
size_t new_capa)
360 size_t alloc_capa = new_capa;
361 size_t old_capa = ARY_HEAP_CAPA(ary);
364 if (new_capa <= old_capa) {
366 alloc_capa = old_capa;
369 VALUE *new_ptr = rb_transient_heap_alloc(ary,
sizeof(
VALUE) * new_capa);
371 if (new_ptr == NULL) {
373 RARY_TRANSIENT_UNSET(ary);
376 MEMCPY(new_ptr, ARY_HEAP_PTR(ary),
VALUE, old_capa);
377 ARY_SET_PTR(ary, new_ptr);
381 SIZED_REALLOC_N(
RARRAY(ary)->as.heap.ptr,
VALUE, new_capa, old_capa);
388 #if USE_TRANSIENT_HEAP
390 rb_ary_transient_heap_evacuate_(
VALUE ary,
int transient,
int promote)
394 const VALUE *old_ptr = ARY_HEAP_PTR(ary);
395 long capa = ARY_HEAP_CAPA(ary);
396 long len = ARY_HEAP_LEN(ary);
398 if (ARY_SHARED_ROOT_P(ary)) {
402 assert(ARY_OWNS_HEAP_P(ary));
404 assert(!ARY_PTR_USING_P(ary));
408 RARY_TRANSIENT_UNSET(ary);
411 new_ptr = ary_heap_alloc(ary, capa);
416 RARRAY(ary)->as.heap.ptr = new_ptr;
423 rb_ary_transient_heap_evacuate(
VALUE ary,
int promote)
432 rb_ary_transient_heap_evacuate_(ary, TRUE, TRUE);
443 ary_resize_capa(
VALUE ary,
long capacity)
447 assert(!ARY_SHARED_P(ary));
450 size_t new_capa = capacity;
451 if (ARY_EMBED_P(ary)) {
452 long len = ARY_EMBED_LEN(ary);
453 VALUE *ptr = ary_heap_alloc(ary, capacity);
457 ARY_SET_PTR(ary, ptr);
458 ARY_SET_HEAP_LEN(ary, len);
461 new_capa = ary_heap_realloc(ary, capacity);
463 ARY_SET_CAPA(ary, new_capa);
466 if (!ARY_EMBED_P(ary)) {
467 long len = ARY_HEAP_LEN(ary);
468 long old_capa = ARY_HEAP_CAPA(ary);
469 const VALUE *ptr = ARY_HEAP_PTR(ary);
471 if (len > capacity) len = capacity;
473 ary_heap_free_ptr(ary, ptr, old_capa);
476 ARY_SET_LEN(ary, len);
484 ary_shrink_capa(
VALUE ary)
486 long capacity = ARY_HEAP_LEN(ary);
487 long old_capa = ARY_HEAP_CAPA(ary);
488 assert(!ARY_SHARED_P(ary));
489 assert(old_capa >= capacity);
490 if (old_capa > capacity) ary_heap_realloc(ary, capacity);
496 ary_double_capa(
VALUE ary,
long min)
498 long new_capa = ARY_CAPA(ary) / 2;
500 if (new_capa < ARY_DEFAULT_SIZE) {
501 new_capa = ARY_DEFAULT_SIZE;
503 if (new_capa >= ARY_MAX_SIZE - min) {
504 new_capa = (ARY_MAX_SIZE - min) / 2;
507 ary_resize_capa(ary, new_capa);
513 rb_ary_decrement_share(
VALUE shared_root)
516 long num = ARY_SHARED_ROOT_REFCNT(shared_root) - 1;
518 ARY_SET_SHARED_ROOT_REFCNT(shared_root, num);
524 rb_ary_unshare(
VALUE ary)
526 VALUE shared_root =
RARRAY(ary)->as.heap.aux.shared_root;
527 rb_ary_decrement_share(shared_root);
528 FL_UNSET_SHARED(ary);
532 rb_ary_unshare_safe(
VALUE ary)
534 if (ARY_SHARED_P(ary) && !ARY_EMBED_P(ary)) {
540 rb_ary_increment_share(
VALUE shared_root)
542 long num = ARY_SHARED_ROOT_REFCNT(shared_root);
544 ARY_SET_SHARED_ROOT_REFCNT(shared_root, num + 1);
550 rb_ary_set_shared(
VALUE ary,
VALUE shared_root)
552 rb_ary_increment_share(shared_root);
554 RB_DEBUG_COUNTER_INC(obj_ary_shared_create);
555 ARY_SET_SHARED(ary, shared_root);
559 rb_ary_modify_check(
VALUE ary)
566 rb_ary_cancel_sharing(
VALUE ary)
568 if (ARY_SHARED_P(ary)) {
570 VALUE shared_root = ARY_SHARED_ROOT(ary);
572 ary_verify(shared_root);
575 const VALUE *ptr = ARY_HEAP_PTR(ary);
576 FL_UNSET_SHARED(ary);
579 rb_ary_decrement_share(shared_root);
580 ARY_SET_EMBED_LEN(ary, len);
582 else if (ARY_SHARED_ROOT_OCCUPIED(shared_root) && len > ((shared_len =
RARRAY_LEN(shared_root))>>1)) {
584 FL_UNSET_SHARED(ary);
586 ARY_SET_CAPA(ary, shared_len);
590 FL_SET_EMBED(shared_root);
591 rb_ary_decrement_share(shared_root);
594 VALUE *ptr = ary_heap_alloc(ary, len);
597 ARY_SET_CAPA(ary, len);
598 ARY_SET_PTR(ary, ptr);
601 rb_gc_writebarrier_remember(ary);
609 rb_ary_modify_check(ary);
610 rb_ary_cancel_sharing(ary);
614 ary_ensure_room_for_push(
VALUE ary,
long add_len)
617 long new_len = old_len + add_len;
620 if (old_len > ARY_MAX_SIZE - add_len) {
623 if (ARY_SHARED_P(ary)) {
625 VALUE shared_root = ARY_SHARED_ROOT(ary);
626 if (ARY_SHARED_ROOT_OCCUPIED(shared_root)) {
628 rb_ary_modify_check(ary);
631 ary_verify(shared_root);
637 capa = ARY_CAPA(ary);
638 if (new_len > capa - (capa >> 6)) {
639 ary_double_capa(ary, new_len);
650 rb_ary_modify_check(ary);
652 capa = ARY_CAPA(ary);
653 if (new_len > capa) {
654 ary_double_capa(ary, new_len);
690 if (!ARY_EMBED_P(ary1) && ARY_SHARED_P(ary1) &&
691 !ARY_EMBED_P(ary2) && ARY_SHARED_P(ary2) &&
692 RARRAY(ary1)->as.heap.aux.shared_root ==
RARRAY(ary2)->as.heap.aux.shared_root &&
693 RARRAY(ary1)->as.heap.len ==
RARRAY(ary2)->as.heap.len) {
700 ary_alloc(
VALUE klass)
711 empty_ary_alloc(
VALUE klass)
713 RUBY_DTRACE_CREATE_HOOK(ARRAY, 0);
714 return ary_alloc(klass);
718 ary_new(
VALUE klass,
long capa)
725 if (capa > ARY_MAX_SIZE) {
729 RUBY_DTRACE_CREATE_HOOK(ARRAY, capa);
731 ary = ary_alloc(klass);
733 ptr = ary_heap_alloc(ary, capa);
735 ARY_SET_PTR(ary, ptr);
736 ARY_SET_CAPA(ary, capa);
737 ARY_SET_HEAP_LEN(ary, 0);
765 for (i=0; i<n; i++) {
766 ARY_SET(ary, i, va_arg(ar,
VALUE));
774 MJIT_FUNC_EXPORTED
VALUE
775 rb_ary_tmp_new_from_values(
VALUE klass,
long n,
const VALUE *elts)
779 ary = ary_new(klass, n);
781 ary_memcpy(ary, 0, n, elts);
791 return rb_ary_tmp_new_from_values(
rb_cArray, n, elts);
813 if (capa > ARY_MAX_SIZE) {
817 RUBY_DTRACE_CREATE_HOOK(ARRAY, capa);
819 ary = ec_ary_alloc(ec, klass);
822 ptr = ary_heap_alloc(ary, capa);
824 ARY_SET_PTR(ary, ptr);
825 ARY_SET_CAPA(ary, capa);
826 ARY_SET_HEAP_LEN(ary, 0);
839 ary_memcpy(ary, 0, n, elts);
849 VALUE ary = ary_new(0, capa);
850 rb_ary_transient_heap_evacuate(ary, TRUE);
855 rb_ary_tmp_new_fill(
long capa)
857 VALUE ary = ary_new(0, capa);
858 ary_memfill(ary, 0, capa,
Qnil);
859 ARY_SET_LEN(ary, capa);
860 rb_ary_transient_heap_evacuate(ary, TRUE);
867 if (ARY_OWNS_HEAP_P(ary)) {
868 if (USE_DEBUG_COUNTER &&
869 !ARY_SHARED_ROOT_P(ary) &&
871 RB_DEBUG_COUNTER_INC(obj_ary_extracapa);
875 RB_DEBUG_COUNTER_INC(obj_ary_transient);
878 RB_DEBUG_COUNTER_INC(obj_ary_ptr);
883 RB_DEBUG_COUNTER_INC(obj_ary_embed);
886 if (ARY_SHARED_P(ary)) {
887 RB_DEBUG_COUNTER_INC(obj_ary_shared);
889 if (ARY_SHARED_ROOT_P(ary) && ARY_SHARED_ROOT_OCCUPIED(ary)) {
890 RB_DEBUG_COUNTER_INC(obj_ary_shared_root_occupied);
894 RUBY_FUNC_EXPORTED
size_t
895 rb_ary_memsize(
VALUE ary)
897 if (ARY_OWNS_HEAP_P(ary)) {
898 return ARY_CAPA(ary) *
sizeof(
VALUE);
906 ary_discard(
VALUE ary)
909 RBASIC(ary)->flags |= RARRAY_EMBED_FLAG;
910 RBASIC(ary)->flags &= ~(RARRAY_EMBED_LEN_MASK | RARRAY_TRANSIENT_FLAG);
914 ary_make_shared(
VALUE ary)
916 assert(!ARY_EMBED_P(ary));
919 if (ARY_SHARED_P(ary)) {
920 return ARY_SHARED_ROOT(ary);
922 else if (ARY_SHARED_ROOT_P(ary)) {
926 rb_ary_transient_heap_evacuate(ary, TRUE);
927 ary_shrink_capa(ary);
928 FL_SET_SHARED_ROOT(ary);
929 ARY_SET_SHARED_ROOT_REFCNT(ary, 1);
933 long capa = ARY_CAPA(ary), len =
RARRAY_LEN(ary);
938 rb_ary_transient_heap_evacuate(ary, TRUE);
939 ptr = ARY_HEAP_PTR(ary);
941 FL_UNSET_EMBED(vshared);
942 ARY_SET_LEN(vshared, capa);
943 ARY_SET_PTR(vshared, ptr);
944 ary_mem_clear(vshared, len, capa - len);
945 FL_SET_SHARED_ROOT(vshared);
946 ARY_SET_SHARED_ROOT_REFCNT(vshared, 1);
948 RB_DEBUG_COUNTER_INC(obj_ary_shared_create);
949 ARY_SET_SHARED(ary, vshared);
960 ary_make_substitution(
VALUE ary)
967 ARY_SET_EMBED_LEN(subst, len);
971 return rb_ary_increment_share(ary_make_shared(ary));
982 rb_to_array_type(
VALUE ary)
984 return rb_convert_type_with_id(ary,
T_ARRAY,
"Array", idTo_ary);
986 #define to_ary rb_to_array_type
991 return rb_check_convert_type_with_id(ary,
T_ARRAY,
"Array", idTo_ary);
994 MJIT_FUNC_EXPORTED
VALUE
995 rb_check_to_array(
VALUE ary)
997 return rb_check_convert_type_with_id(ary,
T_ARRAY,
"Array", idTo_a);
1001 rb_to_array(
VALUE ary)
1003 return rb_convert_type_with_id(ary,
T_ARRAY,
"Array", idTo_a);
1071 rb_ary_initialize(
int argc,
VALUE *argv,
VALUE ary)
1078 if (ARY_OWNS_HEAP_P(ary) && ARY_HEAP_PTR(ary) != NULL) {
1081 rb_ary_unshare_safe(ary);
1083 ARY_SET_EMBED_LEN(ary, 0);
1090 if (argc == 1 && !
FIXNUM_P(size)) {
1103 if (len > ARY_MAX_SIZE) {
1108 ary_resize_capa(ary, len);
1113 rb_warn(
"block supersedes default value argument");
1115 for (i=0; i<len; i++) {
1117 ARY_SET_LEN(ary, i + 1);
1121 ary_memfill(ary, 0, len, val);
1122 ARY_SET_LEN(ary, len);
1136 rb_ary_s_create(
int argc,
VALUE *argv,
VALUE klass)
1138 VALUE ary = ary_new(klass, argc);
1139 if (argc > 0 && argv) {
1140 ary_memcpy(ary, 0, argc, argv);
1141 ARY_SET_LEN(ary, argc);
1159 else if (idx >= ARY_MAX_SIZE) {
1164 if (idx >= ARY_CAPA(ary)) {
1165 ary_double_capa(ary, idx);
1168 ary_mem_clear(ary, len, idx - len + 1);
1172 ARY_SET_LEN(ary, idx + 1);
1174 ARY_SET(ary, idx, val);
1178 ary_make_partial(
VALUE ary,
VALUE klass,
long offset,
long len)
1180 assert(offset >= 0);
1185 VALUE result = ary_alloc(klass);
1187 ARY_SET_EMBED_LEN(result, len);
1191 VALUE shared, result = ary_alloc(klass);
1192 FL_UNSET_EMBED(result);
1194 shared = ary_make_shared(ary);
1197 rb_ary_set_shared(result, shared);
1199 ARY_INCREASE_PTR(result, offset);
1200 ARY_SET_LEN(result, len);
1209 ary_make_partial_step(
VALUE ary,
VALUE klass,
long offset,
long len,
long step)
1211 assert(offset >= 0);
1217 const long orig_len = len;
1219 if ((step > 0 && step >= len) || (step < 0 && (step < -len))) {
1220 VALUE result = ary_new(klass, 1);
1223 ARY_SET_EMBED_LEN(result, 1);
1227 long ustep = (step < 0) ? -step : step;
1228 len = (len + ustep - 1) / ustep;
1231 long j = offset + ((step > 0) ? 0 : (orig_len - 1));
1232 VALUE result = ary_new(klass, len);
1235 for (i = 0; i < len; ++i) {
1239 ARY_SET_EMBED_LEN(result, len);
1243 for (i = 0; i < len; ++i) {
1248 ARY_SET_LEN(result, len);
1255 ary_make_shared_copy(
VALUE ary)
1260 enum ary_take_pos_flags
1267 ary_take_first_or_last(
int argc,
const VALUE *argv,
VALUE ary,
enum ary_take_pos_flags last)
1290 return ary_make_partial(ary,
rb_cArray, offset, n);
1310 long idx =
RARRAY_LEN((ary_verify(ary), ary));
1311 VALUE target_ary = ary_ensure_room_for_push(ary, 1);
1315 ARY_SET_LEN(ary, idx + 1);
1324 VALUE target_ary = ary_ensure_room_for_push(ary, len);
1325 ary_memcpy0(ary, oldlen, len, argv, target_ary);
1326 ARY_SET_LEN(ary, oldlen + len);
1351 rb_ary_push_m(
int argc,
VALUE *argv,
VALUE ary)
1360 rb_ary_modify_check(ary);
1362 if (n == 0)
return Qnil;
1363 if (ARY_OWNS_HEAP_P(ary) &&
1364 n * 3 < ARY_CAPA(ary) &&
1365 ARY_CAPA(ary) > ARY_DEFAULT_SIZE)
1367 ary_resize_capa(ary, n * 2);
1370 ARY_SET_LEN(ary, n);
1404 rb_ary_pop_m(
int argc,
VALUE *argv,
VALUE ary)
1412 rb_ary_modify_check(ary);
1413 result = ary_take_first_or_last(argc, argv, ary, ARY_TAKE_LAST);
1425 rb_ary_modify_check(ary);
1426 if (len == 0)
return Qnil;
1428 if (!ARY_SHARED_P(ary)) {
1429 if (len < ARY_DEFAULT_SIZE) {
1433 ARY_INCREASE_LEN(ary, -1);
1437 assert(!ARY_EMBED_P(ary));
1439 ARY_SET(ary, 0,
Qnil);
1440 ary_make_shared(ary);
1442 else if (ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary))) {
1445 ARY_INCREASE_PTR(ary, 1);
1446 ARY_INCREASE_LEN(ary, -1);
1484 rb_ary_shift_m(
int argc,
VALUE *argv,
VALUE ary)
1493 rb_ary_modify_check(ary);
1494 result = ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST);
1496 rb_ary_behead(ary,n);
1502 behead_shared(
VALUE ary,
long n)
1504 assert(ARY_SHARED_P(ary));
1505 rb_ary_modify_check(ary);
1506 if (ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary))) {
1507 ary_mem_clear(ary, 0, n);
1509 ARY_INCREASE_PTR(ary, n);
1510 ARY_INCREASE_LEN(ary, -n);
1516 behead_transient(
VALUE ary,
long n)
1518 rb_ary_modify_check(ary);
1522 ARY_INCREASE_LEN(ary, -n);
1527 MJIT_FUNC_EXPORTED
VALUE
1528 rb_ary_behead(
VALUE ary,
long n)
1533 else if (ARY_SHARED_P(ary)) {
1534 return behead_shared(ary, n);
1536 else if (
RARRAY_LEN(ary) >= ARY_DEFAULT_SIZE) {
1537 ary_make_shared(ary);
1538 return behead_shared(ary, n);
1541 return behead_transient(ary, n);
1546 make_room_for_unshift(
VALUE ary,
const VALUE *head,
VALUE *sharedp,
int argc,
long capa,
long len)
1548 if (head - sharedp < argc) {
1549 long room = capa - len - argc;
1553 head = sharedp + argc + room;
1555 ARY_SET_PTR(ary, head - argc);
1556 assert(ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary)));
1559 return ARY_SHARED_ROOT(ary);
1563 ary_modify_for_unshift(
VALUE ary,
int argc)
1566 long new_len = len + argc;
1568 const VALUE *head, *sharedp;
1571 capa = ARY_CAPA(ary);
1572 if (capa - (capa >> 6) <= new_len) {
1573 ary_double_capa(ary, new_len);
1577 if (new_len > ARY_DEFAULT_SIZE * 4) {
1581 capa = ARY_CAPA(ary);
1582 ary_make_shared(ary);
1585 return make_room_for_unshift(ary, head, (
void *)sharedp, argc, capa, len);
1599 ary_ensure_room_for_unshift(
VALUE ary,
int argc)
1602 long new_len = len + argc;
1604 if (len > ARY_MAX_SIZE - argc) {
1607 else if (! ARY_SHARED_P(ary)) {
1608 return ary_modify_for_unshift(ary, argc);
1611 VALUE shared_root = ARY_SHARED_ROOT(ary);
1614 if (! ARY_SHARED_ROOT_OCCUPIED(shared_root)) {
1615 return ary_modify_for_unshift(ary, argc);
1617 else if (new_len > capa) {
1618 return ary_modify_for_unshift(ary, argc);
1624 rb_ary_modify_check(ary);
1625 return make_room_for_unshift(ary, head, sharedp, argc, capa, len);
1644 rb_ary_unshift_m(
int argc,
VALUE *argv,
VALUE ary)
1650 rb_ary_modify_check(ary);
1654 target_ary = ary_ensure_room_for_unshift(ary, argc);
1655 ary_memcpy0(ary, 0, argc, argv, target_ary);
1656 ARY_SET_LEN(ary, len + argc);
1663 return rb_ary_unshift_m(1,&item,ary);
1668 rb_ary_elt(
VALUE ary,
long offset)
1671 if (len == 0)
return Qnil;
1672 if (offset < 0 || len <= offset) {
1681 return rb_ary_entry_internal(ary, offset);
1685 rb_ary_subseq_step(
VALUE ary,
long beg,
long len,
long step)
1690 if (beg > alen)
return Qnil;
1691 if (beg < 0 || len < 0)
return Qnil;
1693 if (alen < len || alen < beg + len) {
1697 if (len == 0)
return ary_new(klass, 0);
1701 return ary_make_partial(ary, klass, beg, len);
1703 return ary_make_partial_step(ary, klass, beg, len, step);
1709 return rb_ary_subseq_step(ary, beg, len, 1);
1813 return rb_ary_aref2(ary, argv[0], argv[1]);
1815 return rb_ary_aref1(ary, argv[0]);
1829 MJIT_FUNC_EXPORTED
VALUE
1832 long beg, len, step;
1845 return rb_ary_subseq_step(ary, beg, len, step);
1897 rb_ary_first(
int argc,
VALUE *argv,
VALUE ary)
1904 return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST);
1939 rb_ary_last(
int argc,
const VALUE *argv,
VALUE ary)
1943 if (len == 0)
return Qnil;
1947 return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_LAST);
1985 rb_ary_fetch(
int argc,
VALUE *argv,
VALUE ary)
1993 if (block_given && argc == 2) {
1994 rb_warn(
"block supersedes default value argument");
2002 if (block_given)
return rb_yield(pos);
2048 rb_ary_index(
int argc,
VALUE *argv,
VALUE ary)
2065 rb_warn(
"given block not used");
2107 rb_ary_rindex(
int argc,
VALUE *argv,
VALUE ary)
2126 rb_warn(
"given block not used");
2144 if (!
NIL_P(tmp))
return tmp;
2149 rb_ary_splice(
VALUE ary,
long beg,
long len,
const VALUE *rptr,
long rlen)
2163 if (olen < len || olen < beg + len) {
2169 rofs = (rptr >= optr && rptr < optr + olen) ? rptr - optr : -1;
2174 if (beg > ARY_MAX_SIZE - rlen) {
2177 target_ary = ary_ensure_room_for_push(ary, rlen-len);
2179 ary_mem_clear(ary, olen, beg - olen);
2182 ary_memcpy0(ary, beg, rlen, rptr, target_ary);
2184 ARY_SET_LEN(ary, len);
2189 if (olen - len > ARY_MAX_SIZE - rlen) {
2193 alen = olen + rlen - len;
2194 if (alen >= ARY_CAPA(ary)) {
2195 ary_double_capa(ary, alen);
2200 MEMMOVE(ptr + beg + rlen, ptr + beg + len,
2201 VALUE, olen - (beg + len)));
2202 ARY_SET_LEN(ary, alen);
2219 rb_ary_set_len(
VALUE ary,
long len)
2223 rb_ary_modify_check(ary);
2224 if (ARY_SHARED_P(ary)) {
2227 if (len > (capa = (
long)ARY_CAPA(ary))) {
2228 rb_bug(
"probable buffer overflow: %ld for %ld", len, capa);
2230 ARY_SET_LEN(ary, len);
2240 if (len == olen)
return ary;
2241 if (len > ARY_MAX_SIZE) {
2245 if (len >= ARY_CAPA(ary)) {
2246 ary_double_capa(ary, len);
2248 ary_mem_clear(ary, olen, len - olen);
2249 ARY_SET_LEN(ary, len);
2251 else if (ARY_EMBED_P(ary)) {
2252 ARY_SET_EMBED_LEN(ary, len);
2259 ARY_SET_EMBED_LEN(ary, len);
2262 if (olen > len + ARY_DEFAULT_SIZE) {
2263 size_t new_capa = ary_heap_realloc(ary, len);
2264 ARY_SET_CAPA(ary, new_capa);
2266 ARY_SET_HEAP_LEN(ary, len);
2273 ary_aset_by_rb_ary_store(
VALUE ary,
long key,
VALUE val)
2280 ary_aset_by_rb_ary_splice(
VALUE ary,
long beg,
long len,
VALUE val)
2388 rb_ary_aset(
int argc,
VALUE *argv,
VALUE ary)
2390 long offset, beg, len;
2393 rb_ary_modify_check(ary);
2397 return ary_aset_by_rb_ary_splice(ary, beg, len, argv[2]);
2401 return ary_aset_by_rb_ary_store(ary, offset, argv[1]);
2405 return ary_aset_by_rb_ary_splice(ary, beg, len, argv[1]);
2409 return ary_aset_by_rb_ary_store(ary, offset, argv[1]);
2444 rb_ary_insert(
int argc,
VALUE *argv,
VALUE ary)
2449 rb_ary_modify_check(ary);
2451 if (argc == 1)
return ary;
2463 rb_ary_splice(ary, pos, 0, argv + 1, argc - 1);
2468 rb_ary_length(
VALUE ary);
2473 return rb_ary_length(ary);
2567 rb_ary_each_index(
VALUE ary)
2617 rb_ary_reverse_each(
VALUE ary)
2642 rb_ary_length(
VALUE ary)
2657 rb_ary_empty_p(
VALUE ary)
2668 ARY_SET_LEN(dup, len);
2686 recursive_join(
VALUE obj,
VALUE argp,
int recur)
2691 VALUE result = arg[2];
2692 int *first = (
int *)arg[3];
2698 ary_join_1(obj, ary, sep, 0, result, first);
2710 for (i=0; i<max; i++) {
2713 if (i > 0 && !
NIL_P(sep))
2721 ary_join_1_str(
VALUE dst,
VALUE src,
int *first)
2743 args[3] = (
VALUE)first;
2754 if (i > 0 && !
NIL_P(sep))
2759 ary_join_1_str(result, val, first);
2762 ary_join_1_ary(val, ary, sep, result, val, first);
2765 ary_join_1_str(result, tmp, first);
2768 ary_join_1_ary(val, ary, sep, result, tmp, first);
2780 VALUE val, tmp, result;
2792 if (
NIL_P(tmp) || tmp != val) {
2798 i = ary_join_0(ary, sep, i, result);
2800 ary_join_1(ary, ary, sep, i, result, &first);
2810 ary_join_0(ary, sep,
RARRAY_LEN(ary), result);
2839 rb_ary_join_m(
int argc,
VALUE *argv,
VALUE ary)
2854 inspect_ary(
VALUE ary,
VALUE dummy,
int recur)
2884 rb_ary_inspect(
VALUE ary)
2893 return rb_ary_inspect(ary);
2915 rb_ary_to_a(
VALUE ary)
2948 rb_ary_to_h(
VALUE ary)
2955 const VALUE e = rb_ary_elt(ary, i);
2956 const VALUE elt = block_given ? rb_yield_force_blockarg(e) : e;
2958 if (
NIL_P(key_value_pair)) {
2979 rb_ary_to_ary_m(
VALUE ary)
3004 ary_reverse(p1, p2);
3020 rb_ary_reverse_bang(
VALUE ary)
3036 rb_ary_reverse_m(
VALUE ary)
3044 do *p2-- = *p1++;
while (--len > 0);
3051 rotate_count(
long cnt,
long len)
3053 return (cnt < 0) ? (len - (~cnt % len) - 1) : (cnt % len);
3057 ary_rotate_ptr(
VALUE *ptr,
long len,
long cnt)
3061 memmove(ptr, ptr + 1,
sizeof(
VALUE)*(len - 1));
3062 *(ptr + len - 1) = tmp;
3064 else if (cnt == len - 1) {
3065 VALUE tmp = *(ptr + len - 1);
3066 memmove(ptr + 1, ptr,
sizeof(
VALUE)*(len - 1));
3071 if (cnt < len) ary_reverse(ptr + cnt, ptr + len);
3072 if (--cnt > 0) ary_reverse(ptr, ptr + cnt);
3073 if (len > 0) ary_reverse(ptr, ptr + len);
3084 if (len > 1 && (cnt = rotate_count(cnt, len)) > 0) {
3132 rb_ary_rotate_bang(
int argc,
VALUE *argv,
VALUE ary)
3182 rb_ary_rotate_m(
int argc,
VALUE *argv,
VALUE ary)
3192 cnt = rotate_count(cnt, len);
3195 ary_memcpy(rotated, 0, len, ptr + cnt);
3196 ary_memcpy(rotated, len, cnt, ptr);
3209 sort_reentered(
VALUE ary)
3211 if (
RBASIC(ary)->klass) {
3223 sort_reentered(data->ary);
3227 sort_1(
const void *ap,
const void *bp,
void *dummy)
3230 VALUE retval = sort_reentered(data->ary);
3239 sort_returned(data);
3244 sort_2(
const void *ap,
const void *bp,
void *dummy)
3247 VALUE retval = sort_reentered(data->ary);
3251 if (
FIXNUM_P(a) &&
FIXNUM_P(b) && CMP_OPTIMIZABLE(data->cmp_opt, Integer)) {
3252 if ((
long)a > (long)b)
return 1;
3253 if ((
long)a < (long)b)
return -1;
3256 if (STRING_P(a) && STRING_P(b) && CMP_OPTIMIZABLE(data->cmp_opt, String)) {
3260 return rb_float_cmp(a, b);
3265 sort_returned(data);
3310 assert(!ARY_SHARED_P(ary));
3312 VALUE tmp = ary_make_substitution(ary);
3315 RBASIC_CLEAR_CLASS(tmp);
3317 data.receiver = ary;
3318 data.cmp_opt.opt_methods = 0;
3319 data.cmp_opt.opt_inited = 0;
3325 if (ARY_EMBED_P(tmp)) {
3326 if (ARY_SHARED_P(ary)) {
3327 rb_ary_unshare(ary);
3330 ary_memcpy(ary, 0, ARY_EMBED_LEN(tmp), ARY_EMBED_PTR(tmp));
3331 ARY_SET_LEN(ary, ARY_EMBED_LEN(tmp));
3334 if (!ARY_EMBED_P(ary) && ARY_HEAP_PTR(ary) == ARY_HEAP_PTR(tmp)) {
3335 FL_UNSET_SHARED(ary);
3339 assert(!ARY_SHARED_P(tmp));
3340 if (ARY_EMBED_P(ary)) {
3341 FL_UNSET_EMBED(ary);
3343 else if (ARY_SHARED_P(ary)) {
3345 rb_ary_unshare(ary);
3350 ARY_SET_PTR(ary, ARY_HEAP_PTR(tmp));
3351 ARY_SET_HEAP_LEN(ary, len);
3352 ARY_SET_CAPA(ary, ARY_HEAP_LEN(tmp));
3357 ARY_SET_EMBED_LEN(tmp, 0);
3413 static VALUE rb_ary_bsearch_index(
VALUE ary);
3426 rb_ary_bsearch(
VALUE ary)
3428 VALUE index_result = rb_ary_bsearch_index(ary);
3433 return index_result;
3446 rb_ary_bsearch_index(
VALUE ary)
3449 int smaller = 0, satisfied = 0;
3453 while (low < high) {
3454 mid = low + ((high - low) / 2);
3461 else if (v ==
Qtrue) {
3465 else if (!
RTEST(v)) {
3472 case 1: smaller = 1;
break;
3473 case -1: smaller = 0;
3478 " (must be numeric, true, false or nil)",
3488 if (!satisfied)
return Qnil;
3524 rb_ary_sort_by_bang(
VALUE ary)
3556 rb_ary_collect(
VALUE ary)
3589 rb_ary_collect_bang(
VALUE ary)
3605 long beg, len, i, j;
3607 for (i=0; i<argc; i++) {
3614 long end = olen < beg+len ? olen : beg+len;
3615 for (j = beg; j < end; j++) {
3628 append_values_at_single(
VALUE result,
VALUE ary,
long olen,
VALUE idx)
3638 const long end = beg + len;
3641 rb_ary_cat(result, src + beg, end > olen ? olen-beg : len);
3692 rb_ary_values_at(
int argc,
VALUE *argv,
VALUE ary)
3696 for (i = 0; i < argc; ++i) {
3697 append_values_at_single(result, ary, olen, argv[i]);
3724 rb_ary_select(
VALUE ary)
3745 select_bang_i(
VALUE a)
3748 VALUE ary = arg->ary;
3751 for (i1 = i2 = 0; i1 <
RARRAY_LEN(ary); arg->len[0] = ++i1) {
3759 return (i1 == i2) ?
Qnil : ary;
3763 select_bang_ensure(
VALUE a)
3766 VALUE ary = arg->ary;
3768 long i1 = arg->len[0], i2 = arg->len[1];
3770 if (i2 < len && i2 < i1) {
3779 ARY_SET_LEN(ary, i2 + tail);
3806 rb_ary_select_bang(
VALUE ary)
3814 args.len[0] = args.len[1] = 0;
3834 rb_ary_keep_if(
VALUE ary)
3837 rb_ary_select_bang(ary);
3842 ary_resize_smaller(
VALUE ary,
long len)
3846 ARY_SET_LEN(ary, len);
3847 if (len * 2 < ARY_CAPA(ary) &&
3848 ARY_CAPA(ary) > ARY_DEFAULT_SIZE) {
3849 ary_resize_capa(ary, len * 2);
3892 for (i1 = i2 = 0; i1 <
RARRAY_LEN(ary); i1++) {
3911 ary_resize_smaller(ary, i2);
3922 for (i1 = i2 = 0; i1 <
RARRAY_LEN(ary); i1++) {
3937 ary_resize_smaller(ary, i2);
3946 if (pos >= len)
return Qnil;
3949 if (pos < 0)
return Qnil;
3957 ARY_INCREASE_LEN(ary, -1);
3990 ary_slice_bang_by_rb_ary_splice(
VALUE ary,
long pos,
long len)
3997 else if (pos < -orig_len) {
4003 else if (orig_len < pos) {
4006 if (orig_len < pos + len) {
4007 len = orig_len - pos;
4014 rb_ary_splice(ary, pos, len, 0, 0);
4081 rb_ary_slice_bang(
int argc,
VALUE *argv,
VALUE ary)
4086 rb_ary_modify_check(ary);
4093 return ary_slice_bang_by_rb_ary_splice(ary, pos, len);
4100 return ary_slice_bang_by_rb_ary_splice(ary, pos, len);
4129 reject_bang_i(
VALUE a)
4132 VALUE ary = arg->ary;
4135 for (i1 = i2 = 0; i1 <
RARRAY_LEN(ary); arg->len[0] = ++i1) {
4143 return (i1 == i2) ?
Qnil : ary;
4147 ary_reject_bang(
VALUE ary)
4150 rb_ary_modify_check(ary);
4152 args.len[0] = args.len[1] = 0;
4175 rb_ary_reject_bang(
VALUE ary)
4179 return ary_reject_bang(ary);
4199 rb_ary_reject(
VALUE ary)
4205 ary_reject(ary, rejected_ary);
4206 return rejected_ary;
4225 rb_ary_delete_if(
VALUE ary)
4229 ary_reject_bang(ary);
4244 take_items(
VALUE obj,
long n)
4249 if (n == 0)
return result;
4252 args[0] = result; args[1] = (
VALUE)n;
4253 if (rb_check_block_call(obj, idEach, 0, 0, take_i, (
VALUE)args) ==
Qundef)
4316 for (i=0; i<argc; i++) {
4317 argv[i] = take_items(argv[i], len);
4321 int arity = rb_block_arity();
4330 for (j=0; j<argc; j++) {
4331 tmp[j+1] = rb_ary_elt(argv[j], i);
4343 for (j=0; j<argc; j++) {
4353 for (i=0; i<len; i++) {
4357 for (j=0; j<argc; j++) {
4378 rb_ary_transpose(
VALUE ary)
4380 long elen = -1, alen, i, j;
4381 VALUE tmp, result = 0;
4385 for (i=0; i<alen; i++) {
4386 tmp = to_ary(rb_ary_elt(ary, i));
4390 for (j=0; j<elen; j++) {
4398 for (j=0; j<elen; j++) {
4399 rb_ary_store(rb_ary_elt(result, j), i, rb_ary_elt(tmp, j));
4417 rb_ary_modify_check(copy);
4418 orig = to_ary(orig);
4419 if (copy == orig)
return copy;
4422 VALUE shared_root = 0;
4424 if (ARY_OWNS_HEAP_P(copy)) {
4425 ary_heap_free(copy);
4427 else if (ARY_SHARED_P(copy)) {
4428 shared_root = ARY_SHARED_ROOT(copy);
4429 FL_UNSET_SHARED(copy);
4434 rb_ary_decrement_share(shared_root);
4439 VALUE shared_root = ary_make_shared(orig);
4440 if (ARY_OWNS_HEAP_P(copy)) {
4441 ary_heap_free(copy);
4444 rb_ary_unshare_safe(copy);
4446 FL_UNSET_EMBED(copy);
4447 ARY_SET_PTR(copy, ARY_HEAP_PTR(orig));
4448 ARY_SET_LEN(copy, ARY_HEAP_LEN(orig));
4449 rb_ary_set_shared(copy, shared_root);
4467 rb_ary_modify_check(ary);
4468 if (ARY_SHARED_P(ary)) {
4469 if (!ARY_EMBED_P(ary)) {
4470 rb_ary_unshare(ary);
4472 ARY_SET_EMBED_LEN(ary, 0);
4476 ARY_SET_LEN(ary, 0);
4477 if (ARY_DEFAULT_SIZE * 2 < ARY_CAPA(ary)) {
4478 ary_resize_capa(ary, ARY_DEFAULT_SIZE * 2);
4655 rb_ary_fill(
int argc,
VALUE *argv,
VALUE ary)
4658 long beg = 0, end = 0, len = 0;
4681 if (beg < 0) beg = 0;
4690 if (beg >= ARY_MAX_SIZE || len > ARY_MAX_SIZE - beg) {
4695 if (end >= ARY_CAPA(ary)) {
4696 ary_resize_capa(ary, end);
4699 ARY_SET_LEN(ary, end);
4706 for (i=beg; i<end; i++) {
4713 ary_memfill(ary, beg, len, item);
4734 long len, xlen, ylen;
4744 ARY_SET_LEN(z, len);
4769 rb_ary_concat_multi(
int argc,
VALUE *argv,
VALUE ary)
4771 rb_ary_modify_check(ary);
4776 else if (argc > 1) {
4779 for (i = 0; i < argc; i++) {
4782 ary_append(ary, args);
4792 return ary_append(x, to_ary(y));
4836 ARY_SET_LEN(ary2, len);
4841 ary_memcpy(ary2, 0, t, ptr);
4842 while (t <= len/2) {
4914 recursive_equal(
VALUE ary1,
VALUE ary2,
int recur)
4917 const VALUE *p1, *p2;
4919 if (recur)
return Qtrue;
4926 for (i = 0; i < len1; i++) {
4967 if (ary1 == ary2)
return Qtrue;
4980 recursive_eql(
VALUE ary1,
VALUE ary2,
int recur)
4984 if (recur)
return Qtrue;
4986 if (!
rb_eql(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i)))
5011 if (ary1 == ary2)
return Qtrue;
5030 rb_ary_hash(
VALUE ary)
5072 rb_ary_includes_by_eql(
VALUE ary,
VALUE item)
5087 recursive_cmp(
VALUE ary1,
VALUE ary2,
int recur)
5091 if (recur)
return Qundef;
5096 for (i=0; i<len; i++) {
5097 VALUE e1 = rb_ary_elt(ary1, i), e2 = rb_ary_elt(ary2, i);
5136 if (ary1 == ary2)
return INT2FIX(0);
5138 if (v !=
Qundef)
return v;
5140 if (len == 0)
return INT2FIX(0);
5141 if (len > 0)
return INT2FIX(1);
5152 rb_hash_add_new_element(hash, elt, elt);
5158 ary_tmp_hash_new(
VALUE ary)
5161 VALUE hash = rb_hash_new_with_size(size);
5163 RBASIC_CLEAR_CLASS(hash);
5168 ary_make_hash(
VALUE ary)
5170 VALUE hash = ary_tmp_hash_new(ary);
5171 return ary_add_hash(hash, ary);
5181 rb_hash_add_new_element(hash, k, v);
5187 ary_make_hash_by(
VALUE ary)
5189 VALUE hash = ary_tmp_hash_new(ary);
5190 return ary_add_hash_by(hash, ary);
5194 ary_recycle_hash(
VALUE hash)
5197 if (RHASH_ST_TABLE_P(hash)) {
5198 st_table *tbl = RHASH_ST_TABLE(hash);
5200 RHASH_ST_CLEAR(hash);
5226 ary2 = to_ary(ary2);
5227 if (
RARRAY_LEN(ary2) == 0) {
return ary_make_shared_copy(ary1); }
5232 VALUE elt = rb_ary_elt(ary1, i);
5233 if (rb_ary_includes_by_eql(ary2, elt))
continue;
5239 hash = ary_make_hash(ary2);
5241 if (rb_hash_stlike_lookup(hash,
RARRAY_AREF(ary1, i), NULL))
continue;
5244 ary_recycle_hash(hash);
5265 rb_ary_difference_multi(
int argc,
VALUE *argv,
VALUE ary)
5270 bool *is_hash =
ALLOCV_N(
bool, t0, argc);
5274 for (i = 0; i < argc; i++) {
5275 argv[i] = to_ary(argv[i]);
5276 is_hash[i] = (length > SMALL_ARRAY_LEN &&
RARRAY_LEN(argv[i]) > SMALL_ARRAY_LEN);
5277 if (is_hash[i]) argv[i] = ary_make_hash(argv[i]);
5282 VALUE elt = rb_ary_elt(ary, i);
5283 for (j = 0; j < argc; j++) {
5285 if (rb_hash_stlike_lookup(argv[j],
RARRAY_AREF(ary, i), NULL))
5289 if (rb_ary_includes_by_eql(argv[j], elt))
break;
5320 VALUE hash, ary3, v;
5324 ary2 = to_ary(ary2);
5331 if (!rb_ary_includes_by_eql(ary2, v))
continue;
5332 if (rb_ary_includes_by_eql(ary3, v))
continue;
5338 hash = ary_make_hash(ary2);
5343 if (rb_hash_stlike_delete(hash, &vv, 0)) {
5347 ary_recycle_hash(hash);
5371 rb_ary_intersection_multi(
int argc,
VALUE *argv,
VALUE ary)
5376 for (i = 0; i < argc; i++) {
5377 result = rb_ary_and(result, argv[i]);
5384 ary_hash_orset(st_data_t *key, st_data_t *value, st_data_t arg,
int existing)
5386 if (existing)
return ST_STOP;
5387 *key = *value = (
VALUE)arg;
5396 VALUE elt = rb_ary_elt(ary, i);
5397 if (rb_ary_includes_by_eql(ary_union, elt))
continue;
5408 if (!rb_hash_stlike_update(hash, (st_data_t)elt, ary_hash_orset, (st_data_t)elt)) {
5433 ary2 = to_ary(ary2);
5436 rb_ary_union(ary3, ary1);
5437 rb_ary_union(ary3, ary2);
5441 hash = ary_make_hash(ary1);
5442 rb_ary_union_hash(hash, ary2);
5444 ary3 = rb_hash_values(hash);
5445 ary_recycle_hash(hash);
5465 rb_ary_union_multi(
int argc,
VALUE *argv,
VALUE ary)
5469 VALUE hash, ary_union;
5472 for (i = 0; i < argc; i++) {
5473 argv[i] = to_ary(argv[i]);
5477 if (sum <= SMALL_ARRAY_LEN) {
5480 rb_ary_union(ary_union, ary);
5481 for (i = 0; i < argc; i++) rb_ary_union(ary_union, argv[i]);
5486 hash = ary_make_hash(ary);
5487 for (i = 0; i < argc; i++) rb_ary_union_hash(hash, argv[i]);
5489 ary_union = rb_hash_values(hash);
5490 ary_recycle_hash(hash);
5511 VALUE hash, v, result, shorter, longer;
5515 ary2 = to_ary(ary2);
5521 if (rb_ary_includes_by_eql(ary2, v))
return Qtrue;
5533 hash = ary_make_hash(shorter);
5539 if (rb_hash_stlike_lookup(hash, vv, 0)) {
5544 ary_recycle_hash(hash);
5550 ary_max_generic(
VALUE ary,
long i,
VALUE vmax)
5567 ary_max_opt_fixnum(
VALUE ary,
long i,
VALUE vmax)
5574 for (; i < n; ++i) {
5578 if ((
long)vmax < (
long)v) {
5583 return ary_max_generic(ary, i, vmax);
5591 ary_max_opt_float(
VALUE ary,
long i,
VALUE vmax)
5598 for (; i < n; ++i) {
5602 if (rb_float_cmp(vmax, v) < 0) {
5607 return ary_max_generic(ary, i, vmax);
5615 ary_max_opt_string(
VALUE ary,
long i,
VALUE vmax)
5622 for (; i < n; ++i) {
5631 return ary_max_generic(ary, i, vmax);
5680 return rb_nmin_run(ary, num, 0, 1, 1);
5694 if (
FIXNUM_P(result) && CMP_OPTIMIZABLE(cmp_opt, Integer)) {
5695 return ary_max_opt_fixnum(ary, 1, result);
5697 else if (STRING_P(result) && CMP_OPTIMIZABLE(cmp_opt, String)) {
5698 return ary_max_opt_string(ary, 1, result);
5700 else if (
RB_FLOAT_TYPE_P(result) && CMP_OPTIMIZABLE(cmp_opt, Float)) {
5701 return ary_max_opt_float(ary, 1, result);
5704 return ary_max_generic(ary, 1, result);
5713 ary_min_generic(
VALUE ary,
long i,
VALUE vmin)
5730 ary_min_opt_fixnum(
VALUE ary,
long i,
VALUE vmin)
5737 for (; i < n; ++i) {
5741 if ((
long)vmin > (
long)a) {
5746 return ary_min_generic(ary, i, vmin);
5754 ary_min_opt_float(
VALUE ary,
long i,
VALUE vmin)
5761 for (; i < n; ++i) {
5765 if (rb_float_cmp(vmin, a) > 0) {
5770 return ary_min_generic(ary, i, vmin);
5778 ary_min_opt_string(
VALUE ary,
long i,
VALUE vmin)
5785 for (; i < n; ++i) {
5794 return ary_min_generic(ary, i, vmin);
5843 return rb_nmin_run(ary, num, 0, 0, 1);
5857 if (
FIXNUM_P(result) && CMP_OPTIMIZABLE(cmp_opt, Integer)) {
5858 return ary_min_opt_fixnum(ary, 1, result);
5860 else if (STRING_P(result) && CMP_OPTIMIZABLE(cmp_opt, String)) {
5861 return ary_min_opt_string(ary, 1, result);
5863 else if (
RB_FLOAT_TYPE_P(result) && CMP_OPTIMIZABLE(cmp_opt, Float)) {
5864 return ary_min_opt_float(ary, 1, result);
5867 return ary_min_generic(ary, 1, result);
5896 rb_ary_minmax(
VALUE ary)
5901 return rb_assoc_new(rb_ary_min(0, 0, ary), rb_ary_max(0, 0, ary));
5905 push_value(st_data_t key, st_data_t val, st_data_t ary)
5939 rb_ary_uniq_bang(
VALUE ary)
5944 rb_ary_modify_check(ary);
5948 hash = ary_make_hash_by(ary);
5950 hash = ary_make_hash(ary);
5956 rb_ary_modify_check(ary);
5957 ARY_SET_LEN(ary, 0);
5958 if (ARY_SHARED_P(ary) && !ARY_EMBED_P(ary)) {
5959 rb_ary_unshare(ary);
5962 ary_resize_capa(ary, hash_size);
5964 ary_recycle_hash(hash);
5990 rb_ary_uniq(
VALUE ary)
5999 hash = ary_make_hash_by(ary);
6000 uniq = rb_hash_values(hash);
6003 hash = ary_make_hash(ary);
6004 uniq = rb_hash_values(hash);
6007 ary_recycle_hash(hash);
6023 rb_ary_compact_bang(
VALUE ary)
6040 ary_resize_smaller(ary, n);
6055 rb_ary_compact(
VALUE ary)
6058 rb_ary_compact_bang(ary);
6087 rb_ary_count(
int argc,
VALUE *argv,
VALUE ary)
6103 VALUE obj = argv[0];
6106 rb_warn(
"given block not used");
6117 flatten(
VALUE ary,
int level)
6120 VALUE stack, result, tmp = 0, elt, vmemo;
6137 ARY_SET_LEN(result, i);
6139 stack = ary_new(0, ARY_DEFAULT_SIZE);
6145 RBASIC_CLEAR_CLASS(vmemo);
6146 memo = st_init_numtable();
6147 rb_hash_st_table_set(vmemo, memo);
6148 st_insert(memo, (st_data_t)ary, (st_data_t)
Qtrue);
6149 st_insert(memo, (st_data_t)tmp, (st_data_t)
Qtrue);
6158 if (level >= 0 &&
RARRAY_LEN(stack) / 2 >= level) {
6163 if (
RBASIC(result)->klass) {
6175 id = (st_data_t)tmp;
6176 if (st_is_member(memo,
id)) {
6180 st_insert(memo,
id, (st_data_t)
Qtrue);
6192 id = (st_data_t)ary;
6193 st_delete(memo, &
id, 0);
6237 rb_ary_flatten_bang(
int argc,
VALUE *argv,
VALUE ary)
6239 int mod = 0, level = -1;
6243 rb_ary_modify_check(ary);
6245 if (level == 0)
return Qnil;
6247 result = flatten(ary, level);
6248 if (result == ary) {
6253 if (mod) ARY_SET_EMBED_LEN(result, 0);
6289 rb_ary_flatten(
int argc,
VALUE *argv,
VALUE ary)
6296 if (level == 0)
return ary_make_shared_copy(ary);
6299 result = flatten(ary, level);
6300 if (result == ary) {
6301 result = ary_make_shared_copy(ary);
6307 #define RAND_UPTO(max) (long)rb_random_ulong_limited((randgen), (max)-1)
6318 long j = RAND_UPTO(i);
6335 rb_ary_shuffle_bang(ec, ary, randgen);
6343 long n, len, i, j, k, idx[10];
6344 long rnds[numberof(idx)];
6345 long memo_threshold;
6354 return rb_ary_elt(ary, i);
6358 if (n > len) n = len;
6359 if (n <= numberof(idx)) {
6360 for (i = 0; i < n; ++i) {
6361 rnds[i] = RAND_UPTO(len - i);
6366 if (len < k && n <= numberof(idx)) {
6367 for (i = 0; i < n; ++i) {
6371 if (n > len) n = len;
6389 if (j >= i) l = i, g = ++j;
6390 if (k >= l && (++k >= g)) ++k;
6395 len < 2560 ? len / 128 :
6396 len < 5120 ? len / 64 :
6397 len < 10240 ? len / 32 :
6399 if (n <= numberof(idx)) {
6400 long sorted[numberof(idx)];
6401 sorted[0] = idx[0] = rnds[0];
6402 for (i=1; i<n; i++) {
6404 for (j = 0; j < i; ++j) {
6405 if (k < sorted[j])
break;
6408 memmove(&sorted[j+1], &sorted[j],
sizeof(sorted[0])*(i-j));
6409 sorted[j] = idx[i] = k;
6413 for (i=0; i<n; i++) {
6418 else if (n <= memo_threshold / 2) {
6420 #undef RUBY_UNTYPED_DATA_WARNING
6421 #define RUBY_UNTYPED_DATA_WARNING 0
6423 st_table *memo = st_init_numtable_with_size(n);
6427 for (i=0; i<n; i++) {
6428 long r = RAND_UPTO(len-i) + i;
6430 if (r > max_idx) max_idx = r;
6433 if (len <= max_idx) n = 0;
6434 else if (n > len) n = len;
6436 for (i=0; i<n; i++) {
6437 long j2 = j = ptr_result[i];
6440 if (st_lookup(memo, (st_data_t)i, &value)) i2 = (
long)value;
6441 if (st_lookup(memo, (st_data_t)j, &value)) j2 = (
long)value;
6442 st_insert(memo, (st_data_t)j, (st_data_t)i2);
6443 ptr_result[i] = ptr_ary[j2];
6448 st_free_table(memo);
6452 RBASIC_CLEAR_CLASS(result);
6455 for (i=0; i<n; i++) {
6456 j = RAND_UPTO(len-i) + i;
6458 ptr_result[j] = ptr_result[i];
6462 RBASIC_SET_CLASS_RAW(result,
rb_cArray);
6464 ARY_SET_LEN(result, n);
6486 if (mul <= 0)
return INT2FIX(0);
6488 return rb_fix_mul_fix(rb_ary_length(
self), n);
6521 rb_ary_cycle(
int argc,
VALUE *argv,
VALUE ary)
6528 if (argc == 0 ||
NIL_P(argv[0])) {
6533 if (n <= 0)
return Qnil;
6536 while (
RARRAY_LEN(ary) > 0 && (n < 0 || 0 < n--)) {
6544 #define tmpary(n) rb_ary_tmp_new(n)
6545 #define tmpary_discard(a) (ary_discard(a), RBASIC_SET_CLASS_RAW(a, rb_cArray))
6553 yield_indexed_values(
const VALUE values,
const long r,
const long *
const p)
6558 for (i = 0; i < r; i++) ARY_SET(result, i,
RARRAY_AREF(values, p[i]));
6559 ARY_SET_LEN(result, r);
6561 return !
RBASIC(values)->klass;
6577 permute0(
const long n,
const long r,
long *
const p,
char *
const used,
const VALUE values)
6579 long i = 0, index = 0;
6582 const char *
const unused = memchr(&used[i], 0, n-i);
6597 for (i = 0; i < n; ++i) {
6598 if (used[i])
continue;
6600 if (!yield_indexed_values(values, r, p)) {
6616 descending_factorial(
long from,
long how_many)
6621 while (--how_many > 0) {
6623 cnt = rb_int_mul(cnt,
LONG2FIX(v));
6633 binomial_coefficient(
long comb,
long size)
6637 if (comb > size-comb) {
6643 else if (comb == 0) {
6647 for (i = 1; i < comb; ++i) {
6648 r = rb_int_mul(r,
LONG2FIX(size - i));
6649 r = rb_int_idiv(r,
LONG2FIX(i + 1));
6660 return descending_factorial(n, k);
6728 rb_ary_permutation(
int argc,
VALUE *argv,
VALUE ary)
6738 if (r < 0 || n < r) {
6751 long *p =
ALLOCV_N(
long, t0, r+roomof(n,
sizeof(
long)));
6752 char *used = (
char*)(p + r);
6753 VALUE ary0 = ary_make_shared_copy(ary);
6754 RBASIC_CLEAR_CLASS(ary0);
6758 permute0(n, r, p, used, ary0);
6766 combinate0(
const long len,
const long n,
long *
const stack,
const VALUE values)
6773 for (lev++; lev < n; lev++) {
6774 stack[lev+1] = stack[lev]+1;
6776 if (!yield_indexed_values(values, n, stack+1)) {
6780 if (lev == 0)
return;
6782 }
while (stack[lev+1]+n == len+lev+1);
6792 return binomial_coefficient(k, n);
6845 if (n < 0 || len < n) {
6857 VALUE ary0 = ary_make_shared_copy(ary);
6859 long *stack =
ALLOCV_N(
long, t0, n+1);
6861 RBASIC_CLEAR_CLASS(ary0);
6862 combinate0(len, n, stack, ary0);
6882 rpermute0(
const long n,
const long r,
long *
const p,
const VALUE values)
6884 long i = 0, index = 0;
6888 if (++index < r-1) {
6892 for (i = 0; i < n; ++i) {
6894 if (!yield_indexed_values(values, r, p)) {
6899 if (index <= 0)
return;
6900 }
while ((i = ++p[--index]) >= n);
6975 rb_ary_repeated_permutation(
VALUE ary,
VALUE num)
6997 VALUE ary0 = ary_make_shared_copy(ary);
6998 RBASIC_CLEAR_CLASS(ary0);
7000 rpermute0(n, r, p, ary0);
7008 rcombinate0(
const long n,
const long r,
long *
const p,
const long rest,
const VALUE values)
7010 long i = 0, index = 0;
7014 if (++index < r-1) {
7018 for (; i < n; ++i) {
7020 if (!yield_indexed_values(values, r, p)) {
7025 if (index <= 0)
return;
7026 }
while ((i = ++p[--index]) >= n);
7038 return binomial_coefficient(k, n + k - 1);
7095 rb_ary_repeated_combination(
VALUE ary,
VALUE num)
7113 else if (len == 0) {
7119 VALUE ary0 = ary_make_shared_copy(ary);
7120 RBASIC_CLEAR_CLASS(ary0);
7122 rcombinate0(len, n, p, n, ary0);
7179 rb_ary_product(
int argc,
VALUE *argv,
VALUE ary)
7182 volatile VALUE t0 = tmpary(n);
7185 int *counters =
ALLOCV_N(
int, t1, n);
7190 RBASIC_CLEAR_CLASS(t0);
7195 for (i = 1; i < n; i++) arrays[i] =
Qnil;
7196 for (i = 1; i < n; i++) arrays[i] = to_ary(argv[i-1]);
7199 for (i = 0; i < n; i++) counters[i] = 0;
7204 for (i = 0; i < n; i++) {
7206 arrays[i] = ary_make_shared_copy(arrays[i]);
7211 for (i = 0; i < n; i++) {
7217 if (MUL_OVERFLOW_LONG_P(resultlen, k))
7227 for (j = 0; j < n; j++) {
7232 if (
NIL_P(result)) {
7252 while (counters[m] ==
RARRAY_LEN(arrays[m])) {
7255 if (--m < 0)
goto done;
7263 return NIL_P(result) ? ary : result;
7313 rb_ary_take_while(
VALUE ary)
7321 return rb_ary_take(ary,
LONG2FIX(i));
7372 rb_ary_drop_while(
VALUE ary)
7380 return rb_ary_drop(ary,
LONG2FIX(i));
7414 rb_ary_any_p(
int argc,
VALUE *argv,
VALUE ary)
7422 rb_warn(
"given block not used");
7429 for (i = 0; i < len; ++i) {
7471 rb_ary_all_p(
int argc,
VALUE *argv,
VALUE ary)
7476 if (!len)
return Qtrue;
7479 rb_warn(
"given block not used");
7486 for (i = 0; i < len; ++i) {
7528 rb_ary_none_p(
int argc,
VALUE *argv,
VALUE ary)
7533 if (!len)
return Qtrue;
7536 rb_warn(
"given block not used");
7543 for (i = 0; i < len; ++i) {
7589 rb_ary_one_p(
int argc,
VALUE *argv,
VALUE ary)
7598 rb_warn(
"given block not used");
7602 if (result)
return Qfalse;
7608 for (i = 0; i < len; ++i) {
7610 if (result)
return Qfalse;
7618 if (result)
return Qfalse;
7644 rb_ary_dig(
int argc,
VALUE *argv,
VALUE self)
7647 self = rb_ary_at(
self, *argv);
7648 if (!--argc)
return self;
7650 return rb_obj_dig(argc, argv,
self,
Qnil);
7654 finish_exact_sum(
long n,
VALUE r,
VALUE v,
int z)
7659 v = rb_rational_plus(r, v);
7727 else if (RB_BIGNUM_TYPE_P(e))
7733 r = rb_rational_plus(r, e);
7738 v = finish_exact_sum(n, r, v, argc!=0);
7742 v = finish_exact_sum(n, r, v, i!=0);
7754 goto has_float_value;
7764 else if (RB_BIGNUM_TYPE_P(e))
7771 if (isnan(f))
continue;
7777 if (isinf(f) && signbit(x) != signbit(f))
7783 if (isinf(f))
continue;
7786 if (fabs(f) >= fabs(x))
7799 goto has_some_value;
7811 rb_ary_deconstruct(
VALUE ary)
8388 #include "array.rbinc"
#define RUBY_ASSERT(expr)
Asserts that the given expression is truthy if and only if RUBY_DEBUG is truthy.
#define RUBY_ASSERT_ALWAYS(expr)
A variant of RUBY_ASSERT that does not interface with RUBY_DEBUG.
#define rb_define_singleton_method(klass, mid, func, arity)
Defines klass.mid.
void rb_include_module(VALUE klass, VALUE module)
Includes a module to a class.
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Retrieves argument from argc and argv to given VALUE references according to the format string.
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a method.
int rb_block_given_p(void)
Determines if the current method is given a block.
#define NEWOBJ_OF
Old name of RB_NEWOBJ_OF.
#define FL_UNSET_RAW
Old name of RB_FL_UNSET_RAW.
#define RFLOAT_VALUE
Old name of rb_float_value.
#define T_STRING
Old name of RUBY_T_STRING.
#define Qundef
Old name of RUBY_Qundef.
#define INT2FIX
Old name of RB_INT2FIX.
#define OBJ_FROZEN
Old name of RB_OBJ_FROZEN.
#define rb_str_buf_new2
Old name of rb_str_buf_new_cstr.
#define OBJ_FREEZE
Old name of RB_OBJ_FREEZE.
#define ELTS_SHARED
Old name of RUBY_ELTS_SHARED.
#define rb_ary_new4
Old name of rb_ary_new_from_values.
#define FIXABLE
Old name of RB_FIXABLE.
#define LONG2FIX
Old name of RB_INT2FIX.
#define T_RATIONAL
Old name of RUBY_T_RATIONAL.
#define ALLOC_N
Old name of RB_ALLOC_N.
#define NUM2DBL
Old name of rb_num2dbl.
#define FL_SET
Old name of RB_FL_SET.
#define rb_ary_new3
Old name of rb_ary_new_from_args.
#define LONG2NUM
Old name of RB_LONG2NUM.
#define rb_usascii_str_new2
Old name of rb_usascii_str_new_cstr.
#define Qtrue
Old name of RUBY_Qtrue.
#define ST2FIX
Old name of RB_ST2FIX.
#define NUM2INT
Old name of RB_NUM2INT.
#define Qnil
Old name of RUBY_Qnil.
#define Qfalse
Old name of RUBY_Qfalse.
#define FIX2LONG
Old name of RB_FIX2LONG.
#define T_ARRAY
Old name of RUBY_T_ARRAY.
#define NIL_P
Old name of RB_NIL_P.
#define ALLOCV_N
Old name of RB_ALLOCV_N.
#define FL_WB_PROTECTED
Old name of RUBY_FL_WB_PROTECTED.
#define DBL2NUM
Old name of rb_float_new.
#define FL_TEST
Old name of RB_FL_TEST.
#define FL_FREEZE
Old name of RUBY_FL_FREEZE.
#define NUM2LONG
Old name of RB_NUM2LONG.
#define FL_UNSET
Old name of RB_FL_UNSET.
#define FL_USER5
Old name of RUBY_FL_USER5.
#define FIXNUM_P
Old name of RB_FIXNUM_P.
#define rb_ary_new2
Old name of rb_ary_new_capa.
#define FL_SET_RAW
Old name of RB_FL_SET_RAW.
#define ALLOCV_END
Old name of RB_ALLOCV_END.
void rb_category_warn(rb_warning_category_t category, const char *fmt,...)
Identical to rb_category_warning(), except it reports always regardless of runtime -W flag.
void rb_raise(VALUE exc, const char *fmt,...)
Exception entry point.
void rb_bug(const char *fmt,...)
Interpreter panic switch.
void rb_iter_break(void)
Breaks from a block.
VALUE rb_eFrozenError
FrozenError exception.
VALUE rb_eRangeError
RangeError exception.
VALUE rb_eTypeError
TypeError exception.
VALUE rb_eRuntimeError
RuntimeError exception.
void rb_warn(const char *fmt,...)
Identical to rb_warning(), except it reports always regardless of runtime -W flag.
VALUE rb_eArgError
ArgumentError exception.
VALUE rb_eIndexError
IndexError exception.
VALUE rb_ensure(VALUE(*b_proc)(VALUE), VALUE data1, VALUE(*e_proc)(VALUE), VALUE data2)
An equivalent to ensure clause.
void rb_warning(const char *fmt,...)
Issues a warning.
@ RB_WARN_CATEGORY_DEPRECATED
Warning is for deprecated features.
VALUE rb_cArray
Array class.
VALUE rb_mEnumerable
Enumerable module.
VALUE rb_obj_frozen_p(VALUE obj)
Just calls RB_OBJ_FROZEN() inside.
int rb_eql(VALUE lhs, VALUE rhs)
Checks for equality of the passed objects, in terms of Object#eql?.
VALUE rb_cNumeric
Numeric class.
VALUE rb_cRandom
Random class.
VALUE rb_obj_class(VALUE obj)
Queries the class of an object.
VALUE rb_inspect(VALUE obj)
Generates a human-readable textual representation of the given object.
double rb_num2dbl(VALUE num)
Converts an instance of rb_cNumeric into C's double.
VALUE rb_equal(VALUE lhs, VALUE rhs)
This function is an optimised version of calling #==.
VALUE rb_obj_is_kind_of(VALUE obj, VALUE klass)
Queries if the given object is an instance (of possibly descendants) of the given class.
VALUE rb_obj_freeze(VALUE obj)
Just calls rb_obj_freeze_inline() inside.
#define RB_OBJ_WRITTEN(old, oldv, young)
Identical to RB_OBJ_WRITE(), except it doesn't write any values, but only a WB declaration.
#define RB_OBJ_WRITE(old, slot, young)
Declaration of a "back" pointer.
VALUE rb_enc_associate(VALUE obj, rb_encoding *enc)
Identical to rb_enc_associate(), except it takes an encoding itself instead of its index.
rb_encoding * rb_usascii_encoding(void)
Queries the encoding that represents US-ASCII.
void rb_enc_copy(VALUE dst, VALUE src)
Destructively copies the encoding of the latter object to that of former one.
VALUE rb_funcall(VALUE recv, ID mid, int n,...)
Calls a method.
VALUE rb_funcallv(VALUE recv, ID mid, int argc, const VALUE *argv)
Identical to rb_funcall(), except it takes the method arguments as a C array.
VALUE rb_call_super(int argc, const VALUE *argv)
This resembles ruby's super.
Defines RBIMPL_HAS_BUILTIN.
VALUE rb_ary_rotate(VALUE ary, long rot)
Destructively rotates the passed array in-place to towards its end.
VALUE rb_ary_new_from_values(long n, const VALUE *elts)
Identical to rb_ary_new_from_args(), except how objects are passed.
VALUE rb_ary_cmp(VALUE lhs, VALUE rhs)
Recursively compares each elements of the two arrays one-by-one using <=>.
VALUE rb_ary_rassoc(VALUE alist, VALUE key)
Identical to rb_ary_assoc(), except it scans the passed array from the opposite direction.
VALUE rb_ary_concat(VALUE lhs, VALUE rhs)
Destructively appends the contents of latter into the end of former.
VALUE rb_ary_assoc(VALUE alist, VALUE key)
Looks up the passed key, assuming the passed array is an alist.
VALUE rb_ary_reverse(VALUE ary)
Destructively reverses the passed array in-place.
VALUE rb_ary_shared_with_p(VALUE lhs, VALUE rhs)
Queries if the passed two arrays share the same backend storage.
VALUE rb_ary_shift(VALUE ary)
Destructively deletes an element from the beginning of the passed array and returns what was deleted.
VALUE rb_ary_sort(VALUE ary)
Creates a copy of the passed array, whose elements are sorted according to their <=> result.
VALUE rb_ary_resurrect(VALUE ary)
I guess there is no use case of this function in extension libraries, but this is a routine identical...
VALUE rb_ary_dup(VALUE ary)
Duplicates an array.
VALUE rb_ary_includes(VALUE ary, VALUE elem)
Queries if the passed array has the passed entry.
VALUE rb_ary_aref(int argc, const VALUE *argv, VALUE ary)
Queries element(s) of an array.
VALUE rb_get_values_at(VALUE obj, long olen, int argc, const VALUE *argv, VALUE(*func)(VALUE obj, long oidx))
This was a generalisation of Array#values_at, Struct#values_at, and MatchData#values_at.
void rb_ary_free(VALUE ary)
Destroys the given array for no reason.
VALUE rb_ary_each(VALUE ary)
Iteratively yields each element of the passed array to the implicitly passed block if any.
VALUE rb_ary_delete_at(VALUE ary, long pos)
Destructively removes an element which resides at the specific index of the passed array.
VALUE rb_ary_unshift(VALUE ary, VALUE elem)
Destructively prepends the passed item at the beginning of the passed array.
VALUE rb_ary_plus(VALUE lhs, VALUE rhs)
Creates a new array, concatenating the former to the latter.
VALUE rb_ary_cat(VALUE ary, const VALUE *train, long len)
Destructively appends multiple elements at the end of the array.
void rb_ary_modify(VALUE ary)
Declares that the array is about to be modified.
VALUE rb_ary_replace(VALUE copy, VALUE orig)
Replaces the contents of the former object with the contents of the latter.
VALUE rb_check_array_type(VALUE obj)
Try converting an object to its array representation using its to_ary method, if any.
VALUE rb_ary_to_ary(VALUE obj)
Force converts an object to an array.
VALUE rb_ary_new(void)
Allocates a new, empty array.
VALUE rb_ary_new_capa(long capa)
Identical to rb_ary_new(), except it additionally specifies how many rooms of objects it should alloc...
VALUE rb_ary_resize(VALUE ary, long len)
Expands or shrinks the passed array to the passed length.
VALUE rb_ary_pop(VALUE ary)
Destructively deletes an element from the end of the passed array and returns what was deleted.
VALUE rb_ary_tmp_new(long capa)
Allocates a "temporary" array.
VALUE rb_ary_clear(VALUE ary)
Destructively removes everything form an array.
VALUE rb_ary_subseq(VALUE ary, long beg, long len)
Obtains a part of the passed array.
VALUE rb_ary_push(VALUE ary, VALUE elem)
Special case of rb_ary_cat() that it adds only one element.
VALUE rb_ary_freeze(VALUE obj)
Just another name of rb_obj_freeze.
VALUE rb_ary_to_s(VALUE ary)
Converts an array into a human-readable string.
VALUE rb_ary_new_from_args(long n,...)
Constructs an array from the passed objects.
VALUE rb_ary_entry(VALUE ary, long off)
Queries an element of an array.
VALUE rb_ary_sort_bang(VALUE ary)
Destructively sorts the passed array in-place, according to each elements' <=> result.
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Identical to rb_ary_new_from_values(), except it expects exactly two parameters.
void rb_mem_clear(VALUE *buf, long len)
Fills the memory region with a series of RUBY_Qnil.
VALUE rb_ary_delete(VALUE ary, VALUE elem)
Destructively removes elements from the passed array, so that there would be no elements inside that ...
VALUE rb_ary_join(VALUE ary, VALUE sep)
Recursively stringises the elements of the passed array, flattens that result, then joins the sequenc...
void rb_ary_store(VALUE ary, long key, VALUE val)
Destructively stores the passed value to the passed array's passed index.
VALUE rb_big_plus(VALUE x, VALUE y)
Performs addition of the passed two objects.
double rb_big2dbl(VALUE x)
Converts a bignum into C's double.
int rb_cmpint(VALUE val, VALUE a, VALUE b)
Canonicalises the passed val, which is the return value of a <=> b, into C's {-1, 0,...
VALUE rb_arithmetic_sequence_beg_len_step(VALUE as, long *begp, long *lenp, long *stepp, long len, int err)
Identical to rb_range_beg_len(), except it takes an instance of Enumerator::ArithmericSequence.
#define RETURN_SIZED_ENUMERATOR(obj, argc, argv, size_fn)
This roughly resembles return enum_for(__callee__) unless block_given?.
#define RETURN_ENUMERATOR(obj, argc, argv)
Identical to RETURN_SIZED_ENUMERATOR(), except its size is unknown.
#define UNLIMITED_ARGUMENTS
This macro is used in conjunction with rb_check_arity().
#define rb_check_frozen
Just another name of rb_check_frozen.
static int rb_check_arity(int argc, int min, int max)
Ensures that the passed integer is in the passed range.
void rb_hash_foreach(VALUE hash, int(*func)(VALUE key, VALUE val, VALUE arg), VALUE arg)
Iterates over a hash.
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
Inserts or replaces ("upsert"s) the objects into the given hash table.
VALUE rb_hash(VALUE obj)
Calculates a message authentication code of the passed object.
VALUE rb_hash_new(void)
Creates a new, empty hash object.
VALUE rb_output_fs
The field separator character for outputs, or the $,.
VALUE rb_int_positive_pow(long x, unsigned long y)
Raises the passed x to the power of y.
VALUE rb_range_beg_len(VALUE range, long *begp, long *lenp, long len, int err)
Deconstructs a numerical range.
#define rb_hash_uint(h, i)
Just another name of st_hash_uint.
#define rb_hash_end(h)
Just another name of st_hash_end.
VALUE rb_usascii_str_new(const char *ptr, long len)
Identical to rb_str_new(), except it generates a string of "US ASCII" encoding.
VALUE rb_usascii_str_new_cstr(const char *ptr)
Identical to rb_str_new_cstr(), except it generates a string of "US ASCII" encoding.
VALUE rb_str_buf_cat2(VALUE, const char *)
Just another name of rb_str_cat_cstr.
VALUE rb_str_buf_append(VALUE dst, VALUE src)
Identical to rb_str_cat_cstr(), except it takes Ruby's string instead of C's.
void rb_str_set_len(VALUE str, long len)
Overwrites the length of the string.
st_index_t rb_hash_start(st_index_t i)
Starts a series of hashing.
int rb_str_cmp(VALUE lhs, VALUE rhs)
Compares two strings, as in strcmp(3).
VALUE rb_str_new(const char *ptr, long len)
Allocates an instance of rb_cString.
VALUE rb_check_string_type(VALUE obj)
Try converting an object to its stringised representation using its to_str method,...
VALUE rb_str_buf_new(long capa)
Allocates a "string buffer".
VALUE rb_obj_as_string(VALUE obj)
Try converting an object to its stringised representation using its to_s method, if any.
VALUE rb_exec_recursive(VALUE(*f)(VALUE g, VALUE h, int r), VALUE g, VALUE h)
"Recursion" API entry point.
VALUE rb_exec_recursive_paired(VALUE(*f)(VALUE g, VALUE h, int r), VALUE g, VALUE p, VALUE h)
Identical to rb_exec_recursive(), except it checks for the recursion on the ordered pair of { g,...
int rb_respond_to(VALUE obj, ID mid)
Queries if the object responds to the method.
void rb_define_alloc_func(VALUE klass, rb_alloc_func_t func)
Sets the allocator function of a class.
ID rb_intern(const char *name)
Finds or creates a symbol of the given name.
void ruby_qsort(void *, const size_t, const size_t, int(*)(const void *, const void *, void *), void *)
Reentrant implementation of quick sort.
#define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)
Shim for block function parameters.
VALUE rb_block_call(VALUE obj, ID mid, int argc, const VALUE *argv, rb_block_call_func_t proc, VALUE data2)
Identical to rb_funcallv(), except it additionally passes a function as a block.
VALUE rb_yield_values(int n,...)
Identical to rb_yield(), except it takes variadic number of parameters and pass them to the block.
VALUE rb_yield_values2(int n, const VALUE *argv)
Identical to rb_yield_values(), except it takes the parameters as a C array instead of variadic argum...
VALUE rb_yield(VALUE val)
Yields the block.
#define RBIMPL_ATTR_MAYBE_UNUSED()
Wraps (or simulates) [[maybe_unused]]
#define MEMCPY(p1, p2, type, n)
Handy macro to call memcpy.
#define MEMZERO(p, type, n)
Handy macro to erase a region of memory.
#define RB_GC_GUARD(v)
Prevents premature destruction of local objects.
#define MEMMOVE(p1, p2, type, n)
Handy macro to call memmove.
static VALUE * RARRAY_PTR(VALUE ary)
Wild use of a C pointer.
#define RARRAY_LEN
Just another name of rb_array_len.
#define RARRAY_CONST_PTR_TRANSIENT
Just another name of rb_array_const_ptr_transient.
void rb_ary_detransient(VALUE a)
Destructively converts an array of transient backend into ordinal one.
#define RARRAY(obj)
Convenient casting macro.
static bool RARRAY_TRANSIENT_P(VALUE ary)
Queries if the array is a transient array.
static void RARRAY_ASET(VALUE ary, long i, VALUE v)
Assigns an object in an array.
#define RARRAY_PTR_USE(ary, ptr_name, expr)
Declares a section of code where raw pointers are used.
@ RARRAY_EMBED_LEN_MAX
Max possible number elements that can be embedded.
#define RARRAY_AREF(a, i)
#define RARRAY_PTR_USE_TRANSIENT(ary, ptr_name, expr)
Identical to RARRAY_PTR_USE, except the pointer can be a transient one.
#define RARRAY_CONST_PTR
Just another name of rb_array_const_ptr.
static VALUE RBASIC_CLASS(VALUE obj)
Queries the class of an object.
#define RBASIC(obj)
Convenient casting macro.
#define Data_Wrap_Struct(klass, mark, free, sval)
Converts sval, a pointer to your struct, into a Ruby object.
#define DATA_PTR(obj)
Convenient getter macro.
#define RGENGC_WB_PROTECTED_ARRAY
This is a compile-time flag to enable/disable write barrier for struct RArray.
#define RB_OBJ_WB_UNPROTECT_FOR(type, obj)
Identical to RB_OBJ_WB_UNPROTECT(), except it can also assert that the given object is of given type.
#define RHASH_SIZE(h)
Queries the size of the hash.
#define StringValue(v)
Ensures that the parameter object is a String.
static long RSTRING_LEN(VALUE str)
Queries the length of the string.
#define RTEST
This is an old name of RB_TEST.
intptr_t SIGNED_VALUE
A signed integer type that has the same width with VALUE.
uintptr_t VALUE
Type that represents a Ruby object.
static bool RB_FLOAT_TYPE_P(VALUE obj)
Queries if the object is an instance of rb_cFloat.
static bool RB_TYPE_P(VALUE obj, enum ruby_value_type t)
Queries if the given object is of given type.