Ruby: array.c Source File

Ruby 4.0.5p0 (2026-05-20 revision 64336ffd0ee9e1f4c05891695a3d7b49cb709721)

array.c
1/**********************************************************************
2
3 array.c -
4
5 $Author$
6 created at: Fri Aug 6 09:46:12 JST 1993
7
8 Copyright (C) 1993-2007 Yukihiro Matsumoto
9 Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
10 Copyright (C) 2000 Information-technology Promotion Agency, Japan
11
12**********************************************************************/
13
14#include "debug_counter.h"
15#include "id.h"
16#include "internal.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"
27#include "probes.h"
28#include "ruby/encoding.h"
29#include "ruby/st.h"
30#include "ruby/thread.h"
31#include "ruby/util.h"
32#include "ruby/ractor.h"
33#include "vm_core.h"
34#include "builtin.h"
35
36#if !ARRAY_DEBUG
37# undef NDEBUG
38# define NDEBUG
39#endif
40#include "ruby_assert.h"
41
42 VALUE rb_cArray;
43 VALUE rb_cArray_empty_frozen;
44
45/* Flags of RArray
46 *
47 * 0: RARRAY_SHARED_FLAG (equal to ELTS_SHARED)
48 * The array is shared. The buffer this array points to is owned by
49 * another array (the shared root).
50 * 1: RARRAY_EMBED_FLAG
51 * The array is embedded (its contents follow the header, rather than
52 * being on a separately allocated buffer).
53 * 3-9: RARRAY_EMBED_LEN
54 * The length of the array when RARRAY_EMBED_FLAG is set.
55 * 12: RARRAY_SHARED_ROOT_FLAG
56 * The array is a shared root that does reference counting. The buffer
57 * this array points to is owned by this array but may be pointed to
58 * by other arrays.
59 * Note: Frozen arrays may be a shared root without this flag being
60 * set. Frozen arrays do not have reference counting because
61 * they cannot be modified. Not updating the reference count
62 * improves copy-on-write performance. Their reference count is
63 * assumed to be infinity.
64 * 14: RARRAY_PTR_IN_USE_FLAG
65 * The buffer of the array is in use. This is only used during
66 * debugging.
67 */
68
69/* for OPTIMIZED_CMP: */
70#define id_cmp idCmp
71
72#define ARY_DEFAULT_SIZE 16
73#define ARY_MAX_SIZE (LONG_MAX / (int)sizeof(VALUE))
74#define SMALL_ARRAY_LEN 16
75
76 RBIMPL_ATTR_MAYBE_UNUSED()
77static int
78should_be_T_ARRAY(VALUE ary)
79{
80 return RB_TYPE_P(ary, T_ARRAY);
81}
82
83#define ARY_HEAP_PTR(a) (RUBY_ASSERT(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.ptr)
84#define ARY_HEAP_LEN(a) (RUBY_ASSERT(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.len)
85#define ARY_HEAP_CAPA(a) (RUBY_ASSERT(!ARY_EMBED_P(a)), RUBY_ASSERT(!ARY_SHARED_ROOT_P(a)), \
86 RARRAY(a)->as.heap.aux.capa)
87
88#define ARY_EMBED_PTR(a) (RUBY_ASSERT(ARY_EMBED_P(a)), RARRAY(a)->as.ary)
89#define ARY_EMBED_LEN(a) \
90 (RUBY_ASSERT(ARY_EMBED_P(a)), \
91 (long)((RBASIC(a)->flags >> RARRAY_EMBED_LEN_SHIFT) & \
92 (RARRAY_EMBED_LEN_MASK >> RARRAY_EMBED_LEN_SHIFT)))
93#define ARY_HEAP_SIZE(a) (RUBY_ASSERT(!ARY_EMBED_P(a)), RUBY_ASSERT(ARY_OWNS_HEAP_P(a)), ARY_CAPA(a) * sizeof(VALUE))
94
95#define ARY_OWNS_HEAP_P(a) (RUBY_ASSERT(should_be_T_ARRAY((VALUE)(a))), \
96 !FL_TEST_RAW((a), RARRAY_SHARED_FLAG|RARRAY_EMBED_FLAG))
97
98#define FL_SET_EMBED(a) do { \
99 RUBY_ASSERT(!ARY_SHARED_P(a)); \
100 FL_SET((a), RARRAY_EMBED_FLAG); \
101 ary_verify(a); \
102} while (0)
103
104#define FL_UNSET_EMBED(ary) FL_UNSET((ary), RARRAY_EMBED_FLAG|RARRAY_EMBED_LEN_MASK)
105#define FL_SET_SHARED(ary) do { \
106 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
107 FL_SET((ary), RARRAY_SHARED_FLAG); \
108} while (0)
109#define FL_UNSET_SHARED(ary) FL_UNSET((ary), RARRAY_SHARED_FLAG)
110
111#define ARY_SET_PTR_FORCE(ary, p) \
112 (RARRAY(ary)->as.heap.ptr = (p))
113#define ARY_SET_PTR(ary, p) do { \
114 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
115 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
116 ARY_SET_PTR_FORCE(ary, p); \
117} while (0)
118#define ARY_SET_EMBED_LEN(ary, n) do { \
119 long tmp_n = (n); \
120 RUBY_ASSERT(ARY_EMBED_P(ary)); \
121 RBASIC(ary)->flags &= ~RARRAY_EMBED_LEN_MASK; \
122 RBASIC(ary)->flags |= (tmp_n) << RARRAY_EMBED_LEN_SHIFT; \
123} while (0)
124#define ARY_SET_HEAP_LEN(ary, n) do { \
125 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
126 RARRAY(ary)->as.heap.len = (n); \
127} while (0)
128#define ARY_SET_LEN(ary, n) do { \
129 if (ARY_EMBED_P(ary)) { \
130 ARY_SET_EMBED_LEN((ary), (n)); \
131 } \
132 else { \
133 ARY_SET_HEAP_LEN((ary), (n)); \
134 } \
135 RUBY_ASSERT(RARRAY_LEN(ary) == (n)); \
136} while (0)
137#define ARY_INCREASE_PTR(ary, n) do { \
138 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
139 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
140 RARRAY(ary)->as.heap.ptr += (n); \
141} while (0)
142#define ARY_INCREASE_LEN(ary, n) do { \
143 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
144 if (ARY_EMBED_P(ary)) { \
145 ARY_SET_EMBED_LEN((ary), RARRAY_LEN(ary)+(n)); \
146 } \
147 else { \
148 RARRAY(ary)->as.heap.len += (n); \
149 } \
150} while (0)
151
152#define ARY_CAPA(ary) (ARY_EMBED_P(ary) ? ary_embed_capa(ary) : \
153 ARY_SHARED_ROOT_P(ary) ? RARRAY_LEN(ary) : ARY_HEAP_CAPA(ary))
154#define ARY_SET_CAPA_FORCE(ary, n) \
155 RARRAY(ary)->as.heap.aux.capa = (n);
156#define ARY_SET_CAPA(ary, n) do { \
157 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
158 RUBY_ASSERT(!ARY_SHARED_P(ary)); \
159 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
160 ARY_SET_CAPA_FORCE(ary, n); \
161} while (0)
162
163#define ARY_SHARED_ROOT_OCCUPIED(ary) (!OBJ_FROZEN(ary) && ARY_SHARED_ROOT_REFCNT(ary) == 1)
164#define ARY_SET_SHARED_ROOT_REFCNT(ary, value) do { \
165 RUBY_ASSERT(ARY_SHARED_ROOT_P(ary)); \
166 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
167 RUBY_ASSERT((value) >= 0); \
168 RARRAY(ary)->as.heap.aux.capa = (value); \
169} while (0)
170#define FL_SET_SHARED_ROOT(ary) do { \
171 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
172 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
173 FL_SET((ary), RARRAY_SHARED_ROOT_FLAG); \
174} while (0)
175
176static inline void
177ARY_SET(VALUE a, long i, VALUE v)
178{
179 RUBY_ASSERT(!ARY_SHARED_P(a));
180 RUBY_ASSERT(!OBJ_FROZEN(a));
181
182 RARRAY_ASET(a, i, v);
183}
184#undef RARRAY_ASET
185
186static long
187ary_embed_capa(VALUE ary)
188{
189 size_t size = rb_gc_obj_slot_size(ary) - offsetof(struct RArray, as.ary);
190 RUBY_ASSERT(size % sizeof(VALUE) == 0);
191 return size / sizeof(VALUE);
192}
193
194static size_t
195ary_embed_size(long capa)
196{
197 size_t size = offsetof(struct RArray, as.ary) + (sizeof(VALUE) * capa);
198 if (size < sizeof(struct RArray)) size = sizeof(struct RArray);
199 return size;
200}
201
202static bool
203ary_embeddable_p(long capa)
204{
205 return rb_gc_size_allocatable_p(ary_embed_size(capa));
206}
207
208bool
209rb_ary_embeddable_p(VALUE ary)
210{
211 /* An array cannot be turned embeddable when the array is:
212 * - Shared root: other objects may point to the buffer of this array
213 * so we cannot make it embedded.
214 * - Frozen: this array may also be a shared root without the shared root
215 * flag.
216 * - Shared: we don't want to re-embed an array that points to a shared
217 * root (to save memory).
218 */
219 return !(ARY_SHARED_ROOT_P(ary) || OBJ_FROZEN(ary) || ARY_SHARED_P(ary));
220}
221
222size_t
223rb_ary_size_as_embedded(VALUE ary)
224{
225 size_t real_size;
226
227 if (ARY_EMBED_P(ary)) {
228 real_size = ary_embed_size(ARY_EMBED_LEN(ary));
229 }
230 else if (rb_ary_embeddable_p(ary)) {
231 real_size = ary_embed_size(ARY_HEAP_CAPA(ary));
232 }
233 else {
234 real_size = sizeof(struct RArray);
235 }
236 return real_size;
237}
238
239
240#if ARRAY_DEBUG
241#define ary_verify(ary) ary_verify_(ary, __FILE__, __LINE__)
242
243static VALUE
244ary_verify_(VALUE ary, const char *file, int line)
245{
246 RUBY_ASSERT(RB_TYPE_P(ary, T_ARRAY));
247
248 if (ARY_SHARED_P(ary)) {
249 VALUE root = ARY_SHARED_ROOT(ary);
250 const VALUE *ptr = ARY_HEAP_PTR(ary);
251 const VALUE *root_ptr = RARRAY_CONST_PTR(root);
252 long len = ARY_HEAP_LEN(ary), root_len = RARRAY_LEN(root);
253 RUBY_ASSERT(ARY_SHARED_ROOT_P(root) || OBJ_FROZEN(root));
254 RUBY_ASSERT(root_ptr <= ptr && ptr + len <= root_ptr + root_len);
255 ary_verify(root);
256 }
257 else if (ARY_EMBED_P(ary)) {
258 RUBY_ASSERT(!ARY_SHARED_P(ary));
259 RUBY_ASSERT(RARRAY_LEN(ary) <= ary_embed_capa(ary));
260 }
261 else {
262 const VALUE *ptr = RARRAY_CONST_PTR(ary);
263 long i, len = RARRAY_LEN(ary);
264 volatile VALUE v;
265 if (len > 1) len = 1; /* check only HEAD */
266 for (i=0; i<len; i++) {
267 v = ptr[i]; /* access check */
268 }
269 v = v;
270 }
271
272 return ary;
273}
274#else
275#define ary_verify(ary) ((void)0)
276#endif
277
278 VALUE *
279rb_ary_ptr_use_start(VALUE ary)
280{
281#if ARRAY_DEBUG
282 FL_SET_RAW(ary, RARRAY_PTR_IN_USE_FLAG);
283#endif
284 return (VALUE *)RARRAY_CONST_PTR(ary);
285}
286
287void
288rb_ary_ptr_use_end(VALUE ary)
289{
290#if ARRAY_DEBUG
291 FL_UNSET_RAW(ary, RARRAY_PTR_IN_USE_FLAG);
292#endif
293}
294
295void
296 rb_mem_clear(VALUE *mem, long size)
297{
298 while (size--) {
299 *mem++ = Qnil;
300 }
301}
302
303static void
304ary_mem_clear(VALUE ary, long beg, long size)
305{
306 RARRAY_PTR_USE(ary, ptr, {
307 rb_mem_clear(ptr + beg, size);
308 });
309}
310
311static inline void
312memfill(register VALUE *mem, register long size, register VALUE val)
313{
314 while (size--) {
315 *mem++ = val;
316 }
317}
318
319static void
320ary_memfill(VALUE ary, long beg, long size, VALUE val)
321{
322 RARRAY_PTR_USE(ary, ptr, {
323 memfill(ptr + beg, size, val);
324 RB_OBJ_WRITTEN(ary, Qundef, val);
325 });
326}
327
328static void
329ary_memcpy0(VALUE ary, long beg, long argc, const VALUE *argv, VALUE buff_owner_ary)
330{
331 RUBY_ASSERT(!ARY_SHARED_P(buff_owner_ary));
332
333 if (argc > (int)(128/sizeof(VALUE)) /* is magic number (cache line size) */) {
334 rb_gc_writebarrier_remember(buff_owner_ary);
335 RARRAY_PTR_USE(ary, ptr, {
336 MEMCPY(ptr+beg, argv, VALUE, argc);
337 });
338 }
339 else {
340 int i;
341 RARRAY_PTR_USE(ary, ptr, {
342 for (i=0; i<argc; i++) {
343 RB_OBJ_WRITE(buff_owner_ary, &ptr[i+beg], argv[i]);
344 }
345 });
346 }
347}
348
349static void
350ary_memcpy(VALUE ary, long beg, long argc, const VALUE *argv)
351{
352 ary_memcpy0(ary, beg, argc, argv, ary);
353}
354
355static VALUE *
356ary_heap_alloc_buffer(size_t capa)
357{
358 return ALLOC_N(VALUE, capa);
359}
360
361static void
362ary_heap_free_ptr(VALUE ary, const VALUE *ptr, long size)
363{
364 ruby_sized_xfree((void *)ptr, size);
365}
366
367static void
368ary_heap_free(VALUE ary)
369{
370 ary_heap_free_ptr(ary, ARY_HEAP_PTR(ary), ARY_HEAP_SIZE(ary));
371}
372
373static size_t
374ary_heap_realloc(VALUE ary, size_t new_capa)
375{
376 RUBY_ASSERT(!OBJ_FROZEN(ary));
377 SIZED_REALLOC_N(RARRAY(ary)->as.heap.ptr, VALUE, new_capa, ARY_HEAP_CAPA(ary));
378 ary_verify(ary);
379
380 return new_capa;
381}
382
383void
384rb_ary_make_embedded(VALUE ary)
385{
386 RUBY_ASSERT(rb_ary_embeddable_p(ary));
387 if (!ARY_EMBED_P(ary)) {
388 const VALUE *buf = ARY_HEAP_PTR(ary);
389 long len = ARY_HEAP_LEN(ary);
390
391 FL_SET_EMBED(ary);
392 ARY_SET_EMBED_LEN(ary, len);
393
394 MEMCPY((void *)ARY_EMBED_PTR(ary), (void *)buf, VALUE, len);
395
396 ary_heap_free_ptr(ary, buf, len * sizeof(VALUE));
397 }
398}
399
400static void
401ary_resize_capa(VALUE ary, long capacity)
402{
403 RUBY_ASSERT(RARRAY_LEN(ary) <= capacity);
404 RUBY_ASSERT(!OBJ_FROZEN(ary));
405 RUBY_ASSERT(!ARY_SHARED_P(ary));
406
407 if (capacity > ary_embed_capa(ary)) {
408 size_t new_capa = capacity;
409 if (ARY_EMBED_P(ary)) {
410 long len = ARY_EMBED_LEN(ary);
411 VALUE *ptr = ary_heap_alloc_buffer(capacity);
412
413 MEMCPY(ptr, ARY_EMBED_PTR(ary), VALUE, len);
414 FL_UNSET_EMBED(ary);
415 ARY_SET_PTR(ary, ptr);
416 ARY_SET_HEAP_LEN(ary, len);
417 }
418 else {
419 new_capa = ary_heap_realloc(ary, capacity);
420 }
421 ARY_SET_CAPA(ary, new_capa);
422 }
423 else {
424 if (!ARY_EMBED_P(ary)) {
425 long len = ARY_HEAP_LEN(ary);
426 long old_capa = ARY_HEAP_CAPA(ary);
427 const VALUE *ptr = ARY_HEAP_PTR(ary);
428
429 if (len > capacity) len = capacity;
430 MEMCPY((VALUE *)RARRAY(ary)->as.ary, ptr, VALUE, len);
431 ary_heap_free_ptr(ary, ptr, old_capa);
432
433 FL_SET_EMBED(ary);
434 ARY_SET_LEN(ary, len);
435 }
436 }
437
438 ary_verify(ary);
439}
440
441static inline void
442ary_shrink_capa(VALUE ary)
443{
444 long capacity = ARY_HEAP_LEN(ary);
445 long old_capa = ARY_HEAP_CAPA(ary);
446 RUBY_ASSERT(!ARY_SHARED_P(ary));
447 RUBY_ASSERT(old_capa >= capacity);
448 if (old_capa > capacity) {
449 size_t new_capa = ary_heap_realloc(ary, capacity);
450 ARY_SET_CAPA(ary, new_capa);
451 }
452
453 ary_verify(ary);
454}
455
456static void
457ary_double_capa(VALUE ary, long min)
458{
459 long new_capa = ARY_CAPA(ary) / 2;
460
461 if (new_capa < ARY_DEFAULT_SIZE) {
462 new_capa = ARY_DEFAULT_SIZE;
463 }
464 if (new_capa >= ARY_MAX_SIZE - min) {
465 new_capa = (ARY_MAX_SIZE - min) / 2;
466 }
467 new_capa += min;
468 ary_resize_capa(ary, new_capa);
469
470 ary_verify(ary);
471}
472
473static void
474rb_ary_decrement_share(VALUE shared_root)
475{
476 if (!OBJ_FROZEN(shared_root)) {
477 long num = ARY_SHARED_ROOT_REFCNT(shared_root);
478 ARY_SET_SHARED_ROOT_REFCNT(shared_root, num - 1);
479 }
480}
481
482static void
483rb_ary_unshare(VALUE ary)
484{
485 VALUE shared_root = ARY_SHARED_ROOT(ary);
486 rb_ary_decrement_share(shared_root);
487 FL_UNSET_SHARED(ary);
488}
489
490static void
491rb_ary_reset(VALUE ary)
492{
493 if (ARY_OWNS_HEAP_P(ary)) {
494 ary_heap_free(ary);
495 }
496 else if (ARY_SHARED_P(ary)) {
497 rb_ary_unshare(ary);
498 }
499
500 FL_SET_EMBED(ary);
501 ARY_SET_EMBED_LEN(ary, 0);
502}
503
504static VALUE
505rb_ary_increment_share(VALUE shared_root)
506{
507 if (!OBJ_FROZEN(shared_root)) {
508 long num = ARY_SHARED_ROOT_REFCNT(shared_root);
509 RUBY_ASSERT(num >= 0);
510 ARY_SET_SHARED_ROOT_REFCNT(shared_root, num + 1);
511 }
512 return shared_root;
513}
514
515static void
516rb_ary_set_shared(VALUE ary, VALUE shared_root)
517{
518 RUBY_ASSERT(!ARY_EMBED_P(ary));
519 RUBY_ASSERT(!OBJ_FROZEN(ary));
520 RUBY_ASSERT(ARY_SHARED_ROOT_P(shared_root) || OBJ_FROZEN(shared_root));
521
522 rb_ary_increment_share(shared_root);
523 FL_SET_SHARED(ary);
524 RB_OBJ_WRITE(ary, &RARRAY(ary)->as.heap.aux.shared_root, shared_root);
525
526 RB_DEBUG_COUNTER_INC(obj_ary_shared_create);
527}
528
529static inline void
530rb_ary_modify_check(VALUE ary)
531{
532 RUBY_ASSERT(ruby_thread_has_gvl_p());
533
534 rb_check_frozen(ary);
535 ary_verify(ary);
536}
537
538void
539rb_ary_cancel_sharing(VALUE ary)
540{
541 if (ARY_SHARED_P(ary)) {
542 long shared_len, len = RARRAY_LEN(ary);
543 VALUE shared_root = ARY_SHARED_ROOT(ary);
544
545 ary_verify(shared_root);
546
547 if (len <= ary_embed_capa(ary)) {
548 const VALUE *ptr = ARY_HEAP_PTR(ary);
549 FL_UNSET_SHARED(ary);
550 FL_SET_EMBED(ary);
551 MEMCPY((VALUE *)ARY_EMBED_PTR(ary), ptr, VALUE, len);
552 rb_ary_decrement_share(shared_root);
553 ARY_SET_EMBED_LEN(ary, len);
554 }
555 else if (ARY_SHARED_ROOT_OCCUPIED(shared_root) && len > ((shared_len = RARRAY_LEN(shared_root))>>1)) {
556 long shift = RARRAY_CONST_PTR(ary) - RARRAY_CONST_PTR(shared_root);
557 FL_UNSET_SHARED(ary);
558 ARY_SET_PTR(ary, RARRAY_CONST_PTR(shared_root));
559 ARY_SET_CAPA(ary, shared_len);
560 RARRAY_PTR_USE(ary, ptr, {
561 MEMMOVE(ptr, ptr+shift, VALUE, len);
562 });
563 FL_SET_EMBED(shared_root);
564 rb_ary_decrement_share(shared_root);
565 }
566 else {
567 VALUE *ptr = ary_heap_alloc_buffer(len);
568 MEMCPY(ptr, ARY_HEAP_PTR(ary), VALUE, len);
569 rb_ary_unshare(ary);
570 ARY_SET_CAPA_FORCE(ary, len);
571 ARY_SET_PTR_FORCE(ary, ptr);
572 }
573
574 rb_gc_writebarrier_remember(ary);
575 }
576 ary_verify(ary);
577}
578
579void
580 rb_ary_modify(VALUE ary)
581{
582 rb_ary_modify_check(ary);
583 rb_ary_cancel_sharing(ary);
584}
585
586static VALUE
587ary_ensure_room_for_push(VALUE ary, long add_len)
588{
589 long old_len = RARRAY_LEN(ary);
590 long new_len = old_len + add_len;
591 long capa;
592
593 if (old_len > ARY_MAX_SIZE - add_len) {
594 rb_raise(rb_eIndexError, "index %ld too big", new_len);
595 }
596 if (ARY_SHARED_P(ary)) {
597 if (new_len > ary_embed_capa(ary)) {
598 VALUE shared_root = ARY_SHARED_ROOT(ary);
599 if (ARY_SHARED_ROOT_OCCUPIED(shared_root)) {
600 if (ARY_HEAP_PTR(ary) - RARRAY_CONST_PTR(shared_root) + new_len <= RARRAY_LEN(shared_root)) {
601 rb_ary_modify_check(ary);
602
603 ary_verify(ary);
604 ary_verify(shared_root);
605 return shared_root;
606 }
607 else {
608 /* if array is shared, then it is likely it participate in push/shift pattern */
609 rb_ary_modify(ary);
610 capa = ARY_CAPA(ary);
611 if (new_len > capa - (capa >> 6)) {
612 ary_double_capa(ary, new_len);
613 }
614 ary_verify(ary);
615 return ary;
616 }
617 }
618 }
619 ary_verify(ary);
620 rb_ary_modify(ary);
621 }
622 else {
623 rb_ary_modify_check(ary);
624 }
625 capa = ARY_CAPA(ary);
626 if (new_len > capa) {
627 ary_double_capa(ary, new_len);
628 }
629
630 ary_verify(ary);
631 return ary;
632}
633
634/*
635 * call-seq:
636 * freeze -> self
637 *
638 * Freezes +self+ (if not already frozen); returns +self+:
639 *
640 * a = []
641 * a.frozen? # => false
642 * a.freeze
643 * a.frozen? # => true
644 *
645 * No further changes may be made to +self+;
646 * raises FrozenError if a change is attempted.
647 *
648 * Related: Kernel#frozen?.
649 */
650
651 VALUE
652 rb_ary_freeze(VALUE ary)
653{
654 RUBY_ASSERT(RB_TYPE_P(ary, T_ARRAY));
655
656 if (OBJ_FROZEN(ary)) return ary;
657
658 if (!ARY_EMBED_P(ary) && !ARY_SHARED_P(ary) && !ARY_SHARED_ROOT_P(ary)) {
659 ary_shrink_capa(ary);
660 }
661
662 return rb_obj_freeze(ary);
663}
664
665/* This can be used to take a snapshot of an array (with
666 e.g. rb_ary_replace) and check later whether the array has been
667 modified from the snapshot. The snapshot is cheap, though if
668 something does modify the array it will pay the cost of copying
669 it. If Array#pop or Array#shift has been called, the array will
670 be still shared with the snapshot, but the array length will
671 differ. */
672 VALUE
673 rb_ary_shared_with_p(VALUE ary1, VALUE ary2)
674{
675 if (!ARY_EMBED_P(ary1) && ARY_SHARED_P(ary1) &&
676 !ARY_EMBED_P(ary2) && ARY_SHARED_P(ary2) &&
677 ARY_SHARED_ROOT(ary1) == ARY_SHARED_ROOT(ary2) &&
678 ARY_HEAP_LEN(ary1) == ARY_HEAP_LEN(ary2)) {
679 return Qtrue;
680 }
681 return Qfalse;
682}
683
684static VALUE
685ary_alloc_embed(VALUE klass, long capa)
686{
687 size_t size = ary_embed_size(capa);
688 RUBY_ASSERT(rb_gc_size_allocatable_p(size));
689 NEWOBJ_OF(ary, struct RArray, klass,
690 T_ARRAY | RARRAY_EMBED_FLAG | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0),
691 size, 0);
692 /* Created array is:
693 * FL_SET_EMBED((VALUE)ary);
694 * ARY_SET_EMBED_LEN((VALUE)ary, 0);
695 */
696 return (VALUE)ary;
697}
698
699static VALUE
700ary_alloc_heap(VALUE klass)
701{
702 NEWOBJ_OF(ary, struct RArray, klass,
703 T_ARRAY | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0),
704 sizeof(struct RArray), 0);
705
706 ary->as.heap.len = 0;
707 ary->as.heap.aux.capa = 0;
708 ary->as.heap.ptr = NULL;
709
710 return (VALUE)ary;
711}
712
713static VALUE
714empty_ary_alloc(VALUE klass)
715{
716 RUBY_DTRACE_CREATE_HOOK(ARRAY, 0);
717 return ary_alloc_embed(klass, 0);
718}
719
720static VALUE
721ary_new(VALUE klass, long capa)
722{
723 RUBY_ASSERT(ruby_thread_has_gvl_p());
724
725 VALUE ary;
726
727 if (capa < 0) {
728 rb_raise(rb_eArgError, "negative array size (or size too big)");
729 }
730 if (capa > ARY_MAX_SIZE) {
731 rb_raise(rb_eArgError, "array size too big");
732 }
733
734 RUBY_DTRACE_CREATE_HOOK(ARRAY, capa);
735
736 if (ary_embeddable_p(capa)) {
737 ary = ary_alloc_embed(klass, capa);
738 }
739 else {
740 ary = ary_alloc_heap(klass);
741 ARY_SET_CAPA(ary, capa);
742 RUBY_ASSERT(!ARY_EMBED_P(ary));
743
744 ARY_SET_PTR(ary, ary_heap_alloc_buffer(capa));
745 ARY_SET_HEAP_LEN(ary, 0);
746 }
747
748 return ary;
749}
750
751 VALUE
752 rb_ary_new_capa(long capa)
753{
754 return ary_new(rb_cArray, capa);
755}
756
757 VALUE
758 rb_ary_new(void)
759{
760 return rb_ary_new_capa(0);
761}
762
763 VALUE
764(rb_ary_new_from_args)(long n, ...)
765{
766 va_list ar;
767 VALUE ary;
768 long i;
769
770 ary = rb_ary_new2(n);
771
772 va_start(ar, n);
773 for (i=0; i<n; i++) {
774 ARY_SET(ary, i, va_arg(ar, VALUE));
775 }
776 va_end(ar);
777
778 ARY_SET_LEN(ary, n);
779 return ary;
780}
781
782 VALUE
783rb_ary_tmp_new_from_values(VALUE klass, long n, const VALUE *elts)
784{
785 VALUE ary;
786
787 ary = ary_new(klass, n);
788 if (n > 0 && elts) {
789 ary_memcpy(ary, 0, n, elts);
790 ARY_SET_LEN(ary, n);
791 }
792
793 return ary;
794}
795
796 VALUE
797 rb_ary_new_from_values(long n, const VALUE *elts)
798{
799 return rb_ary_tmp_new_from_values(rb_cArray, n, elts);
800}
801
802static VALUE
803ec_ary_alloc_embed(rb_execution_context_t *ec, VALUE klass, long capa)
804{
805 size_t size = ary_embed_size(capa);
806 RUBY_ASSERT(rb_gc_size_allocatable_p(size));
807 NEWOBJ_OF(ary, struct RArray, klass,
808 T_ARRAY | RARRAY_EMBED_FLAG | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0),
809 size, ec);
810 /* Created array is:
811 * FL_SET_EMBED((VALUE)ary);
812 * ARY_SET_EMBED_LEN((VALUE)ary, 0);
813 */
814 return (VALUE)ary;
815}
816
817static VALUE
818ec_ary_alloc_heap(rb_execution_context_t *ec, VALUE klass)
819{
820 NEWOBJ_OF(ary, struct RArray, klass,
821 T_ARRAY | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0),
822 sizeof(struct RArray), ec);
823
824 ary->as.heap.len = 0;
825 ary->as.heap.aux.capa = 0;
826 ary->as.heap.ptr = NULL;
827
828 return (VALUE)ary;
829}
830
831static VALUE
832ec_ary_new(rb_execution_context_t *ec, VALUE klass, long capa)
833{
834 VALUE ary;
835
836 if (capa < 0) {
837 rb_raise(rb_eArgError, "negative array size (or size too big)");
838 }
839 if (capa > ARY_MAX_SIZE) {
840 rb_raise(rb_eArgError, "array size too big");
841 }
842
843 RUBY_DTRACE_CREATE_HOOK(ARRAY, capa);
844
845 if (ary_embeddable_p(capa)) {
846 ary = ec_ary_alloc_embed(ec, klass, capa);
847 }
848 else {
849 ary = ec_ary_alloc_heap(ec, klass);
850 ARY_SET_CAPA(ary, capa);
851 RUBY_ASSERT(!ARY_EMBED_P(ary));
852
853 ARY_SET_PTR(ary, ary_heap_alloc_buffer(capa));
854 ARY_SET_HEAP_LEN(ary, 0);
855 }
856
857 return ary;
858}
859
860 VALUE
861rb_ec_ary_new_from_values(rb_execution_context_t *ec, long n, const VALUE *elts)
862{
863 VALUE ary;
864
865 ary = ec_ary_new(ec, rb_cArray, n);
866 if (n > 0 && elts) {
867 ary_memcpy(ary, 0, n, elts);
868 ARY_SET_LEN(ary, n);
869 }
870
871 return ary;
872}
873
874 VALUE
875 rb_ary_hidden_new(long capa)
876{
877 VALUE ary = ary_new(0, capa);
878 return ary;
879}
880
881 VALUE
882rb_ary_hidden_new_fill(long capa)
883{
884 VALUE ary = rb_ary_hidden_new(capa);
885 ary_memfill(ary, 0, capa, Qnil);
886 ARY_SET_LEN(ary, capa);
887 return ary;
888}
889
890void
891 rb_ary_free(VALUE ary)
892{
893 if (ARY_OWNS_HEAP_P(ary)) {
894 if (USE_DEBUG_COUNTER &&
895 !ARY_SHARED_ROOT_P(ary) &&
896 ARY_HEAP_CAPA(ary) > RARRAY_LEN(ary)) {
897 RB_DEBUG_COUNTER_INC(obj_ary_extracapa);
898 }
899
900 RB_DEBUG_COUNTER_INC(obj_ary_ptr);
901 ary_heap_free(ary);
902 }
903 else {
904 RB_DEBUG_COUNTER_INC(obj_ary_embed);
905 }
906
907 if (ARY_SHARED_P(ary)) {
908 RB_DEBUG_COUNTER_INC(obj_ary_shared);
909 }
910 if (ARY_SHARED_ROOT_P(ary) && ARY_SHARED_ROOT_OCCUPIED(ary)) {
911 RB_DEBUG_COUNTER_INC(obj_ary_shared_root_occupied);
912 }
913}
914
915static VALUE fake_ary_flags;
916
917static VALUE
918init_fake_ary_flags(void)
919{
920 struct RArray fake_ary = {0};
921 fake_ary.basic.flags = T_ARRAY;
922 VALUE ary = (VALUE)&fake_ary;
923 rb_ary_freeze(ary);
924 return fake_ary.basic.flags;
925}
926
927 VALUE
928rb_setup_fake_ary(struct RArray *fake_ary, const VALUE *list, long len)
929{
930 fake_ary->basic.flags = fake_ary_flags;
931 RBASIC_CLEAR_CLASS((VALUE)fake_ary);
932
933 // bypass frozen checks
934 fake_ary->as.heap.ptr = list;
935 fake_ary->as.heap.len = len;
936 fake_ary->as.heap.aux.capa = len;
937 return (VALUE)fake_ary;
938}
939
940size_t
941rb_ary_memsize(VALUE ary)
942{
943 if (ARY_OWNS_HEAP_P(ary)) {
944 return ARY_CAPA(ary) * sizeof(VALUE);
945 }
946 else {
947 return 0;
948 }
949}
950
951static VALUE
952ary_make_shared(VALUE ary)
953{
954 ary_verify(ary);
955
956 if (ARY_SHARED_P(ary)) {
957 return ARY_SHARED_ROOT(ary);
958 }
959 else if (ARY_SHARED_ROOT_P(ary)) {
960 return ary;
961 }
962 else if (OBJ_FROZEN(ary)) {
963 return ary;
964 }
965 else {
966 long capa = ARY_CAPA(ary);
967 long len = RARRAY_LEN(ary);
968
969 /* Shared roots cannot be embedded because the reference count
970 * (refcnt) is stored in as.heap.aux.capa. */
971 VALUE shared = ary_alloc_heap(0);
972 FL_SET_SHARED_ROOT(shared);
973
974 if (ARY_EMBED_P(ary)) {
975 VALUE *ptr = ary_heap_alloc_buffer(capa);
976 ARY_SET_PTR(shared, ptr);
977 ary_memcpy(shared, 0, len, RARRAY_CONST_PTR(ary));
978
979 FL_UNSET_EMBED(ary);
980 ARY_SET_HEAP_LEN(ary, len);
981 ARY_SET_PTR(ary, ptr);
982 }
983 else {
984 ARY_SET_PTR(shared, RARRAY_CONST_PTR(ary));
985 }
986
987 ARY_SET_LEN(shared, capa);
988 ary_mem_clear(shared, len, capa - len);
989 rb_ary_set_shared(ary, shared);
990
991 ary_verify(shared);
992 ary_verify(ary);
993
994 return shared;
995 }
996}
997
998static VALUE
999ary_make_substitution(VALUE ary)
1000{
1001 long len = RARRAY_LEN(ary);
1002
1003 if (ary_embeddable_p(len)) {
1004 VALUE subst = rb_ary_new_capa(len);
1005 RUBY_ASSERT(ARY_EMBED_P(subst));
1006
1007 ary_memcpy(subst, 0, len, RARRAY_CONST_PTR(ary));
1008 ARY_SET_EMBED_LEN(subst, len);
1009 return subst;
1010 }
1011 else {
1012 return rb_ary_increment_share(ary_make_shared(ary));
1013 }
1014}
1015
1016 VALUE
1017 rb_assoc_new(VALUE car, VALUE cdr)
1018{
1019 return rb_ary_new3(2, car, cdr);
1020}
1021
1022 VALUE
1023rb_to_array_type(VALUE ary)
1024{
1025 return rb_convert_type_with_id(ary, T_ARRAY, "Array", idTo_ary);
1026}
1027#define to_ary rb_to_array_type
1028
1029 VALUE
1030 rb_check_array_type(VALUE ary)
1031{
1032 return rb_check_convert_type_with_id(ary, T_ARRAY, "Array", idTo_ary);
1033}
1034
1035 VALUE
1036rb_check_to_array(VALUE ary)
1037{
1038 return rb_check_convert_type_with_id(ary, T_ARRAY, "Array", idTo_a);
1039}
1040
1041 VALUE
1042rb_to_array(VALUE ary)
1043{
1044 return rb_convert_type_with_id(ary, T_ARRAY, "Array", idTo_a);
1045}
1046
1047/*
1048 * call-seq:
1049 * Array.try_convert(object) -> object, new_array, or nil
1050 *
1051 * Attempts to return an array, based on the given +object+.
1052 *
1053 * If +object+ is an array, returns +object+.
1054 *
1055 * Otherwise if +object+ responds to <tt>:to_ary</tt>.
1056 * calls <tt>object.to_ary</tt>:
1057 * if the return value is an array or +nil+, returns that value;
1058 * if not, raises TypeError.
1059 *
1060 * Otherwise returns +nil+.
1061 *
1062 * Related: see {Methods for Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array].
1063 */
1064
1065static VALUE
1066rb_ary_s_try_convert(VALUE dummy, VALUE ary)
1067{
1068 return rb_check_array_type(ary);
1069}
1070
1071/* :nodoc: */
1072static VALUE
1073rb_ary_s_new(int argc, VALUE *argv, VALUE klass)
1074{
1075 VALUE ary;
1076
1077 if (klass == rb_cArray) {
1078 long size = 0;
1079 if (argc > 0 && FIXNUM_P(argv[0])) {
1080 size = FIX2LONG(argv[0]);
1081 if (size < 0) size = 0;
1082 }
1083
1084 ary = ary_new(klass, size);
1085
1086 rb_obj_call_init_kw(ary, argc, argv, RB_PASS_CALLED_KEYWORDS);
1087 }
1088 else {
1089 ary = rb_class_new_instance_pass_kw(argc, argv, klass);
1090 }
1091
1092 return ary;
1093}
1094
1095/*
1096 * call-seq:
1097 * Array.new -> new_empty_array
1098 * Array.new(array) -> new_array
1099 * Array.new(size, default_value = nil) -> new_array
1100 * Array.new(size = 0) {|index| ... } -> new_array
1101 *
1102 * Returns a new array.
1103 *
1104 * With no block and no argument given, returns a new empty array:
1105 *
1106 * Array.new # => []
1107 *
1108 * With no block and array argument given, returns a new array with the same elements:
1109 *
1110 * Array.new([:foo, 'bar', 2]) # => [:foo, "bar", 2]
1111 *
1112 * With no block and integer argument given, returns a new array containing
1113 * that many instances of the given +default_value+:
1114 *
1115 * Array.new(0) # => []
1116 * Array.new(3) # => [nil, nil, nil]
1117 * Array.new(2, 3) # => [3, 3]
1118 *
1119 * With a block given, returns an array of the given +size+;
1120 * calls the block with each +index+ in the range <tt>(0...size)</tt>;
1121 * the element at that +index+ in the returned array is the blocks return value:
1122 *
1123 * Array.new(3) {|index| "Element #{index}" } # => ["Element 0", "Element 1", "Element 2"]
1124 *
1125 * A common pitfall for new Rubyists is providing an expression as +default_value+:
1126 *
1127 * array = Array.new(2, {})
1128 * array # => [{}, {}]
1129 * array[0][:a] = 1
1130 * array # => [{a: 1}, {a: 1}], as array[0] and array[1] are same object
1131 *
1132 * If you want the elements of the array to be distinct, you should pass a block:
1133 *
1134 * array = Array.new(2) { {} }
1135 * array # => [{}, {}]
1136 * array[0][:a] = 1
1137 * array # => [{a: 1}, {}], as array[0] and array[1] are different objects
1138 *
1139 * Raises TypeError if the first argument is not either an array
1140 * or an {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]).
1141 * Raises ArgumentError if the first argument is a negative integer.
1142 *
1143 * Related: see {Methods for Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array].
1144 */
1145
1146static VALUE
1147rb_ary_initialize(int argc, VALUE *argv, VALUE ary)
1148{
1149 long len;
1150 VALUE size, val;
1151
1152 rb_ary_modify(ary);
1153 if (argc == 0) {
1154 rb_ary_reset(ary);
1155 RUBY_ASSERT(ARY_EMBED_P(ary));
1156 RUBY_ASSERT(ARY_EMBED_LEN(ary) == 0);
1157 if (rb_block_given_p()) {
1158 rb_warning("given block not used");
1159 }
1160 return ary;
1161 }
1162 rb_scan_args(argc, argv, "02", &size, &val);
1163 if (argc == 1 && !FIXNUM_P(size)) {
1164 val = rb_check_array_type(size);
1165 if (!NIL_P(val)) {
1166 rb_ary_replace(ary, val);
1167 return ary;
1168 }
1169 }
1170
1171 len = NUM2LONG(size);
1172 /* NUM2LONG() may call size.to_int, ary can be frozen, modified, etc */
1173 if (len < 0) {
1174 rb_raise(rb_eArgError, "negative array size");
1175 }
1176 if (len > ARY_MAX_SIZE) {
1177 rb_raise(rb_eArgError, "array size too big");
1178 }
1179 /* recheck after argument conversion */
1180 rb_ary_modify(ary);
1181 ary_resize_capa(ary, len);
1182 if (rb_block_given_p()) {
1183 long i;
1184
1185 if (argc == 2) {
1186 rb_warn("block supersedes default value argument");
1187 }
1188 for (i=0; i<len; i++) {
1189 rb_ary_store(ary, i, rb_yield(LONG2NUM(i)));
1190 ARY_SET_LEN(ary, i + 1);
1191 }
1192 }
1193 else {
1194 ary_memfill(ary, 0, len, val);
1195 ARY_SET_LEN(ary, len);
1196 }
1197 return ary;
1198}
1199
1200/*
1201 * Returns a new array, populated with the given objects:
1202 *
1203 * Array[1, 'a', /^A/] # => [1, "a", /^A/]
1204 * Array[] # => []
1205 * Array.[](1, 'a', /^A/) # => [1, "a", /^A/]
1206 *
1207 * Related: see {Methods for Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array].
1208 */
1209
1210static VALUE
1211rb_ary_s_create(int argc, VALUE *argv, VALUE klass)
1212{
1213 VALUE ary = ary_new(klass, argc);
1214 if (argc > 0 && argv) {
1215 ary_memcpy(ary, 0, argc, argv);
1216 ARY_SET_LEN(ary, argc);
1217 }
1218
1219 return ary;
1220}
1221
1222void
1223 rb_ary_store(VALUE ary, long idx, VALUE val)
1224{
1225 long len = RARRAY_LEN(ary);
1226
1227 if (idx < 0) {
1228 idx += len;
1229 if (idx < 0) {
1230 rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
1231 idx - len, -len);
1232 }
1233 }
1234 else if (idx >= ARY_MAX_SIZE) {
1235 rb_raise(rb_eIndexError, "index %ld too big", idx);
1236 }
1237
1238 rb_ary_modify(ary);
1239 if (idx >= ARY_CAPA(ary)) {
1240 ary_double_capa(ary, idx);
1241 }
1242 if (idx > len) {
1243 ary_mem_clear(ary, len, idx - len + 1);
1244 }
1245
1246 if (idx >= len) {
1247 ARY_SET_LEN(ary, idx + 1);
1248 }
1249 ARY_SET(ary, idx, val);
1250}
1251
1252static VALUE
1253ary_make_partial(VALUE ary, VALUE klass, long offset, long len)
1254{
1255 RUBY_ASSERT(offset >= 0);
1256 RUBY_ASSERT(len >= 0);
1257 RUBY_ASSERT(offset+len <= RARRAY_LEN(ary));
1258
1259 VALUE result = ary_alloc_heap(klass);
1260 size_t embed_capa = ary_embed_capa(result);
1261 if ((size_t)len <= embed_capa) {
1262 FL_SET_EMBED(result);
1263 ary_memcpy(result, 0, len, RARRAY_CONST_PTR(ary) + offset);
1264 ARY_SET_EMBED_LEN(result, len);
1265 }
1266 else {
1267 VALUE shared = ary_make_shared(ary);
1268
1269 /* The ary_make_shared call may allocate, which can trigger a GC
1270 * compaction. This can cause the array to be embedded because it has
1271 * a length of 0. */
1272 FL_UNSET_EMBED(result);
1273
1274 ARY_SET_PTR(result, RARRAY_CONST_PTR(ary));
1275 ARY_SET_LEN(result, RARRAY_LEN(ary));
1276 rb_ary_set_shared(result, shared);
1277
1278 ARY_INCREASE_PTR(result, offset);
1279 ARY_SET_LEN(result, len);
1280
1281 ary_verify(shared);
1282 }
1283
1284 ary_verify(result);
1285 return result;
1286}
1287
1288static VALUE
1289ary_make_partial_step(VALUE ary, VALUE klass, long offset, long len, long step)
1290{
1291 RUBY_ASSERT(offset >= 0);
1292 RUBY_ASSERT(len >= 0);
1293 RUBY_ASSERT(offset+len <= RARRAY_LEN(ary));
1294 RUBY_ASSERT(step != 0);
1295
1296 const long orig_len = len;
1297
1298 if (step > 0 && step >= len) {
1299 VALUE result = ary_new(klass, 1);
1300 VALUE *ptr = (VALUE *)ARY_EMBED_PTR(result);
1301 const VALUE *values = RARRAY_CONST_PTR(ary);
1302
1303 RB_OBJ_WRITE(result, ptr, values[offset]);
1304 ARY_SET_EMBED_LEN(result, 1);
1305 return result;
1306 }
1307 else if (step < 0 && step < -len) {
1308 step = -len;
1309 }
1310
1311 long ustep = (step < 0) ? -step : step;
1312 len = roomof(len, ustep);
1313
1314 long i;
1315 long j = offset + ((step > 0) ? 0 : (orig_len - 1));
1316
1317 VALUE result = ary_new(klass, len);
1318 if (ARY_EMBED_P(result)) {
1319 VALUE *ptr = (VALUE *)ARY_EMBED_PTR(result);
1320 const VALUE *values = RARRAY_CONST_PTR(ary);
1321
1322 for (i = 0; i < len; ++i) {
1323 RB_OBJ_WRITE(result, ptr+i, values[j]);
1324 j += step;
1325 }
1326 ARY_SET_EMBED_LEN(result, len);
1327 }
1328 else {
1329 const VALUE *values = RARRAY_CONST_PTR(ary);
1330
1331 RARRAY_PTR_USE(result, ptr, {
1332 for (i = 0; i < len; ++i) {
1333 RB_OBJ_WRITE(result, ptr+i, values[j]);
1334 j += step;
1335 }
1336 });
1337 ARY_SET_LEN(result, len);
1338 }
1339
1340 return result;
1341}
1342
1343static VALUE
1344ary_make_shared_copy(VALUE ary)
1345{
1346 return ary_make_partial(ary, rb_cArray, 0, RARRAY_LEN(ary));
1347}
1348
1349enum ary_take_pos_flags
1350{
1351 ARY_TAKE_FIRST = 0,
1352 ARY_TAKE_LAST = 1
1353};
1354
1355static VALUE
1356ary_take_first_or_last_n(VALUE ary, long n, enum ary_take_pos_flags last)
1357{
1358 long len = RARRAY_LEN(ary);
1359 long offset = 0;
1360
1361 if (n > len) {
1362 n = len;
1363 }
1364 else if (n < 0) {
1365 rb_raise(rb_eArgError, "negative array size");
1366 }
1367 if (last) {
1368 offset = len - n;
1369 }
1370 return ary_make_partial(ary, rb_cArray, offset, n);
1371}
1372
1373static VALUE
1374ary_take_first_or_last(int argc, const VALUE *argv, VALUE ary, enum ary_take_pos_flags last)
1375{
1376 argc = rb_check_arity(argc, 0, 1);
1377 /* the case optional argument is omitted should be handled in
1378 * callers of this function. if another arity case is added,
1379 * this arity check needs to rewrite. */
1380 RUBY_ASSERT_ALWAYS(argc == 1);
1381 return ary_take_first_or_last_n(ary, NUM2LONG(argv[0]), last);
1382}
1383
1384/*
1385 * call-seq:
1386 * self << object -> self
1387 *
1388 * Appends +object+ as the last element in +self+; returns +self+:
1389 *
1390 * [:foo, 'bar', 2] << :baz # => [:foo, "bar", 2, :baz]
1391 *
1392 * Appends +object+ as a single element, even if it is another array:
1393 *
1394 * [:foo, 'bar', 2] << [3, 4] # => [:foo, "bar", 2, [3, 4]]
1395 *
1396 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
1397 */
1398
1399 VALUE
1400 rb_ary_push(VALUE ary, VALUE item)
1401{
1402 long idx = RARRAY_LEN((ary_verify(ary), ary));
1403 VALUE target_ary = ary_ensure_room_for_push(ary, 1);
1404 RARRAY_PTR_USE(ary, ptr, {
1405 RB_OBJ_WRITE(target_ary, &ptr[idx], item);
1406 });
1407 ARY_SET_LEN(ary, idx + 1);
1408 ary_verify(ary);
1409 return ary;
1410}
1411
1412 VALUE
1413 rb_ary_cat(VALUE ary, const VALUE *argv, long len)
1414{
1415 long oldlen = RARRAY_LEN(ary);
1416 VALUE target_ary = ary_ensure_room_for_push(ary, len);
1417 ary_memcpy0(ary, oldlen, len, argv, target_ary);
1418 ARY_SET_LEN(ary, oldlen + len);
1419 return ary;
1420}
1421
1422/*
1423 * call-seq:
1424 * push(*objects) -> self
1425 * append(*objects) -> self
1426 *
1427 * Appends each argument in +objects+ to +self+; returns +self+:
1428 *
1429 * a = [:foo, 'bar', 2] # => [:foo, "bar", 2]
1430 * a.push(:baz, :bat) # => [:foo, "bar", 2, :baz, :bat]
1431 *
1432 * Appends each argument as a single element, even if it is another array:
1433 *
1434 * a = [:foo, 'bar', 2] # => [:foo, "bar", 2]
1435 a.push([:baz, :bat], [:bam, :bad]) # => [:foo, "bar", 2, [:baz, :bat], [:bam, :bad]]
1436 *
1437 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
1438 */
1439
1440static VALUE
1441rb_ary_push_m(int argc, VALUE *argv, VALUE ary)
1442{
1443 return rb_ary_cat(ary, argv, argc);
1444}
1445
1446 VALUE
1447 rb_ary_pop(VALUE ary)
1448{
1449 long n;
1450 rb_ary_modify_check(ary);
1451 n = RARRAY_LEN(ary);
1452 if (n == 0) return Qnil;
1453 if (ARY_OWNS_HEAP_P(ary) &&
1454 n * 3 < ARY_CAPA(ary) &&
1455 ARY_CAPA(ary) > ARY_DEFAULT_SIZE)
1456 {
1457 ary_resize_capa(ary, n * 2);
1458 }
1459
1460 VALUE obj = RARRAY_AREF(ary, n - 1);
1461
1462 ARY_SET_LEN(ary, n - 1);
1463 ary_verify(ary);
1464 return obj;
1465}
1466
1467/*
1468 * call-seq:
1469 * pop -> object or nil
1470 * pop(count) -> new_array
1471 *
1472 * Removes and returns trailing elements of +self+.
1473 *
1474 * With no argument given, removes and returns the last element, if available;
1475 * otherwise returns +nil+:
1476 *
1477 * a = [:foo, 'bar', 2]
1478 * a.pop # => 2
1479 * a # => [:foo, "bar"]
1480 * [].pop # => nil
1481 *
1482 * With non-negative integer argument +count+ given,
1483 * returns a new array containing the trailing +count+ elements of +self+, as available:
1484 *
1485 * a = [:foo, 'bar', 2]
1486 * a.pop(2) # => ["bar", 2]
1487 * a # => [:foo]
1488 *
1489 * a = [:foo, 'bar', 2]
1490 * a.pop(50) # => [:foo, "bar", 2]
1491 * a # => []
1492 *
1493 * Related: Array#push;
1494 * see also {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
1495 */
1496
1497static VALUE
1498rb_ary_pop_m(int argc, VALUE *argv, VALUE ary)
1499{
1500 VALUE result;
1501
1502 if (argc == 0) {
1503 return rb_ary_pop(ary);
1504 }
1505
1506 rb_ary_modify_check(ary);
1507 result = ary_take_first_or_last(argc, argv, ary, ARY_TAKE_LAST);
1508 ARY_INCREASE_LEN(ary, -RARRAY_LEN(result));
1509 ary_verify(ary);
1510 return result;
1511}
1512
1513 VALUE
1514 rb_ary_shift(VALUE ary)
1515{
1516 VALUE top;
1517 long len = RARRAY_LEN(ary);
1518
1519 if (len == 0) {
1520 rb_ary_modify_check(ary);
1521 return Qnil;
1522 }
1523
1524 top = RARRAY_AREF(ary, 0);
1525
1526 rb_ary_behead(ary, 1);
1527
1528 return top;
1529}
1530
1531/*
1532 * call-seq:
1533 * shift -> object or nil
1534 * shift(count) -> new_array or nil
1535 *
1536 * Removes and returns leading elements from +self+.
1537 *
1538 * With no argument, removes and returns one element, if available,
1539 * or +nil+ otherwise:
1540 *
1541 * a = [0, 1, 2, 3]
1542 * a.shift # => 0
1543 * a # => [1, 2, 3]
1544 * [].shift # => nil
1545 *
1546 * With non-negative numeric argument +count+ given,
1547 * removes and returns the first +count+ elements:
1548 *
1549 * a = [0, 1, 2, 3]
1550 * a.shift(2) # => [0, 1]
1551 * a # => [2, 3]
1552 * a.shift(1.1) # => [2]
1553 * a # => [3]
1554 * a.shift(0) # => []
1555 * a # => [3]
1556 *
1557 * If +count+ is large,
1558 * removes and returns all elements:
1559 *
1560 * a = [0, 1, 2, 3]
1561 * a.shift(50) # => [0, 1, 2, 3]
1562 * a # => []
1563 *
1564 * If +self+ is empty, returns a new empty array.
1565 *
1566 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
1567 */
1568
1569static VALUE
1570rb_ary_shift_m(int argc, VALUE *argv, VALUE ary)
1571{
1572 VALUE result;
1573 long n;
1574
1575 if (argc == 0) {
1576 return rb_ary_shift(ary);
1577 }
1578
1579 rb_ary_modify_check(ary);
1580 result = ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST);
1581 n = RARRAY_LEN(result);
1582 rb_ary_behead(ary,n);
1583
1584 return result;
1585}
1586
1587 VALUE
1588rb_ary_behead(VALUE ary, long n)
1589{
1590 if (n <= 0) {
1591 return ary;
1592 }
1593
1594 rb_ary_modify_check(ary);
1595
1596 if (!ARY_SHARED_P(ary)) {
1597 if (ARY_EMBED_P(ary) || RARRAY_LEN(ary) < ARY_DEFAULT_SIZE) {
1598 RARRAY_PTR_USE(ary, ptr, {
1599 MEMMOVE(ptr, ptr + n, VALUE, RARRAY_LEN(ary) - n);
1600 }); /* WB: no new reference */
1601 ARY_INCREASE_LEN(ary, -n);
1602 ary_verify(ary);
1603 return ary;
1604 }
1605
1606 ary_mem_clear(ary, 0, n);
1607 ary_make_shared(ary);
1608 }
1609 else if (ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary))) {
1610 ary_mem_clear(ary, 0, n);
1611 }
1612
1613 ARY_INCREASE_PTR(ary, n);
1614 ARY_INCREASE_LEN(ary, -n);
1615 ary_verify(ary);
1616
1617 return ary;
1618}
1619
1620static VALUE
1621make_room_for_unshift(VALUE ary, const VALUE *head, VALUE *sharedp, int argc, long capa, long len)
1622{
1623 if (head - sharedp < argc) {
1624 long room = capa - len - argc;
1625
1626 room -= room >> 4;
1627 MEMMOVE((VALUE *)sharedp + argc + room, head, VALUE, len);
1628 head = sharedp + argc + room;
1629 }
1630 ARY_SET_PTR(ary, head - argc);
1631 RUBY_ASSERT(ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary)));
1632
1633 ary_verify(ary);
1634 return ARY_SHARED_ROOT(ary);
1635}
1636
1637static VALUE
1638ary_modify_for_unshift(VALUE ary, int argc)
1639{
1640 long len = RARRAY_LEN(ary);
1641 long new_len = len + argc;
1642 long capa;
1643 const VALUE *head, *sharedp;
1644
1645 rb_ary_modify(ary);
1646 capa = ARY_CAPA(ary);
1647 if (capa - (capa >> 6) <= new_len) {
1648 ary_double_capa(ary, new_len);
1649 }
1650
1651 /* use shared array for big "queues" */
1652 if (new_len > ARY_DEFAULT_SIZE * 4 && !ARY_EMBED_P(ary)) {
1653 ary_verify(ary);
1654
1655 /* make a room for unshifted items */
1656 capa = ARY_CAPA(ary);
1657 ary_make_shared(ary);
1658
1659 head = sharedp = RARRAY_CONST_PTR(ary);
1660 return make_room_for_unshift(ary, head, (void *)sharedp, argc, capa, len);
1661 }
1662 else {
1663 /* sliding items */
1664 RARRAY_PTR_USE(ary, ptr, {
1665 MEMMOVE(ptr + argc, ptr, VALUE, len);
1666 });
1667
1668 ary_verify(ary);
1669 return ary;
1670 }
1671}
1672
1673static VALUE
1674ary_ensure_room_for_unshift(VALUE ary, int argc)
1675{
1676 long len = RARRAY_LEN(ary);
1677 long new_len = len + argc;
1678
1679 if (len > ARY_MAX_SIZE - argc) {
1680 rb_raise(rb_eIndexError, "index %ld too big", new_len);
1681 }
1682 else if (! ARY_SHARED_P(ary)) {
1683 return ary_modify_for_unshift(ary, argc);
1684 }
1685 else {
1686 VALUE shared_root = ARY_SHARED_ROOT(ary);
1687 long capa = RARRAY_LEN(shared_root);
1688
1689 if (! ARY_SHARED_ROOT_OCCUPIED(shared_root)) {
1690 return ary_modify_for_unshift(ary, argc);
1691 }
1692 else if (new_len > capa) {
1693 return ary_modify_for_unshift(ary, argc);
1694 }
1695 else {
1696 const VALUE * head = RARRAY_CONST_PTR(ary);
1697 void *sharedp = (void *)RARRAY_CONST_PTR(shared_root);
1698
1699 rb_ary_modify_check(ary);
1700 return make_room_for_unshift(ary, head, sharedp, argc, capa, len);
1701 }
1702 }
1703}
1704
1705/*
1706 * call-seq:
1707 * unshift(*objects) -> self
1708 * prepend(*objects) -> self
1709 *
1710 * Prepends the given +objects+ to +self+:
1711 *
1712 * a = [:foo, 'bar', 2]
1713 * a.unshift(:bam, :bat) # => [:bam, :bat, :foo, "bar", 2]
1714 *
1715 * Related: Array#shift;
1716 * see also {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
1717 */
1718
1719 VALUE
1720rb_ary_unshift_m(int argc, VALUE *argv, VALUE ary)
1721{
1722 long len = RARRAY_LEN(ary);
1723 VALUE target_ary;
1724
1725 if (argc == 0) {
1726 rb_ary_modify_check(ary);
1727 return ary;
1728 }
1729
1730 target_ary = ary_ensure_room_for_unshift(ary, argc);
1731 ary_memcpy0(ary, 0, argc, argv, target_ary);
1732 ARY_SET_LEN(ary, len + argc);
1733 return ary;
1734}
1735
1736 VALUE
1737rb_ary_unshift(VALUE ary, VALUE item)
1738{
1739 return rb_ary_unshift_m(1, &item, ary);
1740}
1741
1742/* faster version - use this if you don't need to treat negative offset */
1743static inline VALUE
1744rb_ary_elt(VALUE ary, long offset)
1745{
1746 long len = RARRAY_LEN(ary);
1747 if (len == 0) return Qnil;
1748 if (offset < 0 || len <= offset) {
1749 return Qnil;
1750 }
1751 return RARRAY_AREF(ary, offset);
1752}
1753
1754 VALUE
1755 rb_ary_entry(VALUE ary, long offset)
1756{
1757 return rb_ary_entry_internal(ary, offset);
1758}
1759
1760 VALUE
1761rb_ary_subseq_step(VALUE ary, long beg, long len, long step)
1762{
1763 VALUE klass;
1764 long alen = RARRAY_LEN(ary);
1765
1766 if (beg > alen) return Qnil;
1767 if (beg < 0 || len < 0) return Qnil;
1768
1769 if (alen < len || alen < beg + len) {
1770 len = alen - beg;
1771 }
1772 klass = rb_cArray;
1773 if (len == 0) return ary_new(klass, 0);
1774 if (step == 0)
1775 rb_raise(rb_eArgError, "slice step cannot be zero");
1776 if (step == 1)
1777 return ary_make_partial(ary, klass, beg, len);
1778 else
1779 return ary_make_partial_step(ary, klass, beg, len, step);
1780}
1781
1782 VALUE
1783 rb_ary_subseq(VALUE ary, long beg, long len)
1784{
1785 return rb_ary_subseq_step(ary, beg, len, 1);
1786}
1787
1788static VALUE rb_ary_aref2(VALUE ary, VALUE b, VALUE e);
1789
1790/*
1791 * call-seq:
1792 * self[index] -> object or nil
1793 * self[start, length] -> object or nil
1794 * self[range] -> object or nil
1795 * self[aseq] -> object or nil
1796 * slice(index) -> object or nil
1797 * slice(start, length) -> object or nil
1798 * slice(range) -> object or nil
1799 * slice(aseq) -> object or nil
1800 *
1801 * Returns elements from +self+; does not modify +self+.
1802 *
1803 * In brief:
1804 *
1805 * a = [:foo, 'bar', 2]
1806 *
1807 * # Single argument index: returns one element.
1808 * a[0] # => :foo # Zero-based index.
1809 * a[-1] # => 2 # Negative index counts backwards from end.
1810 *
1811 * # Arguments start and length: returns an array.
1812 * a[1, 2] # => ["bar", 2]
1813 * a[-2, 2] # => ["bar", 2] # Negative start counts backwards from end.
1814 *
1815 * # Single argument range: returns an array.
1816 * a[0..1] # => [:foo, "bar"]
1817 * a[0..-2] # => [:foo, "bar"] # Negative range-begin counts backwards from end.
1818 * a[-2..2] # => ["bar", 2] # Negative range-end counts backwards from end.
1819 *
1820 * When a single integer argument +index+ is given, returns the element at offset +index+:
1821 *
1822 * a = [:foo, 'bar', 2]
1823 * a[0] # => :foo
1824 * a[2] # => 2
1825 * a # => [:foo, "bar", 2]
1826 *
1827 * If +index+ is negative, counts backwards from the end of +self+:
1828 *
1829 * a = [:foo, 'bar', 2]
1830 * a[-1] # => 2
1831 * a[-2] # => "bar"
1832 *
1833 * If +index+ is out of range, returns +nil+.
1834 *
1835 * When two Integer arguments +start+ and +length+ are given,
1836 * returns a new array of size +length+ containing successive elements beginning at offset +start+:
1837 *
1838 * a = [:foo, 'bar', 2]
1839 * a[0, 2] # => [:foo, "bar"]
1840 * a[1, 2] # => ["bar", 2]
1841 *
1842 * If <tt>start + length</tt> is greater than <tt>self.length</tt>,
1843 * returns all elements from offset +start+ to the end:
1844 *
1845 * a = [:foo, 'bar', 2]
1846 * a[0, 4] # => [:foo, "bar", 2]
1847 * a[1, 3] # => ["bar", 2]
1848 * a[2, 2] # => [2]
1849 *
1850 * If <tt>start == self.size</tt> and <tt>length >= 0</tt>,
1851 * returns a new empty array.
1852 *
1853 * If +length+ is negative, returns +nil+.
1854 *
1855 * When a single Range argument +range+ is given,
1856 * treats <tt>range.min</tt> as +start+ above
1857 * and <tt>range.size</tt> as +length+ above:
1858 *
1859 * a = [:foo, 'bar', 2]
1860 * a[0..1] # => [:foo, "bar"]
1861 * a[1..2] # => ["bar", 2]
1862 *
1863 * Special case: If <tt>range.start == a.size</tt>, returns a new empty array.
1864 *
1865 * If <tt>range.end</tt> is negative, calculates the end index from the end:
1866 *
1867 * a = [:foo, 'bar', 2]
1868 * a[0..-1] # => [:foo, "bar", 2]
1869 * a[0..-2] # => [:foo, "bar"]
1870 * a[0..-3] # => [:foo]
1871 *
1872 * If <tt>range.start</tt> is negative, calculates the start index from the end:
1873 *
1874 * a = [:foo, 'bar', 2]
1875 * a[-1..2] # => [2]
1876 * a[-2..2] # => ["bar", 2]
1877 * a[-3..2] # => [:foo, "bar", 2]
1878 *
1879 * If <tt>range.start</tt> is larger than the array size, returns +nil+.
1880 *
1881 * a = [:foo, 'bar', 2]
1882 * a[4..1] # => nil
1883 * a[4..0] # => nil
1884 * a[4..-1] # => nil
1885 *
1886 * When a single Enumerator::ArithmeticSequence argument +aseq+ is given,
1887 * returns an array of elements corresponding to the indexes produced by
1888 * the sequence.
1889 *
1890 * a = ['--', 'data1', '--', 'data2', '--', 'data3']
1891 * a[(1..).step(2)] # => ["data1", "data2", "data3"]
1892 *
1893 * Unlike slicing with range, if the start or the end of the arithmetic sequence
1894 * is larger than array size, throws RangeError.
1895 *
1896 * a = ['--', 'data1', '--', 'data2', '--', 'data3']
1897 * a[(1..11).step(2)]
1898 * # RangeError (((1..11).step(2)) out of range)
1899 * a[(7..).step(2)]
1900 * # RangeError (((7..).step(2)) out of range)
1901 *
1902 * If given a single argument, and its type is not one of the listed, tries to
1903 * convert it to Integer, and raises if it is impossible:
1904 *
1905 * a = [:foo, 'bar', 2]
1906 * # Raises TypeError (no implicit conversion of Symbol into Integer):
1907 * a[:foo]
1908 *
1909 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
1910 */
1911
1912 VALUE
1913 rb_ary_aref(int argc, const VALUE *argv, VALUE ary)
1914{
1915 rb_check_arity(argc, 1, 2);
1916 if (argc == 2) {
1917 return rb_ary_aref2(ary, argv[0], argv[1]);
1918 }
1919 return rb_ary_aref1(ary, argv[0]);
1920}
1921
1922static VALUE
1923rb_ary_aref2(VALUE ary, VALUE b, VALUE e)
1924{
1925 long beg = NUM2LONG(b);
1926 long len = NUM2LONG(e);
1927 if (beg < 0) {
1928 beg += RARRAY_LEN(ary);
1929 }
1930 return rb_ary_subseq(ary, beg, len);
1931}
1932
1933 VALUE
1934rb_ary_aref1(VALUE ary, VALUE arg)
1935{
1936 long beg, len, step;
1937
1938 /* special case - speeding up */
1939 if (FIXNUM_P(arg)) {
1940 return rb_ary_entry(ary, FIX2LONG(arg));
1941 }
1942 /* check if idx is Range or ArithmeticSequence */
1943 switch (rb_arithmetic_sequence_beg_len_step(arg, &beg, &len, &step, RARRAY_LEN(ary), 0)) {
1944 case Qfalse:
1945 break;
1946 case Qnil:
1947 return Qnil;
1948 default:
1949 return rb_ary_subseq_step(ary, beg, len, step);
1950 }
1951
1952 return rb_ary_entry(ary, NUM2LONG(arg));
1953}
1954
1955/*
1956 * call-seq:
1957 * at(index) -> object or nil
1958 *
1959 * Returns the element of +self+ specified by the given +index+
1960 * or +nil+ if there is no such element;
1961 * +index+ must be an
1962 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
1963 *
1964 * For non-negative +index+, returns the element of +self+ at offset +index+:
1965 *
1966 * a = [:foo, 'bar', 2]
1967 * a.at(0) # => :foo
1968 * a.at(2) # => 2
1969 * a.at(2.0) # => 2
1970 *
1971 * For negative +index+, counts backwards from the end of +self+:
1972 *
1973 * a.at(-2) # => "bar"
1974 *
1975 * Related: Array#[];
1976 * see also {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
1977 */
1978
1979 VALUE
1980rb_ary_at(VALUE ary, VALUE pos)
1981{
1982 return rb_ary_entry(ary, NUM2LONG(pos));
1983}
1984
1985#if 0
1986static VALUE
1987rb_ary_first(int argc, VALUE *argv, VALUE ary)
1988{
1989 if (argc == 0) {
1990 if (RARRAY_LEN(ary) == 0) return Qnil;
1991 return RARRAY_AREF(ary, 0);
1992 }
1993 else {
1994 return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST);
1995 }
1996}
1997#endif
1998
1999static VALUE
2000ary_first(VALUE self)
2001{
2002 return (RARRAY_LEN(self) == 0) ? Qnil : RARRAY_AREF(self, 0);
2003}
2004
2005static VALUE
2006ary_last(VALUE self)
2007{
2008 long len = RARRAY_LEN(self);
2009 return (len == 0) ? Qnil : RARRAY_AREF(self, len-1);
2010}
2011
2012 VALUE
2013rb_ary_last(int argc, const VALUE *argv, VALUE ary) // used by parse.y
2014{
2015 if (argc == 0) {
2016 return ary_last(ary);
2017 }
2018 else {
2019 return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_LAST);
2020 }
2021}
2022
2023/*
2024 * call-seq:
2025 * fetch(index) -> element
2026 * fetch(index, default_value) -> element or default_value
2027 * fetch(index) {|index| ... } -> element or block_return_value
2028 *
2029 * Returns the element of +self+ at offset +index+ if +index+ is in range; +index+ must be an
2030 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
2031 *
2032 * With the single argument +index+ and no block,
2033 * returns the element at offset +index+:
2034 *
2035 * a = [:foo, 'bar', 2]
2036 * a.fetch(1) # => "bar"
2037 * a.fetch(1.1) # => "bar"
2038 *
2039 * If +index+ is negative, counts from the end of the array:
2040 *
2041 * a = [:foo, 'bar', 2]
2042 * a.fetch(-1) # => 2
2043 * a.fetch(-2) # => "bar"
2044 *
2045 * With arguments +index+ and +default_value+ (which may be any object) and no block,
2046 * returns +default_value+ if +index+ is out-of-range:
2047 *
2048 * a = [:foo, 'bar', 2]
2049 * a.fetch(1, nil) # => "bar"
2050 * a.fetch(3, :foo) # => :foo
2051 *
2052 * With argument +index+ and a block,
2053 * returns the element at offset +index+ if index is in range
2054 * (and the block is not called); otherwise calls the block with index and returns its return value:
2055 *
2056 * a = [:foo, 'bar', 2]
2057 * a.fetch(1) {|index| raise 'Cannot happen' } # => "bar"
2058 * a.fetch(50) {|index| "Value for #{index}" } # => "Value for 50"
2059 *
2060 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
2061 */
2062
2063static VALUE
2064rb_ary_fetch(int argc, VALUE *argv, VALUE ary)
2065{
2066 VALUE pos, ifnone;
2067 long block_given;
2068 long idx;
2069
2070 rb_scan_args(argc, argv, "11", &pos, &ifnone);
2071 block_given = rb_block_given_p();
2072 if (block_given && argc == 2) {
2073 rb_warn("block supersedes default value argument");
2074 }
2075 idx = NUM2LONG(pos);
2076
2077 if (idx < 0) {
2078 idx += RARRAY_LEN(ary);
2079 }
2080 if (idx < 0 || RARRAY_LEN(ary) <= idx) {
2081 if (block_given) return rb_yield(pos);
2082 if (argc == 1) {
2083 rb_raise(rb_eIndexError, "index %ld outside of array bounds: %ld...%ld",
2084 idx - (idx < 0 ? RARRAY_LEN(ary) : 0), -RARRAY_LEN(ary), RARRAY_LEN(ary));
2085 }
2086 return ifnone;
2087 }
2088 return RARRAY_AREF(ary, idx);
2089}
2090
2091/*
2092 * call-seq:
2093 * find(if_none_proc = nil) {|element| ... } -> object or nil
2094 * find(if_none_proc = nil) -> enumerator
2095 *
2096 * Returns the first element for which the block returns a truthy value.
2097 *
2098 * With a block given, calls the block with successive elements of the array;
2099 * returns the first element for which the block returns a truthy value:
2100 *
2101 * [1, 3, 5].find {|element| element > 2} # => 3
2102 *
2103 * If no such element is found, calls +if_none_proc+ and returns its return value.
2104 *
2105 * [1, 3, 5].find(proc {-1}) {|element| element > 12} # => -1
2106 *
2107 * With no block given, returns an Enumerator.
2108 *
2109 */
2110
2111static VALUE
2112rb_ary_find(int argc, VALUE *argv, VALUE ary)
2113{
2114 VALUE if_none;
2115 long idx;
2116
2117 RETURN_ENUMERATOR(ary, argc, argv);
2118 if_none = rb_check_arity(argc, 0, 1) ? argv[0] : Qnil;
2119
2120 for (idx = 0; idx < RARRAY_LEN(ary); idx++) {
2121 VALUE elem = RARRAY_AREF(ary, idx);
2122 if (RTEST(rb_yield(elem))) {
2123 return elem;
2124 }
2125 }
2126
2127 if (!NIL_P(if_none)) {
2128 return rb_funcallv(if_none, idCall, 0, 0);
2129 }
2130 return Qnil;
2131}
2132
2133/*
2134 * call-seq:
2135 * rfind(if_none_proc = nil) {|element| ... } -> object or nil
2136 * rfind(if_none_proc = nil) -> enumerator
2137 *
2138 * Returns the last element for which the block returns a truthy value.
2139 *
2140 * With a block given, calls the block with successive elements of the array in
2141 * reverse order; returns the first element for which the block returns a truthy
2142 * value:
2143 *
2144 * [1, 2, 3, 4, 5, 6].rfind {|element| element < 5} # => 4
2145 *
2146 * If no such element is found, calls +if_none_proc+ and returns its return value.
2147 *
2148 * [1, 2, 3, 4].rfind(proc {0}) {|element| element < -2} # => 0
2149 *
2150 * With no block given, returns an Enumerator.
2151 *
2152 */
2153
2154static VALUE
2155rb_ary_rfind(int argc, VALUE *argv, VALUE ary)
2156{
2157 VALUE if_none;
2158 long len, idx;
2159
2160 RETURN_ENUMERATOR(ary, argc, argv);
2161 if_none = rb_check_arity(argc, 0, 1) ? argv[0] : Qnil;
2162
2163 idx = RARRAY_LEN(ary);
2164 while (idx--) {
2165 VALUE elem = RARRAY_AREF(ary, idx);
2166 if (RTEST(rb_yield(elem))) {
2167 return elem;
2168 }
2169
2170 len = RARRAY_LEN(ary);
2171 idx = (idx >= len) ? len : idx;
2172 }
2173
2174 if (!NIL_P(if_none)) {
2175 return rb_funcallv(if_none, idCall, 0, 0);
2176 }
2177 return Qnil;
2178}
2179
2180/*
2181 * call-seq:
2182 * find_index(object) -> integer or nil
2183 * find_index {|element| ... } -> integer or nil
2184 * find_index -> new_enumerator
2185 * index(object) -> integer or nil
2186 * index {|element| ... } -> integer or nil
2187 * index -> new_enumerator
2188 *
2189 * Returns the zero-based integer index of a specified element, or +nil+.
2190 *
2191 * With only argument +object+ given,
2192 * returns the index of the first element +element+
2193 * for which <tt>object == element</tt>:
2194 *
2195 * a = [:foo, 'bar', 2, 'bar']
2196 * a.index('bar') # => 1
2197 *
2198 * Returns +nil+ if no such element found.
2199 *
2200 * With only a block given,
2201 * calls the block with each successive element;
2202 * returns the index of the first element for which the block returns a truthy value:
2203 *
2204 * a = [:foo, 'bar', 2, 'bar']
2205 * a.index {|element| element == 'bar' } # => 1
2206 *
2207 * Returns +nil+ if the block never returns a truthy value.
2208 *
2209 * With neither an argument nor a block given, returns a new Enumerator.
2210 *
2211 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
2212 */
2213
2214static VALUE
2215rb_ary_index(int argc, VALUE *argv, VALUE ary)
2216{
2217 VALUE val;
2218 long i;
2219
2220 if (argc == 0) {
2221 RETURN_ENUMERATOR(ary, 0, 0);
2222 for (i=0; i<RARRAY_LEN(ary); i++) {
2223 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) {
2224 return LONG2NUM(i);
2225 }
2226 }
2227 return Qnil;
2228 }
2229 rb_check_arity(argc, 0, 1);
2230 val = argv[0];
2231 if (rb_block_given_p())
2232 rb_warn("given block not used");
2233 for (i=0; i<RARRAY_LEN(ary); i++) {
2234 VALUE e = RARRAY_AREF(ary, i);
2235 if (rb_equal(e, val)) {
2236 return LONG2NUM(i);
2237 }
2238 }
2239 return Qnil;
2240}
2241
2242/*
2243 * call-seq:
2244 * rindex(object) -> integer or nil
2245 * rindex {|element| ... } -> integer or nil
2246 * rindex -> new_enumerator
2247 *
2248 * Returns the index of the last element for which <tt>object == element</tt>.
2249 *
2250 * With argument +object+ given, returns the index of the last such element found:
2251 *
2252 * a = [:foo, 'bar', 2, 'bar']
2253 * a.rindex('bar') # => 3
2254 *
2255 * Returns +nil+ if no such object found.
2256 *
2257 * With a block given, calls the block with each successive element;
2258 * returns the index of the last element for which the block returns a truthy value:
2259 *
2260 * a = [:foo, 'bar', 2, 'bar']
2261 * a.rindex {|element| element == 'bar' } # => 3
2262 *
2263 * Returns +nil+ if the block never returns a truthy value.
2264 *
2265 * When neither an argument nor a block is given, returns a new Enumerator.
2266 *
2267 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
2268 */
2269
2270static VALUE
2271rb_ary_rindex(int argc, VALUE *argv, VALUE ary)
2272{
2273 VALUE val;
2274 long i = RARRAY_LEN(ary), len;
2275
2276 if (argc == 0) {
2277 RETURN_ENUMERATOR(ary, 0, 0);
2278 while (i--) {
2279 if (RTEST(rb_yield(RARRAY_AREF(ary, i))))
2280 return LONG2NUM(i);
2281 if (i > (len = RARRAY_LEN(ary))) {
2282 i = len;
2283 }
2284 }
2285 return Qnil;
2286 }
2287 rb_check_arity(argc, 0, 1);
2288 val = argv[0];
2289 if (rb_block_given_p())
2290 rb_warn("given block not used");
2291 while (i--) {
2292 VALUE e = RARRAY_AREF(ary, i);
2293 if (rb_equal(e, val)) {
2294 return LONG2NUM(i);
2295 }
2296 if (i > RARRAY_LEN(ary)) {
2297 break;
2298 }
2299 }
2300 return Qnil;
2301}
2302
2303 VALUE
2304 rb_ary_to_ary(VALUE obj)
2305{
2306 VALUE tmp = rb_check_array_type(obj);
2307
2308 if (!NIL_P(tmp)) return tmp;
2309 return rb_ary_new3(1, obj);
2310}
2311
2312static void
2313rb_ary_splice(VALUE ary, long beg, long len, const VALUE *rptr, long rlen)
2314{
2315 long olen;
2316 long rofs;
2317
2318 if (len < 0) rb_raise(rb_eIndexError, "negative length (%ld)", len);
2319 olen = RARRAY_LEN(ary);
2320 if (beg < 0) {
2321 beg += olen;
2322 if (beg < 0) {
2323 rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
2324 beg - olen, -olen);
2325 }
2326 }
2327 if (olen < len || olen < beg + len) {
2328 len = olen - beg;
2329 }
2330
2331 {
2332 const VALUE *optr = RARRAY_CONST_PTR(ary);
2333 rofs = (rptr >= optr && rptr < optr + olen) ? rptr - optr : -1;
2334 }
2335
2336 if (beg >= olen) {
2337 VALUE target_ary;
2338 if (beg > ARY_MAX_SIZE - rlen) {
2339 rb_raise(rb_eIndexError, "index %ld too big", beg);
2340 }
2341 target_ary = ary_ensure_room_for_push(ary, rlen-len); /* len is 0 or negative */
2342 len = beg + rlen;
2343 ary_mem_clear(ary, olen, beg - olen);
2344 if (rlen > 0) {
2345 if (rofs != -1) rptr = RARRAY_CONST_PTR(ary) + rofs;
2346 ary_memcpy0(ary, beg, rlen, rptr, target_ary);
2347 }
2348 ARY_SET_LEN(ary, len);
2349 }
2350 else {
2351 long alen;
2352
2353 if (olen - len > ARY_MAX_SIZE - rlen) {
2354 rb_raise(rb_eIndexError, "index %ld too big", olen + rlen - len);
2355 }
2356 rb_ary_modify(ary);
2357 alen = olen + rlen - len;
2358 if (alen >= ARY_CAPA(ary)) {
2359 ary_double_capa(ary, alen);
2360 }
2361
2362 if (len != rlen) {
2363 RARRAY_PTR_USE(ary, ptr,
2364 MEMMOVE(ptr + beg + rlen, ptr + beg + len,
2365 VALUE, olen - (beg + len)));
2366 ARY_SET_LEN(ary, alen);
2367 }
2368 if (rlen > 0) {
2369 if (rofs == -1) {
2370 rb_gc_writebarrier_remember(ary);
2371 }
2372 else {
2373 /* In this case, we're copying from a region in this array, so
2374 * we don't need to fire the write barrier. */
2375 rptr = RARRAY_CONST_PTR(ary) + rofs;
2376 }
2377
2378 /* do not use RARRAY_PTR() because it can causes GC.
2379 * ary can contain T_NONE object because it is not cleared.
2380 */
2381 RARRAY_PTR_USE(ary, ptr,
2382 MEMMOVE(ptr + beg, rptr, VALUE, rlen));
2383 }
2384 }
2385}
2386
2387void
2388rb_ary_set_len(VALUE ary, long len)
2389{
2390 long capa;
2391
2392 rb_ary_modify_check(ary);
2393 if (ARY_SHARED_P(ary)) {
2394 rb_raise(rb_eRuntimeError, "can't set length of shared ");
2395 }
2396 if (len > (capa = (long)ARY_CAPA(ary))) {
2397 rb_bug("probable buffer overflow: %ld for %ld", len, capa);
2398 }
2399 ARY_SET_LEN(ary, len);
2400}
2401
2402 VALUE
2403 rb_ary_resize(VALUE ary, long len)
2404{
2405 long olen;
2406
2407 rb_ary_modify(ary);
2408 olen = RARRAY_LEN(ary);
2409 if (len == olen) return ary;
2410 if (len > ARY_MAX_SIZE) {
2411 rb_raise(rb_eIndexError, "index %ld too big", len);
2412 }
2413 if (len > olen) {
2414 if (len > ARY_CAPA(ary)) {
2415 ary_double_capa(ary, len);
2416 }
2417 ary_mem_clear(ary, olen, len - olen);
2418 ARY_SET_LEN(ary, len);
2419 }
2420 else if (ARY_EMBED_P(ary)) {
2421 ARY_SET_EMBED_LEN(ary, len);
2422 }
2423 else if (len <= ary_embed_capa(ary)) {
2424 const VALUE *ptr = ARY_HEAP_PTR(ary);
2425 long ptr_capa = ARY_HEAP_SIZE(ary);
2426 bool is_malloc_ptr = !ARY_SHARED_P(ary);
2427
2428 FL_SET_EMBED(ary);
2429
2430 MEMCPY((VALUE *)ARY_EMBED_PTR(ary), ptr, VALUE, len); /* WB: no new reference */
2431 ARY_SET_EMBED_LEN(ary, len);
2432
2433 if (is_malloc_ptr) ruby_sized_xfree((void *)ptr, ptr_capa);
2434 }
2435 else {
2436 if (olen > len + ARY_DEFAULT_SIZE) {
2437 size_t new_capa = ary_heap_realloc(ary, len);
2438 ARY_SET_CAPA(ary, new_capa);
2439 }
2440 ARY_SET_HEAP_LEN(ary, len);
2441 }
2442 ary_verify(ary);
2443 return ary;
2444}
2445
2446static VALUE
2447ary_aset_by_rb_ary_store(VALUE ary, long key, VALUE val)
2448{
2449 rb_ary_store(ary, key, val);
2450 return val;
2451}
2452
2453static VALUE
2454ary_aset_by_rb_ary_splice(VALUE ary, long beg, long len, VALUE val)
2455{
2456 VALUE rpl = rb_ary_to_ary(val);
2457 rb_ary_splice(ary, beg, len, RARRAY_CONST_PTR(rpl), RARRAY_LEN(rpl));
2458 RB_GC_GUARD(rpl);
2459 return val;
2460}
2461
2462/*
2463 * call-seq:
2464 * self[index] = object -> object
2465 * self[start, length] = object -> object
2466 * self[range] = object -> object
2467 *
2468 * Assigns elements in +self+, based on the given +object+; returns +object+.
2469 *
2470 * In brief:
2471 *
2472 * a_orig = [:foo, 'bar', 2]
2473 *
2474 * # With argument index.
2475 * a = a_orig.dup
2476 * a[0] = 'foo' # => "foo"
2477 * a # => ["foo", "bar", 2]
2478 * a = a_orig.dup
2479 * a[7] = 'foo' # => "foo"
2480 * a # => [:foo, "bar", 2, nil, nil, nil, nil, "foo"]
2481 *
2482 * # With arguments start and length.
2483 * a = a_orig.dup
2484 * a[0, 2] = 'foo' # => "foo"
2485 * a # => ["foo", 2]
2486 * a = a_orig.dup
2487 * a[6, 50] = 'foo' # => "foo"
2488 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2489 *
2490 * # With argument range.
2491 * a = a_orig.dup
2492 * a[0..1] = 'foo' # => "foo"
2493 * a # => ["foo", 2]
2494 * a = a_orig.dup
2495 * a[6..50] = 'foo' # => "foo"
2496 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2497 *
2498 * When Integer argument +index+ is given, assigns +object+ to an element in +self+.
2499 *
2500 * If +index+ is non-negative, assigns +object+ the element at offset +index+:
2501 *
2502 * a = [:foo, 'bar', 2]
2503 * a[0] = 'foo' # => "foo"
2504 * a # => ["foo", "bar", 2]
2505 *
2506 * If +index+ is greater than <tt>self.length</tt>, extends the array:
2507 *
2508 * a = [:foo, 'bar', 2]
2509 * a[7] = 'foo' # => "foo"
2510 * a # => [:foo, "bar", 2, nil, nil, nil, nil, "foo"]
2511 *
2512 * If +index+ is negative, counts backwards from the end of the array:
2513 *
2514 * a = [:foo, 'bar', 2]
2515 * a[-1] = 'two' # => "two"
2516 * a # => [:foo, "bar", "two"]
2517 *
2518 * When Integer arguments +start+ and +length+ are given and +object+ is not an array,
2519 * removes <tt>length - 1</tt> elements beginning at offset +start+,
2520 * and assigns +object+ at offset +start+:
2521 *
2522 * a = [:foo, 'bar', 2]
2523 * a[0, 2] = 'foo' # => "foo"
2524 * a # => ["foo", 2]
2525 *
2526 * If +start+ is negative, counts backwards from the end of the array:
2527 *
2528 * a = [:foo, 'bar', 2]
2529 * a[-2, 2] = 'foo' # => "foo"
2530 * a # => [:foo, "foo"]
2531 *
2532 * If +start+ is non-negative and outside the array (<tt> >= self.size</tt>),
2533 * extends the array with +nil+, assigns +object+ at offset +start+,
2534 * and ignores +length+:
2535 *
2536 * a = [:foo, 'bar', 2]
2537 * a[6, 50] = 'foo' # => "foo"
2538 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2539 *
2540 * If +length+ is zero, shifts elements at and following offset +start+
2541 * and assigns +object+ at offset +start+:
2542 *
2543 * a = [:foo, 'bar', 2]
2544 * a[1, 0] = 'foo' # => "foo"
2545 * a # => [:foo, "foo", "bar", 2]
2546 *
2547 * If +length+ is too large for the existing array, does not extend the array:
2548 *
2549 * a = [:foo, 'bar', 2]
2550 * a[1, 5] = 'foo' # => "foo"
2551 * a # => [:foo, "foo"]
2552 *
2553 * When Range argument +range+ is given and +object+ is not an array,
2554 * removes <tt>length - 1</tt> elements beginning at offset +start+,
2555 * and assigns +object+ at offset +start+:
2556 *
2557 * a = [:foo, 'bar', 2]
2558 * a[0..1] = 'foo' # => "foo"
2559 * a # => ["foo", 2]
2560 *
2561 * if <tt>range.begin</tt> is negative, counts backwards from the end of the array:
2562 *
2563 * a = [:foo, 'bar', 2]
2564 * a[-2..2] = 'foo' # => "foo"
2565 * a # => [:foo, "foo"]
2566 *
2567 * If the array length is less than <tt>range.begin</tt>,
2568 * extends the array with +nil+, assigns +object+ at offset <tt>range.begin</tt>,
2569 * and ignores +length+:
2570 *
2571 * a = [:foo, 'bar', 2]
2572 * a[6..50] = 'foo' # => "foo"
2573 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2574 *
2575 * If <tt>range.end</tt> is zero, shifts elements at and following offset +start+
2576 * and assigns +object+ at offset +start+:
2577 *
2578 * a = [:foo, 'bar', 2]
2579 * a[1..0] = 'foo' # => "foo"
2580 * a # => [:foo, "foo", "bar", 2]
2581 *
2582 * If <tt>range.end</tt> is negative, assigns +object+ at offset +start+,
2583 * retains <tt>range.end.abs -1</tt> elements past that, and removes those beyond:
2584 *
2585 * a = [:foo, 'bar', 2]
2586 * a[1..-1] = 'foo' # => "foo"
2587 * a # => [:foo, "foo"]
2588 * a = [:foo, 'bar', 2]
2589 * a[1..-2] = 'foo' # => "foo"
2590 * a # => [:foo, "foo", 2]
2591 * a = [:foo, 'bar', 2]
2592 * a[1..-3] = 'foo' # => "foo"
2593 * a # => [:foo, "foo", "bar", 2]
2594 * a = [:foo, 'bar', 2]
2595 *
2596 * If <tt>range.end</tt> is too large for the existing array,
2597 * replaces array elements, but does not extend the array with +nil+ values:
2598 *
2599 * a = [:foo, 'bar', 2]
2600 * a[1..5] = 'foo' # => "foo"
2601 * a # => [:foo, "foo"]
2602 *
2603 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
2604 */
2605
2606static VALUE
2607rb_ary_aset(int argc, VALUE *argv, VALUE ary)
2608{
2609 long offset, beg, len;
2610
2611 rb_check_arity(argc, 2, 3);
2612 rb_ary_modify_check(ary);
2613 if (argc == 3) {
2614 beg = NUM2LONG(argv[0]);
2615 len = NUM2LONG(argv[1]);
2616 return ary_aset_by_rb_ary_splice(ary, beg, len, argv[2]);
2617 }
2618 if (FIXNUM_P(argv[0])) {
2619 offset = FIX2LONG(argv[0]);
2620 return ary_aset_by_rb_ary_store(ary, offset, argv[1]);
2621 }
2622 if (rb_range_beg_len(argv[0], &beg, &len, RARRAY_LEN(ary), 1)) {
2623 /* check if idx is Range */
2624 return ary_aset_by_rb_ary_splice(ary, beg, len, argv[1]);
2625 }
2626
2627 offset = NUM2LONG(argv[0]);
2628 return ary_aset_by_rb_ary_store(ary, offset, argv[1]);
2629}
2630
2631/*
2632 * call-seq:
2633 * insert(index, *objects) -> self
2634 *
2635 * Inserts the given +objects+ as elements of +self+;
2636 * returns +self+.
2637 *
2638 * When +index+ is non-negative, inserts +objects+
2639 * _before_ the element at offset +index+:
2640 *
2641 * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
2642 * a.insert(1, :x, :y, :z) # => ["a", :x, :y, :z, "b", "c"]
2643 *
2644 * Extends the array if +index+ is beyond the array (<tt>index >= self.size</tt>):
2645 *
2646 * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
2647 * a.insert(5, :x, :y, :z) # => ["a", "b", "c", nil, nil, :x, :y, :z]
2648 *
2649 * When +index+ is negative, inserts +objects+
2650 * _after_ the element at offset <tt>index + self.size</tt>:
2651 *
2652 * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
2653 * a.insert(-2, :x, :y, :z) # => ["a", "b", :x, :y, :z, "c"]
2654 *
2655 * With no +objects+ given, does nothing:
2656 *
2657 * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
2658 * a.insert(1) # => ["a", "b", "c"]
2659 * a.insert(50) # => ["a", "b", "c"]
2660 * a.insert(-50) # => ["a", "b", "c"]
2661 *
2662 * Raises IndexError if +objects+ are given and +index+ is negative and out of range.
2663 *
2664 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
2665 */
2666
2667static VALUE
2668rb_ary_insert(int argc, VALUE *argv, VALUE ary)
2669{
2670 long pos;
2671
2672 rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
2673 rb_ary_modify_check(ary);
2674 pos = NUM2LONG(argv[0]);
2675 if (argc == 1) return ary;
2676 if (pos == -1) {
2677 pos = RARRAY_LEN(ary);
2678 }
2679 else if (pos < 0) {
2680 long minpos = -RARRAY_LEN(ary) - 1;
2681 if (pos < minpos) {
2682 rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
2683 pos, minpos);
2684 }
2685 pos++;
2686 }
2687 rb_ary_splice(ary, pos, 0, argv + 1, argc - 1);
2688 return ary;
2689}
2690
2691static VALUE
2692rb_ary_length(VALUE ary);
2693
2694static VALUE
2695ary_enum_length(VALUE ary, VALUE args, VALUE eobj)
2696{
2697 return rb_ary_length(ary);
2698}
2699
2700// Primitive to avoid a race condition in Array#each.
2701// Return `true` and write `value` and `index` if the element exists.
2702static VALUE
2703ary_fetch_next(VALUE self, VALUE *index, VALUE *value)
2704{
2705 long i = NUM2LONG(*index);
2706 if (i >= RARRAY_LEN(self)) {
2707 return Qfalse;
2708 }
2709 *value = RARRAY_AREF(self, i);
2710 *index = LONG2NUM(i + 1);
2711 return Qtrue;
2712}
2713
2714/*
2715 * call-seq:
2716 * each {|element| ... } -> self
2717 * each -> new_enumerator
2718 *
2719 * With a block given, iterates over the elements of +self+,
2720 * passing each element to the block;
2721 * returns +self+:
2722 *
2723 * a = [:foo, 'bar', 2]
2724 * a.each {|element| puts "#{element.class} #{element}" }
2725 *
2726 * Output:
2727 *
2728 * Symbol foo
2729 * String bar
2730 * Integer 2
2731 *
2732 * Allows the array to be modified during iteration:
2733 *
2734 * a = [:foo, 'bar', 2]
2735 * a.each {|element| puts element; a.clear if element.to_s.start_with?('b') }
2736 *
2737 * Output:
2738 *
2739 * foo
2740 * bar
2741 *
2742 * With no block given, returns a new Enumerator.
2743 *
2744 * Related: see {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
2745 */
2746
2747 VALUE
2748 rb_ary_each(VALUE ary)
2749{
2750 long i;
2751 ary_verify(ary);
2752 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
2753 for (i=0; i<RARRAY_LEN(ary); i++) {
2754 rb_yield(RARRAY_AREF(ary, i));
2755 }
2756 return ary;
2757}
2758
2759/*
2760 * call-seq:
2761 * each_index {|index| ... } -> self
2762 * each_index -> new_enumerator
2763 *
2764 * With a block given, iterates over the elements of +self+,
2765 * passing each <i>array index</i> to the block;
2766 * returns +self+:
2767 *
2768 * a = [:foo, 'bar', 2]
2769 * a.each_index {|index| puts "#{index} #{a[index]}" }
2770 *
2771 * Output:
2772 *
2773 * 0 foo
2774 * 1 bar
2775 * 2 2
2776 *
2777 * Allows the array to be modified during iteration:
2778 *
2779 * a = [:foo, 'bar', 2]
2780 * a.each_index {|index| puts index; a.clear if index > 0 }
2781 * a # => []
2782 *
2783 * Output:
2784 *
2785 * 0
2786 * 1
2787 *
2788 * With no block given, returns a new Enumerator.
2789 *
2790 * Related: see {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
2791 */
2792
2793static VALUE
2794rb_ary_each_index(VALUE ary)
2795{
2796 long i;
2797 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
2798
2799 for (i=0; i<RARRAY_LEN(ary); i++) {
2800 rb_yield(LONG2NUM(i));
2801 }
2802 return ary;
2803}
2804
2805/*
2806 * call-seq:
2807 * reverse_each {|element| ... } -> self
2808 * reverse_each -> Enumerator
2809 *
2810 * When a block given, iterates backwards over the elements of +self+,
2811 * passing, in reverse order, each element to the block;
2812 * returns +self+:
2813 *
2814 * a = []
2815 * [0, 1, 2].reverse_each {|element| a.push(element) }
2816 * a # => [2, 1, 0]
2817 *
2818 * Allows the array to be modified during iteration:
2819 *
2820 * a = ['a', 'b', 'c']
2821 * a.reverse_each {|element| a.clear if element.start_with?('b') }
2822 * a # => []
2823 *
2824 * When no block given, returns a new Enumerator.
2825 *
2826 * Related: see {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
2827 */
2828
2829static VALUE
2830rb_ary_reverse_each(VALUE ary)
2831{
2832 long len;
2833
2834 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
2835 len = RARRAY_LEN(ary);
2836 while (len--) {
2837 long nlen;
2838 rb_yield(RARRAY_AREF(ary, len));
2839 nlen = RARRAY_LEN(ary);
2840 if (nlen < len) {
2841 len = nlen;
2842 }
2843 }
2844 return ary;
2845}
2846
2847/*
2848 * call-seq:
2849 * length -> integer
2850 * size -> integer
2851 *
2852 * Returns the count of elements in +self+:
2853 *
2854 * [0, 1, 2].length # => 3
2855 * [].length # => 0
2856 *
2857 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
2858 */
2859
2860static VALUE
2861rb_ary_length(VALUE ary)
2862{
2863 long len = RARRAY_LEN(ary);
2864 return LONG2NUM(len);
2865}
2866
2867/*
2868 * call-seq:
2869 * empty? -> true or false
2870 *
2871 * Returns +true+ if the count of elements in +self+ is zero,
2872 * +false+ otherwise.
2873 *
2874 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
2875 */
2876
2877static VALUE
2878rb_ary_empty_p(VALUE ary)
2879{
2880 return RBOOL(RARRAY_LEN(ary) == 0);
2881}
2882
2883 VALUE
2884 rb_ary_dup(VALUE ary)
2885{
2886 long len = RARRAY_LEN(ary);
2887 VALUE dup = rb_ary_new2(len);
2888 ary_memcpy(dup, 0, len, RARRAY_CONST_PTR(ary));
2889 ARY_SET_LEN(dup, len);
2890
2891 ary_verify(ary);
2892 ary_verify(dup);
2893 return dup;
2894}
2895
2896 VALUE
2897 rb_ary_resurrect(VALUE ary)
2898{
2899 return ary_make_partial(ary, rb_cArray, 0, RARRAY_LEN(ary));
2900}
2901
2902extern VALUE rb_output_fs;
2903
2904static void ary_join_1(VALUE obj, VALUE ary, VALUE sep, long i, VALUE result, int *first);
2905
2906static VALUE
2907recursive_join(VALUE obj, VALUE argp, int recur)
2908{
2909 VALUE *arg = (VALUE *)argp;
2910 VALUE ary = arg[0];
2911 VALUE sep = arg[1];
2912 VALUE result = arg[2];
2913 int *first = (int *)arg[3];
2914
2915 if (recur) {
2916 rb_raise(rb_eArgError, "recursive array join");
2917 }
2918 else {
2919 ary_join_1(obj, ary, sep, 0, result, first);
2920 }
2921 return Qnil;
2922}
2923
2924static long
2925ary_join_0(VALUE ary, VALUE sep, long max, VALUE result)
2926{
2927 long i;
2928 VALUE val;
2929
2930 if (max > 0) rb_enc_copy(result, RARRAY_AREF(ary, 0));
2931 for (i=0; i<max; i++) {
2932 val = RARRAY_AREF(ary, i);
2933 if (!RB_TYPE_P(val, T_STRING)) break;
2934 if (i > 0 && !NIL_P(sep))
2935 rb_str_buf_append(result, sep);
2936 rb_str_buf_append(result, val);
2937 }
2938 return i;
2939}
2940
2941static void
2942ary_join_1_str(VALUE dst, VALUE src, int *first)
2943{
2944 rb_str_buf_append(dst, src);
2945 if (*first) {
2946 rb_enc_copy(dst, src);
2947 *first = FALSE;
2948 }
2949}
2950
2951static void
2952ary_join_1_ary(VALUE obj, VALUE ary, VALUE sep, VALUE result, VALUE val, int *first)
2953{
2954 if (val == ary) {
2955 rb_raise(rb_eArgError, "recursive array join");
2956 }
2957 else {
2958 VALUE args[4];
2959
2960 *first = FALSE;
2961 args[0] = val;
2962 args[1] = sep;
2963 args[2] = result;
2964 args[3] = (VALUE)first;
2965 rb_exec_recursive(recursive_join, obj, (VALUE)args);
2966 }
2967}
2968
2969static void
2970ary_join_1(VALUE obj, VALUE ary, VALUE sep, long i, VALUE result, int *first)
2971{
2972 VALUE val, tmp;
2973
2974 for (; i<RARRAY_LEN(ary); i++) {
2975 if (i > 0 && !NIL_P(sep))
2976 rb_str_buf_append(result, sep);
2977
2978 val = RARRAY_AREF(ary, i);
2979 if (RB_TYPE_P(val, T_STRING)) {
2980 ary_join_1_str(result, val, first);
2981 }
2982 else if (RB_TYPE_P(val, T_ARRAY)) {
2983 ary_join_1_ary(val, ary, sep, result, val, first);
2984 }
2985 else if (!NIL_P(tmp = rb_check_string_type(val))) {
2986 ary_join_1_str(result, tmp, first);
2987 }
2988 else if (!NIL_P(tmp = rb_check_array_type(val))) {
2989 ary_join_1_ary(val, ary, sep, result, tmp, first);
2990 }
2991 else {
2992 ary_join_1_str(result, rb_obj_as_string(val), first);
2993 }
2994 }
2995}
2996
2997 VALUE
2998 rb_ary_join(VALUE ary, VALUE sep)
2999{
3000 long len = 1, i;
3001 VALUE val, tmp, result;
3002
3003 if (RARRAY_LEN(ary) == 0) return rb_usascii_str_new(0, 0);
3004
3005 if (!NIL_P(sep)) {
3006 StringValue(sep);
3007 len += RSTRING_LEN(sep) * (RARRAY_LEN(ary) - 1);
3008 }
3009 long len_memo = RARRAY_LEN(ary);
3010 for (i=0; i < len_memo; i++) {
3011 val = RARRAY_AREF(ary, i);
3012 if (RB_UNLIKELY(!RB_TYPE_P(val, T_STRING))) {
3013 tmp = rb_check_string_type(val);
3014 if (NIL_P(tmp) || tmp != val) {
3015 int first;
3016 long n = RARRAY_LEN(ary);
3017 if (i > n) i = n;
3018 result = rb_str_buf_new(len + (n-i)*10);
3019 rb_enc_associate(result, rb_usascii_encoding());
3020 i = ary_join_0(ary, sep, i, result);
3021 first = i == 0;
3022 ary_join_1(ary, ary, sep, i, result, &first);
3023 return result;
3024 }
3025 len += RSTRING_LEN(tmp);
3026 len_memo = RARRAY_LEN(ary);
3027 }
3028 else {
3029 len += RSTRING_LEN(val);
3030 }
3031 }
3032
3033 result = rb_str_new(0, len);
3034 rb_str_set_len(result, 0);
3035
3036 ary_join_0(ary, sep, RARRAY_LEN(ary), result);
3037
3038 return result;
3039}
3040
3041/*
3042 * call-seq:
3043 * join(separator = $,) -> new_string
3044 *
3045 * Returns the new string formed by joining the converted elements of +self+;
3046 * for each element +element+:
3047 *
3048 * - Converts recursively using <tt>element.join(separator)</tt>
3049 * if +element+ is a <tt>kind_of?(Array)</tt>.
3050 * - Otherwise, converts using <tt>element.to_s</tt>.
3051 *
3052 * With no argument given, joins using the output field separator, <tt>$,</tt>:
3053 *
3054 * a = [:foo, 'bar', 2]
3055 * $, # => nil
3056 * a.join # => "foobar2"
3057 *
3058 * With string argument +separator+ given, joins using that separator:
3059 *
3060 * a = [:foo, 'bar', 2]
3061 * a.join("\n") # => "foo\nbar\n2"
3062 *
3063 * Joins recursively for nested arrays:
3064 *
3065 * a = [:foo, [:bar, [:baz, :bat]]]
3066 * a.join # => "foobarbazbat"
3067 *
3068 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3069 */
3070static VALUE
3071rb_ary_join_m(int argc, VALUE *argv, VALUE ary)
3072{
3073 VALUE sep;
3074
3075 if (rb_check_arity(argc, 0, 1) == 0 || NIL_P(sep = argv[0])) {
3076 sep = rb_output_fs;
3077 if (!NIL_P(sep)) {
3078 rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "$, is set to non-nil value");
3079 }
3080 }
3081
3082 return rb_ary_join(ary, sep);
3083}
3084
3085static VALUE
3086inspect_ary(VALUE ary, VALUE dummy, int recur)
3087{
3088 long i;
3089 VALUE s, str;
3090
3091 if (recur) return rb_usascii_str_new_cstr("[...]");
3092 str = rb_str_buf_new2("[");
3093 for (i=0; i<RARRAY_LEN(ary); i++) {
3094 s = rb_inspect(RARRAY_AREF(ary, i));
3095 if (i > 0) rb_str_buf_cat2(str, ", ");
3096 else rb_enc_copy(str, s);
3097 rb_str_buf_append(str, s);
3098 }
3099 rb_str_buf_cat2(str, "]");
3100 return str;
3101}
3102
3103/*
3104 * call-seq:
3105 * inspect -> new_string
3106 * to_s -> new_string
3107 *
3108 * Returns the new string formed by calling method <tt>#inspect</tt>
3109 * on each array element:
3110 *
3111 * a = [:foo, 'bar', 2]
3112 * a.inspect # => "[:foo, \"bar\", 2]"
3113 *
3114 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3115 */
3116
3117static VALUE
3118rb_ary_inspect(VALUE ary)
3119{
3120 if (RARRAY_LEN(ary) == 0) return rb_usascii_str_new2("[]");
3121 return rb_exec_recursive(inspect_ary, ary, 0);
3122}
3123
3124 VALUE
3125 rb_ary_to_s(VALUE ary)
3126{
3127 return rb_ary_inspect(ary);
3128}
3129
3130/*
3131 * call-seq:
3132 * to_a -> self or new_array
3133 *
3134 * When +self+ is an instance of \Array, returns +self+.
3135 *
3136 * Otherwise, returns a new array containing the elements of +self+:
3137 *
3138 * class MyArray < Array; end
3139 * my_a = MyArray.new(['foo', 'bar', 'two'])
3140 * a = my_a.to_a
3141 * a # => ["foo", "bar", "two"]
3142 * a.class # => Array # Not MyArray.
3143 *
3144 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3145 */
3146
3147static VALUE
3148rb_ary_to_a(VALUE ary)
3149{
3150 if (rb_obj_class(ary) != rb_cArray) {
3151 VALUE dup = rb_ary_new2(RARRAY_LEN(ary));
3152 rb_ary_replace(dup, ary);
3153 return dup;
3154 }
3155 return ary;
3156}
3157
3158/*
3159 * call-seq:
3160 * to_h -> new_hash
3161 * to_h {|element| ... } -> new_hash
3162 *
3163 * Returns a new hash formed from +self+.
3164 *
3165 * With no block given, each element of +self+ must be a 2-element sub-array;
3166 * forms each sub-array into a key-value pair in the new hash:
3167 *
3168 * a = [['foo', 'zero'], ['bar', 'one'], ['baz', 'two']]
3169 * a.to_h # => {"foo"=>"zero", "bar"=>"one", "baz"=>"two"}
3170 * [].to_h # => {}
3171 *
3172 * With a block given, the block must return a 2-element array;
3173 * calls the block with each element of +self+;
3174 * forms each returned array into a key-value pair in the returned hash:
3175 *
3176 * a = ['foo', :bar, 1, [2, 3], {baz: 4}]
3177 * a.to_h {|element| [element, element.class] }
3178 * # => {"foo"=>String, :bar=>Symbol, 1=>Integer, [2, 3]=>Array, {:baz=>4}=>Hash}
3179 *
3180 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3181 */
3182
3183static VALUE
3184rb_ary_to_h(VALUE ary)
3185{
3186 long i;
3187 VALUE hash = rb_hash_new_with_size(RARRAY_LEN(ary));
3188 int block_given = rb_block_given_p();
3189
3190 for (i=0; i<RARRAY_LEN(ary); i++) {
3191 const VALUE e = rb_ary_elt(ary, i);
3192 const VALUE elt = block_given ? rb_yield_force_blockarg(e) : e;
3193 const VALUE key_value_pair = rb_check_array_type(elt);
3194 if (NIL_P(key_value_pair)) {
3195 rb_raise(rb_eTypeError, "wrong element type %"PRIsVALUE" at %ld (expected array)",
3196 rb_obj_class(elt), i);
3197 }
3198 if (RARRAY_LEN(key_value_pair) != 2) {
3199 rb_raise(rb_eArgError, "wrong array length at %ld (expected 2, was %ld)",
3200 i, RARRAY_LEN(key_value_pair));
3201 }
3202 rb_hash_aset(hash, RARRAY_AREF(key_value_pair, 0), RARRAY_AREF(key_value_pair, 1));
3203 }
3204 return hash;
3205}
3206
3207/*
3208 * call-seq:
3209 * to_ary -> self
3210 *
3211 * Returns +self+.
3212 */
3213
3214static VALUE
3215rb_ary_to_ary_m(VALUE ary)
3216{
3217 return ary;
3218}
3219
3220static void
3221ary_reverse(VALUE *p1, VALUE *p2)
3222{
3223 while (p1 < p2) {
3224 VALUE tmp = *p1;
3225 *p1++ = *p2;
3226 *p2-- = tmp;
3227 }
3228}
3229
3230 VALUE
3231 rb_ary_reverse(VALUE ary)
3232{
3233 VALUE *p2;
3234 long len = RARRAY_LEN(ary);
3235
3236 rb_ary_modify(ary);
3237 if (len > 1) {
3238 RARRAY_PTR_USE(ary, p1, {
3239 p2 = p1 + len - 1; /* points last item */
3240 ary_reverse(p1, p2);
3241 }); /* WB: no new reference */
3242 }
3243 return ary;
3244}
3245
3246/*
3247 * call-seq:
3248 * reverse! -> self
3249 *
3250 * Reverses the order of the elements of +self+;
3251 * returns +self+:
3252 *
3253 * a = [0, 1, 2]
3254 * a.reverse! # => [2, 1, 0]
3255 * a # => [2, 1, 0]
3256 *
3257 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
3258 */
3259
3260static VALUE
3261rb_ary_reverse_bang(VALUE ary)
3262{
3263 return rb_ary_reverse(ary);
3264}
3265
3266/*
3267 * call-seq:
3268 * reverse -> new_array
3269 *
3270 * Returns a new array containing the elements of +self+ in reverse order:
3271 *
3272 * [0, 1, 2].reverse # => [2, 1, 0]
3273 *
3274 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
3275 */
3276
3277static VALUE
3278rb_ary_reverse_m(VALUE ary)
3279{
3280 long len = RARRAY_LEN(ary);
3281 VALUE dup = rb_ary_new2(len);
3282
3283 if (len > 0) {
3284 const VALUE *p1 = RARRAY_CONST_PTR(ary);
3285 VALUE *p2 = (VALUE *)RARRAY_CONST_PTR(dup) + len - 1;
3286 do *p2-- = *p1++; while (--len > 0);
3287 }
3288 ARY_SET_LEN(dup, RARRAY_LEN(ary));
3289 return dup;
3290}
3291
3292static inline long
3293rotate_count(long cnt, long len)
3294{
3295 return (cnt < 0) ? (len - (~cnt % len) - 1) : (cnt % len);
3296}
3297
3298static void
3299ary_rotate_ptr(VALUE *ptr, long len, long cnt)
3300{
3301 if (cnt == 1) {
3302 VALUE tmp = *ptr;
3303 memmove(ptr, ptr + 1, sizeof(VALUE)*(len - 1));
3304 *(ptr + len - 1) = tmp;
3305 }
3306 else if (cnt == len - 1) {
3307 VALUE tmp = *(ptr + len - 1);
3308 memmove(ptr + 1, ptr, sizeof(VALUE)*(len - 1));
3309 *ptr = tmp;
3310 }
3311 else {
3312 --len;
3313 if (cnt < len) ary_reverse(ptr + cnt, ptr + len);
3314 if (--cnt > 0) ary_reverse(ptr, ptr + cnt);
3315 if (len > 0) ary_reverse(ptr, ptr + len);
3316 }
3317}
3318
3319 VALUE
3320 rb_ary_rotate(VALUE ary, long cnt)
3321{
3322 rb_ary_modify(ary);
3323
3324 if (cnt != 0) {
3325 long len = RARRAY_LEN(ary);
3326 if (len > 1 && (cnt = rotate_count(cnt, len)) > 0) {
3327 RARRAY_PTR_USE(ary, ptr, ary_rotate_ptr(ptr, len, cnt));
3328 return ary;
3329 }
3330 }
3331 return Qnil;
3332}
3333
3334/*
3335 * call-seq:
3336 * rotate!(count = 1) -> self
3337 *
3338 * Rotates +self+ in place by moving elements from one end to the other; returns +self+.
3339 *
3340 * With non-negative numeric +count+,
3341 * rotates +count+ elements from the beginning to the end:
3342 *
3343 * [0, 1, 2, 3].rotate!(2) # => [2, 3, 0, 1]
3344 [0, 1, 2, 3].rotate!(2.1) # => [2, 3, 0, 1]
3345 *
3346 * If +count+ is large, uses <tt>count % array.size</tt> as the count:
3347 *
3348 * [0, 1, 2, 3].rotate!(21) # => [1, 2, 3, 0]
3349 *
3350 * If +count+ is zero, rotates no elements:
3351 *
3352 * [0, 1, 2, 3].rotate!(0) # => [0, 1, 2, 3]
3353 *
3354 * With a negative numeric +count+, rotates in the opposite direction,
3355 * from end to beginning:
3356 *
3357 * [0, 1, 2, 3].rotate!(-1) # => [3, 0, 1, 2]
3358 *
3359 * If +count+ is small (far from zero), uses <tt>count % array.size</tt> as the count:
3360 *
3361 * [0, 1, 2, 3].rotate!(-21) # => [3, 0, 1, 2]
3362 *
3363 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
3364 */
3365
3366static VALUE
3367rb_ary_rotate_bang(int argc, VALUE *argv, VALUE ary)
3368{
3369 long n = (rb_check_arity(argc, 0, 1) ? NUM2LONG(argv[0]) : 1);
3370 rb_ary_rotate(ary, n);
3371 return ary;
3372}
3373
3374/*
3375 * call-seq:
3376 * rotate(count = 1) -> new_array
3377 *
3378 * Returns a new array formed from +self+ with elements
3379 * rotated from one end to the other.
3380 *
3381 * With non-negative numeric +count+,
3382 * rotates elements from the beginning to the end:
3383 *
3384 * [0, 1, 2, 3].rotate(2) # => [2, 3, 0, 1]
3385 * [0, 1, 2, 3].rotate(2.1) # => [2, 3, 0, 1]
3386 *
3387 * If +count+ is large, uses <tt>count % array.size</tt> as the count:
3388 *
3389 * [0, 1, 2, 3].rotate(22) # => [2, 3, 0, 1]
3390 *
3391 * With a +count+ of zero, rotates no elements:
3392 *
3393 * [0, 1, 2, 3].rotate(0) # => [0, 1, 2, 3]
3394 *
3395 * With negative numeric +count+, rotates in the opposite direction,
3396 * from the end to the beginning:
3397 *
3398 * [0, 1, 2, 3].rotate(-1) # => [3, 0, 1, 2]
3399 *
3400 * If +count+ is small (far from zero), uses <tt>count % array.size</tt> as the count:
3401 *
3402 * [0, 1, 2, 3].rotate(-21) # => [3, 0, 1, 2]
3403 *
3404 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3405 */
3406
3407static VALUE
3408rb_ary_rotate_m(int argc, VALUE *argv, VALUE ary)
3409{
3410 VALUE rotated;
3411 const VALUE *ptr;
3412 long len;
3413 long cnt = (rb_check_arity(argc, 0, 1) ? NUM2LONG(argv[0]) : 1);
3414
3415 len = RARRAY_LEN(ary);
3416 rotated = rb_ary_new2(len);
3417 if (len > 0) {
3418 cnt = rotate_count(cnt, len);
3419 ptr = RARRAY_CONST_PTR(ary);
3420 len -= cnt;
3421 ary_memcpy(rotated, 0, len, ptr + cnt);
3422 ary_memcpy(rotated, len, cnt, ptr);
3423 }
3424 ARY_SET_LEN(rotated, RARRAY_LEN(ary));
3425 return rotated;
3426}
3427
3428struct ary_sort_data {
3429 VALUE ary;
3430 VALUE receiver;
3431};
3432
3433static VALUE
3434sort_reentered(VALUE ary)
3435{
3436 if (RBASIC(ary)->klass) {
3437 rb_raise(rb_eRuntimeError, "sort reentered");
3438 }
3439 return Qnil;
3440}
3441
3442static void
3443sort_returned(struct ary_sort_data *data)
3444{
3445 if (rb_obj_frozen_p(data->receiver)) {
3446 rb_raise(rb_eFrozenError, "array frozen during sort");
3447 }
3448 sort_reentered(data->ary);
3449}
3450
3451static int
3452sort_1(const void *ap, const void *bp, void *dummy)
3453{
3454 struct ary_sort_data *data = dummy;
3455 VALUE retval = sort_reentered(data->ary);
3456 VALUE a = *(const VALUE *)ap, b = *(const VALUE *)bp;
3457 VALUE args[2];
3458 int n;
3459
3460 args[0] = a;
3461 args[1] = b;
3462 retval = rb_yield_values2(2, args);
3463 n = rb_cmpint(retval, a, b);
3464 sort_returned(data);
3465 return n;
3466}
3467
3468static int
3469sort_2(const void *ap, const void *bp, void *dummy)
3470{
3471 struct ary_sort_data *data = dummy;
3472 VALUE retval = sort_reentered(data->ary);
3473 VALUE a = *(const VALUE *)ap, b = *(const VALUE *)bp;
3474 int n;
3475
3476 if (FIXNUM_P(a) && FIXNUM_P(b) && CMP_OPTIMIZABLE(INTEGER)) {
3477 if ((long)a > (long)b) return 1;
3478 if ((long)a < (long)b) return -1;
3479 return 0;
3480 }
3481 if (STRING_P(a) && STRING_P(b) && CMP_OPTIMIZABLE(STRING)) {
3482 return rb_str_cmp(a, b);
3483 }
3484 if (RB_FLOAT_TYPE_P(a) && CMP_OPTIMIZABLE(FLOAT)) {
3485 return rb_float_cmp(a, b);
3486 }
3487
3488 retval = rb_funcallv(a, id_cmp, 1, &b);
3489 n = rb_cmpint(retval, a, b);
3490 sort_returned(data);
3491
3492 return n;
3493}
3494
3495/*
3496 * call-seq:
3497 * sort! -> self
3498 * sort! {|a, b| ... } -> self
3499 *
3500 * Like Array#sort, but returns +self+ with its elements sorted in place.
3501 *
3502 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
3503 */
3504
3505 VALUE
3506 rb_ary_sort_bang(VALUE ary)
3507{
3508 rb_ary_modify(ary);
3509 RUBY_ASSERT(!ARY_SHARED_P(ary));
3510 if (RARRAY_LEN(ary) > 1) {
3511 VALUE tmp = ary_make_substitution(ary); /* only ary refers tmp */
3512 struct ary_sort_data data;
3513 long len = RARRAY_LEN(ary);
3514 RBASIC_CLEAR_CLASS(tmp);
3515 data.ary = tmp;
3516 data.receiver = ary;
3517 RARRAY_PTR_USE(tmp, ptr, {
3518 ruby_qsort(ptr, len, sizeof(VALUE),
3519 rb_block_given_p()?sort_1:sort_2, &data);
3520 }); /* WB: no new reference */
3521 rb_ary_modify(ary);
3522 if (ARY_EMBED_P(tmp)) {
3523 if (ARY_SHARED_P(ary)) { /* ary might be destructively operated in the given block */
3524 rb_ary_unshare(ary);
3525 FL_SET_EMBED(ary);
3526 }
3527 if (ARY_EMBED_LEN(tmp) > ARY_CAPA(ary)) {
3528 ary_resize_capa(ary, ARY_EMBED_LEN(tmp));
3529 }
3530 ary_memcpy(ary, 0, ARY_EMBED_LEN(tmp), ARY_EMBED_PTR(tmp));
3531 ARY_SET_LEN(ary, ARY_EMBED_LEN(tmp));
3532 }
3533 else {
3534 if (!ARY_EMBED_P(ary) && ARY_HEAP_PTR(ary) == ARY_HEAP_PTR(tmp)) {
3535 FL_UNSET_SHARED(ary);
3536 ARY_SET_CAPA(ary, RARRAY_LEN(tmp));
3537 }
3538 else {
3539 RUBY_ASSERT(!ARY_SHARED_P(tmp));
3540 if (ARY_EMBED_P(ary)) {
3541 FL_UNSET_EMBED(ary);
3542 }
3543 else if (ARY_SHARED_P(ary)) {
3544 /* ary might be destructively operated in the given block */
3545 rb_ary_unshare(ary);
3546 }
3547 else {
3548 ary_heap_free(ary);
3549 }
3550 ARY_SET_PTR(ary, ARY_HEAP_PTR(tmp));
3551 ARY_SET_HEAP_LEN(ary, len);
3552 ARY_SET_CAPA(ary, ARY_HEAP_LEN(tmp));
3553 }
3554 /* tmp was lost ownership for the ptr */
3555 FL_SET_EMBED(tmp);
3556 ARY_SET_EMBED_LEN(tmp, 0);
3557 OBJ_FREEZE(tmp);
3558 }
3559 /* tmp will be GC'ed. */
3560 RBASIC_SET_CLASS_RAW(tmp, rb_cArray); /* rb_cArray must be marked */
3561 }
3562 ary_verify(ary);
3563 return ary;
3564}
3565
3566/*
3567 * call-seq:
3568 * sort -> new_array
3569 * sort {|a, b| ... } -> new_array
3570 *
3571 * Returns a new array containing the elements of +self+, sorted.
3572 *
3573 * With no block given, compares elements using operator <tt>#<=></tt>
3574 * (see Object#<=>):
3575 *
3576 * [0, 2, 3, 1].sort # => [0, 1, 2, 3]
3577 *
3578 * With a block given, calls the block with each combination of pairs of elements from +self+;
3579 * for each pair +a+ and +b+, the block should return a numeric:
3580 *
3581 * - Negative when +b+ is to follow +a+.
3582 * - Zero when +a+ and +b+ are equivalent.
3583 * - Positive when +a+ is to follow +b+.
3584 *
3585 * Example:
3586 *
3587 * a = [3, 2, 0, 1]
3588 * a.sort {|a, b| a <=> b } # => [0, 1, 2, 3]
3589 * a.sort {|a, b| b <=> a } # => [3, 2, 1, 0]
3590 *
3591 * When the block returns zero, the order for +a+ and +b+ is indeterminate,
3592 * and may be unstable.
3593 *
3594 * See an example in Numeric#nonzero? for the idiom to sort more
3595 * complex structure.
3596 *
3597 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3598 */
3599
3600 VALUE
3601 rb_ary_sort(VALUE ary)
3602{
3603 ary = rb_ary_dup(ary);
3604 rb_ary_sort_bang(ary);
3605 return ary;
3606}
3607
3608static VALUE rb_ary_bsearch_index(VALUE ary);
3609
3610/*
3611 * call-seq:
3612 * bsearch {|element| ... } -> found_element or nil
3613 * bsearch -> new_enumerator
3614 *
3615 * Returns the element from +self+ found by a binary search,
3616 * or +nil+ if the search found no suitable element.
3617 *
3618 * See {Binary Searching}[rdoc-ref:language/bsearch.rdoc].
3619 *
3620 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3621 */
3622
3623static VALUE
3624rb_ary_bsearch(VALUE ary)
3625{
3626 VALUE index_result = rb_ary_bsearch_index(ary);
3627
3628 if (FIXNUM_P(index_result)) {
3629 return rb_ary_entry(ary, FIX2LONG(index_result));
3630 }
3631 return index_result;
3632}
3633
3634/*
3635 * call-seq:
3636 * bsearch_index {|element| ... } -> integer or nil
3637 * bsearch_index -> new_enumerator
3638 *
3639 * Returns the integer index of the element from +self+ found by a binary search,
3640 * or +nil+ if the search found no suitable element.
3641 *
3642 * See {Binary Searching}[rdoc-ref:language/bsearch.rdoc].
3643 *
3644 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3645 */
3646
3647static VALUE
3648rb_ary_bsearch_index(VALUE ary)
3649{
3650 long low = 0, high = RARRAY_LEN(ary), mid;
3651 int smaller = 0, satisfied = 0;
3652 VALUE v, val;
3653
3654 RETURN_ENUMERATOR(ary, 0, 0);
3655 while (low < high) {
3656 mid = low + ((high - low) / 2);
3657 val = rb_ary_entry(ary, mid);
3658 v = rb_yield(val);
3659 if (FIXNUM_P(v)) {
3660 if (v == INT2FIX(0)) return INT2FIX(mid);
3661 smaller = (SIGNED_VALUE)v < 0; /* Fixnum preserves its sign-bit */
3662 }
3663 else if (v == Qtrue) {
3664 satisfied = 1;
3665 smaller = 1;
3666 }
3667 else if (!RTEST(v)) {
3668 smaller = 0;
3669 }
3670 else if (rb_obj_is_kind_of(v, rb_cNumeric)) {
3671 const VALUE zero = INT2FIX(0);
3672 switch (rb_cmpint(rb_funcallv(v, id_cmp, 1, &zero), v, zero)) {
3673 case 0: return INT2FIX(mid);
3674 case 1: smaller = 0; break;
3675 case -1: smaller = 1;
3676 }
3677 }
3678 else {
3679 rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE
3680 " (must be numeric, true, false or nil)",
3681 rb_obj_class(v));
3682 }
3683 if (smaller) {
3684 high = mid;
3685 }
3686 else {
3687 low = mid + 1;
3688 }
3689 }
3690 if (!satisfied) return Qnil;
3691 return INT2FIX(low);
3692}
3693
3694
3695static VALUE
3696sort_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, dummy))
3697{
3698 return rb_yield(i);
3699}
3700
3701/*
3702 * call-seq:
3703 * sort_by! {|element| ... } -> self
3704 * sort_by! -> new_enumerator
3705 *
3706 * With a block given, sorts the elements of +self+ in place;
3707 * returns self.
3708 *
3709 * Calls the block with each successive element;
3710 * sorts elements based on the values returned from the block:
3711 *
3712 * a = ['aaaa', 'bbb', 'cc', 'd']
3713 * a.sort_by! {|element| element.size }
3714 * a # => ["d", "cc", "bbb", "aaaa"]
3715 *
3716 * For duplicate values returned by the block, the ordering is indeterminate, and may be unstable.
3717 *
3718 * With no block given, returns a new Enumerator.
3719 *
3720 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
3721 */
3722
3723static VALUE
3724rb_ary_sort_by_bang(VALUE ary)
3725{
3726 VALUE sorted;
3727
3728 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3729 rb_ary_modify(ary);
3730 if (RARRAY_LEN(ary) > 1) {
3731 sorted = rb_block_call(ary, rb_intern("sort_by"), 0, 0, sort_by_i, 0);
3732 rb_ary_replace(ary, sorted);
3733 }
3734 return ary;
3735}
3736
3737
3738/*
3739 * call-seq:
3740 * collect {|element| ... } -> new_array
3741 * collect -> new_enumerator
3742 * map {|element| ... } -> new_array
3743 * map -> new_enumerator
3744 *
3745 * With a block given, calls the block with each element of +self+;
3746 * returns a new array whose elements are the return values from the block:
3747 *
3748 * a = [:foo, 'bar', 2]
3749 * a1 = a.map {|element| element.class }
3750 * a1 # => [Symbol, String, Integer]
3751 *
3752 * With no block given, returns a new Enumerator.
3753 *
3754 * Related: #collect!;
3755 * see also {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3756 */
3757
3758static VALUE
3759rb_ary_collect(VALUE ary)
3760{
3761 long i;
3762 VALUE collect;
3763
3764 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3765 collect = rb_ary_new2(RARRAY_LEN(ary));
3766 for (i = 0; i < RARRAY_LEN(ary); i++) {
3767 rb_ary_push(collect, rb_yield(RARRAY_AREF(ary, i)));
3768 }
3769 return collect;
3770}
3771
3772
3773/*
3774 * call-seq:
3775 * collect! {|element| ... } -> self
3776 * collect! -> new_enumerator
3777 * map! {|element| ... } -> self
3778 * map! -> new_enumerator
3779 *
3780 * With a block given, calls the block with each element of +self+
3781 * and replaces the element with the block's return value;
3782 * returns +self+:
3783 *
3784 * a = [:foo, 'bar', 2]
3785 * a.map! { |element| element.class } # => [Symbol, String, Integer]
3786 *
3787 * With no block given, returns a new Enumerator.
3788 *
3789 * Related: #collect;
3790 * see also {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3791 */
3792
3793static VALUE
3794rb_ary_collect_bang(VALUE ary)
3795{
3796 long i;
3797
3798 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3799 rb_ary_modify(ary);
3800 for (i = 0; i < RARRAY_LEN(ary); i++) {
3801 rb_ary_store(ary, i, rb_yield(RARRAY_AREF(ary, i)));
3802 }
3803 return ary;
3804}
3805
3806 VALUE
3807 rb_get_values_at(VALUE obj, long olen, int argc, const VALUE *argv, VALUE (*func) (VALUE, long))
3808{
3809 VALUE result = rb_ary_new2(argc);
3810 long beg, len, i, j;
3811
3812 for (i=0; i<argc; i++) {
3813 if (FIXNUM_P(argv[i])) {
3814 rb_ary_push(result, (*func)(obj, FIX2LONG(argv[i])));
3815 continue;
3816 }
3817 /* check if idx is Range */
3818 if (rb_range_beg_len(argv[i], &beg, &len, olen, 1)) {
3819 long end = olen < beg+len ? olen : beg+len;
3820 for (j = beg; j < end; j++) {
3821 rb_ary_push(result, (*func)(obj, j));
3822 }
3823 if (beg + len > j)
3824 rb_ary_resize(result, RARRAY_LEN(result) + (beg + len) - j);
3825 continue;
3826 }
3827 rb_ary_push(result, (*func)(obj, NUM2LONG(argv[i])));
3828 }
3829 return result;
3830}
3831
3832static VALUE
3833append_values_at_single(VALUE result, VALUE ary, long olen, VALUE idx)
3834{
3835 long beg, len;
3836 if (FIXNUM_P(idx)) {
3837 beg = FIX2LONG(idx);
3838 }
3839 /* check if idx is Range */
3840 else if (rb_range_beg_len(idx, &beg, &len, olen, 1)) {
3841 if (len > 0) {
3842 const VALUE *const src = RARRAY_CONST_PTR(ary);
3843 const long end = beg + len;
3844 const long prevlen = RARRAY_LEN(result);
3845 if (beg < olen) {
3846 rb_ary_cat(result, src + beg, end > olen ? olen-beg : len);
3847 }
3848 if (end > olen) {
3849 rb_ary_store(result, prevlen + len - 1, Qnil);
3850 }
3851 }
3852 return result;
3853 }
3854 else {
3855 beg = NUM2LONG(idx);
3856 }
3857 return rb_ary_push(result, rb_ary_entry(ary, beg));
3858}
3859
3860/*
3861 * call-seq:
3862 * values_at(*specifiers) -> new_array
3863 *
3864 * Returns elements from +self+ in a new array; does not modify +self+.
3865 *
3866 * The objects included in the returned array are the elements of +self+
3867 * selected by the given +specifiers+,
3868 * each of which must be a numeric index or a Range.
3869 *
3870 * In brief:
3871 *
3872 * a = ['a', 'b', 'c', 'd']
3873 *
3874 * # Index specifiers.
3875 * a.values_at(2, 0, 2, 0) # => ["c", "a", "c", "a"] # May repeat.
3876 * a.values_at(-4, -3, -2, -1) # => ["a", "b", "c", "d"] # Counts backwards if negative.
3877 * a.values_at(-50, 50) # => [nil, nil] # Outside of self.
3878 *
3879 * # Range specifiers.
3880 * a.values_at(1..3) # => ["b", "c", "d"] # From range.begin to range.end.
3881 * a.values_at(1...3) # => ["b", "c"] # End excluded.
3882 * a.values_at(3..1) # => [] # No such elements.
3883 *
3884 * a.values_at(-3..3) # => ["b", "c", "d"] # Negative range.begin counts backwards.
3885 * a.values_at(-50..3) # Raises RangeError.
3886 *
3887 * a.values_at(1..-2) # => ["b", "c"] # Negative range.end counts backwards.
3888 * a.values_at(1..-50) # => [] # No such elements.
3889 *
3890 * # Mixture of specifiers.
3891 * a.values_at(2..3, 3, 0..1, 0) # => ["c", "d", "d", "a", "b", "a"]
3892 *
3893 * With no +specifiers+ given, returns a new empty array:
3894 *
3895 * a = ['a', 'b', 'c', 'd']
3896 * a.values_at # => []
3897 *
3898 * For each numeric specifier +index+, includes an element:
3899 *
3900 * - For each non-negative numeric specifier +index+ that is in-range (less than <tt>self.size</tt>),
3901 * includes the element at offset +index+:
3902 *
3903 * a.values_at(0, 2) # => ["a", "c"]
3904 * a.values_at(0.1, 2.9) # => ["a", "c"]
3905 *
3906 * - For each negative numeric +index+ that is in-range (greater than or equal to <tt>- self.size</tt>),
3907 * counts backwards from the end of +self+:
3908 *
3909 * a.values_at(-1, -4) # => ["d", "a"]
3910 *
3911 * The given indexes may be in any order, and may repeat:
3912 *
3913 * a.values_at(2, 0, 1, 0, 2) # => ["c", "a", "b", "a", "c"]
3914 *
3915 * For each +index+ that is out-of-range, includes +nil+:
3916 *
3917 * a.values_at(4, -5) # => [nil, nil]
3918 *
3919 * For each Range specifier +range+, includes elements
3920 * according to <tt>range.begin</tt> and <tt>range.end</tt>:
3921 *
3922 * - If both <tt>range.begin</tt> and <tt>range.end</tt>
3923 * are non-negative and in-range (less than <tt>self.size</tt>),
3924 * includes elements from index <tt>range.begin</tt>
3925 * through <tt>range.end - 1</tt> (if <tt>range.exclude_end?</tt>),
3926 * or through <tt>range.end</tt> (otherwise):
3927 *
3928 * a.values_at(1..2) # => ["b", "c"]
3929 * a.values_at(1...2) # => ["b"]
3930 *
3931 * - If <tt>range.begin</tt> is negative and in-range (greater than or equal to <tt>- self.size</tt>),
3932 * counts backwards from the end of +self+:
3933 *
3934 * a.values_at(-2..3) # => ["c", "d"]
3935 *
3936 * - If <tt>range.begin</tt> is negative and out-of-range, raises an exception:
3937 *
3938 * a.values_at(-5..3) # Raises RangeError.
3939 *
3940 * - If <tt>range.end</tt> is positive and out-of-range,
3941 * extends the returned array with +nil+ elements:
3942 *
3943 * a.values_at(1..5) # => ["b", "c", "d", nil, nil]
3944 *
3945 * - If <tt>range.end</tt> is negative and in-range,
3946 * counts backwards from the end of +self+:
3947 *
3948 * a.values_at(1..-2) # => ["b", "c"]
3949 *
3950 * - If <tt>range.end</tt> is negative and out-of-range,
3951 * returns an empty array:
3952 *
3953 * a.values_at(1..-5) # => []
3954 *
3955 * The given ranges may be in any order and may repeat:
3956 *
3957 * a.values_at(2..3, 0..1, 2..3) # => ["c", "d", "a", "b", "c", "d"]
3958 *
3959 * The given specifiers may be any mixture of indexes and ranges:
3960 *
3961 * a.values_at(3, 1..2, 0, 2..3) # => ["d", "b", "c", "a", "c", "d"]
3962 *
3963 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3964 */
3965
3966static VALUE
3967rb_ary_values_at(int argc, VALUE *argv, VALUE ary)
3968{
3969 long i, olen = RARRAY_LEN(ary);
3970 VALUE result = rb_ary_new_capa(argc);
3971 for (i = 0; i < argc; ++i) {
3972 append_values_at_single(result, ary, olen, argv[i]);
3973 }
3974 RB_GC_GUARD(ary);
3975 return result;
3976}
3977
3978
3979/*
3980 * call-seq:
3981 * select {|element| ... } -> new_array
3982 * select -> new_enumerator
3983 * filter {|element| ... } -> new_array
3984 * filter -> new_enumerator
3985 *
3986 * With a block given, calls the block with each element of +self+;
3987 * returns a new array containing those elements of +self+
3988 * for which the block returns a truthy value:
3989 *
3990 * a = [:foo, 'bar', 2, :bam]
3991 * a.select {|element| element.to_s.start_with?('b') }
3992 * # => ["bar", :bam]
3993 *
3994 * With no block given, returns a new Enumerator.
3995 *
3996 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3997 */
3998
3999static VALUE
4000rb_ary_select(VALUE ary)
4001{
4002 VALUE result;
4003 long i;
4004
4005 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
4006 result = rb_ary_new2(RARRAY_LEN(ary));
4007 for (i = 0; i < RARRAY_LEN(ary); i++) {
4008 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) {
4009 rb_ary_push(result, rb_ary_elt(ary, i));
4010 }
4011 }
4012 return result;
4013}
4014
4015struct select_bang_arg {
4016 VALUE ary;
4017 long len[2];
4018};
4019
4020static VALUE
4021select_bang_i(VALUE a)
4022{
4023 volatile struct select_bang_arg *arg = (void *)a;
4024 VALUE ary = arg->ary;
4025 long i1, i2;
4026
4027 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); arg->len[0] = ++i1) {
4028 VALUE v = RARRAY_AREF(ary, i1);
4029 if (!RTEST(rb_yield(v))) continue;
4030 if (i1 != i2) {
4031 rb_ary_store(ary, i2, v);
4032 }
4033 arg->len[1] = ++i2;
4034 }
4035 return (i1 == i2) ? Qnil : ary;
4036}
4037
4038static VALUE
4039select_bang_ensure(VALUE a)
4040{
4041 volatile struct select_bang_arg *arg = (void *)a;
4042 VALUE ary = arg->ary;
4043 long len = RARRAY_LEN(ary);
4044 long i1 = arg->len[0], i2 = arg->len[1];
4045
4046 if (i2 < len && i2 < i1) {
4047 long tail = 0;
4048 rb_ary_modify(ary);
4049 if (i1 < len) {
4050 tail = len - i1;
4051 RARRAY_PTR_USE(ary, ptr, {
4052 MEMMOVE(ptr + i2, ptr + i1, VALUE, tail);
4053 });
4054 }
4055 ARY_SET_LEN(ary, i2 + tail);
4056 }
4057 return ary;
4058}
4059
4060/*
4061 * call-seq:
4062 * select! {|element| ... } -> self or nil
4063 * select! -> new_enumerator
4064 * filter! {|element| ... } -> self or nil
4065 * filter! -> new_enumerator
4066 *
4067 * With a block given, calls the block with each element of +self+;
4068 * removes from +self+ those elements for which the block returns +false+ or +nil+.
4069 *
4070 * Returns +self+ if any elements were removed:
4071 *
4072 * a = [:foo, 'bar', 2, :bam]
4073 * a.select! {|element| element.to_s.start_with?('b') } # => ["bar", :bam]
4074 *
4075 * Returns +nil+ if no elements were removed.
4076 *
4077 * With no block given, returns a new Enumerator.
4078 *
4079 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4080 */
4081
4082static VALUE
4083rb_ary_select_bang(VALUE ary)
4084{
4085 struct select_bang_arg args;
4086
4087 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
4088 rb_ary_modify(ary);
4089
4090 args.ary = ary;
4091 args.len[0] = args.len[1] = 0;
4092 return rb_ensure(select_bang_i, (VALUE)&args, select_bang_ensure, (VALUE)&args);
4093}
4094
4095/*
4096 * call-seq:
4097 * keep_if {|element| ... } -> self
4098 * keep_if -> new_enumerator
4099 *
4100 * With a block given, calls the block with each element of +self+;
4101 * removes the element from +self+ if the block does not return a truthy value:
4102 *
4103 * a = [:foo, 'bar', 2, :bam]
4104 * a.keep_if {|element| element.to_s.start_with?('b') } # => ["bar", :bam]
4105 *
4106 * With no block given, returns a new Enumerator.
4107 *
4108 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4109 */
4110
4111static VALUE
4112rb_ary_keep_if(VALUE ary)
4113{
4114 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
4115 rb_ary_select_bang(ary);
4116 return ary;
4117}
4118
4119static void
4120ary_resize_smaller(VALUE ary, long len)
4121{
4122 rb_ary_modify(ary);
4123 if (RARRAY_LEN(ary) > len) {
4124 ARY_SET_LEN(ary, len);
4125 if (len * 2 < ARY_CAPA(ary) &&
4126 ARY_CAPA(ary) > ARY_DEFAULT_SIZE) {
4127 ary_resize_capa(ary, len * 2);
4128 }
4129 }
4130}
4131
4132/*
4133 * call-seq:
4134 * delete(object) -> last_removed_object
4135 * delete(object) {|element| ... } -> last_removed_object or block_return
4136 *
4137 * Removes zero or more elements from +self+.
4138 *
4139 * With no block given,
4140 * removes from +self+ each element +ele+ such that <tt>ele == object</tt>;
4141 * returns the last removed element:
4142 *
4143 * a = [0, 1, 2, 2.0]
4144 * a.delete(2) # => 2.0
4145 * a # => [0, 1]
4146 *
4147 * Returns +nil+ if no elements removed:
4148 *
4149 * a.delete(2) # => nil
4150 *
4151 * With a block given,
4152 * removes from +self+ each element +ele+ such that <tt>ele == object</tt>.
4153 *
4154 * If any such elements are found, ignores the block
4155 * and returns the last removed element:
4156 *
4157 * a = [0, 1, 2, 2.0]
4158 * a.delete(2) {|element| fail 'Cannot happen' } # => 2.0
4159 * a # => [0, 1]
4160 *
4161 * If no such element is found, returns the block's return value:
4162 *
4163 * a.delete(2) {|element| "Element #{element} not found." }
4164 * # => "Element 2 not found."
4165 *
4166 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4167 */
4168
4169 VALUE
4170 rb_ary_delete(VALUE ary, VALUE item)
4171{
4172 VALUE v = item;
4173 long i1, i2;
4174
4175 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
4176 VALUE e = RARRAY_AREF(ary, i1);
4177
4178 if (rb_equal(e, item)) {
4179 v = e;
4180 continue;
4181 }
4182 if (i1 != i2) {
4183 rb_ary_store(ary, i2, e);
4184 }
4185 i2++;
4186 }
4187 if (RARRAY_LEN(ary) == i2) {
4188 if (rb_block_given_p()) {
4189 return rb_yield(item);
4190 }
4191 return Qnil;
4192 }
4193
4194 ary_resize_smaller(ary, i2);
4195
4196 ary_verify(ary);
4197 return v;
4198}
4199
4200void
4201rb_ary_delete_same(VALUE ary, VALUE item)
4202{
4203 long i1, i2;
4204
4205 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
4206 VALUE e = RARRAY_AREF(ary, i1);
4207
4208 if (e == item) {
4209 continue;
4210 }
4211 if (i1 != i2) {
4212 rb_ary_store(ary, i2, e);
4213 }
4214 i2++;
4215 }
4216 if (RARRAY_LEN(ary) == i2) {
4217 return;
4218 }
4219
4220 ary_resize_smaller(ary, i2);
4221}
4222
4223 VALUE
4224 rb_ary_delete_at(VALUE ary, long pos)
4225{
4226 long len = RARRAY_LEN(ary);
4227 VALUE del;
4228
4229 if (pos >= len) return Qnil;
4230 if (pos < 0) {
4231 pos += len;
4232 if (pos < 0) return Qnil;
4233 }
4234
4235 rb_ary_modify(ary);
4236 del = RARRAY_AREF(ary, pos);
4237 RARRAY_PTR_USE(ary, ptr, {
4238 MEMMOVE(ptr+pos, ptr+pos+1, VALUE, len-pos-1);
4239 });
4240 ARY_INCREASE_LEN(ary, -1);
4241 ary_verify(ary);
4242 return del;
4243}
4244
4245/*
4246 * call-seq:
4247 * delete_at(index) -> removed_object or nil
4248 *
4249 * Removes the element of +self+ at the given +index+, which must be an
4250 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
4251 *
4252 * When +index+ is non-negative, deletes the element at offset +index+:
4253 *
4254 * a = [:foo, 'bar', 2]
4255 * a.delete_at(1) # => "bar"
4256 * a # => [:foo, 2]
4257 *
4258 * When +index+ is negative, counts backward from the end of the array:
4259 *
4260 * a = [:foo, 'bar', 2]
4261 * a.delete_at(-2) # => "bar"
4262 * a # => [:foo, 2]
4263 *
4264 * When +index+ is out of range, returns +nil+.
4265 *
4266 * a = [:foo, 'bar', 2]
4267 * a.delete_at(3) # => nil
4268 * a.delete_at(-4) # => nil
4269 *
4270 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4271 */
4272
4273static VALUE
4274rb_ary_delete_at_m(VALUE ary, VALUE pos)
4275{
4276 return rb_ary_delete_at(ary, NUM2LONG(pos));
4277}
4278
4279static VALUE
4280ary_slice_bang_by_rb_ary_splice(VALUE ary, long pos, long len)
4281{
4282 const long orig_len = RARRAY_LEN(ary);
4283
4284 if (len < 0) {
4285 return Qnil;
4286 }
4287 else if (pos < -orig_len) {
4288 return Qnil;
4289 }
4290 else if (pos < 0) {
4291 pos += orig_len;
4292 }
4293 else if (orig_len < pos) {
4294 return Qnil;
4295 }
4296 if (orig_len < pos + len) {
4297 len = orig_len - pos;
4298 }
4299 if (len == 0) {
4300 return rb_ary_new2(0);
4301 }
4302 else {
4303 VALUE arg2 = rb_ary_new4(len, RARRAY_CONST_PTR(ary)+pos);
4304 rb_ary_splice(ary, pos, len, 0, 0);
4305 return arg2;
4306 }
4307}
4308
4309/*
4310 * call-seq:
4311 * slice!(index) -> object or nil
4312 * slice!(start, length) -> new_array or nil
4313 * slice!(range) -> new_array or nil
4314 *
4315 * Removes and returns elements from +self+.
4316 *
4317 * With numeric argument +index+ given,
4318 * removes and returns the element at offset +index+:
4319 *
4320 * a = ['a', 'b', 'c', 'd']
4321 * a.slice!(2) # => "c"
4322 * a # => ["a", "b", "d"]
4323 * a.slice!(2.1) # => "d"
4324 * a # => ["a", "b"]
4325 *
4326 * If +index+ is negative, counts backwards from the end of +self+:
4327 *
4328 * a = ['a', 'b', 'c', 'd']
4329 * a.slice!(-2) # => "c"
4330 * a # => ["a", "b", "d"]
4331 *
4332 * If +index+ is out of range, returns +nil+.
4333 *
4334 * With numeric arguments +start+ and +length+ given,
4335 * removes +length+ elements from +self+ beginning at zero-based offset +start+;
4336 * returns the removed objects in a new array:
4337 *
4338 * a = ['a', 'b', 'c', 'd']
4339 * a.slice!(1, 2) # => ["b", "c"]
4340 * a # => ["a", "d"]
4341 * a.slice!(0.1, 1.1) # => ["a"]
4342 * a # => ["d"]
4343 *
4344 * If +start+ is negative, counts backwards from the end of +self+:
4345 *
4346 * a = ['a', 'b', 'c', 'd']
4347 * a.slice!(-2, 1) # => ["c"]
4348 * a # => ["a", "b", "d"]
4349 *
4350 * If +start+ is out-of-range, returns +nil+:
4351 *
4352 * a = ['a', 'b', 'c', 'd']
4353 * a.slice!(5, 1) # => nil
4354 * a.slice!(-5, 1) # => nil
4355 *
4356 * If <tt>start + length</tt> exceeds the array size,
4357 * removes and returns all elements from offset +start+ to the end:
4358 *
4359 * a = ['a', 'b', 'c', 'd']
4360 * a.slice!(2, 50) # => ["c", "d"]
4361 * a # => ["a", "b"]
4362 *
4363 * If <tt>start == a.size</tt> and +length+ is non-negative,
4364 * returns a new empty array.
4365 *
4366 * If +length+ is negative, returns +nil+.
4367 *
4368 * With Range argument +range+ given,
4369 * treats <tt>range.min</tt> as +start+ (as above)
4370 * and <tt>range.size</tt> as +length+ (as above):
4371 *
4372 * a = ['a', 'b', 'c', 'd']
4373 * a.slice!(1..2) # => ["b", "c"]
4374 * a # => ["a", "d"]
4375 *
4376 * If <tt>range.start == a.size</tt>, returns a new empty array:
4377 *
4378 * a = ['a', 'b', 'c', 'd']
4379 * a.slice!(4..5) # => []
4380 *
4381 * If <tt>range.start</tt> is larger than the array size, returns +nil+:
4382 *
4383 * a = ['a', 'b', 'c', 'd']
4384 a.slice!(5..6) # => nil
4385 *
4386 * If <tt>range.start</tt> is negative,
4387 * calculates the start index by counting backwards from the end of +self+:
4388 *
4389 * a = ['a', 'b', 'c', 'd']
4390 * a.slice!(-2..2) # => ["c"]
4391 *
4392 * If <tt>range.end</tt> is negative,
4393 * calculates the end index by counting backwards from the end of +self+:
4394 *
4395 * a = ['a', 'b', 'c', 'd']
4396 * a.slice!(0..-2) # => ["a", "b", "c"]
4397 *
4398 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4399 */
4400
4401static VALUE
4402rb_ary_slice_bang(int argc, VALUE *argv, VALUE ary)
4403{
4404 VALUE arg1;
4405 long pos, len;
4406
4407 rb_ary_modify_check(ary);
4408 rb_check_arity(argc, 1, 2);
4409 arg1 = argv[0];
4410
4411 if (argc == 2) {
4412 pos = NUM2LONG(argv[0]);
4413 len = NUM2LONG(argv[1]);
4414 return ary_slice_bang_by_rb_ary_splice(ary, pos, len);
4415 }
4416
4417 if (!FIXNUM_P(arg1)) {
4418 switch (rb_range_beg_len(arg1, &pos, &len, RARRAY_LEN(ary), 0)) {
4419 case Qtrue:
4420 /* valid range */
4421 return ary_slice_bang_by_rb_ary_splice(ary, pos, len);
4422 case Qnil:
4423 /* invalid range */
4424 return Qnil;
4425 default:
4426 /* not a range */
4427 break;
4428 }
4429 }
4430
4431 return rb_ary_delete_at(ary, NUM2LONG(arg1));
4432}
4433
4434static VALUE
4435ary_reject(VALUE orig, VALUE result)
4436{
4437 long i;
4438
4439 for (i = 0; i < RARRAY_LEN(orig); i++) {
4440 VALUE v = RARRAY_AREF(orig, i);
4441
4442 if (!RTEST(rb_yield(v))) {
4443 rb_ary_push(result, v);
4444 }
4445 }
4446 return result;
4447}
4448
4449static VALUE
4450reject_bang_i(VALUE a)
4451{
4452 volatile struct select_bang_arg *arg = (void *)a;
4453 VALUE ary = arg->ary;
4454 long i1, i2;
4455
4456 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); arg->len[0] = ++i1) {
4457 VALUE v = RARRAY_AREF(ary, i1);
4458 if (RTEST(rb_yield(v))) continue;
4459 if (i1 != i2) {
4460 rb_ary_store(ary, i2, v);
4461 }
4462 arg->len[1] = ++i2;
4463 }
4464 return (i1 == i2) ? Qnil : ary;
4465}
4466
4467static VALUE
4468ary_reject_bang(VALUE ary)
4469{
4470 struct select_bang_arg args;
4471 rb_ary_modify_check(ary);
4472 args.ary = ary;
4473 args.len[0] = args.len[1] = 0;
4474 return rb_ensure(reject_bang_i, (VALUE)&args, select_bang_ensure, (VALUE)&args);
4475}
4476
4477/*
4478 * call-seq:
4479 * reject! {|element| ... } -> self or nil
4480 * reject! -> new_enumerator
4481 *
4482 * With a block given, calls the block with each element of +self+;
4483 * removes each element for which the block returns a truthy value.
4484 *
4485 * Returns +self+ if any elements removed:
4486 *
4487 * a = [:foo, 'bar', 2, 'bat']
4488 * a.reject! {|element| element.to_s.start_with?('b') } # => [:foo, 2]
4489 *
4490 * Returns +nil+ if no elements removed.
4491 *
4492 * With no block given, returns a new Enumerator.
4493 *
4494 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4495 */
4496
4497static VALUE
4498rb_ary_reject_bang(VALUE ary)
4499{
4500 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
4501 rb_ary_modify(ary);
4502 return ary_reject_bang(ary);
4503}
4504
4505/*
4506 * call-seq:
4507 * reject {|element| ... } -> new_array
4508 * reject -> new_enumerator
4509 *
4510 * With a block given, returns a new array whose elements are all those from +self+
4511 * for which the block returns +false+ or +nil+:
4512 *
4513 * a = [:foo, 'bar', 2, 'bat']
4514 * a1 = a.reject {|element| element.to_s.start_with?('b') }
4515 * a1 # => [:foo, 2]
4516 *
4517 * With no block given, returns a new Enumerator.
4518 *
4519 * Related: {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
4520 */
4521
4522static VALUE
4523rb_ary_reject(VALUE ary)
4524{
4525 VALUE rejected_ary;
4526
4527 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
4528 rejected_ary = rb_ary_new();
4529 ary_reject(ary, rejected_ary);
4530 return rejected_ary;
4531}
4532
4533/*
4534 * call-seq:
4535 * delete_if {|element| ... } -> self
4536 * delete_if -> new_numerator
4537 *
4538 * With a block given, calls the block with each element of +self+;
4539 * removes the element if the block returns a truthy value;
4540 * returns +self+:
4541 *
4542 * a = [:foo, 'bar', 2, 'bat']
4543 * a.delete_if {|element| element.to_s.start_with?('b') } # => [:foo, 2]
4544 *
4545 * With no block given, returns a new Enumerator.
4546 *
4547 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4548 */
4549
4550static VALUE
4551rb_ary_delete_if(VALUE ary)
4552{
4553 ary_verify(ary);
4554 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
4555 ary_reject_bang(ary);
4556 return ary;
4557}
4558
4559static VALUE
4560take_i(RB_BLOCK_CALL_FUNC_ARGLIST(val, cbarg))
4561{
4562 VALUE *args = (VALUE *)cbarg;
4563 if (argc > 1) val = rb_ary_new4(argc, argv);
4564 rb_ary_push(args[0], val);
4565 if (--args[1] == 0) rb_iter_break();
4566 return Qnil;
4567}
4568
4569static VALUE
4570take_items(VALUE obj, long n)
4571{
4572 VALUE result = rb_check_array_type(obj);
4573 VALUE args[2];
4574
4575 if (n == 0) return result;
4576 if (!NIL_P(result)) return rb_ary_subseq(result, 0, n);
4577 result = rb_ary_new2(n);
4578 args[0] = result; args[1] = (VALUE)n;
4579 if (UNDEF_P(rb_check_block_call(obj, idEach, 0, 0, take_i, (VALUE)args)))
4580 rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (must respond to :each)",
4581 rb_obj_class(obj));
4582 return result;
4583}
4584
4585
4586/*
4587 * call-seq:
4588 * zip(*other_arrays) -> new_array
4589 * zip(*other_arrays) {|sub_array| ... } -> nil
4590 *
4591 * With no block given, combines +self+ with the collection of +other_arrays+;
4592 * returns a new array of sub-arrays:
4593 *
4594 * [0, 1].zip(['zero', 'one'], [:zero, :one])
4595 * # => [[0, "zero", :zero], [1, "one", :one]]
4596 *
4597 * Returned:
4598 *
4599 * - The outer array is of size <tt>self.size</tt>.
4600 * - Each sub-array is of size <tt>other_arrays.size + 1</tt>.
4601 * - The _nth_ sub-array contains (in order):
4602 *
4603 * - The _nth_ element of +self+.
4604 * - The _nth_ element of each of the other arrays, as available.
4605 *
4606 * Example:
4607 *
4608 * a = [0, 1]
4609 * zipped = a.zip(['zero', 'one'], [:zero, :one])
4610 * # => [[0, "zero", :zero], [1, "one", :one]]
4611 * zipped.size # => 2 # Same size as a.
4612 * zipped.first.size # => 3 # Size of other arrays plus 1.
4613 *
4614 * When the other arrays are all the same size as +self+,
4615 * the returned sub-arrays are a rearrangement containing exactly elements of all the arrays
4616 * (including +self+), with no omissions or additions:
4617 *
4618 * a = [:a0, :a1, :a2, :a3]
4619 * b = [:b0, :b1, :b2, :b3]
4620 * c = [:c0, :c1, :c2, :c3]
4621 * d = a.zip(b, c)
4622 * pp d
4623 * # =>
4624 * [[:a0, :b0, :c0],
4625 * [:a1, :b1, :c1],
4626 * [:a2, :b2, :c2],
4627 * [:a3, :b3, :c3]]
4628 *
4629 * When one of the other arrays is smaller than +self+,
4630 * pads the corresponding sub-array with +nil+ elements:
4631 *
4632 * a = [:a0, :a1, :a2, :a3]
4633 * b = [:b0, :b1, :b2]
4634 * c = [:c0, :c1]
4635 * d = a.zip(b, c)
4636 * pp d
4637 * # =>
4638 * [[:a0, :b0, :c0],
4639 * [:a1, :b1, :c1],
4640 * [:a2, :b2, nil],
4641 * [:a3, nil, nil]]
4642 *
4643 * When one of the other arrays is larger than +self+,
4644 * _ignores_ its trailing elements:
4645 *
4646 * a = [:a0, :a1, :a2, :a3]
4647 * b = [:b0, :b1, :b2, :b3, :b4]
4648 * c = [:c0, :c1, :c2, :c3, :c4, :c5]
4649 * d = a.zip(b, c)
4650 * pp d
4651 * # =>
4652 * [[:a0, :b0, :c0],
4653 * [:a1, :b1, :c1],
4654 * [:a2, :b2, :c2],
4655 * [:a3, :b3, :c3]]
4656 *
4657 * With a block given, calls the block with each of the other arrays;
4658 * returns +nil+:
4659 *
4660 * d = []
4661 * a = [:a0, :a1, :a2, :a3]
4662 * b = [:b0, :b1, :b2, :b3]
4663 * c = [:c0, :c1, :c2, :c3]
4664 * a.zip(b, c) {|sub_array| d.push(sub_array.reverse) } # => nil
4665 * pp d
4666 * # =>
4667 * [[:c0, :b0, :a0],
4668 * [:c1, :b1, :a1],
4669 * [:c2, :b2, :a2],
4670 * [:c3, :b3, :a3]]
4671 *
4672 * For an *object* in *other_arrays* that is not actually an array,
4673 * forms the "other array" as <tt>object.to_ary</tt>, if defined,
4674 * or as <tt>object.each.to_a</tt> otherwise.
4675 *
4676 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
4677 */
4678
4679static VALUE
4680rb_ary_zip(int argc, VALUE *argv, VALUE ary)
4681{
4682 int i, j;
4683 long len = RARRAY_LEN(ary);
4684 VALUE result = Qnil;
4685
4686 for (i=0; i<argc; i++) {
4687 argv[i] = take_items(argv[i], len);
4688 }
4689
4690 if (rb_block_given_p()) {
4691 int arity = rb_block_arity();
4692
4693 if (arity > 1) {
4694 VALUE work, *tmp;
4695
4696 tmp = ALLOCV_N(VALUE, work, argc+1);
4697
4698 for (i=0; i<RARRAY_LEN(ary); i++) {
4699 tmp[0] = RARRAY_AREF(ary, i);
4700 for (j=0; j<argc; j++) {
4701 tmp[j+1] = rb_ary_elt(argv[j], i);
4702 }
4703 rb_yield_values2(argc+1, tmp);
4704 }
4705
4706 if (work) ALLOCV_END(work);
4707 }
4708 else {
4709 for (i=0; i<RARRAY_LEN(ary); i++) {
4710 VALUE tmp = rb_ary_new2(argc+1);
4711
4712 rb_ary_push(tmp, RARRAY_AREF(ary, i));
4713 for (j=0; j<argc; j++) {
4714 rb_ary_push(tmp, rb_ary_elt(argv[j], i));
4715 }
4716 rb_yield(tmp);
4717 }
4718 }
4719 }
4720 else {
4721 result = rb_ary_new_capa(len);
4722
4723 for (i=0; i<len; i++) {
4724 VALUE tmp = rb_ary_new_capa(argc+1);
4725
4726 rb_ary_push(tmp, RARRAY_AREF(ary, i));
4727 for (j=0; j<argc; j++) {
4728 rb_ary_push(tmp, rb_ary_elt(argv[j], i));
4729 }
4730 rb_ary_push(result, tmp);
4731 }
4732 }
4733
4734 return result;
4735}
4736
4737/*
4738 * call-seq:
4739 * transpose -> new_array
4740 *
4741 * Returns a new array that is +self+
4742 * as a {transposed matrix}[https://en.wikipedia.org/wiki/Transpose]:
4743 *
4744 * a = [[:a0, :a1], [:b0, :b1], [:c0, :c1]]
4745 * a.transpose # => [[:a0, :b0, :c0], [:a1, :b1, :c1]]
4746 *
4747 * The elements of +self+ must all be the same size.
4748 *
4749 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
4750 */
4751
4752static VALUE
4753rb_ary_transpose(VALUE ary)
4754{
4755 long elen = -1, alen, i, j;
4756 VALUE tmp, result = 0;
4757
4758 alen = RARRAY_LEN(ary);
4759 if (alen == 0) return rb_ary_dup(ary);
4760 for (i=0; i<alen; i++) {
4761 tmp = to_ary(rb_ary_elt(ary, i));
4762 if (elen < 0) { /* first element */
4763 elen = RARRAY_LEN(tmp);
4764 result = rb_ary_new2(elen);
4765 for (j=0; j<elen; j++) {
4766 rb_ary_store(result, j, rb_ary_new2(alen));
4767 }
4768 }
4769 else if (elen != RARRAY_LEN(tmp)) {
4770 rb_raise(rb_eIndexError, "element size differs (%ld should be %ld)",
4771 RARRAY_LEN(tmp), elen);
4772 }
4773 for (j=0; j<elen; j++) {
4774 rb_ary_store(rb_ary_elt(result, j), i, rb_ary_elt(tmp, j));
4775 }
4776 }
4777 return result;
4778}
4779
4780/*
4781 * call-seq:
4782 * initialize_copy(other_array) -> self
4783 * replace(other_array) -> self
4784 *
4785 * Replaces the elements of +self+ with the elements of +other_array+, which must be an
4786 * {array-convertible object}[rdoc-ref:implicit_conversion.rdoc@Array-Convertible+Objects];
4787 * returns +self+:
4788 *
4789 * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
4790 * a.replace(['d', 'e']) # => ["d", "e"]
4791 *
4792 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
4793 */
4794
4795 VALUE
4796 rb_ary_replace(VALUE copy, VALUE orig)
4797{
4798 rb_ary_modify_check(copy);
4799 orig = to_ary(orig);
4800 if (copy == orig) return copy;
4801
4802 rb_ary_reset(copy);
4803
4804 /* orig has enough space to embed the contents of orig. */
4805 if (RARRAY_LEN(orig) <= ary_embed_capa(copy)) {
4806 RUBY_ASSERT(ARY_EMBED_P(copy));
4807 ary_memcpy(copy, 0, RARRAY_LEN(orig), RARRAY_CONST_PTR(orig));
4808 ARY_SET_EMBED_LEN(copy, RARRAY_LEN(orig));
4809 }
4810 /* orig is embedded but copy does not have enough space to embed the
4811 * contents of orig. */
4812 else if (ARY_EMBED_P(orig)) {
4813 long len = ARY_EMBED_LEN(orig);
4814 VALUE *ptr = ary_heap_alloc_buffer(len);
4815
4816 FL_UNSET_EMBED(copy);
4817 ARY_SET_PTR(copy, ptr);
4818 ARY_SET_LEN(copy, len);
4819 ARY_SET_CAPA(copy, len);
4820
4821 // No allocation and exception expected that could leave `copy` in a
4822 // bad state from the edits above.
4823 ary_memcpy(copy, 0, len, RARRAY_CONST_PTR(orig));
4824 }
4825 /* Otherwise, orig is on heap and copy does not have enough space to embed
4826 * the contents of orig. */
4827 else {
4828 VALUE shared_root = ary_make_shared(orig);
4829 FL_UNSET_EMBED(copy);
4830 ARY_SET_PTR(copy, ARY_HEAP_PTR(orig));
4831 ARY_SET_LEN(copy, ARY_HEAP_LEN(orig));
4832 rb_ary_set_shared(copy, shared_root);
4833
4834 RUBY_ASSERT(RB_OBJ_SHAREABLE_P(copy) ? RB_OBJ_SHAREABLE_P(shared_root) : 1);
4835 }
4836 ary_verify(copy);
4837 return copy;
4838}
4839
4840/*
4841 * call-seq:
4842 * clear -> self
4843 *
4844 * Removes all elements from +self+; returns +self+:
4845 *
4846 * a = [:foo, 'bar', 2]
4847 * a.clear # => []
4848 *
4849 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4850 */
4851
4852 VALUE
4853 rb_ary_clear(VALUE ary)
4854{
4855 rb_ary_modify_check(ary);
4856 if (ARY_SHARED_P(ary)) {
4857 rb_ary_unshare(ary);
4858 FL_SET_EMBED(ary);
4859 ARY_SET_EMBED_LEN(ary, 0);
4860 }
4861 else {
4862 ARY_SET_LEN(ary, 0);
4863 if (ARY_DEFAULT_SIZE * 2 < ARY_CAPA(ary)) {
4864 ary_resize_capa(ary, ARY_DEFAULT_SIZE * 2);
4865 }
4866 }
4867 ary_verify(ary);
4868 return ary;
4869}
4870
4871/*
4872 * call-seq:
4873 * fill(object, start = nil, count = nil) -> self
4874 * fill(object, range) -> self
4875 * fill(start = nil, count = nil) {|element| ... } -> self
4876 * fill(range) {|element| ... } -> self
4877 *
4878 * Replaces selected elements in +self+;
4879 * may add elements to +self+;
4880 * always returns +self+ (never a new array).
4881 *
4882 * In brief:
4883 *
4884 * # Non-negative start.
4885 * ['a', 'b', 'c', 'd'].fill('-', 1, 2) # => ["a", "-", "-", "d"]
4886 * ['a', 'b', 'c', 'd'].fill(1, 2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4887 *
4888 * # Extends with specified values if necessary.
4889 * ['a', 'b', 'c', 'd'].fill('-', 3, 2) # => ["a", "b", "c", "-", "-"]
4890 * ['a', 'b', 'c', 'd'].fill(3, 2) {|e| e.to_s } # => ["a", "b", "c", "3", "4"]
4891 *
4892 * # Fills with nils if necessary.
4893 * ['a', 'b', 'c', 'd'].fill('-', 6, 2) # => ["a", "b", "c", "d", nil, nil, "-", "-"]
4894 * ['a', 'b', 'c', 'd'].fill(6, 2) {|e| e.to_s } # => ["a", "b", "c", "d", nil, nil, "6", "7"]
4895 *
4896 * # For negative start, counts backwards from the end.
4897 * ['a', 'b', 'c', 'd'].fill('-', -3, 3) # => ["a", "-", "-", "-"]
4898 * ['a', 'b', 'c', 'd'].fill(-3, 3) {|e| e.to_s } # => ["a", "1", "2", "3"]
4899 *
4900 * # Range.
4901 * ['a', 'b', 'c', 'd'].fill('-', 1..2) # => ["a", "-", "-", "d"]
4902 * ['a', 'b', 'c', 'd'].fill(1..2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4903 *
4904 * When arguments +start+ and +count+ are given,
4905 * they select the elements of +self+ to be replaced;
4906 * each must be an
4907 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]
4908 * (or +nil+):
4909 *
4910 * - +start+ specifies the zero-based offset of the first element to be replaced;
4911 * +nil+ means zero.
4912 * - +count+ is the number of consecutive elements to be replaced;
4913 * +nil+ means "all the rest."
4914 *
4915 * With argument +object+ given,
4916 * that one object is used for all replacements:
4917 *
4918 * o = Object.new # => #<Object:0x0000014e7bff7600>
4919 * a = ['a', 'b', 'c', 'd'] # => ["a", "b", "c", "d"]
4920 * a.fill(o, 1, 2)
4921 * # => ["a", #<Object:0x0000014e7bff7600>, #<Object:0x0000014e7bff7600>, "d"]
4922 *
4923 * With a block given, the block is called once for each element to be replaced;
4924 * the value passed to the block is the _index_ of the element to be replaced
4925 * (not the element itself);
4926 * the block's return value replaces the element:
4927 *
4928 * a = ['a', 'b', 'c', 'd'] # => ["a", "b", "c", "d"]
4929 * a.fill(1, 2) {|element| element.to_s } # => ["a", "1", "2", "d"]
4930 *
4931 * For arguments +start+ and +count+:
4932 *
4933 * - If +start+ is non-negative,
4934 * replaces +count+ elements beginning at offset +start+:
4935 *
4936 * ['a', 'b', 'c', 'd'].fill('-', 0, 2) # => ["-", "-", "c", "d"]
4937 * ['a', 'b', 'c', 'd'].fill('-', 1, 2) # => ["a", "-", "-", "d"]
4938 * ['a', 'b', 'c', 'd'].fill('-', 2, 2) # => ["a", "b", "-", "-"]
4939 *
4940 * ['a', 'b', 'c', 'd'].fill(0, 2) {|e| e.to_s } # => ["0", "1", "c", "d"]
4941 * ['a', 'b', 'c', 'd'].fill(1, 2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4942 * ['a', 'b', 'c', 'd'].fill(2, 2) {|e| e.to_s } # => ["a", "b", "2", "3"]
4943 *
4944 * Extends +self+ if necessary:
4945 *
4946 * ['a', 'b', 'c', 'd'].fill('-', 3, 2) # => ["a", "b", "c", "-", "-"]
4947 * ['a', 'b', 'c', 'd'].fill('-', 4, 2) # => ["a", "b", "c", "d", "-", "-"]
4948 *
4949 * ['a', 'b', 'c', 'd'].fill(3, 2) {|e| e.to_s } # => ["a", "b", "c", "3", "4"]
4950 * ['a', 'b', 'c', 'd'].fill(4, 2) {|e| e.to_s } # => ["a", "b", "c", "d", "4", "5"]
4951 *
4952 * Fills with +nil+ if necessary:
4953 *
4954 * ['a', 'b', 'c', 'd'].fill('-', 5, 2) # => ["a", "b", "c", "d", nil, "-", "-"]
4955 * ['a', 'b', 'c', 'd'].fill('-', 6, 2) # => ["a", "b", "c", "d", nil, nil, "-", "-"]
4956 *
4957 * ['a', 'b', 'c', 'd'].fill(5, 2) {|e| e.to_s } # => ["a", "b", "c", "d", nil, "5", "6"]
4958 * ['a', 'b', 'c', 'd'].fill(6, 2) {|e| e.to_s } # => ["a", "b", "c", "d", nil, nil, "6", "7"]
4959 *
4960 * Does nothing if +count+ is non-positive:
4961 *
4962 * ['a', 'b', 'c', 'd'].fill('-', 2, 0) # => ["a", "b", "c", "d"]
4963 * ['a', 'b', 'c', 'd'].fill('-', 2, -100) # => ["a", "b", "c", "d"]
4964 * ['a', 'b', 'c', 'd'].fill('-', 6, -100) # => ["a", "b", "c", "d"]
4965 *
4966 * ['a', 'b', 'c', 'd'].fill(2, 0) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4967 * ['a', 'b', 'c', 'd'].fill(2, -100) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4968 * ['a', 'b', 'c', 'd'].fill(6, -100) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4969 *
4970 * - If +start+ is negative, counts backwards from the end of +self+:
4971 *
4972 * ['a', 'b', 'c', 'd'].fill('-', -4, 3) # => ["-", "-", "-", "d"]
4973 * ['a', 'b', 'c', 'd'].fill('-', -3, 3) # => ["a", "-", "-", "-"]
4974 *
4975 * ['a', 'b', 'c', 'd'].fill(-4, 3) {|e| e.to_s } # => ["0", "1", "2", "d"]
4976 * ['a', 'b', 'c', 'd'].fill(-3, 3) {|e| e.to_s } # => ["a", "1", "2", "3"]
4977 *
4978 * Extends +self+ if necessary:
4979 *
4980 * ['a', 'b', 'c', 'd'].fill('-', -2, 3) # => ["a", "b", "-", "-", "-"]
4981 * ['a', 'b', 'c', 'd'].fill('-', -1, 3) # => ["a", "b", "c", "-", "-", "-"]
4982 *
4983 * ['a', 'b', 'c', 'd'].fill(-2, 3) {|e| e.to_s } # => ["a", "b", "2", "3", "4"]
4984 * ['a', 'b', 'c', 'd'].fill(-1, 3) {|e| e.to_s } # => ["a", "b", "c", "3", "4", "5"]
4985 *
4986 * Starts at the beginning of +self+ if +start+ is negative and out-of-range:
4987 *
4988 * ['a', 'b', 'c', 'd'].fill('-', -5, 2) # => ["-", "-", "c", "d"]
4989 * ['a', 'b', 'c', 'd'].fill('-', -6, 2) # => ["-", "-", "c", "d"]
4990 *
4991 * ['a', 'b', 'c', 'd'].fill(-5, 2) {|e| e.to_s } # => ["0", "1", "c", "d"]
4992 * ['a', 'b', 'c', 'd'].fill(-6, 2) {|e| e.to_s } # => ["0", "1", "c", "d"]
4993 *
4994 * Does nothing if +count+ is non-positive:
4995 *
4996 * ['a', 'b', 'c', 'd'].fill('-', -2, 0) # => ["a", "b", "c", "d"]
4997 * ['a', 'b', 'c', 'd'].fill('-', -2, -1) # => ["a", "b", "c", "d"]
4998 *
4999 * ['a', 'b', 'c', 'd'].fill(-2, 0) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
5000 * ['a', 'b', 'c', 'd'].fill(-2, -1) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
5001 *
5002 * When argument +range+ is given,
5003 * it must be a Range object whose members are numeric;
5004 * its +begin+ and +end+ values determine the elements of +self+
5005 * to be replaced:
5006 *
5007 * - If both +begin+ and +end+ are positive, they specify the first and last elements
5008 * to be replaced:
5009 *
5010 * ['a', 'b', 'c', 'd'].fill('-', 1..2) # => ["a", "-", "-", "d"]
5011 * ['a', 'b', 'c', 'd'].fill(1..2) {|e| e.to_s } # => ["a", "1", "2", "d"]
5012 *
5013 * If +end+ is smaller than +begin+, replaces no elements:
5014 *
5015 * ['a', 'b', 'c', 'd'].fill('-', 2..1) # => ["a", "b", "c", "d"]
5016 * ['a', 'b', 'c', 'd'].fill(2..1) {|e| e.to_s } # => ["a", "b", "c", "d"]
5017 *
5018 * - If either is negative (or both are negative), counts backwards from the end of +self+:
5019 *
5020 * ['a', 'b', 'c', 'd'].fill('-', -3..2) # => ["a", "-", "-", "d"]
5021 * ['a', 'b', 'c', 'd'].fill('-', 1..-2) # => ["a", "-", "-", "d"]
5022 * ['a', 'b', 'c', 'd'].fill('-', -3..-2) # => ["a", "-", "-", "d"]
5023 *
5024 * ['a', 'b', 'c', 'd'].fill(-3..2) {|e| e.to_s } # => ["a", "1", "2", "d"]
5025 * ['a', 'b', 'c', 'd'].fill(1..-2) {|e| e.to_s } # => ["a", "1", "2", "d"]
5026 * ['a', 'b', 'c', 'd'].fill(-3..-2) {|e| e.to_s } # => ["a", "1", "2", "d"]
5027 *
5028 * - If the +end+ value is excluded (see Range#exclude_end?), omits the last replacement:
5029 *
5030 * ['a', 'b', 'c', 'd'].fill('-', 1...2) # => ["a", "-", "c", "d"]
5031 * ['a', 'b', 'c', 'd'].fill('-', 1...-2) # => ["a", "-", "c", "d"]
5032 *
5033 * ['a', 'b', 'c', 'd'].fill(1...2) {|e| e.to_s } # => ["a", "1", "c", "d"]
5034 * ['a', 'b', 'c', 'd'].fill(1...-2) {|e| e.to_s } # => ["a", "1", "c", "d"]
5035 *
5036 * - If the range is endless (see {Endless Ranges}[rdoc-ref:Range@Endless+Ranges]),
5037 * replaces elements to the end of +self+:
5038 *
5039 * ['a', 'b', 'c', 'd'].fill('-', 1..) # => ["a", "-", "-", "-"]
5040 * ['a', 'b', 'c', 'd'].fill(1..) {|e| e.to_s } # => ["a", "1", "2", "3"]
5041 *
5042 * - If the range is beginless (see {Beginless Ranges}[rdoc-ref:Range@Beginless+Ranges]),
5043 * replaces elements from the beginning of +self+:
5044 *
5045 * ['a', 'b', 'c', 'd'].fill('-', ..2) # => ["-", "-", "-", "d"]
5046 * ['a', 'b', 'c', 'd'].fill(..2) {|e| e.to_s } # => ["0", "1", "2", "d"]
5047 *
5048 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
5049 */
5050
5051static VALUE
5052rb_ary_fill(int argc, VALUE *argv, VALUE ary)
5053{
5054 VALUE item = Qundef, arg1, arg2;
5055 long beg = 0, end = 0, len = 0;
5056
5057 if (rb_block_given_p()) {
5058 rb_scan_args(argc, argv, "02", &arg1, &arg2);
5059 argc += 1; /* hackish */
5060 }
5061 else {
5062 rb_scan_args(argc, argv, "12", &item, &arg1, &arg2);
5063 }
5064 switch (argc) {
5065 case 1:
5066 beg = 0;
5067 len = RARRAY_LEN(ary);
5068 break;
5069 case 2:
5070 if (rb_range_beg_len(arg1, &beg, &len, RARRAY_LEN(ary), 1)) {
5071 break;
5072 }
5073 /* fall through */
5074 case 3:
5075 beg = NIL_P(arg1) ? 0 : NUM2LONG(arg1);
5076 if (beg < 0) {
5077 beg = RARRAY_LEN(ary) + beg;
5078 if (beg < 0) beg = 0;
5079 }
5080 len = NIL_P(arg2) ? RARRAY_LEN(ary) - beg : NUM2LONG(arg2);
5081 break;
5082 }
5083 rb_ary_modify(ary);
5084 if (len < 0) {
5085 return ary;
5086 }
5087 if (beg >= ARY_MAX_SIZE || len > ARY_MAX_SIZE - beg) {
5088 rb_raise(rb_eArgError, "argument too big");
5089 }
5090 end = beg + len;
5091 if (RARRAY_LEN(ary) < end) {
5092 if (end >= ARY_CAPA(ary)) {
5093 ary_resize_capa(ary, end);
5094 }
5095 ary_mem_clear(ary, RARRAY_LEN(ary), end - RARRAY_LEN(ary));
5096 ARY_SET_LEN(ary, end);
5097 }
5098
5099 if (UNDEF_P(item)) {
5100 VALUE v;
5101 long i;
5102
5103 for (i=beg; i<end; i++) {
5104 v = rb_yield(LONG2NUM(i));
5105 if (i>=RARRAY_LEN(ary)) break;
5106 ARY_SET(ary, i, v);
5107 }
5108 }
5109 else {
5110 ary_memfill(ary, beg, len, item);
5111 }
5112 return ary;
5113}
5114
5115/*
5116 * call-seq:
5117 * self + other_array -> new_array
5118 *
5119 * Returns a new array containing all elements of +self+
5120 * followed by all elements of +other_array+:
5121 *
5122 * a = [0, 1] + [2, 3]
5123 * a # => [0, 1, 2, 3]
5124 *
5125 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5126 */
5127
5128 VALUE
5129 rb_ary_plus(VALUE x, VALUE y)
5130{
5131 VALUE z;
5132 long len, xlen, ylen;
5133
5134 y = to_ary(y);
5135 xlen = RARRAY_LEN(x);
5136 ylen = RARRAY_LEN(y);
5137 len = xlen + ylen;
5138 z = rb_ary_new2(len);
5139
5140 ary_memcpy(z, 0, xlen, RARRAY_CONST_PTR(x));
5141 ary_memcpy(z, xlen, ylen, RARRAY_CONST_PTR(y));
5142 ARY_SET_LEN(z, len);
5143 return z;
5144}
5145
5146static VALUE
5147ary_append(VALUE x, VALUE y)
5148{
5149 long n = RARRAY_LEN(y);
5150 if (n > 0) {
5151 rb_ary_splice(x, RARRAY_LEN(x), 0, RARRAY_CONST_PTR(y), n);
5152 }
5153 RB_GC_GUARD(y);
5154 return x;
5155}
5156
5157/*
5158 * call-seq:
5159 * concat(*other_arrays) -> self
5160 *
5161 * Adds to +self+ all elements from each array in +other_arrays+; returns +self+:
5162 *
5163 * a = [0, 1]
5164 * a.concat(['two', 'three'], [:four, :five], a)
5165 * # => [0, 1, "two", "three", :four, :five, 0, 1]
5166 *
5167 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
5168 */
5169
5170static VALUE
5171rb_ary_concat_multi(int argc, VALUE *argv, VALUE ary)
5172{
5173 rb_ary_modify_check(ary);
5174
5175 if (argc == 1) {
5176 rb_ary_concat(ary, argv[0]);
5177 }
5178 else if (argc > 1) {
5179 int i;
5180 VALUE args = rb_ary_hidden_new(argc);
5181 for (i = 0; i < argc; i++) {
5182 rb_ary_concat(args, argv[i]);
5183 }
5184 ary_append(ary, args);
5185 }
5186
5187 ary_verify(ary);
5188 return ary;
5189}
5190
5191 VALUE
5192 rb_ary_concat(VALUE x, VALUE y)
5193{
5194 return ary_append(x, to_ary(y));
5195}
5196
5197/*
5198 * call-seq:
5199 * self * n -> new_array
5200 * self * string_separator -> new_string
5201 *
5202 * When non-negative integer argument +n+ is given,
5203 * returns a new array built by concatenating +n+ copies of +self+:
5204 *
5205 * a = ['x', 'y']
5206 * a * 3 # => ["x", "y", "x", "y", "x", "y"]
5207 *
5208 * When string argument +string_separator+ is given,
5209 * equivalent to <tt>self.join(string_separator)</tt>:
5210 *
5211 * [0, [0, 1], {foo: 0}] * ', ' # => "0, 0, 1, {foo: 0}"
5212 *
5213 */
5214
5215static VALUE
5216rb_ary_times(VALUE ary, VALUE times)
5217{
5218 VALUE ary2, tmp;
5219 const VALUE *ptr;
5220 long t, len;
5221
5222 tmp = rb_check_string_type(times);
5223 if (!NIL_P(tmp)) {
5224 return rb_ary_join(ary, tmp);
5225 }
5226
5227 len = NUM2LONG(times);
5228 if (len == 0) {
5229 ary2 = ary_new(rb_cArray, 0);
5230 goto out;
5231 }
5232 if (len < 0) {
5233 rb_raise(rb_eArgError, "negative argument");
5234 }
5235 if (ARY_MAX_SIZE/len < RARRAY_LEN(ary)) {
5236 rb_raise(rb_eArgError, "argument too big");
5237 }
5238 len *= RARRAY_LEN(ary);
5239
5240 ary2 = ary_new(rb_cArray, len);
5241 ARY_SET_LEN(ary2, len);
5242
5243 ptr = RARRAY_CONST_PTR(ary);
5244 t = RARRAY_LEN(ary);
5245 if (0 < t) {
5246 ary_memcpy(ary2, 0, t, ptr);
5247 while (t <= len/2) {
5248 ary_memcpy(ary2, t, t, RARRAY_CONST_PTR(ary2));
5249 t *= 2;
5250 }
5251 if (t < len) {
5252 ary_memcpy(ary2, t, len-t, RARRAY_CONST_PTR(ary2));
5253 }
5254 }
5255 out:
5256 return ary2;
5257}
5258
5259/*
5260 * call-seq:
5261 * assoc(object) -> found_array or nil
5262 *
5263 * Returns the first element +ele+ in +self+ such that +ele+ is an array
5264 * and <tt>ele[0] == object</tt>:
5265 *
5266 * a = [{foo: 0}, [2, 4], [4, 5, 6], [4, 5]]
5267 * a.assoc(4) # => [4, 5, 6]
5268 *
5269 * Returns +nil+ if no such element is found.
5270 *
5271 * Related: Array#rassoc;
5272 * see also {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
5273 */
5274
5275 VALUE
5276 rb_ary_assoc(VALUE ary, VALUE key)
5277{
5278 long i;
5279 VALUE v;
5280
5281 for (i = 0; i < RARRAY_LEN(ary); ++i) {
5282 v = rb_check_array_type(RARRAY_AREF(ary, i));
5283 if (!NIL_P(v) && RARRAY_LEN(v) > 0 &&
5284 rb_equal(RARRAY_AREF(v, 0), key))
5285 return v;
5286 }
5287 return Qnil;
5288}
5289
5290/*
5291 * call-seq:
5292 * rassoc(object) -> found_array or nil
5293 *
5294 * Returns the first element +ele+ in +self+ such that +ele+ is an array
5295 * and <tt>ele[1] == object</tt>:
5296 *
5297 * a = [{foo: 0}, [2, 4], [4, 5, 6], [4, 5]]
5298 * a.rassoc(4) # => [2, 4]
5299 * a.rassoc(5) # => [4, 5, 6]
5300 *
5301 * Returns +nil+ if no such element is found.
5302 *
5303 * Related: Array#assoc;
5304 * see also {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
5305 */
5306
5307 VALUE
5308 rb_ary_rassoc(VALUE ary, VALUE value)
5309{
5310 long i;
5311 VALUE v;
5312
5313 for (i = 0; i < RARRAY_LEN(ary); ++i) {
5314 v = rb_check_array_type(RARRAY_AREF(ary, i));
5315 if (RB_TYPE_P(v, T_ARRAY) &&
5316 RARRAY_LEN(v) > 1 &&
5317 rb_equal(RARRAY_AREF(v, 1), value))
5318 return v;
5319 }
5320 return Qnil;
5321}
5322
5323static VALUE
5324recursive_equal(VALUE ary1, VALUE ary2, int recur)
5325{
5326 long i, len1;
5327 const VALUE *p1, *p2;
5328
5329 if (recur) return Qtrue; /* Subtle! */
5330
5331 /* rb_equal() can evacuate ptrs */
5332 p1 = RARRAY_CONST_PTR(ary1);
5333 p2 = RARRAY_CONST_PTR(ary2);
5334 len1 = RARRAY_LEN(ary1);
5335
5336 for (i = 0; i < len1; i++) {
5337 if (*p1 != *p2) {
5338 if (rb_equal(*p1, *p2)) {
5339 len1 = RARRAY_LEN(ary1);
5340 if (len1 != RARRAY_LEN(ary2))
5341 return Qfalse;
5342 if (len1 < i)
5343 return Qtrue;
5344 p1 = RARRAY_CONST_PTR(ary1) + i;
5345 p2 = RARRAY_CONST_PTR(ary2) + i;
5346 }
5347 else {
5348 return Qfalse;
5349 }
5350 }
5351 p1++;
5352 p2++;
5353 }
5354 return Qtrue;
5355}
5356
5357/*
5358 * call-seq:
5359 * self == other_array -> true or false
5360 *
5361 * Returns whether both:
5362 *
5363 * - +self+ and +other_array+ are the same size.
5364 * - Their corresponding elements are the same;
5365 * that is, for each index +i+ in <tt>(0...self.size)</tt>,
5366 * <tt>self[i] == other_array[i]</tt>.
5367 *
5368 * Examples:
5369 *
5370 * [:foo, 'bar', 2] == [:foo, 'bar', 2] # => true
5371 * [:foo, 'bar', 2] == [:foo, 'bar', 2.0] # => true
5372 * [:foo, 'bar', 2] == [:foo, 'bar'] # => false # Different sizes.
5373 * [:foo, 'bar', 2] == [:foo, 'bar', 3] # => false # Different elements.
5374 *
5375 * This method is different from method Array#eql?,
5376 * which compares elements using <tt>Object#eql?</tt>.
5377 *
5378 * Related: see {Methods for Comparing}[rdoc-ref:Array@Methods+for+Comparing].
5379 */
5380
5381static VALUE
5382rb_ary_equal(VALUE ary1, VALUE ary2)
5383{
5384 if (ary1 == ary2) return Qtrue;
5385 if (!RB_TYPE_P(ary2, T_ARRAY)) {
5386 if (!rb_respond_to(ary2, idTo_ary)) {
5387 return Qfalse;
5388 }
5389 return rb_equal(ary2, ary1);
5390 }
5391 if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return Qfalse;
5392 if (RARRAY_CONST_PTR(ary1) == RARRAY_CONST_PTR(ary2)) return Qtrue;
5393 return rb_exec_recursive_paired(recursive_equal, ary1, ary2, ary2);
5394}
5395
5396static VALUE
5397recursive_eql(VALUE ary1, VALUE ary2, int recur)
5398{
5399 long i;
5400
5401 if (recur) return Qtrue; /* Subtle! */
5402 for (i=0; i<RARRAY_LEN(ary1); i++) {
5403 if (!rb_eql(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i)))
5404 return Qfalse;
5405 }
5406 return Qtrue;
5407}
5408
5409/*
5410 * call-seq:
5411 * eql?(other_array) -> true or false
5412 *
5413 * Returns +true+ if +self+ and +other_array+ are the same size,
5414 * and if, for each index +i+ in +self+, <tt>self[i].eql?(other_array[i])</tt>:
5415 *
5416 * a0 = [:foo, 'bar', 2]
5417 * a1 = [:foo, 'bar', 2]
5418 * a1.eql?(a0) # => true
5419 *
5420 * Otherwise, returns +false+.
5421 *
5422 * This method is different from method Array#==,
5423 * which compares using method <tt>Object#==</tt>.
5424 *
5425 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
5426 */
5427
5428static VALUE
5429rb_ary_eql(VALUE ary1, VALUE ary2)
5430{
5431 if (ary1 == ary2) return Qtrue;
5432 if (!RB_TYPE_P(ary2, T_ARRAY)) return Qfalse;
5433 if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return Qfalse;
5434 if (RARRAY_CONST_PTR(ary1) == RARRAY_CONST_PTR(ary2)) return Qtrue;
5435 return rb_exec_recursive_paired(recursive_eql, ary1, ary2, ary2);
5436}
5437
5438static VALUE
5439ary_hash_values(long len, const VALUE *elements, const VALUE ary)
5440{
5441 long i;
5442 st_index_t h;
5443 VALUE n;
5444
5445 h = rb_hash_start(len);
5446 h = rb_hash_uint(h, (st_index_t)rb_ary_hash_values);
5447 for (i=0; i<len; i++) {
5448 n = rb_hash(elements[i]);
5449 h = rb_hash_uint(h, NUM2LONG(n));
5450 if (ary) {
5451 len = RARRAY_LEN(ary);
5452 elements = RARRAY_CONST_PTR(ary);
5453 }
5454 }
5455 h = rb_hash_end(h);
5456 return ST2FIX(h);
5457}
5458
5459 VALUE
5460rb_ary_hash_values(long len, const VALUE *elements)
5461{
5462 return ary_hash_values(len, elements, 0);
5463}
5464
5465/*
5466 * call-seq:
5467 * hash -> integer
5468 *
5469 * Returns the integer hash value for +self+.
5470 *
5471 * Two arrays with the same content will have the same hash value
5472 * (and will compare using eql?):
5473 *
5474 * ['a', 'b'].hash == ['a', 'b'].hash # => true
5475 * ['a', 'b'].hash == ['a', 'c'].hash # => false
5476 * ['a', 'b'].hash == ['a'].hash # => false
5477 *
5478 */
5479
5480static VALUE
5481rb_ary_hash(VALUE ary)
5482{
5483 RBIMPL_ASSERT_OR_ASSUME(ary);
5484 return ary_hash_values(RARRAY_LEN(ary), RARRAY_CONST_PTR(ary), ary);
5485}
5486
5487/*
5488 * call-seq:
5489 * include?(object) -> true or false
5490 *
5491 * Returns whether for some element +element+ in +self+,
5492 * <tt>object == element</tt>:
5493 *
5494 * [0, 1, 2].include?(2) # => true
5495 * [0, 1, 2].include?(2.0) # => true
5496 * [0, 1, 2].include?(2.1) # => false
5497 *
5498 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
5499 */
5500
5501 VALUE
5502 rb_ary_includes(VALUE ary, VALUE item)
5503{
5504 long i;
5505 VALUE e;
5506
5507 for (i=0; i<RARRAY_LEN(ary); i++) {
5508 e = RARRAY_AREF(ary, i);
5509 if (rb_equal(e, item)) {
5510 return Qtrue;
5511 }
5512 }
5513 return Qfalse;
5514}
5515
5516static VALUE
5517rb_ary_includes_by_eql(VALUE ary, VALUE item)
5518{
5519 long i;
5520 VALUE e;
5521
5522 for (i=0; i<RARRAY_LEN(ary); i++) {
5523 e = RARRAY_AREF(ary, i);
5524 if (rb_eql(item, e)) {
5525 return Qtrue;
5526 }
5527 }
5528 return Qfalse;
5529}
5530
5531static VALUE
5532recursive_cmp(VALUE ary1, VALUE ary2, int recur)
5533{
5534 long i, len;
5535
5536 if (recur) return Qundef; /* Subtle! */
5537 len = RARRAY_LEN(ary1);
5538 if (len > RARRAY_LEN(ary2)) {
5539 len = RARRAY_LEN(ary2);
5540 }
5541 for (i=0; i<len; i++) {
5542 VALUE e1 = rb_ary_elt(ary1, i), e2 = rb_ary_elt(ary2, i);
5543 VALUE v = rb_funcallv(e1, id_cmp, 1, &e2);
5544 if (v != INT2FIX(0)) {
5545 return v;
5546 }
5547 }
5548 return Qundef;
5549}
5550
5551/*
5552 * call-seq:
5553 * self <=> other_array -> -1, 0, or 1
5554 *
5555 * Returns -1, 0, or 1 as +self+ is determined
5556 * to be less than, equal to, or greater than +other_array+.
5557 *
5558 * Iterates over each index +i+ in <tt>(0...self.size)</tt>:
5559 *
5560 * - Computes <tt>result[i]</tt> as <tt>self[i] <=> other_array[i]</tt>.
5561 * - Immediately returns 1 if <tt>result[i]</tt> is 1:
5562 *
5563 * [0, 1, 2] <=> [0, 0, 2] # => 1
5564 *
5565 * - Immediately returns -1 if <tt>result[i]</tt> is -1:
5566 *
5567 * [0, 1, 2] <=> [0, 2, 2] # => -1
5568 *
5569 * - Continues if <tt>result[i]</tt> is 0.
5570 *
5571 * When every +result+ is 0,
5572 * returns <tt>self.size <=> other_array.size</tt>
5573 * (see Integer#<=>):
5574 *
5575 * [0, 1, 2] <=> [0, 1] # => 1
5576 * [0, 1, 2] <=> [0, 1, 2] # => 0
5577 * [0, 1, 2] <=> [0, 1, 2, 3] # => -1
5578 *
5579 * Note that when +other_array+ is larger than +self+,
5580 * its trailing elements do not affect the result:
5581 *
5582 * [0, 1, 2] <=> [0, 1, 2, -3] # => -1
5583 * [0, 1, 2] <=> [0, 1, 2, 0] # => -1
5584 * [0, 1, 2] <=> [0, 1, 2, 3] # => -1
5585 *
5586 * Related: see {Methods for Comparing}[rdoc-ref:Array@Methods+for+Comparing].
5587 */
5588
5589 VALUE
5590 rb_ary_cmp(VALUE ary1, VALUE ary2)
5591{
5592 long len;
5593 VALUE v;
5594
5595 ary2 = rb_check_array_type(ary2);
5596 if (NIL_P(ary2)) return Qnil;
5597 if (ary1 == ary2) return INT2FIX(0);
5598 v = rb_exec_recursive_paired(recursive_cmp, ary1, ary2, ary2);
5599 if (!UNDEF_P(v)) return v;
5600 len = RARRAY_LEN(ary1) - RARRAY_LEN(ary2);
5601 if (len == 0) return INT2FIX(0);
5602 if (len > 0) return INT2FIX(1);
5603 return INT2FIX(-1);
5604}
5605
5606static VALUE
5607ary_add_hash(VALUE hash, VALUE ary)
5608{
5609 long i;
5610
5611 for (i=0; i<RARRAY_LEN(ary); i++) {
5612 VALUE elt = RARRAY_AREF(ary, i);
5613 rb_hash_add_new_element(hash, elt, elt);
5614 }
5615 return hash;
5616}
5617
5618static inline VALUE
5619ary_tmp_hash_new(VALUE ary)
5620{
5621 long size = RARRAY_LEN(ary);
5622 VALUE hash = rb_hash_new_with_size(size);
5623
5624 RBASIC_CLEAR_CLASS(hash);
5625 return hash;
5626}
5627
5628static VALUE
5629ary_make_hash(VALUE ary)
5630{
5631 VALUE hash = ary_tmp_hash_new(ary);
5632 return ary_add_hash(hash, ary);
5633}
5634
5635static VALUE
5636ary_add_hash_by(VALUE hash, VALUE ary)
5637{
5638 long i;
5639
5640 for (i = 0; i < RARRAY_LEN(ary); ++i) {
5641 VALUE v = rb_ary_elt(ary, i), k = rb_yield(v);
5642 rb_hash_add_new_element(hash, k, v);
5643 }
5644 return hash;
5645}
5646
5647static VALUE
5648ary_make_hash_by(VALUE ary)
5649{
5650 VALUE hash = ary_tmp_hash_new(ary);
5651 return ary_add_hash_by(hash, ary);
5652}
5653
5654/*
5655 * call-seq:
5656 * self - other_array -> new_array
5657 *
5658 * Returns a new array containing only those elements of +self+
5659 * that are not found in +other_array+;
5660 * the order from +self+ is preserved:
5661 *
5662 * [0, 1, 1, 2, 1, 1, 3, 1, 1] - [1] # => [0, 2, 3]
5663 * [0, 1, 1, 2, 1, 1, 3, 1, 1] - [3, 2, 0, :foo] # => [1, 1, 1, 1, 1, 1]
5664 * [0, 1, 2] - [:foo] # => [0, 1, 2]
5665 *
5666 * Element are compared using method <tt>#eql?</tt>
5667 * (as defined in each element of +self+).
5668 *
5669 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5670 */
5671
5672 VALUE
5673rb_ary_diff(VALUE ary1, VALUE ary2)
5674{
5675 VALUE ary3;
5676 VALUE hash;
5677 long i;
5678
5679 ary2 = to_ary(ary2);
5680 if (RARRAY_LEN(ary2) == 0) { return ary_make_shared_copy(ary1); }
5681 ary3 = rb_ary_new();
5682
5683 if (RARRAY_LEN(ary1) <= SMALL_ARRAY_LEN || RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
5684 for (i=0; i<RARRAY_LEN(ary1); i++) {
5685 VALUE elt = rb_ary_elt(ary1, i);
5686 if (rb_ary_includes_by_eql(ary2, elt)) continue;
5687 rb_ary_push(ary3, elt);
5688 }
5689 return ary3;
5690 }
5691
5692 hash = ary_make_hash(ary2);
5693 for (i=0; i<RARRAY_LEN(ary1); i++) {
5694 if (rb_hash_stlike_lookup(hash, RARRAY_AREF(ary1, i), NULL)) continue;
5695 rb_ary_push(ary3, rb_ary_elt(ary1, i));
5696 }
5697
5698 return ary3;
5699}
5700
5701/*
5702 * call-seq:
5703 * difference(*other_arrays = []) -> new_array
5704 *
5705 * Returns a new array containing only those elements from +self+
5706 * that are not found in any of the given +other_arrays+;
5707 * items are compared using <tt>eql?</tt>; order from +self+ is preserved:
5708 *
5709 * [0, 1, 1, 2, 1, 1, 3, 1, 1].difference([1]) # => [0, 2, 3]
5710 * [0, 1, 2, 3].difference([3, 0], [1, 3]) # => [2]
5711 * [0, 1, 2].difference([4]) # => [0, 1, 2]
5712 * [0, 1, 2].difference # => [0, 1, 2]
5713 *
5714 * Returns a copy of +self+ if no arguments are given.
5715 *
5716 * Related: Array#-;
5717 * see also {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5718 */
5719
5720static VALUE
5721rb_ary_difference_multi(int argc, VALUE *argv, VALUE ary)
5722{
5723 VALUE ary_diff;
5724 long i, length;
5725 volatile VALUE t0;
5726 bool *is_hash = ALLOCV_N(bool, t0, argc);
5727 ary_diff = rb_ary_new();
5728 length = RARRAY_LEN(ary);
5729
5730 for (i = 0; i < argc; i++) {
5731 argv[i] = to_ary(argv[i]);
5732 is_hash[i] = (length > SMALL_ARRAY_LEN && RARRAY_LEN(argv[i]) > SMALL_ARRAY_LEN);
5733 if (is_hash[i]) argv[i] = ary_make_hash(argv[i]);
5734 }
5735
5736 for (i = 0; i < RARRAY_LEN(ary); i++) {
5737 int j;
5738 VALUE elt = rb_ary_elt(ary, i);
5739 for (j = 0; j < argc; j++) {
5740 if (is_hash[j]) {
5741 if (rb_hash_stlike_lookup(argv[j], elt, NULL))
5742 break;
5743 }
5744 else {
5745 if (rb_ary_includes_by_eql(argv[j], elt)) break;
5746 }
5747 }
5748 if (j == argc) rb_ary_push(ary_diff, elt);
5749 }
5750
5751 ALLOCV_END(t0);
5752
5753 return ary_diff;
5754}
5755
5756
5757/*
5758 * call-seq:
5759 * self & other_array -> new_array
5760 *
5761 * Returns a new array containing the _intersection_ of +self+ and +other_array+;
5762 * that is, containing those elements found in both +self+ and +other_array+:
5763 *
5764 * [0, 1, 2, 3] & [1, 2] # => [1, 2]
5765 *
5766 * Omits duplicates:
5767 *
5768 * [0, 1, 1, 0] & [0, 1] # => [0, 1]
5769 *
5770 * Preserves order from +self+:
5771 *
5772 * [0, 1, 2] & [3, 2, 1, 0] # => [0, 1, 2]
5773 *
5774 * Identifies common elements using method <tt>#eql?</tt>
5775 * (as defined in each element of +self+).
5776 *
5777 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5778 */
5779
5780
5781static VALUE
5782rb_ary_and(VALUE ary1, VALUE ary2)
5783{
5784 VALUE hash, ary3, v;
5785 st_data_t vv;
5786 long i;
5787
5788 ary2 = to_ary(ary2);
5789 ary3 = rb_ary_new();
5790 if (RARRAY_LEN(ary1) == 0 || RARRAY_LEN(ary2) == 0) return ary3;
5791
5792 if (RARRAY_LEN(ary1) <= SMALL_ARRAY_LEN && RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
5793 for (i=0; i<RARRAY_LEN(ary1); i++) {
5794 v = RARRAY_AREF(ary1, i);
5795 if (!rb_ary_includes_by_eql(ary2, v)) continue;
5796 if (rb_ary_includes_by_eql(ary3, v)) continue;
5797 rb_ary_push(ary3, v);
5798 }
5799 return ary3;
5800 }
5801
5802 hash = ary_make_hash(ary2);
5803
5804 for (i=0; i<RARRAY_LEN(ary1); i++) {
5805 v = RARRAY_AREF(ary1, i);
5806 vv = (st_data_t)v;
5807 if (rb_hash_stlike_delete(hash, &vv, 0)) {
5808 rb_ary_push(ary3, v);
5809 }
5810 }
5811
5812 return ary3;
5813}
5814
5815/*
5816 * call-seq:
5817 * intersection(*other_arrays) -> new_array
5818 *
5819 * Returns a new array containing each element in +self+ that is +#eql?+
5820 * to at least one element in each of the given +other_arrays+;
5821 * duplicates are omitted:
5822 *
5823 * [0, 0, 1, 1, 2, 3].intersection([0, 1, 2], [0, 1, 3]) # => [0, 1]
5824 *
5825 * Each element must correctly implement method <tt>#hash</tt>.
5826 *
5827 * Order from +self+ is preserved:
5828 *
5829 * [0, 1, 2].intersection([2, 1, 0]) # => [0, 1, 2]
5830 *
5831 * Returns a copy of +self+ if no arguments are given.
5832 *
5833 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5834 */
5835
5836static VALUE
5837rb_ary_intersection_multi(int argc, VALUE *argv, VALUE ary)
5838{
5839 VALUE result = rb_ary_dup(ary);
5840 int i;
5841
5842 for (i = 0; i < argc; i++) {
5843 result = rb_ary_and(result, argv[i]);
5844 }
5845
5846 return result;
5847}
5848
5849static int
5850ary_hash_orset(st_data_t *key, st_data_t *value, st_data_t arg, int existing)
5851{
5852 if (existing) return ST_STOP;
5853 *key = *value = (VALUE)arg;
5854 return ST_CONTINUE;
5855}
5856
5857static void
5858rb_ary_union(VALUE ary_union, VALUE ary)
5859{
5860 long i;
5861 for (i = 0; i < RARRAY_LEN(ary); i++) {
5862 VALUE elt = rb_ary_elt(ary, i);
5863 if (rb_ary_includes_by_eql(ary_union, elt)) continue;
5864 rb_ary_push(ary_union, elt);
5865 }
5866}
5867
5868static void
5869rb_ary_union_hash(VALUE hash, VALUE ary2)
5870{
5871 long i;
5872 for (i = 0; i < RARRAY_LEN(ary2); i++) {
5873 VALUE elt = RARRAY_AREF(ary2, i);
5874 if (!rb_hash_stlike_update(hash, (st_data_t)elt, ary_hash_orset, (st_data_t)elt)) {
5875 RB_OBJ_WRITTEN(hash, Qundef, elt);
5876 }
5877 }
5878}
5879
5880/*
5881 * call-seq:
5882 * self | other_array -> new_array
5883 *
5884 * Returns the union of +self+ and +other_array+;
5885 * duplicates are removed; order is preserved;
5886 * items are compared using <tt>eql?</tt>:
5887 *
5888 * [0, 1] | [2, 3] # => [0, 1, 2, 3]
5889 * [0, 1, 1] | [2, 2, 3] # => [0, 1, 2, 3]
5890 * [0, 1, 2] | [3, 2, 1, 0] # => [0, 1, 2, 3]
5891 *
5892 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5893 */
5894
5895static VALUE
5896rb_ary_or(VALUE ary1, VALUE ary2)
5897{
5898 VALUE hash;
5899
5900 ary2 = to_ary(ary2);
5901 if (RARRAY_LEN(ary1) + RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
5902 VALUE ary3 = rb_ary_new();
5903 rb_ary_union(ary3, ary1);
5904 rb_ary_union(ary3, ary2);
5905 return ary3;
5906 }
5907
5908 hash = ary_make_hash(ary1);
5909 rb_ary_union_hash(hash, ary2);
5910
5911 return rb_hash_values(hash);
5912}
5913
5914/*
5915 * call-seq:
5916 * union(*other_arrays) -> new_array
5917 *
5918 * Returns a new array that is the union of the elements of +self+
5919 * and all given arrays +other_arrays+;
5920 * items are compared using <tt>eql?</tt>:
5921 *
5922 * [0, 1, 2, 3].union([4, 5], [6, 7]) # => [0, 1, 2, 3, 4, 5, 6, 7]
5923 *
5924 * Removes duplicates (preserving the first found):
5925 *
5926 * [0, 1, 1].union([2, 1], [3, 1]) # => [0, 1, 2, 3]
5927 *
5928 * Preserves order (preserving the position of the first found):
5929 *
5930 * [3, 2, 1, 0].union([5, 3], [4, 2]) # => [3, 2, 1, 0, 5, 4]
5931 *
5932 * With no arguments given, returns a copy of +self+.
5933 *
5934 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5935 */
5936
5937static VALUE
5938rb_ary_union_multi(int argc, VALUE *argv, VALUE ary)
5939{
5940 int i;
5941 long sum;
5942 VALUE hash;
5943
5944 sum = RARRAY_LEN(ary);
5945 for (i = 0; i < argc; i++) {
5946 argv[i] = to_ary(argv[i]);
5947 sum += RARRAY_LEN(argv[i]);
5948 }
5949
5950 if (sum <= SMALL_ARRAY_LEN) {
5951 VALUE ary_union = rb_ary_new();
5952
5953 rb_ary_union(ary_union, ary);
5954 for (i = 0; i < argc; i++) rb_ary_union(ary_union, argv[i]);
5955
5956 return ary_union;
5957 }
5958
5959 hash = ary_make_hash(ary);
5960 for (i = 0; i < argc; i++) rb_ary_union_hash(hash, argv[i]);
5961
5962 return rb_hash_values(hash);
5963}
5964
5965/*
5966 * call-seq:
5967 * intersect?(other_array) -> true or false
5968 *
5969 * Returns whether +other_array+ has at least one element that is +#eql?+ to some element of +self+:
5970 *
5971 * [1, 2, 3].intersect?([3, 4, 5]) # => true
5972 * [1, 2, 3].intersect?([4, 5, 6]) # => false
5973 *
5974 * Each element must correctly implement method <tt>#hash</tt>.
5975 *
5976 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
5977 */
5978
5979static VALUE
5980rb_ary_intersect_p(VALUE ary1, VALUE ary2)
5981{
5982 VALUE hash, v, result, shorter, longer;
5983 st_data_t vv;
5984 long i;
5985
5986 ary2 = to_ary(ary2);
5987 if (RARRAY_LEN(ary1) == 0 || RARRAY_LEN(ary2) == 0) return Qfalse;
5988
5989 if (RARRAY_LEN(ary1) <= SMALL_ARRAY_LEN && RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
5990 for (i=0; i<RARRAY_LEN(ary1); i++) {
5991 v = RARRAY_AREF(ary1, i);
5992 if (rb_ary_includes_by_eql(ary2, v)) return Qtrue;
5993 }
5994 return Qfalse;
5995 }
5996
5997 shorter = ary1;
5998 longer = ary2;
5999 if (RARRAY_LEN(ary1) > RARRAY_LEN(ary2)) {
6000 longer = ary1;
6001 shorter = ary2;
6002 }
6003
6004 hash = ary_make_hash(shorter);
6005 result = Qfalse;
6006
6007 for (i=0; i<RARRAY_LEN(longer); i++) {
6008 v = RARRAY_AREF(longer, i);
6009 vv = (st_data_t)v;
6010 if (rb_hash_stlike_lookup(hash, vv, 0)) {
6011 result = Qtrue;
6012 break;
6013 }
6014 }
6015
6016 return result;
6017}
6018
6019static VALUE
6020ary_max_generic(VALUE ary, long i, VALUE vmax)
6021{
6022 RUBY_ASSERT(i > 0 && i < RARRAY_LEN(ary));
6023
6024 VALUE v;
6025 for (; i < RARRAY_LEN(ary); ++i) {
6026 v = RARRAY_AREF(ary, i);
6027
6028 if (rb_cmpint(rb_funcallv(vmax, id_cmp, 1, &v), vmax, v) < 0) {
6029 vmax = v;
6030 }
6031 }
6032
6033 return vmax;
6034}
6035
6036static VALUE
6037ary_max_opt_fixnum(VALUE ary, long i, VALUE vmax)
6038{
6039 const long n = RARRAY_LEN(ary);
6040 RUBY_ASSERT(i > 0 && i < n);
6041 RUBY_ASSERT(FIXNUM_P(vmax));
6042
6043 VALUE v;
6044 for (; i < n; ++i) {
6045 v = RARRAY_AREF(ary, i);
6046
6047 if (FIXNUM_P(v)) {
6048 if ((long)vmax < (long)v) {
6049 vmax = v;
6050 }
6051 }
6052 else {
6053 return ary_max_generic(ary, i, vmax);
6054 }
6055 }
6056
6057 return vmax;
6058}
6059
6060static VALUE
6061ary_max_opt_float(VALUE ary, long i, VALUE vmax)
6062{
6063 const long n = RARRAY_LEN(ary);
6064 RUBY_ASSERT(i > 0 && i < n);
6065 RUBY_ASSERT(RB_FLOAT_TYPE_P(vmax));
6066
6067 VALUE v;
6068 for (; i < n; ++i) {
6069 v = RARRAY_AREF(ary, i);
6070
6071 if (RB_FLOAT_TYPE_P(v)) {
6072 if (rb_float_cmp(vmax, v) < 0) {
6073 vmax = v;
6074 }
6075 }
6076 else {
6077 return ary_max_generic(ary, i, vmax);
6078 }
6079 }
6080
6081 return vmax;
6082}
6083
6084static VALUE
6085ary_max_opt_string(VALUE ary, long i, VALUE vmax)
6086{
6087 const long n = RARRAY_LEN(ary);
6088 RUBY_ASSERT(i > 0 && i < n);
6089 RUBY_ASSERT(STRING_P(vmax));
6090
6091 VALUE v;
6092 for (; i < n; ++i) {
6093 v = RARRAY_AREF(ary, i);
6094
6095 if (STRING_P(v)) {
6096 if (rb_str_cmp(vmax, v) < 0) {
6097 vmax = v;
6098 }
6099 }
6100 else {
6101 return ary_max_generic(ary, i, vmax);
6102 }
6103 }
6104
6105 return vmax;
6106}
6107
6108/*
6109 * call-seq:
6110 * max -> element
6111 * max(count) -> new_array
6112 * max {|a, b| ... } -> element
6113 * max(count) {|a, b| ... } -> new_array
6114 *
6115 * Returns one of the following:
6116 *
6117 * - The maximum-valued element from +self+.
6118 * - A new array of maximum-valued elements from +self+.
6119 *
6120 * Does not modify +self+.
6121 *
6122 * With no block given, each element in +self+ must respond to method <tt>#<=></tt>
6123 * with a numeric.
6124 *
6125 * With no argument and no block, returns the element in +self+
6126 * having the maximum value per method <tt>#<=></tt>:
6127 *
6128 * [1, 0, 3, 2].max # => 3
6129 *
6130 * With non-negative numeric argument +count+ and no block,
6131 * returns a new array with at most +count+ elements,
6132 * in descending order, per method <tt>#<=></tt>:
6133 *
6134 * [1, 0, 3, 2].max(3) # => [3, 2, 1]
6135 * [1, 0, 3, 2].max(3.0) # => [3, 2, 1]
6136 * [1, 0, 3, 2].max(9) # => [3, 2, 1, 0]
6137 * [1, 0, 3, 2].max(0) # => []
6138 *
6139 * With a block given, the block must return a numeric.
6140 *
6141 * With a block and no argument, calls the block <tt>self.size - 1</tt> times to compare elements;
6142 * returns the element having the maximum value per the block:
6143 *
6144 * ['0', '', '000', '00'].max {|a, b| a.size <=> b.size }
6145 * # => "000"
6146 *
6147 * With non-negative numeric argument +count+ and a block,
6148 * returns a new array with at most +count+ elements,
6149 * in descending order, per the block:
6150 *
6151 * ['0', '', '000', '00'].max(2) {|a, b| a.size <=> b.size }
6152 * # => ["000", "00"]
6153 *
6154 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
6155 */
6156static VALUE
6157rb_ary_max(int argc, VALUE *argv, VALUE ary)
6158{
6159 VALUE result = Qundef, v;
6160 VALUE num;
6161 long i;
6162
6163 if (rb_check_arity(argc, 0, 1) && !NIL_P(num = argv[0]))
6164 return rb_nmin_run(ary, num, 0, 1, 1);
6165
6166 const long n = RARRAY_LEN(ary);
6167 if (rb_block_given_p()) {
6168 for (i = 0; i < RARRAY_LEN(ary); i++) {
6169 v = RARRAY_AREF(ary, i);
6170 if (UNDEF_P(result) || rb_cmpint(rb_yield_values(2, v, result), v, result) > 0) {
6171 result = v;
6172 }
6173 }
6174 }
6175 else if (n > 0) {
6176 result = RARRAY_AREF(ary, 0);
6177 if (n > 1) {
6178 if (FIXNUM_P(result) && CMP_OPTIMIZABLE(INTEGER)) {
6179 return ary_max_opt_fixnum(ary, 1, result);
6180 }
6181 else if (STRING_P(result) && CMP_OPTIMIZABLE(STRING)) {
6182 return ary_max_opt_string(ary, 1, result);
6183 }
6184 else if (RB_FLOAT_TYPE_P(result) && CMP_OPTIMIZABLE(FLOAT)) {
6185 return ary_max_opt_float(ary, 1, result);
6186 }
6187 else {
6188 return ary_max_generic(ary, 1, result);
6189 }
6190 }
6191 }
6192 if (UNDEF_P(result)) return Qnil;
6193 return result;
6194}
6195
6196static VALUE
6197ary_min_generic(VALUE ary, long i, VALUE vmin)
6198{
6199 RUBY_ASSERT(i > 0 && i < RARRAY_LEN(ary));
6200
6201 VALUE v;
6202 for (; i < RARRAY_LEN(ary); ++i) {
6203 v = RARRAY_AREF(ary, i);
6204
6205 if (rb_cmpint(rb_funcallv(vmin, id_cmp, 1, &v), vmin, v) > 0) {
6206 vmin = v;
6207 }
6208 }
6209
6210 return vmin;
6211}
6212
6213static VALUE
6214ary_min_opt_fixnum(VALUE ary, long i, VALUE vmin)
6215{
6216 const long n = RARRAY_LEN(ary);
6217 RUBY_ASSERT(i > 0 && i < n);
6218 RUBY_ASSERT(FIXNUM_P(vmin));
6219
6220 VALUE a;
6221 for (; i < n; ++i) {
6222 a = RARRAY_AREF(ary, i);
6223
6224 if (FIXNUM_P(a)) {
6225 if ((long)vmin > (long)a) {
6226 vmin = a;
6227 }
6228 }
6229 else {
6230 return ary_min_generic(ary, i, vmin);
6231 }
6232 }
6233
6234 return vmin;
6235}
6236
6237static VALUE
6238ary_min_opt_float(VALUE ary, long i, VALUE vmin)
6239{
6240 const long n = RARRAY_LEN(ary);
6241 RUBY_ASSERT(i > 0 && i < n);
6242 RUBY_ASSERT(RB_FLOAT_TYPE_P(vmin));
6243
6244 VALUE a;
6245 for (; i < n; ++i) {
6246 a = RARRAY_AREF(ary, i);
6247
6248 if (RB_FLOAT_TYPE_P(a)) {
6249 if (rb_float_cmp(vmin, a) > 0) {
6250 vmin = a;
6251 }
6252 }
6253 else {
6254 return ary_min_generic(ary, i, vmin);
6255 }
6256 }
6257
6258 return vmin;
6259}
6260
6261static VALUE
6262ary_min_opt_string(VALUE ary, long i, VALUE vmin)
6263{
6264 const long n = RARRAY_LEN(ary);
6265 RUBY_ASSERT(i > 0 && i < n);
6266 RUBY_ASSERT(STRING_P(vmin));
6267
6268 VALUE a;
6269 for (; i < n; ++i) {
6270 a = RARRAY_AREF(ary, i);
6271
6272 if (STRING_P(a)) {
6273 if (rb_str_cmp(vmin, a) > 0) {
6274 vmin = a;
6275 }
6276 }
6277 else {
6278 return ary_min_generic(ary, i, vmin);
6279 }
6280 }
6281
6282 return vmin;
6283}
6284
6285/*
6286 * call-seq:
6287 * min -> element
6288 * min(count) -> new_array
6289 * min {|a, b| ... } -> element
6290 * min(count) {|a, b| ... } -> new_array
6291 *
6292 * Returns one of the following:
6293 *
6294 * - The minimum-valued element from +self+.
6295 * - A new array of minimum-valued elements from +self+.
6296 *
6297 * Does not modify +self+.
6298 *
6299 * With no block given, each element in +self+ must respond to method <tt>#<=></tt>
6300 * with a numeric.
6301 *
6302 * With no argument and no block, returns the element in +self+
6303 * having the minimum value per method <tt>#<=></tt>:
6304 *
6305 * [1, 0, 3, 2].min # => 0
6306 *
6307 * With non-negative numeric argument +count+ and no block,
6308 * returns a new array with at most +count+ elements,
6309 * in ascending order, per method <tt>#<=></tt>:
6310 *
6311 * [1, 0, 3, 2].min(3) # => [0, 1, 2]
6312 * [1, 0, 3, 2].min(3.0) # => [0, 1, 2]
6313 * [1, 0, 3, 2].min(9) # => [0, 1, 2, 3]
6314 * [1, 0, 3, 2].min(0) # => []
6315 *
6316 * With a block given, the block must return a numeric.
6317 *
6318 * With a block and no argument, calls the block <tt>self.size - 1</tt> times to compare elements;
6319 * returns the element having the minimum value per the block:
6320 *
6321 * ['0', '', '000', '00'].min {|a, b| a.size <=> b.size }
6322 * # => ""
6323 *
6324 * With non-negative numeric argument +count+ and a block,
6325 * returns a new array with at most +count+ elements,
6326 * in ascending order, per the block:
6327 *
6328 * ['0', '', '000', '00'].min(2) {|a, b| a.size <=> b.size }
6329 * # => ["", "0"]
6330 *
6331 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
6332 */
6333static VALUE
6334rb_ary_min(int argc, VALUE *argv, VALUE ary)
6335{
6336 VALUE result = Qundef, v;
6337 VALUE num;
6338 long i;
6339
6340 if (rb_check_arity(argc, 0, 1) && !NIL_P(num = argv[0]))
6341 return rb_nmin_run(ary, num, 0, 0, 1);
6342
6343 const long n = RARRAY_LEN(ary);
6344 if (rb_block_given_p()) {
6345 for (i = 0; i < RARRAY_LEN(ary); i++) {
6346 v = RARRAY_AREF(ary, i);
6347 if (UNDEF_P(result) || rb_cmpint(rb_yield_values(2, v, result), v, result) < 0) {
6348 result = v;
6349 }
6350 }
6351 }
6352 else if (n > 0) {
6353 result = RARRAY_AREF(ary, 0);
6354 if (n > 1) {
6355 if (FIXNUM_P(result) && CMP_OPTIMIZABLE(INTEGER)) {
6356 return ary_min_opt_fixnum(ary, 1, result);
6357 }
6358 else if (STRING_P(result) && CMP_OPTIMIZABLE(STRING)) {
6359 return ary_min_opt_string(ary, 1, result);
6360 }
6361 else if (RB_FLOAT_TYPE_P(result) && CMP_OPTIMIZABLE(FLOAT)) {
6362 return ary_min_opt_float(ary, 1, result);
6363 }
6364 else {
6365 return ary_min_generic(ary, 1, result);
6366 }
6367 }
6368 }
6369 if (UNDEF_P(result)) return Qnil;
6370 return result;
6371}
6372
6373/*
6374 * call-seq:
6375 * minmax -> array
6376 * minmax {|a, b| ... } -> array
6377 *
6378 * Returns a 2-element array containing the minimum-valued and maximum-valued
6379 * elements from +self+;
6380 * does not modify +self+.
6381 *
6382 * With no block given, the minimum and maximum values are determined using method <tt>#<=></tt>:
6383 *
6384 * [1, 0, 3, 2].minmax # => [0, 3]
6385 *
6386 * With a block given, the block must return a numeric;
6387 * the block is called <tt>self.size - 1</tt> times to compare elements;
6388 * returns the elements having the minimum and maximum values per the block:
6389 *
6390 * ['0', '', '000', '00'].minmax {|a, b| a.size <=> b.size }
6391 * # => ["", "000"]
6392 *
6393 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
6394 */
6395static VALUE
6396rb_ary_minmax(VALUE ary)
6397{
6398 if (rb_block_given_p()) {
6399 return rb_call_super(0, NULL);
6400 }
6401 return rb_assoc_new(rb_ary_min(0, 0, ary), rb_ary_max(0, 0, ary));
6402}
6403
6404static int
6405push_value(st_data_t key, st_data_t val, st_data_t ary)
6406{
6407 rb_ary_push((VALUE)ary, (VALUE)val);
6408 return ST_CONTINUE;
6409}
6410
6411/*
6412 * call-seq:
6413 * uniq! -> self or nil
6414 * uniq! {|element| ... } -> self or nil
6415 *
6416 * Removes duplicate elements from +self+, the first occurrence always being retained;
6417 * returns +self+ if any elements removed, +nil+ otherwise.
6418 *
6419 * With no block given, identifies and removes elements using method <tt>eql?</tt>
6420 * to compare elements:
6421 *
6422 * a = [0, 0, 1, 1, 2, 2]
6423 * a.uniq! # => [0, 1, 2]
6424 * a.uniq! # => nil
6425 *
6426 * With a block given, calls the block for each element;
6427 * identifies and omits "duplicate" elements using method <tt>eql?</tt>
6428 * to compare <i>block return values</i>;
6429 * that is, an element is a duplicate if its block return value
6430 * is the same as that of a previous element:
6431 *
6432 * a = ['a', 'aa', 'aaa', 'b', 'bb', 'bbb']
6433 * a.uniq! {|element| element.size } # => ["a", "aa", "aaa"]
6434 * a.uniq! {|element| element.size } # => nil
6435 *
6436 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
6437 */
6438static VALUE
6439rb_ary_uniq_bang(VALUE ary)
6440{
6441 VALUE hash;
6442 long hash_size;
6443
6444 rb_ary_modify_check(ary);
6445 if (RARRAY_LEN(ary) <= 1)
6446 return Qnil;
6447 if (rb_block_given_p())
6448 hash = ary_make_hash_by(ary);
6449 else
6450 hash = ary_make_hash(ary);
6451
6452 hash_size = RHASH_SIZE(hash);
6453 if (RARRAY_LEN(ary) == hash_size) {
6454 return Qnil;
6455 }
6456 rb_ary_modify_check(ary);
6457 ARY_SET_LEN(ary, 0);
6458 if (ARY_SHARED_P(ary)) {
6459 rb_ary_unshare(ary);
6460 FL_SET_EMBED(ary);
6461 }
6462 ary_resize_capa(ary, hash_size);
6463 rb_hash_foreach(hash, push_value, ary);
6464
6465 return ary;
6466}
6467
6468/*
6469 * call-seq:
6470 * uniq -> new_array
6471 * uniq {|element| ... } -> new_array
6472 *
6473 * Returns a new array containing those elements from +self+ that are not duplicates,
6474 * the first occurrence always being retained.
6475 *
6476 * With no block given, identifies and omits duplicate elements using method <tt>eql?</tt>
6477 * to compare elements:
6478 *
6479 * a = [0, 0, 1, 1, 2, 2]
6480 * a.uniq # => [0, 1, 2]
6481 *
6482 * With a block given, calls the block for each element;
6483 * identifies and omits "duplicate" elements using method <tt>eql?</tt>
6484 * to compare <i>block return values</i>;
6485 * that is, an element is a duplicate if its block return value
6486 * is the same as that of a previous element:
6487 *
6488 * a = ['a', 'aa', 'aaa', 'b', 'bb', 'bbb']
6489 * a.uniq {|element| element.size } # => ["a", "aa", "aaa"]
6490 *
6491 * Related: {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
6492 */
6493
6494static VALUE
6495rb_ary_uniq(VALUE ary)
6496{
6497 VALUE hash, uniq;
6498
6499 if (RARRAY_LEN(ary) <= 1) {
6500 hash = 0;
6501 uniq = rb_ary_dup(ary);
6502 }
6503 else if (rb_block_given_p()) {
6504 hash = ary_make_hash_by(ary);
6505 uniq = rb_hash_values(hash);
6506 }
6507 else {
6508 hash = ary_make_hash(ary);
6509 uniq = rb_hash_values(hash);
6510 }
6511
6512 return uniq;
6513}
6514
6515/*
6516 * call-seq:
6517 * compact! -> self or nil
6518 *
6519 * Removes all +nil+ elements from +self+;
6520 * Returns +self+ if any elements are removed, +nil+ otherwise:
6521 *
6522 * a = [nil, 0, nil, false, nil, '', nil, [], nil, {}]
6523 * a.compact! # => [0, false, "", [], {}]
6524 * a # => [0, false, "", [], {}]
6525 * a.compact! # => nil
6526 *
6527 * Related: Array#compact;
6528 * see also {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
6529 */
6530
6531 VALUE
6532rb_ary_compact_bang(VALUE ary)
6533{
6534 VALUE *p, *t, *end;
6535 long n;
6536
6537 rb_ary_modify(ary);
6538 p = t = (VALUE *)RARRAY_CONST_PTR(ary); /* WB: no new reference */
6539 end = p + RARRAY_LEN(ary);
6540
6541 while (t < end) {
6542 if (NIL_P(*t)) t++;
6543 else *p++ = *t++;
6544 }
6545 n = p - RARRAY_CONST_PTR(ary);
6546 if (RARRAY_LEN(ary) == n) {
6547 return Qnil;
6548 }
6549 ary_resize_smaller(ary, n);
6550
6551 return ary;
6552}
6553
6554/*
6555 * call-seq:
6556 * compact -> new_array
6557 *
6558 * Returns a new array containing only the non-+nil+ elements from +self+;
6559 * element order is preserved:
6560 *
6561 * a = [nil, 0, nil, false, nil, '', nil, [], nil, {}]
6562 * a.compact # => [0, false, "", [], {}]
6563 *
6564 * Related: Array#compact!;
6565 * see also {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
6566 */
6567
6568static VALUE
6569rb_ary_compact(VALUE ary)
6570{
6571 ary = rb_ary_dup(ary);
6572 rb_ary_compact_bang(ary);
6573 return ary;
6574}
6575
6576/*
6577 * call-seq:
6578 * count -> integer
6579 * count(object) -> integer
6580 * count {|element| ... } -> integer
6581 *
6582 * Returns a count of specified elements.
6583 *
6584 * With no argument and no block, returns the count of all elements:
6585 *
6586 * [0, :one, 'two', 3, 3.0].count # => 5
6587 *
6588 * With argument +object+ given, returns the count of elements <tt>==</tt> to +object+:
6589 *
6590 * [0, :one, 'two', 3, 3.0].count(3) # => 2
6591 *
6592 * With no argument and a block given, calls the block with each element;
6593 * returns the count of elements for which the block returns a truthy value:
6594 *
6595 * [0, 1, 2, 3].count {|element| element > 1 } # => 2
6596 *
6597 * With argument +object+ and a block given, issues a warning, ignores the block,
6598 * and returns the count of elements <tt>==</tt> to +object+.
6599 *
6600 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
6601 */
6602
6603static VALUE
6604rb_ary_count(int argc, VALUE *argv, VALUE ary)
6605{
6606 long i, n = 0;
6607
6608 if (rb_check_arity(argc, 0, 1) == 0) {
6609 VALUE v;
6610
6611 if (!rb_block_given_p())
6612 return LONG2NUM(RARRAY_LEN(ary));
6613
6614 for (i = 0; i < RARRAY_LEN(ary); i++) {
6615 v = RARRAY_AREF(ary, i);
6616 if (RTEST(rb_yield(v))) n++;
6617 }
6618 }
6619 else {
6620 VALUE obj = argv[0];
6621
6622 if (rb_block_given_p()) {
6623 rb_warn("given block not used");
6624 }
6625 for (i = 0; i < RARRAY_LEN(ary); i++) {
6626 if (rb_equal(RARRAY_AREF(ary, i), obj)) n++;
6627 }
6628 }
6629
6630 return LONG2NUM(n);
6631}
6632
6633static VALUE
6634flatten(VALUE ary, int level)
6635{
6636 long i;
6637 VALUE stack, result, tmp = 0, elt;
6638 VALUE memo = Qfalse;
6639
6640 for (i = 0; i < RARRAY_LEN(ary); i++) {
6641 elt = RARRAY_AREF(ary, i);
6642 tmp = rb_check_array_type(elt);
6643 if (!NIL_P(tmp)) {
6644 break;
6645 }
6646 }
6647 if (i == RARRAY_LEN(ary)) {
6648 return ary;
6649 }
6650
6651 result = ary_new(0, RARRAY_LEN(ary));
6652 ary_memcpy(result, 0, i, RARRAY_CONST_PTR(ary));
6653 ARY_SET_LEN(result, i);
6654
6655 stack = ary_new(0, ARY_DEFAULT_SIZE);
6656 rb_ary_push(stack, ary);
6657 rb_ary_push(stack, LONG2NUM(i + 1));
6658
6659 if (level < 0) {
6660 memo = rb_obj_hide(rb_ident_hash_new());
6661 rb_hash_aset(memo, ary, Qtrue);
6662 rb_hash_aset(memo, tmp, Qtrue);
6663 }
6664
6665 ary = tmp;
6666 i = 0;
6667
6668 while (1) {
6669 while (i < RARRAY_LEN(ary)) {
6670 elt = RARRAY_AREF(ary, i++);
6671 if (level >= 0 && RARRAY_LEN(stack) / 2 >= level) {
6672 rb_ary_push(result, elt);
6673 continue;
6674 }
6675 tmp = rb_check_array_type(elt);
6676 if (RBASIC(result)->klass) {
6677 if (RTEST(memo)) {
6678 rb_hash_clear(memo);
6679 }
6680 rb_raise(rb_eRuntimeError, "flatten reentered");
6681 }
6682 if (NIL_P(tmp)) {
6683 rb_ary_push(result, elt);
6684 }
6685 else {
6686 if (memo) {
6687 if (rb_hash_aref(memo, tmp) == Qtrue) {
6688 rb_hash_clear(memo);
6689 rb_raise(rb_eArgError, "tried to flatten recursive array");
6690 }
6691 rb_hash_aset(memo, tmp, Qtrue);
6692 }
6693 rb_ary_push(stack, ary);
6694 rb_ary_push(stack, LONG2NUM(i));
6695 ary = tmp;
6696 i = 0;
6697 }
6698 }
6699 if (RARRAY_LEN(stack) == 0) {
6700 break;
6701 }
6702 if (memo) {
6703 rb_hash_delete(memo, ary);
6704 }
6705 tmp = rb_ary_pop(stack);
6706 i = NUM2LONG(tmp);
6707 ary = rb_ary_pop(stack);
6708 }
6709
6710 if (memo) {
6711 rb_hash_clear(memo);
6712 }
6713
6714 RBASIC_SET_CLASS(result, rb_cArray);
6715 return result;
6716}
6717
6718/*
6719 * call-seq:
6720 * flatten!(depth = nil) -> self or nil
6721 *
6722 * Returns +self+ as a recursively flattening of +self+ to +depth+ levels of recursion;
6723 * +depth+ must be an
6724 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects],
6725 * or +nil+.
6726 * At each level of recursion:
6727 *
6728 * - Each element that is an array is "flattened"
6729 * (that is, replaced by its individual array elements).
6730 * - Each element that is not an array is unchanged
6731 * (even if the element is an object that has instance method +flatten+).
6732 *
6733 * Returns +nil+ if no elements were flattened.
6734 *
6735 * With non-negative integer argument +depth+, flattens recursively through +depth+ levels:
6736 *
6737 * a = [ 0, [ 1, [2, 3], 4 ], 5, {foo: 0}, Set.new([6, 7]) ]
6738 * a # => [0, [1, [2, 3], 4], 5, {:foo=>0}, #<Set: {6, 7}>]
6739 * a.dup.flatten!(1) # => [0, 1, [2, 3], 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6740 * a.dup.flatten!(1.1) # => [0, 1, [2, 3], 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6741 * a.dup.flatten!(2) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6742 * a.dup.flatten!(3) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6743 *
6744 * With +nil+ or negative argument +depth+, flattens all levels:
6745 *
6746 * a.dup.flatten! # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6747 * a.dup.flatten!(-1) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6748 *
6749 * Related: Array#flatten;
6750 * see also {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
6751 */
6752
6753static VALUE
6754rb_ary_flatten_bang(int argc, VALUE *argv, VALUE ary)
6755{
6756 int mod = 0, level = -1;
6757 VALUE result, lv;
6758
6759 lv = (rb_check_arity(argc, 0, 1) ? argv[0] : Qnil);
6760 rb_ary_modify_check(ary);
6761 if (!NIL_P(lv)) level = NUM2INT(lv);
6762 if (level == 0) return Qnil;
6763
6764 result = flatten(ary, level);
6765 if (result == ary) {
6766 return Qnil;
6767 }
6768 if (!(mod = ARY_EMBED_P(result))) rb_ary_freeze(result);
6769 rb_ary_replace(ary, result);
6770 if (mod) ARY_SET_EMBED_LEN(result, 0);
6771
6772 return ary;
6773}
6774
6775/*
6776 * call-seq:
6777 * flatten(depth = nil) -> new_array
6778 *
6779 * Returns a new array that is a recursive flattening of +self+
6780 * to +depth+ levels of recursion;
6781 * +depth+ must be an
6782 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]
6783 * or +nil+.
6784 * At each level of recursion:
6785 *
6786 * - Each element that is an array is "flattened"
6787 * (that is, replaced by its individual array elements).
6788 * - Each element that is not an array is unchanged
6789 * (even if the element is an object that has instance method +flatten+).
6790 *
6791 * With non-negative integer argument +depth+, flattens recursively through +depth+ levels:
6792 *
6793 * a = [ 0, [ 1, [2, 3], 4 ], 5, {foo: 0}, Set.new([6, 7]) ]
6794 * a # => [0, [1, [2, 3], 4], 5, {:foo=>0}, #<Set: {6, 7}>]
6795 * a.flatten(0) # => [0, [1, [2, 3], 4], 5, {:foo=>0}, #<Set: {6, 7}>]
6796 * a.flatten(1 ) # => [0, 1, [2, 3], 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6797 * a.flatten(1.1) # => [0, 1, [2, 3], 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6798 * a.flatten(2) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6799 * a.flatten(3) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6800 *
6801 * With +nil+ or negative +depth+, flattens all levels.
6802 *
6803 * a.flatten # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6804 * a.flatten(-1) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6805 *
6806 * Related: Array#flatten!;
6807 * see also {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
6808 */
6809
6810static VALUE
6811rb_ary_flatten(int argc, VALUE *argv, VALUE ary)
6812{
6813 int level = -1;
6814 VALUE result;
6815
6816 if (rb_check_arity(argc, 0, 1) && !NIL_P(argv[0])) {
6817 level = NUM2INT(argv[0]);
6818 if (level == 0) return ary_make_shared_copy(ary);
6819 }
6820
6821 result = flatten(ary, level);
6822 if (result == ary) {
6823 result = ary_make_shared_copy(ary);
6824 }
6825
6826 return result;
6827}
6828
6829#define RAND_UPTO(max) (long)rb_random_ulong_limited((randgen), (max)-1)
6830
6831static VALUE
6832rb_ary_shuffle_bang(rb_execution_context_t *ec, VALUE ary, VALUE randgen)
6833{
6834 long i, len;
6835
6836 rb_ary_modify(ary);
6837 i = len = RARRAY_LEN(ary);
6838 RARRAY_PTR_USE(ary, ptr, {
6839 while (i > 1) {
6840 long j = RAND_UPTO(i);
6841 VALUE tmp;
6842 if (len != RARRAY_LEN(ary) || ptr != RARRAY_CONST_PTR(ary)) {
6843 rb_raise(rb_eRuntimeError, "modified during shuffle");
6844 }
6845 tmp = ptr[--i];
6846 ptr[i] = ptr[j];
6847 ptr[j] = tmp;
6848 }
6849 }); /* WB: no new reference */
6850 return ary;
6851}
6852
6853static VALUE
6854rb_ary_shuffle(rb_execution_context_t *ec, VALUE ary, VALUE randgen)
6855{
6856 ary = rb_ary_dup(ary);
6857 rb_ary_shuffle_bang(ec, ary, randgen);
6858 return ary;
6859}
6860
6861static const rb_data_type_t ary_sample_memo_type = {
6862 .wrap_struct_name = "ary_sample_memo",
6863 .function = {
6864 .dfree = (RUBY_DATA_FUNC)st_free_table,
6865 },
6866 .flags = RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY
6867};
6868
6869static VALUE
6870ary_sample(rb_execution_context_t *ec, VALUE ary, VALUE randgen, VALUE nv, VALUE to_array)
6871{
6872 VALUE result;
6873 long n, len, i, j, k, idx[10];
6874 long rnds[numberof(idx)];
6875 long memo_threshold;
6876
6877 len = RARRAY_LEN(ary);
6878 if (!to_array) {
6879 if (len < 2)
6880 i = 0;
6881 else
6882 i = RAND_UPTO(len);
6883
6884 return rb_ary_elt(ary, i);
6885 }
6886 n = NUM2LONG(nv);
6887 if (n < 0) rb_raise(rb_eArgError, "negative sample number");
6888 if (n > len) n = len;
6889 if (n <= numberof(idx)) {
6890 for (i = 0; i < n; ++i) {
6891 rnds[i] = RAND_UPTO(len - i);
6892 }
6893 }
6894 k = len;
6895 len = RARRAY_LEN(ary);
6896 if (len < k && n <= numberof(idx)) {
6897 for (i = 0; i < n; ++i) {
6898 if (rnds[i] >= len) return rb_ary_new_capa(0);
6899 }
6900 }
6901 if (n > len) n = len;
6902 switch (n) {
6903 case 0:
6904 return rb_ary_new_capa(0);
6905 case 1:
6906 i = rnds[0];
6907 return rb_ary_new_from_args(1, RARRAY_AREF(ary, i));
6908 case 2:
6909 i = rnds[0];
6910 j = rnds[1];
6911 if (j >= i) j++;
6912 return rb_ary_new_from_args(2, RARRAY_AREF(ary, i), RARRAY_AREF(ary, j));
6913 case 3:
6914 i = rnds[0];
6915 j = rnds[1];
6916 k = rnds[2];
6917 {
6918 long l = j, g = i;
6919 if (j >= i) l = i, g = ++j;
6920 if (k >= l && (++k >= g)) ++k;
6921 }
6922 return rb_ary_new_from_args(3, RARRAY_AREF(ary, i), RARRAY_AREF(ary, j), RARRAY_AREF(ary, k));
6923 }
6924 memo_threshold =
6925 len < 2560 ? len / 128 :
6926 len < 5120 ? len / 64 :
6927 len < 10240 ? len / 32 :
6928 len / 16;
6929 if (n <= numberof(idx)) {
6930 long sorted[numberof(idx)];
6931 sorted[0] = idx[0] = rnds[0];
6932 for (i=1; i<n; i++) {
6933 k = rnds[i];
6934 for (j = 0; j < i; ++j) {
6935 if (k < sorted[j]) break;
6936 ++k;
6937 }
6938 memmove(&sorted[j+1], &sorted[j], sizeof(sorted[0])*(i-j));
6939 sorted[j] = idx[i] = k;
6940 }
6941 result = rb_ary_new_capa(n);
6942 RARRAY_PTR_USE(result, ptr_result, {
6943 for (i=0; i<n; i++) {
6944 ptr_result[i] = RARRAY_AREF(ary, idx[i]);
6945 }
6946 });
6947 }
6948 else if (n <= memo_threshold / 2) {
6949 long max_idx = 0;
6950 VALUE vmemo = TypedData_Wrap_Struct(0, &ary_sample_memo_type, 0);
6951 st_table *memo = st_init_numtable_with_size(n);
6952 RTYPEDDATA_DATA(vmemo) = memo;
6953 result = rb_ary_new_capa(n);
6954 RARRAY_PTR_USE(result, ptr_result, {
6955 for (i=0; i<n; i++) {
6956 long r = RAND_UPTO(len-i) + i;
6957 ptr_result[i] = r;
6958 if (r > max_idx) max_idx = r;
6959 }
6960 len = RARRAY_LEN(ary);
6961 if (len <= max_idx) n = 0;
6962 else if (n > len) n = len;
6963 RARRAY_PTR_USE(ary, ptr_ary, {
6964 for (i=0; i<n; i++) {
6965 long j2 = j = ptr_result[i];
6966 long i2 = i;
6967 st_data_t value;
6968 if (st_lookup(memo, (st_data_t)i, &value)) i2 = (long)value;
6969 if (st_lookup(memo, (st_data_t)j, &value)) j2 = (long)value;
6970 st_insert(memo, (st_data_t)j, (st_data_t)i2);
6971 ptr_result[i] = ptr_ary[j2];
6972 }
6973 });
6974 });
6975 RTYPEDDATA_DATA(vmemo) = 0;
6976 st_free_table(memo);
6977 RB_GC_GUARD(vmemo);
6978 }
6979 else {
6980 result = rb_ary_dup(ary);
6981 RBASIC_CLEAR_CLASS(result);
6982 RB_GC_GUARD(ary);
6983 RARRAY_PTR_USE(result, ptr_result, {
6984 for (i=0; i<n; i++) {
6985 j = RAND_UPTO(len-i) + i;
6986 nv = ptr_result[j];
6987 ptr_result[j] = ptr_result[i];
6988 ptr_result[i] = nv;
6989 }
6990 });
6991 RBASIC_SET_CLASS_RAW(result, rb_cArray);
6992 }
6993 ARY_SET_LEN(result, n);
6994
6995 return result;
6996}
6997
6998static VALUE
6999ary_sized_alloc(rb_execution_context_t *ec, VALUE self)
7000{
7001 return rb_ary_new2(RARRAY_LEN(self));
7002}
7003
7004static VALUE
7005ary_sample0(rb_execution_context_t *ec, VALUE ary)
7006{
7007 return ary_sample(ec, ary, rb_cRandom, Qfalse, Qfalse);
7008}
7009
7010static VALUE
7011rb_ary_cycle_size(VALUE self, VALUE args, VALUE eobj)
7012{
7013 long mul;
7014 VALUE n = Qnil;
7015 if (args && (RARRAY_LEN(args) > 0)) {
7016 n = RARRAY_AREF(args, 0);
7017 }
7018 if (RARRAY_LEN(self) == 0) return INT2FIX(0);
7019 if (NIL_P(n)) return DBL2NUM(HUGE_VAL);
7020 mul = NUM2LONG(n);
7021 if (mul <= 0) return INT2FIX(0);
7022 n = LONG2FIX(mul);
7023 return rb_fix_mul_fix(rb_ary_length(self), n);
7024}
7025
7026/*
7027 * call-seq:
7028 * cycle(count = nil) {|element| ... } -> nil
7029 * cycle(count = nil) -> new_enumerator
7030 *
7031 * With a block given, may call the block, depending on the value of argument +count+;
7032 * +count+ must be an
7033 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects],
7034 * or +nil+.
7035 *
7036 * When +count+ is positive,
7037 * calls the block with each element, then does so repeatedly,
7038 * until it has done so +count+ times; returns +nil+:
7039 *
7040 * output = []
7041 * [0, 1].cycle(2) {|element| output.push(element) } # => nil
7042 * output # => [0, 1, 0, 1]
7043 *
7044 * When +count+ is zero or negative, does not call the block:
7045 *
7046 * [0, 1].cycle(0) {|element| fail 'Cannot happen' } # => nil
7047 * [0, 1].cycle(-1) {|element| fail 'Cannot happen' } # => nil
7048 *
7049 * When +count+ is +nil+, cycles forever:
7050 *
7051 * # Prints 0 and 1 forever.
7052 * [0, 1].cycle {|element| puts element }
7053 * [0, 1].cycle(nil) {|element| puts element }
7054 *
7055 * With no block given, returns a new Enumerator.
7056 *
7057 * Related: see {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
7058 */
7059static VALUE
7060rb_ary_cycle(int argc, VALUE *argv, VALUE ary)
7061{
7062 long n, i;
7063
7064 rb_check_arity(argc, 0, 1);
7065
7066 RETURN_SIZED_ENUMERATOR(ary, argc, argv, rb_ary_cycle_size);
7067 if (argc == 0 || NIL_P(argv[0])) {
7068 n = -1;
7069 }
7070 else {
7071 n = NUM2LONG(argv[0]);
7072 if (n <= 0) return Qnil;
7073 }
7074
7075 while (RARRAY_LEN(ary) > 0 && (n < 0 || 0 < n--)) {
7076 for (i=0; i<RARRAY_LEN(ary); i++) {
7077 rb_yield(RARRAY_AREF(ary, i));
7078 }
7079 }
7080 return Qnil;
7081}
7082
7083/*
7084 * Build a ruby array of the corresponding values and yield it to the
7085 * associated block.
7086 * Return the class of +values+ for reentry check.
7087 */
7088static int
7089yield_indexed_values(const VALUE values, const long r, const long *const p)
7090{
7091 const VALUE result = rb_ary_new2(r);
7092 long i;
7093
7094 for (i = 0; i < r; i++) ARY_SET(result, i, RARRAY_AREF(values, p[i]));
7095 ARY_SET_LEN(result, r);
7096 rb_yield(result);
7097 return !RBASIC(values)->klass;
7098}
7099
7100/*
7101 * Compute permutations of +r+ elements of the set <code>[0..n-1]</code>.
7102 *
7103 * When we have a complete permutation of array indices, copy the values
7104 * at those indices into a new array and yield that array.
7105 *
7106 * n: the size of the set
7107 * r: the number of elements in each permutation
7108 * p: the array (of size r) that we're filling in
7109 * used: an array of booleans: whether a given index is already used
7110 * values: the Ruby array that holds the actual values to permute
7111 */
7112static void
7113permute0(const long n, const long r, long *const p, char *const used, const VALUE values)
7114{
7115 long i = 0, index = 0;
7116
7117 for (;;) {
7118 const char *const unused = memchr(&used[i], 0, n-i);
7119 if (!unused) {
7120 if (!index) break;
7121 i = p[--index]; /* pop index */
7122 used[i++] = 0; /* index unused */
7123 }
7124 else {
7125 i = unused - used;
7126 p[index] = i;
7127 used[i] = 1; /* mark index used */
7128 ++index;
7129 if (index < r-1) { /* if not done yet */
7130 p[index] = i = 0;
7131 continue;
7132 }
7133 for (i = 0; i < n; ++i) {
7134 if (used[i]) continue;
7135 p[index] = i;
7136 if (!yield_indexed_values(values, r, p)) {
7137 rb_raise(rb_eRuntimeError, "permute reentered");
7138 }
7139 }
7140 i = p[--index]; /* pop index */
7141 used[i] = 0; /* index unused */
7142 p[index] = ++i;
7143 }
7144 }
7145}
7146
7147/*
7148 * Returns the product of from, from-1, ..., from - how_many + 1.
7149 * https://en.wikipedia.org/wiki/Pochhammer_symbol
7150 */
7151static VALUE
7152descending_factorial(long from, long how_many)
7153{
7154 VALUE cnt;
7155 if (how_many > 0) {
7156 cnt = LONG2FIX(from);
7157 while (--how_many > 0) {
7158 long v = --from;
7159 cnt = rb_int_mul(cnt, LONG2FIX(v));
7160 }
7161 }
7162 else {
7163 cnt = LONG2FIX(how_many == 0);
7164 }
7165 return cnt;
7166}
7167
7168static VALUE
7169binomial_coefficient(long comb, long size)
7170{
7171 VALUE r;
7172 long i;
7173 if (comb > size-comb) {
7174 comb = size-comb;
7175 }
7176 if (comb < 0) {
7177 return LONG2FIX(0);
7178 }
7179 else if (comb == 0) {
7180 return LONG2FIX(1);
7181 }
7182 r = LONG2FIX(size);
7183 for (i = 1; i < comb; ++i) {
7184 r = rb_int_mul(r, LONG2FIX(size - i));
7185 r = rb_int_idiv(r, LONG2FIX(i + 1));
7186 }
7187 return r;
7188}
7189
7190static VALUE
7191rb_ary_permutation_size(VALUE ary, VALUE args, VALUE eobj)
7192{
7193 long n = RARRAY_LEN(ary);
7194 long k = (args && (RARRAY_LEN(args) > 0)) ? NUM2LONG(RARRAY_AREF(args, 0)) : n;
7195
7196 return descending_factorial(n, k);
7197}
7198
7199/*
7200 * call-seq:
7201 * permutation(count = self.size) {|permutation| ... } -> self
7202 * permutation(count = self.size) -> new_enumerator
7203 *
7204 * Iterates over permutations of the elements of +self+;
7205 * the order of permutations is indeterminate.
7206 *
7207 * With a block and an in-range positive integer argument +count+ (<tt>0 < count <= self.size</tt>) given,
7208 * calls the block with each permutation of +self+ of size +count+;
7209 * returns +self+:
7210 *
7211 * a = [0, 1, 2]
7212 * perms = []
7213 * a.permutation(1) {|perm| perms.push(perm) }
7214 * perms # => [[0], [1], [2]]
7215 *
7216 * perms = []
7217 * a.permutation(2) {|perm| perms.push(perm) }
7218 * perms # => [[0, 1], [0, 2], [1, 0], [1, 2], [2, 0], [2, 1]]
7219 *
7220 * perms = []
7221 * a.permutation(3) {|perm| perms.push(perm) }
7222 * perms # => [[0, 1, 2], [0, 2, 1], [1, 0, 2], [1, 2, 0], [2, 0, 1], [2, 1, 0]]
7223 *
7224 * When +count+ is zero, calls the block once with a new empty array:
7225 *
7226 * perms = []
7227 * a.permutation(0) {|perm| perms.push(perm) }
7228 * perms # => [[]]
7229 *
7230 * When +count+ is out of range (negative or larger than <tt>self.size</tt>),
7231 * does not call the block:
7232 *
7233 * a.permutation(-1) {|permutation| fail 'Cannot happen' }
7234 * a.permutation(4) {|permutation| fail 'Cannot happen' }
7235 *
7236 * With no block given, returns a new Enumerator.
7237 *
7238 * Related: {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
7239 */
7240
7241static VALUE
7242rb_ary_permutation(int argc, VALUE *argv, VALUE ary)
7243{
7244 long r, n, i;
7245
7246 n = RARRAY_LEN(ary); /* Array length */
7247 RETURN_SIZED_ENUMERATOR(ary, argc, argv, rb_ary_permutation_size); /* Return enumerator if no block */
7248 r = n;
7249 if (rb_check_arity(argc, 0, 1) && !NIL_P(argv[0]))
7250 r = NUM2LONG(argv[0]); /* Permutation size from argument */
7251
7252 if (r < 0 || n < r) {
7253 /* no permutations: yield nothing */
7254 }
7255 else if (r == 0) { /* exactly one permutation: the zero-length array */
7256 rb_yield(rb_ary_new2(0));
7257 }
7258 else if (r == 1) { /* this is a special, easy case */
7259 for (i = 0; i < RARRAY_LEN(ary); i++) {
7260 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
7261 }
7262 }
7263 else { /* this is the general case */
7264 volatile VALUE t0;
7265 long *p = ALLOCV_N(long, t0, r+roomof(n, sizeof(long)));
7266 char *used = (char*)(p + r);
7267 VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
7268 RBASIC_CLEAR_CLASS(ary0);
7269
7270 MEMZERO(used, char, n); /* initialize array */
7271
7272 permute0(n, r, p, used, ary0); /* compute and yield permutations */
7273 ALLOCV_END(t0);
7274 RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
7275 }
7276 return ary;
7277}
7278
7279static void
7280combinate0(const long len, const long n, long *const stack, const VALUE values)
7281{
7282 long lev = 0;
7283
7284 MEMZERO(stack+1, long, n);
7285 stack[0] = -1;
7286 for (;;) {
7287 for (lev++; lev < n; lev++) {
7288 stack[lev+1] = stack[lev]+1;
7289 }
7290 if (!yield_indexed_values(values, n, stack+1)) {
7291 rb_raise(rb_eRuntimeError, "combination reentered");
7292 }
7293 do {
7294 if (lev == 0) return;
7295 stack[lev--]++;
7296 } while (stack[lev+1]+n == len+lev+1);
7297 }
7298}
7299
7300static VALUE
7301rb_ary_combination_size(VALUE ary, VALUE args, VALUE eobj)
7302{
7303 long n = RARRAY_LEN(ary);
7304 long k = NUM2LONG(RARRAY_AREF(args, 0));
7305
7306 return binomial_coefficient(k, n);
7307}
7308
7309/*
7310 * call-seq:
7311 * combination(count) {|element| ... } -> self
7312 * combination(count) -> new_enumerator
7313 *
7314 * When a block and a positive
7315 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]
7316 * argument +count+ (<tt>0 < count <= self.size</tt>)
7317 * are given, calls the block with each combination of +self+ of size +count+;
7318 * returns +self+:
7319 *
7320 * a = %w[a b c] # => ["a", "b", "c"]
7321 * a.combination(2) {|combination| p combination } # => ["a", "b", "c"]
7322 *
7323 * Output:
7324 *
7325 * ["a", "b"]
7326 * ["a", "c"]
7327 * ["b", "c"]
7328 *
7329 * The order of the yielded combinations is not guaranteed.
7330 *
7331 * When +count+ is zero, calls the block once with a new empty array:
7332 *
7333 * a.combination(0) {|combination| p combination }
7334 * [].combination(0) {|combination| p combination }
7335 *
7336 * Output:
7337 *
7338 * []
7339 * []
7340 *
7341 * When +count+ is negative or larger than +self.size+ and +self+ is non-empty,
7342 * does not call the block:
7343 *
7344 * a.combination(-1) {|combination| fail 'Cannot happen' } # => ["a", "b", "c"]
7345 * a.combination(4) {|combination| fail 'Cannot happen' } # => ["a", "b", "c"]
7346 *
7347 * With no block given, returns a new Enumerator.
7348 *
7349 * Related: Array#permutation;
7350 * see also {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
7351 */
7352
7353static VALUE
7354rb_ary_combination(VALUE ary, VALUE num)
7355{
7356 long i, n, len;
7357
7358 n = NUM2LONG(num);
7359 RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_combination_size);
7360 len = RARRAY_LEN(ary);
7361 if (n < 0 || len < n) {
7362 /* yield nothing */
7363 }
7364 else if (n == 0) {
7365 rb_yield(rb_ary_new2(0));
7366 }
7367 else if (n == 1) {
7368 for (i = 0; i < RARRAY_LEN(ary); i++) {
7369 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
7370 }
7371 }
7372 else {
7373 VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
7374 volatile VALUE t0;
7375 long *stack = ALLOCV_N(long, t0, n+1);
7376
7377 RBASIC_CLEAR_CLASS(ary0);
7378 combinate0(len, n, stack, ary0);
7379 ALLOCV_END(t0);
7380 RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
7381 }
7382 return ary;
7383}
7384
7385/*
7386 * Compute repeated permutations of +r+ elements of the set
7387 * <code>[0..n-1]</code>.
7388 *
7389 * When we have a complete repeated permutation of array indices, copy the
7390 * values at those indices into a new array and yield that array.
7391 *
7392 * n: the size of the set
7393 * r: the number of elements in each permutation
7394 * p: the array (of size r) that we're filling in
7395 * values: the Ruby array that holds the actual values to permute
7396 */
7397static void
7398rpermute0(const long n, const long r, long *const p, const VALUE values)
7399{
7400 long i = 0, index = 0;
7401
7402 p[index] = i;
7403 for (;;) {
7404 if (++index < r-1) {
7405 p[index] = i = 0;
7406 continue;
7407 }
7408 for (i = 0; i < n; ++i) {
7409 p[index] = i;
7410 if (!yield_indexed_values(values, r, p)) {
7411 rb_raise(rb_eRuntimeError, "repeated permute reentered");
7412 }
7413 }
7414 do {
7415 if (index <= 0) return;
7416 } while ((i = ++p[--index]) >= n);
7417 }
7418}
7419
7420static VALUE
7421rb_ary_repeated_permutation_size(VALUE ary, VALUE args, VALUE eobj)
7422{
7423 long n = RARRAY_LEN(ary);
7424 long k = NUM2LONG(RARRAY_AREF(args, 0));
7425
7426 if (k < 0) {
7427 return LONG2FIX(0);
7428 }
7429 if (n <= 0) {
7430 return LONG2FIX(!k);
7431 }
7432 return rb_int_positive_pow(n, (unsigned long)k);
7433}
7434
7435/*
7436 * call-seq:
7437 * repeated_permutation(size) {|permutation| ... } -> self
7438 * repeated_permutation(size) -> new_enumerator
7439 *
7440 * With a block given, calls the block with each repeated permutation of length +size+
7441 * of the elements of +self+;
7442 * each permutation is an array;
7443 * returns +self+. The order of the permutations is indeterminate.
7444 *
7445 * If a positive integer argument +size+ is given,
7446 * calls the block with each +size+-tuple repeated permutation of the elements of +self+.
7447 * The number of permutations is <tt>self.size**size</tt>.
7448 *
7449 * Examples:
7450 *
7451 * - +size+ is 1:
7452 *
7453 * p = []
7454 * [0, 1, 2].repeated_permutation(1) {|permutation| p.push(permutation) }
7455 * p # => [[0], [1], [2]]
7456 *
7457 * - +size+ is 2:
7458 *
7459 * p = []
7460 * [0, 1, 2].repeated_permutation(2) {|permutation| p.push(permutation) }
7461 * p # => [[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2], [2, 0], [2, 1], [2, 2]]
7462 *
7463 * If +size+ is zero, calls the block once with an empty array.
7464 *
7465 * If +size+ is negative, does not call the block:
7466 *
7467 * [0, 1, 2].repeated_permutation(-1) {|permutation| fail 'Cannot happen' }
7468 *
7469 * With no block given, returns a new Enumerator.
7470 *
7471 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
7472 */
7473static VALUE
7474rb_ary_repeated_permutation(VALUE ary, VALUE num)
7475{
7476 long r, n, i;
7477
7478 n = RARRAY_LEN(ary); /* Array length */
7479 RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_repeated_permutation_size); /* Return Enumerator if no block */
7480 r = NUM2LONG(num); /* Permutation size from argument */
7481
7482 if (r < 0) {
7483 /* no permutations: yield nothing */
7484 }
7485 else if (r == 0) { /* exactly one permutation: the zero-length array */
7486 rb_yield(rb_ary_new2(0));
7487 }
7488 else if (r == 1) { /* this is a special, easy case */
7489 for (i = 0; i < RARRAY_LEN(ary); i++) {
7490 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
7491 }
7492 }
7493 else { /* this is the general case */
7494 volatile VALUE t0;
7495 long *p = ALLOCV_N(long, t0, r);
7496 VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
7497 RBASIC_CLEAR_CLASS(ary0);
7498
7499 rpermute0(n, r, p, ary0); /* compute and yield repeated permutations */
7500 ALLOCV_END(t0);
7501 RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
7502 }
7503 return ary;
7504}
7505
7506static void
7507rcombinate0(const long n, const long r, long *const p, const long rest, const VALUE values)
7508{
7509 long i = 0, index = 0;
7510
7511 p[index] = i;
7512 for (;;) {
7513 if (++index < r-1) {
7514 p[index] = i;
7515 continue;
7516 }
7517 for (; i < n; ++i) {
7518 p[index] = i;
7519 if (!yield_indexed_values(values, r, p)) {
7520 rb_raise(rb_eRuntimeError, "repeated combination reentered");
7521 }
7522 }
7523 do {
7524 if (index <= 0) return;
7525 } while ((i = ++p[--index]) >= n);
7526 }
7527}
7528
7529static VALUE
7530rb_ary_repeated_combination_size(VALUE ary, VALUE args, VALUE eobj)
7531{
7532 long n = RARRAY_LEN(ary);
7533 long k = NUM2LONG(RARRAY_AREF(args, 0));
7534 if (k == 0) {
7535 return LONG2FIX(1);
7536 }
7537 return binomial_coefficient(k, n + k - 1);
7538}
7539
7540/*
7541 * call-seq:
7542 * repeated_combination(size) {|combination| ... } -> self
7543 * repeated_combination(size) -> new_enumerator
7544 *
7545 * With a block given, calls the block with each repeated combination of length +size+
7546 * of the elements of +self+;
7547 * each combination is an array;
7548 * returns +self+. The order of the combinations is indeterminate.
7549 *
7550 * If a positive integer argument +size+ is given,
7551 * calls the block with each +size+-tuple repeated combination of the elements of +self+.
7552 * The number of combinations is <tt>(size+1)(size+2)/2</tt>.
7553 *
7554 * Examples:
7555 *
7556 * - +size+ is 1:
7557 *
7558 * c = []
7559 * [0, 1, 2].repeated_combination(1) {|combination| c.push(combination) }
7560 * c # => [[0], [1], [2]]
7561 *
7562 * - +size+ is 2:
7563 *
7564 * c = []
7565 * [0, 1, 2].repeated_combination(2) {|combination| c.push(combination) }
7566 * c # => [[0, 0], [0, 1], [0, 2], [1, 1], [1, 2], [2, 2]]
7567 *
7568 * If +size+ is zero, calls the block once with an empty array.
7569 *
7570 * If +size+ is negative, does not call the block:
7571 *
7572 * [0, 1, 2].repeated_combination(-1) {|combination| fail 'Cannot happen' }
7573 *
7574 * With no block given, returns a new Enumerator.
7575 *
7576 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
7577 */
7578
7579static VALUE
7580rb_ary_repeated_combination(VALUE ary, VALUE num)
7581{
7582 long n, i, len;
7583
7584 n = NUM2LONG(num); /* Combination size from argument */
7585 RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_repeated_combination_size); /* Return enumerator if no block */
7586 len = RARRAY_LEN(ary);
7587 if (n < 0) {
7588 /* yield nothing */
7589 }
7590 else if (n == 0) {
7591 rb_yield(rb_ary_new2(0));
7592 }
7593 else if (n == 1) {
7594 for (i = 0; i < RARRAY_LEN(ary); i++) {
7595 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
7596 }
7597 }
7598 else if (len == 0) {
7599 /* yield nothing */
7600 }
7601 else {
7602 volatile VALUE t0;
7603 long *p = ALLOCV_N(long, t0, n);
7604 VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
7605 RBASIC_CLEAR_CLASS(ary0);
7606
7607 rcombinate0(len, n, p, n, ary0); /* compute and yield repeated combinations */
7608 ALLOCV_END(t0);
7609 RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
7610 }
7611 return ary;
7612}
7613
7614/*
7615 * call-seq:
7616 * product(*other_arrays) -> new_array
7617 * product(*other_arrays) {|combination| ... } -> self
7618 *
7619 * Computes all combinations of elements from all the arrays,
7620 * including both +self+ and +other_arrays+:
7621 *
7622 * - The number of combinations is the product of the sizes of all the arrays,
7623 * including both +self+ and +other_arrays+.
7624 * - The order of the returned combinations is indeterminate.
7625 *
7626 * With no block given, returns the combinations as an array of arrays:
7627 *
7628 * p = [0, 1].product([2, 3])
7629 * # => [[0, 2], [0, 3], [1, 2], [1, 3]]
7630 * p.size # => 4
7631 * p = [0, 1].product([2, 3], [4, 5])
7632 * # => [[0, 2, 4], [0, 2, 5], [0, 3, 4], [0, 3, 5], [1, 2, 4], [1, 2, 5], [1, 3, 4], [1, 3,...
7633 * p.size # => 8
7634 *
7635 * If +self+ or any argument is empty, returns an empty array:
7636 *
7637 * [].product([2, 3], [4, 5]) # => []
7638 * [0, 1].product([2, 3], []) # => []
7639 *
7640 * If no argument is given, returns an array of 1-element arrays,
7641 * each containing an element of +self+:
7642 *
7643 * a.product # => [[0], [1], [2]]
7644 *
7645 * With a block given, calls the block with each combination; returns +self+:
7646 *
7647 * p = []
7648 * [0, 1].product([2, 3]) {|combination| p.push(combination) }
7649 * p # => [[0, 2], [0, 3], [1, 2], [1, 3]]
7650 *
7651 * If +self+ or any argument is empty, does not call the block:
7652 *
7653 * [].product([2, 3], [4, 5]) {|combination| fail 'Cannot happen' }
7654 * # => []
7655 * [0, 1].product([2, 3], []) {|combination| fail 'Cannot happen' }
7656 * # => [0, 1]
7657 *
7658 * If no argument is given, calls the block with each element of +self+ as a 1-element array:
7659 *
7660 * p = []
7661 * [0, 1].product {|combination| p.push(combination) }
7662 * p # => [[0], [1]]
7663 *
7664 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
7665 */
7666
7667static VALUE
7668rb_ary_product(int argc, VALUE *argv, VALUE ary)
7669{
7670 int n = argc+1; /* How many arrays we're operating on */
7671 volatile VALUE t0 = rb_ary_hidden_new(n);
7672 volatile VALUE t1 = Qundef;
7673 VALUE *arrays = RARRAY_PTR(t0); /* The arrays we're computing the product of */
7674 int *counters = ALLOCV_N(int, t1, n); /* The current position in each one */
7675 VALUE result = Qnil; /* The array we'll be returning, when no block given */
7676 long i,j;
7677 long resultlen = 1;
7678
7679 RBASIC_CLEAR_CLASS(t0);
7680
7681 /* initialize the arrays of arrays */
7682 ARY_SET_LEN(t0, n);
7683 arrays[0] = ary;
7684 for (i = 1; i < n; i++) arrays[i] = Qnil;
7685 for (i = 1; i < n; i++) arrays[i] = to_ary(argv[i-1]);
7686
7687 /* initialize the counters for the arrays */
7688 for (i = 0; i < n; i++) counters[i] = 0;
7689
7690 /* Otherwise, allocate and fill in an array of results */
7691 if (rb_block_given_p()) {
7692 /* Make defensive copies of arrays; exit if any is empty */
7693 for (i = 0; i < n; i++) {
7694 if (RARRAY_LEN(arrays[i]) == 0) goto done;
7695 arrays[i] = ary_make_shared_copy(arrays[i]);
7696 }
7697 }
7698 else {
7699 /* Compute the length of the result array; return [] if any is empty */
7700 for (i = 0; i < n; i++) {
7701 long k = RARRAY_LEN(arrays[i]);
7702 if (k == 0) {
7703 result = rb_ary_new2(0);
7704 goto done;
7705 }
7706 if (MUL_OVERFLOW_LONG_P(resultlen, k))
7707 rb_raise(rb_eRangeError, "too big to product");
7708 resultlen *= k;
7709 }
7710 result = rb_ary_new2(resultlen);
7711 }
7712 for (;;) {
7713 int m;
7714 /* fill in one subarray */
7715 VALUE subarray = rb_ary_new2(n);
7716 for (j = 0; j < n; j++) {
7717 rb_ary_push(subarray, rb_ary_entry(arrays[j], counters[j]));
7718 }
7719
7720 /* put it on the result array */
7721 if (NIL_P(result)) {
7722 FL_SET(t0, RARRAY_SHARED_ROOT_FLAG);
7723 rb_yield(subarray);
7724 if (!FL_TEST(t0, RARRAY_SHARED_ROOT_FLAG)) {
7725 rb_raise(rb_eRuntimeError, "product reentered");
7726 }
7727 else {
7728 FL_UNSET(t0, RARRAY_SHARED_ROOT_FLAG);
7729 }
7730 }
7731 else {
7732 rb_ary_push(result, subarray);
7733 }
7734
7735 /*
7736 * Increment the last counter. If it overflows, reset to 0
7737 * and increment the one before it.
7738 */
7739 m = n-1;
7740 counters[m]++;
7741 while (counters[m] == RARRAY_LEN(arrays[m])) {
7742 counters[m] = 0;
7743 /* If the first counter overflows, we are done */
7744 if (--m < 0) goto done;
7745 counters[m]++;
7746 }
7747 }
7748
7749done:
7750 ALLOCV_END(t1);
7751
7752 return NIL_P(result) ? ary : result;
7753}
7754
7755/*
7756 * call-seq:
7757 * take(count) -> new_array
7758 *
7759 * Returns a new array containing the first +count+ element of +self+
7760 * (as available);
7761 * +count+ must be a non-negative numeric;
7762 * does not modify +self+:
7763 *
7764 * a = ['a', 'b', 'c', 'd']
7765 * a.take(2) # => ["a", "b"]
7766 * a.take(2.1) # => ["a", "b"]
7767 * a.take(50) # => ["a", "b", "c", "d"]
7768 * a.take(0) # => []
7769 *
7770 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
7771 */
7772
7773static VALUE
7774rb_ary_take(VALUE obj, VALUE n)
7775{
7776 long len = NUM2LONG(n);
7777 if (len < 0) {
7778 rb_raise(rb_eArgError, "attempt to take negative size");
7779 }
7780 return rb_ary_subseq(obj, 0, len);
7781}
7782
7783/*
7784 * call-seq:
7785 * take_while {|element| ... } -> new_array
7786 * take_while -> new_enumerator
7787 *
7788 * With a block given, calls the block with each successive element of +self+;
7789 * stops iterating if the block returns +false+ or +nil+;
7790 * returns a new array containing those elements for which the block returned a truthy value:
7791 *
7792 * a = [0, 1, 2, 3, 4, 5]
7793 * a.take_while {|element| element < 3 } # => [0, 1, 2]
7794 * a.take_while {|element| true } # => [0, 1, 2, 3, 4, 5]
7795 * a.take_while {|element| false } # => []
7796 *
7797 * With no block given, returns a new Enumerator.
7798 *
7799 * Does not modify +self+.
7800 *
7801 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
7802 */
7803
7804static VALUE
7805rb_ary_take_while(VALUE ary)
7806{
7807 long i;
7808
7809 RETURN_ENUMERATOR(ary, 0, 0);
7810 for (i = 0; i < RARRAY_LEN(ary); i++) {
7811 if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) break;
7812 }
7813 return rb_ary_take(ary, LONG2FIX(i));
7814}
7815
7816/*
7817 * call-seq:
7818 * drop(count) -> new_array
7819 *
7820 * Returns a new array containing all but the first +count+ element of +self+,
7821 * where +count+ is a non-negative integer;
7822 * does not modify +self+.
7823 *
7824 * Examples:
7825 *
7826 * a = [0, 1, 2, 3, 4, 5]
7827 * a.drop(0) # => [0, 1, 2, 3, 4, 5]
7828 * a.drop(1) # => [1, 2, 3, 4, 5]
7829 * a.drop(2) # => [2, 3, 4, 5]
7830 * a.drop(9) # => []
7831 *
7832 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
7833 */
7834
7835static VALUE
7836rb_ary_drop(VALUE ary, VALUE n)
7837{
7838 VALUE result;
7839 long pos = NUM2LONG(n);
7840 if (pos < 0) {
7841 rb_raise(rb_eArgError, "attempt to drop negative size");
7842 }
7843
7844 result = rb_ary_subseq(ary, pos, RARRAY_LEN(ary));
7845 if (NIL_P(result)) result = rb_ary_new();
7846 return result;
7847}
7848
7849/*
7850 * call-seq:
7851 * drop_while {|element| ... } -> new_array
7852 * drop_while -> new_enumerator
7853 *
7854 * With a block given, calls the block with each successive element of +self+;
7855 * stops if the block returns +false+ or +nil+;
7856 * returns a new array _omitting_ those elements for which the block returned a truthy value;
7857 * does not modify +self+:
7858 *
7859 * a = [0, 1, 2, 3, 4, 5]
7860 * a.drop_while {|element| element < 3 } # => [3, 4, 5]
7861 *
7862 * With no block given, returns a new Enumerator.
7863 *
7864 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
7865 */
7866
7867static VALUE
7868rb_ary_drop_while(VALUE ary)
7869{
7870 long i;
7871
7872 RETURN_ENUMERATOR(ary, 0, 0);
7873 for (i = 0; i < RARRAY_LEN(ary); i++) {
7874 if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) break;
7875 }
7876 return rb_ary_drop(ary, LONG2FIX(i));
7877}
7878
7879/*
7880 * call-seq:
7881 * any? -> true or false
7882 * any?(object) -> true or false
7883 * any? {|element| ... } -> true or false
7884 *
7885 * Returns whether for any element of +self+, a given criterion is satisfied.
7886 *
7887 * With no block and no argument, returns whether any element of +self+ is truthy:
7888 *
7889 * [nil, false, []].any? # => true # Array object is truthy.
7890 * [nil, false, {}].any? # => true # Hash object is truthy.
7891 * [nil, false, ''].any? # => true # String object is truthy.
7892 * [nil, false].any? # => false # Nil and false are not truthy.
7893 *
7894 * With argument +object+ given,
7895 * returns whether <tt>object === ele</tt> for any element +ele+ in +self+:
7896 *
7897 * [nil, false, 0].any?(0) # => true
7898 * [nil, false, 1].any?(0) # => false
7899 * [nil, false, 'food'].any?(/foo/) # => true
7900 * [nil, false, 'food'].any?(/bar/) # => false
7901 *
7902 * With a block given,
7903 * calls the block with each element in +self+;
7904 * returns whether the block returns any truthy value:
7905 *
7906 * [0, 1, 2].any? {|ele| ele < 1 } # => true
7907 * [0, 1, 2].any? {|ele| ele < 0 } # => false
7908 *
7909 * With both a block and argument +object+ given,
7910 * ignores the block and uses +object+ as above.
7911 *
7912 * <b>Special case</b>: returns +false+ if +self+ is empty
7913 * (regardless of any given argument or block).
7914 *
7915 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
7916 */
7917
7918static VALUE
7919rb_ary_any_p(int argc, VALUE *argv, VALUE ary)
7920{
7921 long i, len = RARRAY_LEN(ary);
7922
7923 rb_check_arity(argc, 0, 1);
7924 if (!len) return Qfalse;
7925 if (argc) {
7926 if (rb_block_given_p()) {
7927 rb_warn("given block not used");
7928 }
7929 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7930 if (RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) return Qtrue;
7931 }
7932 }
7933 else if (!rb_block_given_p()) {
7934 for (i = 0; i < len; ++i) {
7935 if (RTEST(RARRAY_AREF(ary, i))) return Qtrue;
7936 }
7937 }
7938 else {
7939 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7940 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) return Qtrue;
7941 }
7942 }
7943 return Qfalse;
7944}
7945
7946/*
7947 * call-seq:
7948 * all? -> true or false
7949 * all?(object) -> true or false
7950 * all? {|element| ... } -> true or false
7951 *
7952 * Returns whether for every element of +self+,
7953 * a given criterion is satisfied.
7954 *
7955 * With no block and no argument,
7956 * returns whether every element of +self+ is truthy:
7957 *
7958 * [[], {}, '', 0, 0.0, Object.new].all? # => true # All truthy objects.
7959 * [[], {}, '', 0, 0.0, nil].all? # => false # nil is not truthy.
7960 * [[], {}, '', 0, 0.0, false].all? # => false # false is not truthy.
7961 *
7962 * With argument +object+ given, returns whether <tt>object === ele</tt>
7963 * for every element +ele+ in +self+:
7964 *
7965 * [0, 0, 0].all?(0) # => true
7966 * [0, 1, 2].all?(1) # => false
7967 * ['food', 'fool', 'foot'].all?(/foo/) # => true
7968 * ['food', 'drink'].all?(/foo/) # => false
7969 *
7970 * With a block given, calls the block with each element in +self+;
7971 * returns whether the block returns only truthy values:
7972 *
7973 * [0, 1, 2].all? { |ele| ele < 3 } # => true
7974 * [0, 1, 2].all? { |ele| ele < 2 } # => false
7975 *
7976 * With both a block and argument +object+ given,
7977 * ignores the block and uses +object+ as above.
7978 *
7979 * <b>Special case</b>: returns +true+ if +self+ is empty
7980 * (regardless of any given argument or block).
7981 *
7982 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
7983 */
7984
7985static VALUE
7986rb_ary_all_p(int argc, VALUE *argv, VALUE ary)
7987{
7988 long i, len = RARRAY_LEN(ary);
7989
7990 rb_check_arity(argc, 0, 1);
7991 if (!len) return Qtrue;
7992 if (argc) {
7993 if (rb_block_given_p()) {
7994 rb_warn("given block not used");
7995 }
7996 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7997 if (!RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) return Qfalse;
7998 }
7999 }
8000 else if (!rb_block_given_p()) {
8001 for (i = 0; i < len; ++i) {
8002 if (!RTEST(RARRAY_AREF(ary, i))) return Qfalse;
8003 }
8004 }
8005 else {
8006 for (i = 0; i < RARRAY_LEN(ary); ++i) {
8007 if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) return Qfalse;
8008 }
8009 }
8010 return Qtrue;
8011}
8012
8013/*
8014 * call-seq:
8015 * none? -> true or false
8016 * none?(object) -> true or false
8017 * none? {|element| ... } -> true or false
8018 *
8019 * Returns +true+ if no element of +self+ meets a given criterion, +false+ otherwise.
8020 *
8021 * With no block given and no argument, returns +true+ if +self+ has no truthy elements,
8022 * +false+ otherwise:
8023 *
8024 * [nil, false].none? # => true
8025 * [nil, 0, false].none? # => false
8026 * [].none? # => true
8027 *
8028 * With argument +object+ given, returns +false+ if for any element +element+,
8029 * <tt>object === element</tt>; +true+ otherwise:
8030 *
8031 * ['food', 'drink'].none?(/bar/) # => true
8032 * ['food', 'drink'].none?(/foo/) # => false
8033 * [].none?(/foo/) # => true
8034 * [0, 1, 2].none?(3) # => true
8035 * [0, 1, 2].none?(1) # => false
8036 *
8037 * With a block given, calls the block with each element in +self+;
8038 * returns +true+ if the block returns no truthy value, +false+ otherwise:
8039 *
8040 * [0, 1, 2].none? {|element| element > 3 } # => true
8041 * [0, 1, 2].none? {|element| element > 1 } # => false
8042 *
8043 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
8044 */
8045
8046static VALUE
8047rb_ary_none_p(int argc, VALUE *argv, VALUE ary)
8048{
8049 long i, len = RARRAY_LEN(ary);
8050
8051 rb_check_arity(argc, 0, 1);
8052 if (!len) return Qtrue;
8053 if (argc) {
8054 if (rb_block_given_p()) {
8055 rb_warn("given block not used");
8056 }
8057 for (i = 0; i < RARRAY_LEN(ary); ++i) {
8058 if (RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) return Qfalse;
8059 }
8060 }
8061 else if (!rb_block_given_p()) {
8062 for (i = 0; i < len; ++i) {
8063 if (RTEST(RARRAY_AREF(ary, i))) return Qfalse;
8064 }
8065 }
8066 else {
8067 for (i = 0; i < RARRAY_LEN(ary); ++i) {
8068 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) return Qfalse;
8069 }
8070 }
8071 return Qtrue;
8072}
8073
8074/*
8075 * call-seq:
8076 * one? -> true or false
8077 * one? {|element| ... } -> true or false
8078 * one?(object) -> true or false
8079 *
8080 * Returns +true+ if exactly one element of +self+ meets a given criterion.
8081 *
8082 * With no block given and no argument, returns +true+ if +self+ has exactly one truthy element,
8083 * +false+ otherwise:
8084 *
8085 * [nil, 0].one? # => true
8086 * [0, 0].one? # => false
8087 * [nil, nil].one? # => false
8088 * [].one? # => false
8089 *
8090 * With a block given, calls the block with each element in +self+;
8091 * returns +true+ if the block a truthy value for exactly one element, +false+ otherwise:
8092 *
8093 * [0, 1, 2].one? {|element| element > 0 } # => false
8094 * [0, 1, 2].one? {|element| element > 1 } # => true
8095 * [0, 1, 2].one? {|element| element > 2 } # => false
8096 *
8097 * With argument +object+ given, returns +true+ if for exactly one element +element+, <tt>object === element</tt>;
8098 * +false+ otherwise:
8099 *
8100 * [0, 1, 2].one?(0) # => true
8101 * [0, 0, 1].one?(0) # => false
8102 * [1, 1, 2].one?(0) # => false
8103 * ['food', 'drink'].one?(/bar/) # => false
8104 * ['food', 'drink'].one?(/foo/) # => true
8105 * [].one?(/foo/) # => false
8106 *
8107 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
8108 */
8109
8110static VALUE
8111rb_ary_one_p(int argc, VALUE *argv, VALUE ary)
8112{
8113 long i, len = RARRAY_LEN(ary);
8114 VALUE result = Qfalse;
8115
8116 rb_check_arity(argc, 0, 1);
8117 if (!len) return Qfalse;
8118 if (argc) {
8119 if (rb_block_given_p()) {
8120 rb_warn("given block not used");
8121 }
8122 for (i = 0; i < RARRAY_LEN(ary); ++i) {
8123 if (RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) {
8124 if (result) return Qfalse;
8125 result = Qtrue;
8126 }
8127 }
8128 }
8129 else if (!rb_block_given_p()) {
8130 for (i = 0; i < len; ++i) {
8131 if (RTEST(RARRAY_AREF(ary, i))) {
8132 if (result) return Qfalse;
8133 result = Qtrue;
8134 }
8135 }
8136 }
8137 else {
8138 for (i = 0; i < RARRAY_LEN(ary); ++i) {
8139 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) {
8140 if (result) return Qfalse;
8141 result = Qtrue;
8142 }
8143 }
8144 }
8145 return result;
8146}
8147
8148/*
8149 * call-seq:
8150 * dig(index, *identifiers) -> object
8151 *
8152 * Finds and returns the object in nested object
8153 * specified by +index+ and +identifiers+;
8154 * the nested objects may be instances of various classes.
8155 * See {Dig Methods}[rdoc-ref:dig_methods.rdoc].
8156 *
8157 * Examples:
8158 *
8159 * a = [:foo, [:bar, :baz, [:bat, :bam]]]
8160 * a.dig(1) # => [:bar, :baz, [:bat, :bam]]
8161 * a.dig(1, 2) # => [:bat, :bam]
8162 * a.dig(1, 2, 0) # => :bat
8163 * a.dig(1, 2, 3) # => nil
8164 *
8165 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
8166 */
8167
8168static VALUE
8169rb_ary_dig(int argc, VALUE *argv, VALUE self)
8170{
8171 rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
8172 self = rb_ary_at(self, *argv);
8173 if (!--argc) return self;
8174 ++argv;
8175 return rb_obj_dig(argc, argv, self, Qnil);
8176}
8177
8178static inline VALUE
8179finish_exact_sum(long n, VALUE r, VALUE v, int z)
8180{
8181 if (n != 0)
8182 v = rb_fix_plus(LONG2FIX(n), v);
8183 if (!UNDEF_P(r)) {
8184 v = rb_rational_plus(r, v);
8185 }
8186 else if (!n && z) {
8187 v = rb_fix_plus(LONG2FIX(0), v);
8188 }
8189 return v;
8190}
8191
8192/*
8193 * call-seq:
8194 * sum(init = 0) -> object
8195 * sum(init = 0) {|element| ... } -> object
8196 *
8197 * With no block given, returns the sum of +init+ and all elements of +self+;
8198 * for array +array+ and value +init+, equivalent to:
8199 *
8200 * sum = init
8201 * array.each {|element| sum += element }
8202 * sum
8203 *
8204 * For example, <tt>[e0, e1, e2].sum</tt> returns <tt>init + e0 + e1 + e2</tt>.
8205 *
8206 * Examples:
8207 *
8208 * [0, 1, 2, 3].sum # => 6
8209 * [0, 1, 2, 3].sum(100) # => 106
8210 * ['abc', 'def', 'ghi'].sum('jkl') # => "jklabcdefghi"
8211 * [[:foo, :bar], ['foo', 'bar']].sum([2, 3])
8212 * # => [2, 3, :foo, :bar, "foo", "bar"]
8213 *
8214 * The +init+ value and elements need not be numeric, but must all be <tt>+</tt>-compatible:
8215 *
8216 * # Raises TypeError: Array can't be coerced into Integer.
8217 * [[:foo, :bar], ['foo', 'bar']].sum(2)
8218 *
8219 * With a block given, calls the block with each element of +self+;
8220 * the block's return value (instead of the element itself) is used as the addend:
8221 *
8222 * ['zero', 1, :two].sum('Coerced and concatenated: ') {|element| element.to_s }
8223 * # => "Coerced and concatenated: zero1two"
8224 *
8225 * Notes:
8226 *
8227 * - Array#join and Array#flatten may be faster than Array#sum
8228 * for an array of strings or an array of arrays.
8229 * - Array#sum method may not respect method redefinition of "+" methods such as Integer#+.
8230 *
8231 */
8232
8233static VALUE
8234rb_ary_sum(int argc, VALUE *argv, VALUE ary)
8235{
8236 VALUE e, v, r;
8237 long i, n;
8238 int block_given;
8239
8240 v = (rb_check_arity(argc, 0, 1) ? argv[0] : LONG2FIX(0));
8241
8242 block_given = rb_block_given_p();
8243
8244 if (RARRAY_LEN(ary) == 0)
8245 return v;
8246
8247 n = 0;
8248 r = Qundef;
8249
8250 if (!FIXNUM_P(v) && !RB_BIGNUM_TYPE_P(v) && !RB_TYPE_P(v, T_RATIONAL)) {
8251 i = 0;
8252 goto init_is_a_value;
8253 }
8254
8255 for (i = 0; i < RARRAY_LEN(ary); i++) {
8256 e = RARRAY_AREF(ary, i);
8257 if (block_given)
8258 e = rb_yield(e);
8259 if (FIXNUM_P(e)) {
8260 n += FIX2LONG(e); /* should not overflow long type */
8261 if (!FIXABLE(n)) {
8262 v = rb_big_plus(LONG2NUM(n), v);
8263 n = 0;
8264 }
8265 }
8266 else if (RB_BIGNUM_TYPE_P(e))
8267 v = rb_big_plus(e, v);
8268 else if (RB_TYPE_P(e, T_RATIONAL)) {
8269 if (UNDEF_P(r))
8270 r = e;
8271 else
8272 r = rb_rational_plus(r, e);
8273 }
8274 else
8275 goto not_exact;
8276 }
8277 v = finish_exact_sum(n, r, v, argc!=0);
8278 return v;
8279
8280 not_exact:
8281 v = finish_exact_sum(n, r, v, i!=0);
8282
8283 if (RB_FLOAT_TYPE_P(e)) {
8284 /*
8285 * Kahan-Babuska balancing compensated summation algorithm
8286 * See https://link.springer.com/article/10.1007/s00607-005-0139-x
8287 */
8288 double f, c;
8289 double x, t;
8290
8291 f = NUM2DBL(v);
8292 c = 0.0;
8293 goto has_float_value;
8294 for (; i < RARRAY_LEN(ary); i++) {
8295 e = RARRAY_AREF(ary, i);
8296 if (block_given)
8297 e = rb_yield(e);
8298 if (RB_FLOAT_TYPE_P(e))
8299 has_float_value:
8300 x = RFLOAT_VALUE(e);
8301 else if (FIXNUM_P(e))
8302 x = FIX2LONG(e);
8303 else if (RB_BIGNUM_TYPE_P(e))
8304 x = rb_big2dbl(e);
8305 else if (RB_TYPE_P(e, T_RATIONAL))
8306 x = rb_num2dbl(e);
8307 else
8308 goto not_float;
8309
8310 if (isnan(f)) continue;
8311 if (isnan(x)) {
8312 f = x;
8313 continue;
8314 }
8315 if (isinf(x)) {
8316 if (isinf(f) && signbit(x) != signbit(f))
8317 f = NAN;
8318 else
8319 f = x;
8320 continue;
8321 }
8322 if (isinf(f)) continue;
8323
8324 t = f + x;
8325 if (fabs(f) >= fabs(x))
8326 c += ((f - t) + x);
8327 else
8328 c += ((x - t) + f);
8329 f = t;
8330 }
8331 f += c;
8332 return DBL2NUM(f);
8333
8334 not_float:
8335 v = DBL2NUM(f);
8336 }
8337
8338 goto has_some_value;
8339 init_is_a_value:
8340 for (; i < RARRAY_LEN(ary); i++) {
8341 e = RARRAY_AREF(ary, i);
8342 if (block_given)
8343 e = rb_yield(e);
8344 has_some_value:
8345 v = rb_funcall(v, idPLUS, 1, e);
8346 }
8347 return v;
8348}
8349
8350/* :nodoc: */
8351static VALUE
8352rb_ary_deconstruct(VALUE ary)
8353{
8354 return ary;
8355}
8356
8357/*
8358 * An \Array object is an ordered, integer-indexed collection of objects,
8359 * called _elements_;
8360 * the object represents
8361 * an {array data structure}[https://en.wikipedia.org/wiki/Array_(data_structure)].
8362 *
8363 * An element may be any object (even another array);
8364 * elements may be any mixture of objects of different types.
8365 *
8366 * Important data structures that use arrays include:
8367 *
8368 * - {Coordinate vector}[https://en.wikipedia.org/wiki/Coordinate_vector].
8369 * - {Matrix}[https://en.wikipedia.org/wiki/Matrix_(mathematics)].
8370 * - {Heap}[https://en.wikipedia.org/wiki/Heap_(data_structure)].
8371 * - {Hash table}[https://en.wikipedia.org/wiki/Hash_table].
8372 * - {Deque (double-ended queue)}[https://en.wikipedia.org/wiki/Double-ended_queue].
8373 * - {Queue}[https://en.wikipedia.org/wiki/Queue_(abstract_data_type)].
8374 * - {Stack}[https://en.wikipedia.org/wiki/Stack_(abstract_data_type)].
8375 *
8376 * There are also array-like data structures:
8377 *
8378 * - {Associative array}[https://en.wikipedia.org/wiki/Associative_array] (see Hash).
8379 * - {Directory}[https://en.wikipedia.org/wiki/Directory_(computing)] (see Dir).
8380 * - {Environment}[https://en.wikipedia.org/wiki/Environment_variable] (see ENV).
8381 * - {Set}[https://en.wikipedia.org/wiki/Set_(abstract_data_type)] (see Set).
8382 * - {String}[https://en.wikipedia.org/wiki/String_(computer_science)] (see String).
8383 *
8384 * == \Array Indexes
8385 *
8386 * \Array indexing starts at 0, as in C or Java.
8387 *
8388 * A non-negative index is an offset from the first element:
8389 *
8390 * - Index 0 indicates the first element.
8391 * - Index 1 indicates the second element.
8392 * - ...
8393 *
8394 * A negative index is an offset, backwards, from the end of the array:
8395 *
8396 * - Index -1 indicates the last element.
8397 * - Index -2 indicates the next-to-last element.
8398 * - ...
8399 *
8400 *
8401 * === In-Range and Out-of-Range Indexes
8402 *
8403 * A non-negative index is <i>in range</i> if and only if it is smaller than
8404 * the size of the array. For a 3-element array:
8405 *
8406 * - Indexes 0 through 2 are in range.
8407 * - Index 3 is out of range.
8408 *
8409 * A negative index is <i>in range</i> if and only if its absolute value is
8410 * not larger than the size of the array. For a 3-element array:
8411 *
8412 * - Indexes -1 through -3 are in range.
8413 * - Index -4 is out of range.
8414 *
8415 * === Effective Index
8416 *
8417 * Although the effective index into an array is always an integer,
8418 * some methods (both within class \Array and elsewhere)
8419 * accept one or more non-integer arguments that are
8420 * {integer-convertible objects}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
8421 *
8422 * == Creating Arrays
8423 *
8424 * You can create an \Array object explicitly with:
8425 *
8426 * - An {array literal}[rdoc-ref:syntax/literals.rdoc@Array+Literals]:
8427 *
8428 * [1, 'one', :one, [2, 'two', :two]]
8429 *
8430 * - A {%w or %W string-array Literal}[rdoc-ref:syntax/literals.rdoc@25w+and+-25W-3A+String-Array+Literals]:
8431 *
8432 * %w[foo bar baz] # => ["foo", "bar", "baz"]
8433 * %w[1 % *] # => ["1", "%", "*"]
8434 *
8435 * - A {%i or %I symbol-array Literal}[rdoc-ref:syntax/literals.rdoc@25i+and+-25I-3A+Symbol-Array+Literals]:
8436 *
8437 * %i[foo bar baz] # => [:foo, :bar, :baz]
8438 * %i[1 % *] # => [:"1", :%, :*]
8439 *
8440 * - Method Kernel#Array:
8441 *
8442 * Array(["a", "b"]) # => ["a", "b"]
8443 * Array(1..5) # => [1, 2, 3, 4, 5]
8444 * Array(key: :value) # => [[:key, :value]]
8445 * Array(nil) # => []
8446 * Array(1) # => [1]
8447 * Array({:a => "a", :b => "b"}) # => [[:a, "a"], [:b, "b"]]
8448 *
8449 * - Method Array.new:
8450 *
8451 * Array.new # => []
8452 * Array.new(3) # => [nil, nil, nil]
8453 * Array.new(4) {Hash.new} # => [{}, {}, {}, {}]
8454 * Array.new(3, true) # => [true, true, true]
8455 *
8456 * Note that the last example above populates the array
8457 * with references to the same object.
8458 * This is recommended only in cases where that object is a natively immutable object
8459 * such as a symbol, a numeric, +nil+, +true+, or +false+.
8460 *
8461 * Another way to create an array with various objects, using a block;
8462 * this usage is safe for mutable objects such as hashes, strings or
8463 * other arrays:
8464 *
8465 * Array.new(4) {|i| i.to_s } # => ["0", "1", "2", "3"]
8466 *
8467 * Here is a way to create a multi-dimensional array:
8468 *
8469 * Array.new(3) {Array.new(3)}
8470 * # => [[nil, nil, nil], [nil, nil, nil], [nil, nil, nil]]
8471 *
8472 * A number of Ruby methods, both in the core and in the standard library,
8473 * provide instance method +to_a+, which converts an object to an array.
8474 *
8475 * - ARGF#to_a
8476 * - Array#to_a
8477 * - Enumerable#to_a
8478 * - Hash#to_a
8479 * - MatchData#to_a
8480 * - NilClass#to_a
8481 * - OptionParser#to_a
8482 * - Range#to_a
8483 * - Set#to_a
8484 * - Struct#to_a
8485 * - Time#to_a
8486 * - Benchmark::Tms#to_a
8487 * - CSV::Table#to_a
8488 * - Enumerator::Lazy#to_a
8489 * - Gem::List#to_a
8490 * - Gem::NameTuple#to_a
8491 * - Gem::Platform#to_a
8492 * - Gem::RequestSet::Lockfile::Tokenizer#to_a
8493 * - Gem::SourceList#to_a
8494 * - OpenSSL::X509::Extension#to_a
8495 * - OpenSSL::X509::Name#to_a
8496 * - Racc::ISet#to_a
8497 * - Rinda::RingFinger#to_a
8498 * - Ripper::Lexer::Elem#to_a
8499 * - RubyVM::InstructionSequence#to_a
8500 * - YAML::DBM#to_a
8501 *
8502 * == Example Usage
8503 *
8504 * In addition to the methods it mixes in through the Enumerable module,
8505 * class \Array has proprietary methods for accessing, searching and otherwise
8506 * manipulating arrays.
8507 *
8508 * Some of the more common ones are illustrated below.
8509 *
8510 * == Accessing Elements
8511 *
8512 * Elements in an array can be retrieved using the Array#[] method. It can
8513 * take a single integer argument (a numeric index), a pair of arguments
8514 * (start and length) or a range. Negative indices start counting from the end,
8515 * with -1 being the last element.
8516 *
8517 * arr = [1, 2, 3, 4, 5, 6]
8518 * arr[2] #=> 3
8519 * arr[100] #=> nil
8520 * arr[-3] #=> 4
8521 * arr[2, 3] #=> [3, 4, 5]
8522 * arr[1..4] #=> [2, 3, 4, 5]
8523 * arr[1..-3] #=> [2, 3, 4]
8524 *
8525 * Another way to access a particular array element is by using the #at method
8526 *
8527 * arr.at(0) #=> 1
8528 *
8529 * The #slice method works in an identical manner to Array#[].
8530 *
8531 * To raise an error for indices outside of the array bounds or else to
8532 * provide a default value when that happens, you can use #fetch.
8533 *
8534 * arr = ['a', 'b', 'c', 'd', 'e', 'f']
8535 * arr.fetch(100) #=> IndexError: index 100 outside of array bounds: -6...6
8536 * arr.fetch(100, "oops") #=> "oops"
8537 *
8538 * The special methods #first and #last will return the first and last
8539 * elements of an array, respectively.
8540 *
8541 * arr.first #=> 1
8542 * arr.last #=> 6
8543 *
8544 * To return the first +n+ elements of an array, use #take
8545 *
8546 * arr.take(3) #=> [1, 2, 3]
8547 *
8548 * #drop does the opposite of #take, by returning the elements after +n+
8549 * elements have been dropped:
8550 *
8551 * arr.drop(3) #=> [4, 5, 6]
8552 *
8553 * == Obtaining Information about an \Array
8554 *
8555 * An array keeps track of its own length at all times. To query an array
8556 * about the number of elements it contains, use #length, #count or #size.
8557 *
8558 * browsers = ['Chrome', 'Firefox', 'Safari', 'Opera', 'IE']
8559 * browsers.length #=> 5
8560 * browsers.count #=> 5
8561 *
8562 * To check whether an array contains any elements at all
8563 *
8564 * browsers.empty? #=> false
8565 *
8566 * To check whether a particular item is included in the array
8567 *
8568 * browsers.include?('Konqueror') #=> false
8569 *
8570 * == Adding Items to an \Array
8571 *
8572 * Items can be added to the end of an array by using either #push or #<<
8573 *
8574 * arr = [1, 2, 3, 4]
8575 * arr.push(5) #=> [1, 2, 3, 4, 5]
8576 * arr << 6 #=> [1, 2, 3, 4, 5, 6]
8577 *
8578 * #unshift will add a new item to the beginning of an array.
8579 *
8580 * arr.unshift(0) #=> [0, 1, 2, 3, 4, 5, 6]
8581 *
8582 * With #insert you can add a new element to an array at any position.
8583 *
8584 * arr.insert(3, 'apple') #=> [0, 1, 2, 'apple', 3, 4, 5, 6]
8585 *
8586 * Using the #insert method, you can also insert multiple values at once:
8587 *
8588 * arr.insert(3, 'orange', 'pear', 'grapefruit')
8589 * #=> [0, 1, 2, "orange", "pear", "grapefruit", "apple", 3, 4, 5, 6]
8590 *
8591 * == Removing Items from an \Array
8592 *
8593 * The method #pop removes the last element in an array and returns it:
8594 *
8595 * arr = [1, 2, 3, 4, 5, 6]
8596 * arr.pop #=> 6
8597 * arr #=> [1, 2, 3, 4, 5]
8598 *
8599 * To retrieve and at the same time remove the first item, use #shift:
8600 *
8601 * arr.shift #=> 1
8602 * arr #=> [2, 3, 4, 5]
8603 *
8604 * To delete an element at a particular index:
8605 *
8606 * arr.delete_at(2) #=> 4
8607 * arr #=> [2, 3, 5]
8608 *
8609 * To delete a particular element anywhere in an array, use #delete:
8610 *
8611 * arr = [1, 2, 2, 3]
8612 * arr.delete(2) #=> 2
8613 * arr #=> [1,3]
8614 *
8615 * A useful method if you need to remove +nil+ values from an array is
8616 * #compact:
8617 *
8618 * arr = ['foo', 0, nil, 'bar', 7, 'baz', nil]
8619 * arr.compact #=> ['foo', 0, 'bar', 7, 'baz']
8620 * arr #=> ['foo', 0, nil, 'bar', 7, 'baz', nil]
8621 * arr.compact! #=> ['foo', 0, 'bar', 7, 'baz']
8622 * arr #=> ['foo', 0, 'bar', 7, 'baz']
8623 *
8624 * Another common need is to remove duplicate elements from an array.
8625 *
8626 * It has the non-destructive #uniq, and destructive method #uniq!
8627 *
8628 * arr = [2, 5, 6, 556, 6, 6, 8, 9, 0, 123, 556]
8629 * arr.uniq #=> [2, 5, 6, 556, 8, 9, 0, 123]
8630 *
8631 * == Iterating over an \Array
8632 *
8633 * Like all classes that include the Enumerable module, class \Array has an each
8634 * method, which defines what elements should be iterated over and how. In
8635 * case of Array#each, all elements in +self+ are yielded to
8636 * the supplied block in sequence.
8637 *
8638 * Note that this operation leaves the array unchanged.
8639 *
8640 * arr = [1, 2, 3, 4, 5]
8641 * arr.each {|a| print a -= 10, " "}
8642 * # prints: -9 -8 -7 -6 -5
8643 * #=> [1, 2, 3, 4, 5]
8644 *
8645 * Another sometimes useful iterator is #reverse_each which will iterate over
8646 * the elements in the array in reverse order.
8647 *
8648 * words = %w[first second third fourth fifth sixth]
8649 * str = ""
8650 * words.reverse_each {|word| str += "#{word} "}
8651 * p str #=> "sixth fifth fourth third second first "
8652 *
8653 * The #map method can be used to create a new array based on the original
8654 * array, but with the values modified by the supplied block:
8655 *
8656 * arr.map {|a| 2*a} #=> [2, 4, 6, 8, 10]
8657 * arr #=> [1, 2, 3, 4, 5]
8658 * arr.map! {|a| a**2} #=> [1, 4, 9, 16, 25]
8659 * arr #=> [1, 4, 9, 16, 25]
8660 *
8661 *
8662 * == Selecting Items from an \Array
8663 *
8664 * Elements can be selected from an array according to criteria defined in a
8665 * block. The selection can happen in a destructive or a non-destructive
8666 * manner. While the destructive operations will modify the array they were
8667 * called on, the non-destructive methods usually return a new array with the
8668 * selected elements, but leave the original array unchanged.
8669 *
8670 * === Non-destructive Selection
8671 *
8672 * arr = [1, 2, 3, 4, 5, 6]
8673 * arr.select {|a| a > 3} #=> [4, 5, 6]
8674 * arr.reject {|a| a < 3} #=> [3, 4, 5, 6]
8675 * arr.drop_while {|a| a < 4} #=> [4, 5, 6]
8676 * arr #=> [1, 2, 3, 4, 5, 6]
8677 *
8678 * === Destructive Selection
8679 *
8680 * #select! and #reject! are the corresponding destructive methods to #select
8681 * and #reject
8682 *
8683 * Similar to #select vs. #reject, #delete_if and #keep_if have the exact
8684 * opposite result when supplied with the same block:
8685 *
8686 * arr.delete_if {|a| a < 4} #=> [4, 5, 6]
8687 * arr #=> [4, 5, 6]
8688 *
8689 * arr = [1, 2, 3, 4, 5, 6]
8690 * arr.keep_if {|a| a < 4} #=> [1, 2, 3]
8691 * arr #=> [1, 2, 3]
8692 *
8693 * == What's Here
8694 *
8695 * First, what's elsewhere. Class \Array:
8696 *
8697 * - Inherits from {class Object}[rdoc-ref:Object@What-27s+Here].
8698 * - Includes {module Enumerable}[rdoc-ref:Enumerable@What-27s+Here],
8699 * which provides dozens of additional methods.
8700 *
8701 * Here, class \Array provides methods that are useful for:
8702 *
8703 * - {Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array]
8704 * - {Querying}[rdoc-ref:Array@Methods+for+Querying]
8705 * - {Comparing}[rdoc-ref:Array@Methods+for+Comparing]
8706 * - {Fetching}[rdoc-ref:Array@Methods+for+Fetching]
8707 * - {Assigning}[rdoc-ref:Array@Methods+for+Assigning]
8708 * - {Deleting}[rdoc-ref:Array@Methods+for+Deleting]
8709 * - {Combining}[rdoc-ref:Array@Methods+for+Combining]
8710 * - {Iterating}[rdoc-ref:Array@Methods+for+Iterating]
8711 * - {Converting}[rdoc-ref:Array@Methods+for+Converting]
8712 * - {And more....}[rdoc-ref:Array@Other+Methods]
8713 *
8714 * === Methods for Creating an \Array
8715 *
8716 * - ::[]: Returns a new array populated with given objects.
8717 * - ::new: Returns a new array.
8718 * - ::try_convert: Returns a new array created from a given object.
8719 *
8720 * See also {Creating Arrays}[rdoc-ref:Array@Creating+Arrays].
8721 *
8722 * === Methods for Querying
8723 *
8724 * - #all?: Returns whether all elements meet a given criterion.
8725 * - #any?: Returns whether any element meets a given criterion.
8726 * - #count: Returns the count of elements that meet a given criterion.
8727 * - #empty?: Returns whether there are no elements.
8728 * - #find_index (aliased as #index): Returns the index of the first element that meets a given criterion.
8729 * - #hash: Returns the integer hash code.
8730 * - #include?: Returns whether any element <tt>==</tt> a given object.
8731 * - #length (aliased as #size): Returns the count of elements.
8732 * - #none?: Returns whether no element <tt>==</tt> a given object.
8733 * - #one?: Returns whether exactly one element <tt>==</tt> a given object.
8734 * - #rindex: Returns the index of the last element that meets a given criterion.
8735 *
8736 * === Methods for Comparing
8737 *
8738 * - #<=>: Returns -1, 0, or 1, as +self+ is less than, equal to, or greater than a given object.
8739 * - #==: Returns whether each element in +self+ is <tt>==</tt> to the corresponding element in a given object.
8740 * - #eql?: Returns whether each element in +self+ is <tt>eql?</tt> to the corresponding element in a given object.
8741
8742 * === Methods for Fetching
8743 *
8744 * These methods do not modify +self+.
8745 *
8746 * - #[] (aliased as #slice): Returns consecutive elements as determined by a given argument.
8747 * - #assoc: Returns the first element that is an array whose first element <tt>==</tt> a given object.
8748 * - #at: Returns the element at a given offset.
8749 * - #bsearch: Returns an element selected via a binary search as determined by a given block.
8750 * - #bsearch_index: Returns the index of an element selected via a binary search as determined by a given block.
8751 * - #compact: Returns an array containing all non-+nil+ elements.
8752 * - #dig: Returns the object in nested objects that is specified by a given index and additional arguments.
8753 * - #drop: Returns trailing elements as determined by a given index.
8754 * - #drop_while: Returns trailing elements as determined by a given block.
8755 * - #fetch: Returns the element at a given offset.
8756 * - #fetch_values: Returns elements at given offsets.
8757 * - #first: Returns one or more leading elements.
8758 * - #last: Returns one or more trailing elements.
8759 * - #max: Returns one or more maximum-valued elements, as determined by <tt>#<=></tt> or a given block.
8760 * - #min: Returns one or more minimum-valued elements, as determined by <tt>#<=></tt> or a given block.
8761 * - #minmax: Returns the minimum-valued and maximum-valued elements, as determined by <tt>#<=></tt> or a given block.
8762 * - #rassoc: Returns the first element that is an array whose second element <tt>==</tt> a given object.
8763 * - #reject: Returns an array containing elements not rejected by a given block.
8764 * - #reverse: Returns all elements in reverse order.
8765 * - #rotate: Returns all elements with some rotated from one end to the other.
8766 * - #sample: Returns one or more random elements.
8767 * - #select (aliased as #filter): Returns an array containing elements selected by a given block.
8768 * - #shuffle: Returns elements in a random order.
8769 * - #sort: Returns all elements in an order determined by <tt>#<=></tt> or a given block.
8770 * - #take: Returns leading elements as determined by a given index.
8771 * - #take_while: Returns leading elements as determined by a given block.
8772 * - #uniq: Returns an array containing non-duplicate elements.
8773 * - #values_at: Returns the elements at given offsets.
8774 *
8775 * === Methods for Assigning
8776 *
8777 * These methods add, replace, or reorder elements in +self+.
8778 *
8779 * - #<<: Appends an element.
8780 * - #[]=: Assigns specified elements with a given object.
8781 * - #concat: Appends all elements from given arrays.
8782 * - #fill: Replaces specified elements with specified objects.
8783 * - #flatten!: Replaces each nested array in +self+ with the elements from that array.
8784 * - #initialize_copy (aliased as #replace): Replaces the content of +self+ with the content of a given array.
8785 * - #insert: Inserts given objects at a given offset; does not replace elements.
8786 * - #push (aliased as #append): Appends elements.
8787 * - #reverse!: Replaces +self+ with its elements reversed.
8788 * - #rotate!: Replaces +self+ with its elements rotated.
8789 * - #shuffle!: Replaces +self+ with its elements in random order.
8790 * - #sort!: Replaces +self+ with its elements sorted, as determined by <tt>#<=></tt> or a given block.
8791 * - #sort_by!: Replaces +self+ with its elements sorted, as determined by a given block.
8792 * - #unshift (aliased as #prepend): Prepends leading elements.
8793 *
8794 * === Methods for Deleting
8795 *
8796 * Each of these methods removes elements from +self+:
8797 *
8798 * - #clear: Removes all elements.
8799 * - #compact!: Removes all +nil+ elements.
8800 * - #delete: Removes elements equal to a given object.
8801 * - #delete_at: Removes the element at a given offset.
8802 * - #delete_if: Removes elements specified by a given block.
8803 * - #keep_if: Removes elements not specified by a given block.
8804 * - #pop: Removes and returns the last element.
8805 * - #reject!: Removes elements specified by a given block.
8806 * - #select! (aliased as #filter!): Removes elements not specified by a given block.
8807 * - #shift: Removes and returns the first element.
8808 * - #slice!: Removes and returns a sequence of elements.
8809 * - #uniq!: Removes duplicates.
8810 *
8811 * === Methods for Combining
8812 *
8813 * - #&: Returns an array containing elements found both in +self+ and a given array.
8814 * - #+: Returns an array containing all elements of +self+ followed by all elements of a given array.
8815 * - #-: Returns an array containing all elements of +self+ that are not found in a given array.
8816 * - #|: Returns an array containing all element of +self+ and all elements of a given array, duplicates removed.
8817 * - #difference: Returns an array containing all elements of +self+ that are not found in any of the given arrays..
8818 * - #intersection: Returns an array containing elements found both in +self+ and in each given array.
8819 * - #product: Returns or yields all combinations of elements from +self+ and given arrays.
8820 * - #reverse: Returns an array containing all elements of +self+ in reverse order.
8821 * - #union: Returns an array containing all elements of +self+ and all elements of given arrays, duplicates removed.
8822 *
8823 * === Methods for Iterating
8824 *
8825 * - #combination: Calls a given block with combinations of elements of +self+; a combination does not use the same element more than once.
8826 * - #cycle: Calls a given block with each element, then does so again, for a specified number of times, or forever.
8827 * - #each: Passes each element to a given block.
8828 * - #each_index: Passes each element index to a given block.
8829 * - #permutation: Calls a given block with permutations of elements of +self+; a permutation does not use the same element more than once.
8830 * - #repeated_combination: Calls a given block with combinations of elements of +self+; a combination may use the same element more than once.
8831 * - #repeated_permutation: Calls a given block with permutations of elements of +self+; a permutation may use the same element more than once.
8832 * - #reverse_each: Passes each element, in reverse order, to a given block.
8833 *
8834 * === Methods for Converting
8835 *
8836 * - #collect (aliased as #map): Returns an array containing the block return-value for each element.
8837 * - #collect! (aliased as #map!): Replaces each element with a block return-value.
8838 * - #flatten: Returns an array that is a recursive flattening of +self+.
8839 * - #inspect (aliased as #to_s): Returns a new String containing the elements.
8840 * - #join: Returns a new String containing the elements joined by the field separator.
8841 * - #to_a: Returns +self+ or a new array containing all elements.
8842 * - #to_ary: Returns +self+.
8843 * - #to_h: Returns a new hash formed from the elements.
8844 * - #transpose: Transposes +self+, which must be an array of arrays.
8845 * - #zip: Returns a new array of arrays containing +self+ and given arrays.
8846 *
8847 * === Other Methods
8848 *
8849 * - #*: Returns one of the following:
8850 *
8851 * - With integer argument +n+, a new array that is the concatenation
8852 * of +n+ copies of +self+.
8853 * - With string argument +field_separator+, a new string that is equivalent to
8854 * <tt>join(field_separator)</tt>.
8855 *
8856 * - #pack: Packs the elements into a binary sequence.
8857 * - #sum: Returns a sum of elements according to either <tt>+</tt> or a given block.
8858 */
8859
8860void
8861Init_Array(void)
8862{
8863 fake_ary_flags = init_fake_ary_flags();
8864
8865 rb_cArray = rb_define_class("Array", rb_cObject);
8866 rb_include_module(rb_cArray, rb_mEnumerable);
8867
8868 rb_define_alloc_func(rb_cArray, empty_ary_alloc);
8869 rb_define_singleton_method(rb_cArray, "new", rb_ary_s_new, -1);
8870 rb_define_singleton_method(rb_cArray, "[]", rb_ary_s_create, -1);
8871 rb_define_singleton_method(rb_cArray, "try_convert", rb_ary_s_try_convert, 1);
8872 rb_define_method(rb_cArray, "initialize", rb_ary_initialize, -1);
8873 rb_define_method(rb_cArray, "initialize_copy", rb_ary_replace, 1);
8874
8875 rb_define_method(rb_cArray, "inspect", rb_ary_inspect, 0);
8876 rb_define_alias(rb_cArray, "to_s", "inspect");
8877 rb_define_method(rb_cArray, "to_a", rb_ary_to_a, 0);
8878 rb_define_method(rb_cArray, "to_h", rb_ary_to_h, 0);
8879 rb_define_method(rb_cArray, "to_ary", rb_ary_to_ary_m, 0);
8880
8881 rb_define_method(rb_cArray, "==", rb_ary_equal, 1);
8882 rb_define_method(rb_cArray, "eql?", rb_ary_eql, 1);
8883 rb_define_method(rb_cArray, "hash", rb_ary_hash, 0);
8884
8885 rb_define_method(rb_cArray, "[]", rb_ary_aref, -1);
8886 rb_define_method(rb_cArray, "[]=", rb_ary_aset, -1);
8887 rb_define_method(rb_cArray, "at", rb_ary_at, 1);
8888 rb_define_method(rb_cArray, "fetch", rb_ary_fetch, -1);
8889 rb_define_method(rb_cArray, "concat", rb_ary_concat_multi, -1);
8890 rb_define_method(rb_cArray, "union", rb_ary_union_multi, -1);
8891 rb_define_method(rb_cArray, "difference", rb_ary_difference_multi, -1);
8892 rb_define_method(rb_cArray, "intersection", rb_ary_intersection_multi, -1);
8893 rb_define_method(rb_cArray, "intersect?", rb_ary_intersect_p, 1);
8894 rb_define_method(rb_cArray, "<<", rb_ary_push, 1);
8895 rb_define_method(rb_cArray, "push", rb_ary_push_m, -1);
8896 rb_define_alias(rb_cArray, "append", "push");
8897 rb_define_method(rb_cArray, "pop", rb_ary_pop_m, -1);
8898 rb_define_method(rb_cArray, "shift", rb_ary_shift_m, -1);
8899 rb_define_method(rb_cArray, "unshift", rb_ary_unshift_m, -1);
8900 rb_define_alias(rb_cArray, "prepend", "unshift");
8901 rb_define_method(rb_cArray, "insert", rb_ary_insert, -1);
8902 rb_define_method(rb_cArray, "each", rb_ary_each, 0);
8903 rb_define_method(rb_cArray, "each_index", rb_ary_each_index, 0);
8904 rb_define_method(rb_cArray, "reverse_each", rb_ary_reverse_each, 0);
8905 rb_define_method(rb_cArray, "length", rb_ary_length, 0);
8906 rb_define_method(rb_cArray, "size", rb_ary_length, 0);
8907 rb_define_method(rb_cArray, "empty?", rb_ary_empty_p, 0);
8908 rb_define_method(rb_cArray, "find", rb_ary_find, -1);
8909 rb_define_method(rb_cArray, "detect", rb_ary_find, -1);
8910 rb_define_method(rb_cArray, "rfind", rb_ary_rfind, -1);
8911 rb_define_method(rb_cArray, "find_index", rb_ary_index, -1);
8912 rb_define_method(rb_cArray, "index", rb_ary_index, -1);
8913 rb_define_method(rb_cArray, "rindex", rb_ary_rindex, -1);
8914 rb_define_method(rb_cArray, "join", rb_ary_join_m, -1);
8915 rb_define_method(rb_cArray, "reverse", rb_ary_reverse_m, 0);
8916 rb_define_method(rb_cArray, "reverse!", rb_ary_reverse_bang, 0);
8917 rb_define_method(rb_cArray, "rotate", rb_ary_rotate_m, -1);
8918 rb_define_method(rb_cArray, "rotate!", rb_ary_rotate_bang, -1);
8919 rb_define_method(rb_cArray, "sort", rb_ary_sort, 0);
8920 rb_define_method(rb_cArray, "sort!", rb_ary_sort_bang, 0);
8921 rb_define_method(rb_cArray, "sort_by!", rb_ary_sort_by_bang, 0);
8922 rb_define_method(rb_cArray, "collect", rb_ary_collect, 0);
8923 rb_define_method(rb_cArray, "collect!", rb_ary_collect_bang, 0);
8924 rb_define_method(rb_cArray, "map", rb_ary_collect, 0);
8925 rb_define_method(rb_cArray, "map!", rb_ary_collect_bang, 0);
8926 rb_define_method(rb_cArray, "select", rb_ary_select, 0);
8927 rb_define_method(rb_cArray, "select!", rb_ary_select_bang, 0);
8928 rb_define_method(rb_cArray, "filter", rb_ary_select, 0);
8929 rb_define_method(rb_cArray, "filter!", rb_ary_select_bang, 0);
8930 rb_define_method(rb_cArray, "keep_if", rb_ary_keep_if, 0);
8931 rb_define_method(rb_cArray, "values_at", rb_ary_values_at, -1);
8932 rb_define_method(rb_cArray, "delete", rb_ary_delete, 1);
8933 rb_define_method(rb_cArray, "delete_at", rb_ary_delete_at_m, 1);
8934 rb_define_method(rb_cArray, "delete_if", rb_ary_delete_if, 0);
8935 rb_define_method(rb_cArray, "reject", rb_ary_reject, 0);
8936 rb_define_method(rb_cArray, "reject!", rb_ary_reject_bang, 0);
8937 rb_define_method(rb_cArray, "zip", rb_ary_zip, -1);
8938 rb_define_method(rb_cArray, "transpose", rb_ary_transpose, 0);
8939 rb_define_method(rb_cArray, "replace", rb_ary_replace, 1);
8940 rb_define_method(rb_cArray, "clear", rb_ary_clear, 0);
8941 rb_define_method(rb_cArray, "fill", rb_ary_fill, -1);
8942 rb_define_method(rb_cArray, "include?", rb_ary_includes, 1);
8943 rb_define_method(rb_cArray, "<=>", rb_ary_cmp, 1);
8944
8945 rb_define_method(rb_cArray, "slice", rb_ary_aref, -1);
8946 rb_define_method(rb_cArray, "slice!", rb_ary_slice_bang, -1);
8947
8948 rb_define_method(rb_cArray, "assoc", rb_ary_assoc, 1);
8949 rb_define_method(rb_cArray, "rassoc", rb_ary_rassoc, 1);
8950
8951 rb_define_method(rb_cArray, "+", rb_ary_plus, 1);
8952 rb_define_method(rb_cArray, "*", rb_ary_times, 1);
8953
8954 rb_define_method(rb_cArray, "-", rb_ary_diff, 1);
8955 rb_define_method(rb_cArray, "&", rb_ary_and, 1);
8956 rb_define_method(rb_cArray, "|", rb_ary_or, 1);
8957
8958 rb_define_method(rb_cArray, "max", rb_ary_max, -1);
8959 rb_define_method(rb_cArray, "min", rb_ary_min, -1);
8960 rb_define_method(rb_cArray, "minmax", rb_ary_minmax, 0);
8961
8962 rb_define_method(rb_cArray, "uniq", rb_ary_uniq, 0);
8963 rb_define_method(rb_cArray, "uniq!", rb_ary_uniq_bang, 0);
8964 rb_define_method(rb_cArray, "compact", rb_ary_compact, 0);
8965 rb_define_method(rb_cArray, "compact!", rb_ary_compact_bang, 0);
8966 rb_define_method(rb_cArray, "flatten", rb_ary_flatten, -1);
8967 rb_define_method(rb_cArray, "flatten!", rb_ary_flatten_bang, -1);
8968 rb_define_method(rb_cArray, "count", rb_ary_count, -1);
8969 rb_define_method(rb_cArray, "cycle", rb_ary_cycle, -1);
8970 rb_define_method(rb_cArray, "permutation", rb_ary_permutation, -1);
8971 rb_define_method(rb_cArray, "combination", rb_ary_combination, 1);
8972 rb_define_method(rb_cArray, "repeated_permutation", rb_ary_repeated_permutation, 1);
8973 rb_define_method(rb_cArray, "repeated_combination", rb_ary_repeated_combination, 1);
8974 rb_define_method(rb_cArray, "product", rb_ary_product, -1);
8975
8976 rb_define_method(rb_cArray, "take", rb_ary_take, 1);
8977 rb_define_method(rb_cArray, "take_while", rb_ary_take_while, 0);
8978 rb_define_method(rb_cArray, "drop", rb_ary_drop, 1);
8979 rb_define_method(rb_cArray, "drop_while", rb_ary_drop_while, 0);
8980 rb_define_method(rb_cArray, "bsearch", rb_ary_bsearch, 0);
8981 rb_define_method(rb_cArray, "bsearch_index", rb_ary_bsearch_index, 0);
8982 rb_define_method(rb_cArray, "any?", rb_ary_any_p, -1);
8983 rb_define_method(rb_cArray, "all?", rb_ary_all_p, -1);
8984 rb_define_method(rb_cArray, "none?", rb_ary_none_p, -1);
8985 rb_define_method(rb_cArray, "one?", rb_ary_one_p, -1);
8986 rb_define_method(rb_cArray, "dig", rb_ary_dig, -1);
8987 rb_define_method(rb_cArray, "sum", rb_ary_sum, -1);
8988 rb_define_method(rb_cArray, "freeze", rb_ary_freeze, 0);
8989
8990 rb_define_method(rb_cArray, "deconstruct", rb_ary_deconstruct, 0);
8991
8992 rb_cArray_empty_frozen = RB_OBJ_SET_SHAREABLE(rb_ary_freeze(rb_ary_new()));
8993 rb_vm_register_global_object(rb_cArray_empty_frozen);
8994}
8995
8996#include "array.rbinc"
RUBY_ASSERT_ALWAYS
#define RUBY_ASSERT_ALWAYS(expr,...)
A variant of RUBY_ASSERT that does not interface with RUBY_DEBUG.
Definition assert.h:199
RBIMPL_ASSERT_OR_ASSUME
#define RBIMPL_ASSERT_OR_ASSUME(...)
This is either RUBY_ASSERT or RBIMPL_ASSUME, depending on RUBY_DEBUG.
Definition assert.h:311
RUBY_ASSERT
#define RUBY_ASSERT(...)
Asserts that the given expression is truthy if and only if RUBY_DEBUG is truthy.
Definition assert.h:219
rb_define_method
#define rb_define_method(klass, mid, func, arity)
Defines klass#mid.
Definition cxxanyargs.hpp:670
rb_define_singleton_method
#define rb_define_singleton_method(klass, mid, func, arity)
Defines klass.mid.
Definition cxxanyargs.hpp:685
rb_include_module
void rb_include_module(VALUE klass, VALUE module)
Includes a module to a class.
Definition class.c:1685
rb_define_class
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition class.c:1478
rb_define_alias
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
Definition class.c:2843
rb_scan_args
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.
Definition class.c:3133
rb_block_given_p
int rb_block_given_p(void)
Determines if the current method is given a block.
Definition eval.c:1010
FL_UNSET_RAW
#define FL_UNSET_RAW
Old name of RB_FL_UNSET_RAW.
Definition fl_type.h:133
rb_str_buf_cat2
#define rb_str_buf_cat2
Old name of rb_usascii_str_new_cstr.
Definition string.h:1683
RFLOAT_VALUE
#define RFLOAT_VALUE
Old name of rb_float_value.
Definition double.h:28
T_STRING
#define T_STRING
Old name of RUBY_T_STRING.
Definition value_type.h:78
Qundef
#define Qundef
Old name of RUBY_Qundef.
Definition special_consts.h:62
INT2FIX
#define INT2FIX
Old name of RB_INT2FIX.
Definition long.h:48
OBJ_FROZEN
#define OBJ_FROZEN
Old name of RB_OBJ_FROZEN.
Definition fl_type.h:136
rb_str_buf_new2
#define rb_str_buf_new2
Old name of rb_str_buf_new_cstr.
Definition string.h:1680
OBJ_FREEZE
#define OBJ_FREEZE
Old name of RB_OBJ_FREEZE.
Definition fl_type.h:134
rb_ary_new4
#define rb_ary_new4
Old name of rb_ary_new_from_values.
Definition array.h:659
FIXABLE
#define FIXABLE
Old name of RB_FIXABLE.
Definition fixnum.h:25
LONG2FIX
#define LONG2FIX
Old name of RB_INT2FIX.
Definition long.h:49
T_RATIONAL
#define T_RATIONAL
Old name of RUBY_T_RATIONAL.
Definition value_type.h:76
ALLOC_N
#define ALLOC_N
Old name of RB_ALLOC_N.
Definition memory.h:399
NUM2DBL
#define NUM2DBL
Old name of rb_num2dbl.
Definition double.h:27
FL_SET
#define FL_SET
Old name of RB_FL_SET.
Definition fl_type.h:128
rb_ary_new3
#define rb_ary_new3
Old name of rb_ary_new_from_args.
Definition array.h:658
LONG2NUM
#define LONG2NUM
Old name of RB_LONG2NUM.
Definition long.h:50
rb_usascii_str_new2
#define rb_usascii_str_new2
Old name of rb_usascii_str_new_cstr.
Definition string.h:1681
Qtrue
#define Qtrue
Old name of RUBY_Qtrue.
Definition special_consts.h:61
ST2FIX
#define ST2FIX
Old name of RB_ST2FIX.
Definition st_data_t.h:33
NUM2INT
#define NUM2INT
Old name of RB_NUM2INT.
Definition int.h:44
Qnil
#define Qnil
Old name of RUBY_Qnil.
Definition special_consts.h:60
Qfalse
#define Qfalse
Old name of RUBY_Qfalse.
Definition special_consts.h:59
FIX2LONG
#define FIX2LONG
Old name of RB_FIX2LONG.
Definition long.h:46
T_ARRAY
#define T_ARRAY
Old name of RUBY_T_ARRAY.
Definition value_type.h:56
NIL_P
#define NIL_P
Old name of RB_NIL_P.
Definition special_consts.h:55
ALLOCV_N
#define ALLOCV_N
Old name of RB_ALLOCV_N.
Definition memory.h:405
FL_WB_PROTECTED
#define FL_WB_PROTECTED
Old name of RUBY_FL_WB_PROTECTED.
Definition fl_type.h:59
DBL2NUM
#define DBL2NUM
Old name of rb_float_new.
Definition double.h:29
FL_TEST
#define FL_TEST
Old name of RB_FL_TEST.
Definition fl_type.h:130
NUM2LONG
#define NUM2LONG
Old name of RB_NUM2LONG.
Definition long.h:51
FL_UNSET
#define FL_UNSET
Old name of RB_FL_UNSET.
Definition fl_type.h:132
FIXNUM_P
#define FIXNUM_P
Old name of RB_FIXNUM_P.
Definition special_consts.h:53
rb_ary_new2
#define rb_ary_new2
Old name of rb_ary_new_capa.
Definition array.h:657
FL_SET_RAW
#define FL_SET_RAW
Old name of RB_FL_SET_RAW.
Definition fl_type.h:129
ALLOCV_END
#define ALLOCV_END
Old name of RB_ALLOCV_END.
Definition memory.h:406
rb_category_warn
void rb_category_warn(rb_warning_category_t category, const char *fmt,...)
Identical to rb_category_warning(), except it reports unless $VERBOSE is nil.
Definition error.c:476
rb_iter_break
void rb_iter_break(void)
Breaks from a block.
Definition vm.c:2280
rb_eFrozenError
VALUE rb_eFrozenError
FrozenError exception.
Definition error.c:1430
rb_eRangeError
VALUE rb_eRangeError
RangeError exception.
Definition error.c:1435
rb_eTypeError
VALUE rb_eTypeError
TypeError exception.
Definition error.c:1431
rb_eRuntimeError
VALUE rb_eRuntimeError
RuntimeError exception.
Definition error.c:1429
rb_warn
void rb_warn(const char *fmt,...)
Identical to rb_warning(), except it reports unless $VERBOSE is nil.
Definition error.c:466
rb_eIndexError
VALUE rb_eIndexError
IndexError exception.
Definition error.c:1433
rb_warning
void rb_warning(const char *fmt,...)
Issues a warning.
Definition error.c:497
RB_WARN_CATEGORY_DEPRECATED
@ RB_WARN_CATEGORY_DEPRECATED
Warning is for deprecated features.
Definition error.h:48
rb_cArray
VALUE rb_cArray
Array class.
rb_mEnumerable
VALUE rb_mEnumerable
Enumerable module.
Definition enum.c:27
rb_obj_hide
VALUE rb_obj_hide(VALUE obj)
Make the object invisible from Ruby code.
Definition object.c:100
rb_class_new_instance_pass_kw
VALUE rb_class_new_instance_pass_kw(int argc, const VALUE *argv, VALUE klass)
Identical to rb_class_new_instance(), except it passes the passed keywords if any to the #initialize ...
Definition object.c:2226
rb_obj_frozen_p
VALUE rb_obj_frozen_p(VALUE obj)
Just calls RB_OBJ_FROZEN() inside.
Definition object.c:1354
rb_eql
int rb_eql(VALUE lhs, VALUE rhs)
Checks for equality of the passed objects, in terms of Object#eql?.
Definition object.c:189
rb_cNumeric
VALUE rb_cNumeric
Numeric class.
Definition numeric.c:196
rb_cRandom
VALUE rb_cRandom
Random class.
Definition random.c:245
rb_obj_class
VALUE rb_obj_class(VALUE obj)
Queries the class of an object.
Definition object.c:264
rb_inspect
VALUE rb_inspect(VALUE obj)
Generates a human-readable textual representation of the given object.
Definition object.c:686
rb_num2dbl
double rb_num2dbl(VALUE num)
Converts an instance of rb_cNumeric into C's double.
Definition object.c:3829
rb_equal
VALUE rb_equal(VALUE lhs, VALUE rhs)
This function is an optimised version of calling #==.
Definition object.c:176
rb_obj_is_kind_of
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.
Definition object.c:923
rb_obj_freeze
VALUE rb_obj_freeze(VALUE obj)
Just calls rb_obj_freeze_inline() inside.
Definition object.c:1342
RB_OBJ_WRITTEN
#define RB_OBJ_WRITTEN(old, oldv, young)
Identical to RB_OBJ_WRITE(), except it doesn't write any values, but only a WB declaration.
Definition gc.h:615
RB_OBJ_WRITE
#define RB_OBJ_WRITE(old, slot, young)
Declaration of a "back" pointer.
Definition gc.h:603
encoding.h
Encoding relates APIs.
rb_usascii_encoding
rb_encoding * rb_usascii_encoding(void)
Queries the encoding that represents US-ASCII.
Definition encoding.c:1547
rb_funcall
VALUE rb_funcall(VALUE recv, ID mid, int n,...)
Calls a method.
Definition vm_eval.c:1117
rb_call_super
VALUE rb_call_super(int argc, const VALUE *argv)
This resembles ruby's super.
Definition vm_eval.c:362
RGENGC_WB_PROTECTED_ARRAY
#define RGENGC_WB_PROTECTED_ARRAY
This is a compile-time flag to enable/disable write barrier for struct RArray.
Definition gc.h:446
rb_ary_rotate
VALUE rb_ary_rotate(VALUE ary, long rot)
Destructively rotates the passed array in-place to towards its end.
rb_ary_new_from_values
VALUE rb_ary_new_from_values(long n, const VALUE *elts)
Identical to rb_ary_new_from_args(), except how objects are passed.
rb_ary_cmp
VALUE rb_ary_cmp(VALUE lhs, VALUE rhs)
Recursively compares each elements of the two arrays one-by-one using <=>.
rb_ary_rassoc
VALUE rb_ary_rassoc(VALUE alist, VALUE key)
Identical to rb_ary_assoc(), except it scans the passed array from the opposite direction.
rb_ary_concat
VALUE rb_ary_concat(VALUE lhs, VALUE rhs)
Destructively appends the contents of latter into the end of former.
rb_ary_assoc
VALUE rb_ary_assoc(VALUE alist, VALUE key)
Looks up the passed key, assuming the passed array is an alist.
rb_ary_reverse
VALUE rb_ary_reverse(VALUE ary)
Destructively reverses the passed array in-place.
rb_ary_shared_with_p
VALUE rb_ary_shared_with_p(VALUE lhs, VALUE rhs)
Queries if the passed two arrays share the same backend storage.
rb_ary_shift
VALUE rb_ary_shift(VALUE ary)
Destructively deletes an element from the beginning of the passed array and returns what was deleted.
rb_ary_sort
VALUE rb_ary_sort(VALUE ary)
Creates a copy of the passed array, whose elements are sorted according to their <=> result.
rb_ary_resurrect
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...
rb_ary_dup
VALUE rb_ary_dup(VALUE ary)
Duplicates an array.
rb_ary_includes
VALUE rb_ary_includes(VALUE ary, VALUE elem)
Queries if the passed array has the passed entry.
rb_ary_aref
VALUE rb_ary_aref(int argc, const VALUE *argv, VALUE ary)
Queries element(s) of an array.
rb_get_values_at
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.
rb_ary_free
void rb_ary_free(VALUE ary)
Destroys the given array for no reason.
rb_ary_each
VALUE rb_ary_each(VALUE ary)
Iteratively yields each element of the passed array to the implicitly passed block if any.
rb_ary_delete_at
VALUE rb_ary_delete_at(VALUE ary, long pos)
Destructively removes an element which resides at the specific index of the passed array.
rb_ary_plus
VALUE rb_ary_plus(VALUE lhs, VALUE rhs)
Creates a new array, concatenating the former to the latter.
rb_ary_cat
VALUE rb_ary_cat(VALUE ary, const VALUE *train, long len)
Destructively appends multiple elements at the end of the array.
rb_ary_modify
void rb_ary_modify(VALUE ary)
Declares that the array is about to be modified.
rb_ary_replace
VALUE rb_ary_replace(VALUE copy, VALUE orig)
Replaces the contents of the former object with the contents of the latter.
rb_check_array_type
VALUE rb_check_array_type(VALUE obj)
Try converting an object to its array representation using its to_ary method, if any.
rb_ary_to_ary
VALUE rb_ary_to_ary(VALUE obj)
Force converts an object to an array.
rb_ary_new
VALUE rb_ary_new(void)
Allocates a new, empty array.
rb_ary_new_capa
VALUE rb_ary_new_capa(long capa)
Identical to rb_ary_new(), except it additionally specifies how many rooms of objects it should alloc...
rb_ary_resize
VALUE rb_ary_resize(VALUE ary, long len)
Expands or shrinks the passed array to the passed length.
rb_ary_pop
VALUE rb_ary_pop(VALUE ary)
Destructively deletes an element from the end of the passed array and returns what was deleted.
rb_ary_hidden_new
VALUE rb_ary_hidden_new(long capa)
Allocates a hidden (no class) empty array.
rb_ary_clear
VALUE rb_ary_clear(VALUE ary)
Destructively removes everything form an array.
rb_ary_subseq
VALUE rb_ary_subseq(VALUE ary, long beg, long len)
Obtains a part of the passed array.
rb_ary_push
VALUE rb_ary_push(VALUE ary, VALUE elem)
Special case of rb_ary_cat() that it adds only one element.
rb_ary_freeze
VALUE rb_ary_freeze(VALUE obj)
Freeze an array, preventing further modifications.
rb_ary_to_s
VALUE rb_ary_to_s(VALUE ary)
Converts an array into a human-readable string.
rb_ary_entry
VALUE rb_ary_entry(VALUE ary, long off)
Queries an element of an array.
rb_ary_sort_bang
VALUE rb_ary_sort_bang(VALUE ary)
Destructively sorts the passed array in-place, according to each elements' <=> result.
rb_assoc_new
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Identical to rb_ary_new_from_values(), except it expects exactly two parameters.
rb_mem_clear
void rb_mem_clear(VALUE *buf, long len)
Fills the memory region with a series of RUBY_Qnil.
rb_ary_delete
VALUE rb_ary_delete(VALUE ary, VALUE elem)
Destructively removes elements from the passed array, so that there would be no elements inside that ...
rb_ary_join
VALUE rb_ary_join(VALUE ary, VALUE sep)
Recursively stringises the elements of the passed array, flattens that result, then joins the sequenc...
rb_ary_store
void rb_ary_store(VALUE ary, long key, VALUE val)
Destructively stores the passed value to the passed array's passed index.
RETURN_SIZED_ENUMERATOR
#define RETURN_SIZED_ENUMERATOR(obj, argc, argv, size_fn)
This roughly resembles return enum_for(__callee__) unless block_given?.
Definition enumerator.h:208
RETURN_ENUMERATOR
#define RETURN_ENUMERATOR(obj, argc, argv)
Identical to RETURN_SIZED_ENUMERATOR(), except its size is unknown.
Definition enumerator.h:242
UNLIMITED_ARGUMENTS
#define UNLIMITED_ARGUMENTS
This macro is used in conjunction with rb_check_arity().
Definition error.h:35
rb_check_arity
static int rb_check_arity(int argc, int min, int max)
Ensures that the passed integer is in the passed range.
Definition error.h:284
rb_output_fs
VALUE rb_output_fs
The field separator character for outputs, or the $,.
Definition io.c:204
rb_int_positive_pow
VALUE rb_int_positive_pow(long x, unsigned long y)
Raises the passed x to the power of y.
Definition numeric.c:4694
rb_range_beg_len
VALUE rb_range_beg_len(VALUE range, long *begp, long *lenp, long len, int err)
Deconstructs a numerical range.
Definition range.c:1950
rb_hash_uint
#define rb_hash_uint(h, i)
Just another name of st_hash_uint.
Definition string.h:943
rb_hash_end
#define rb_hash_end(h)
Just another name of st_hash_end.
Definition string.h:946
rb_str_new
#define rb_str_new(str, len)
Allocates an instance of rb_cString.
Definition string.h:1499
rb_usascii_str_new
#define rb_usascii_str_new(str, len)
Identical to rb_str_new, except it generates a string of "US ASCII" encoding.
Definition string.h:1533
rb_usascii_str_new_cstr
#define rb_usascii_str_new_cstr(str)
Identical to rb_str_new_cstr, except it generates a string of "US ASCII" encoding.
Definition string.h:1568
rb_str_buf_append
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.
Definition string.c:3765
rb_str_set_len
void rb_str_set_len(VALUE str, long len)
Overwrites the length of the string.
Definition string.c:3389
rb_hash_start
st_index_t rb_hash_start(st_index_t i)
Starts a series of hashing.
Definition random.c:1776
rb_str_cmp
int rb_str_cmp(VALUE lhs, VALUE rhs)
Compares two strings, as in strcmp(3).
Definition string.c:4216
rb_check_string_type
VALUE rb_check_string_type(VALUE obj)
Try converting an object to its stringised representation using its to_str method,...
Definition string.c:2952
rb_str_buf_new
VALUE rb_str_buf_new(long capa)
Allocates a "string buffer".
Definition string.c:1718
rb_obj_as_string
VALUE rb_obj_as_string(VALUE obj)
Try converting an object to its stringised representation using its to_s method, if any.
Definition string.c:1850
rb_exec_recursive
VALUE rb_exec_recursive(VALUE(*f)(VALUE g, VALUE h, int r), VALUE g, VALUE h)
"Recursion" API entry point.
Definition thread.c:5583
rb_exec_recursive_paired
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,...
Definition thread.c:5594
rb_respond_to
int rb_respond_to(VALUE obj, ID mid)
Queries if the object responds to the method.
Definition vm_method.c:3416
rb_define_alloc_func
void rb_define_alloc_func(VALUE klass, rb_alloc_func_t func)
Sets the allocator function of a class.
capa
int capa
Designed capacity of the buffer.
Definition io.h:11
len
int len
Length of the buffer.
Definition io.h:8
ractor.h
RB_OBJ_SHAREABLE_P
#define RB_OBJ_SHAREABLE_P(obj)
Queries if the passed object has previously classified as shareable or not.
Definition ractor.h:235
thread.h
ruby_thread_has_gvl_p
int ruby_thread_has_gvl_p(void)
Whether the current thread is holding the GVL.
Definition thread.c:2103
util.h
ruby_qsort
void ruby_qsort(void *, const size_t, const size_t, int(*)(const void *, const void *, void *), void *)
Reentrant implementation of quick sort.
RB_BLOCK_CALL_FUNC_ARGLIST
#define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)
Shim for block function parameters.
Definition iterator.h:58
rb_yield_values
VALUE rb_yield_values(int n,...)
Identical to rb_yield(), except it takes variadic number of parameters and pass them to the block.
Definition vm_eval.c:1395
rb_yield_values2
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...
Definition vm_eval.c:1417
rb_yield
VALUE rb_yield(VALUE val)
Yields the block.
Definition vm_eval.c:1372
RBIMPL_ATTR_MAYBE_UNUSED
#define RBIMPL_ATTR_MAYBE_UNUSED()
Wraps (or simulates) [[maybe_unused]].
Definition maybe_unused.h:35
MEMCPY
#define MEMCPY(p1, p2, type, n)
Handy macro to call memcpy.
Definition memory.h:372
MEMZERO
#define MEMZERO(p, type, n)
Handy macro to erase a region of memory.
Definition memory.h:360
RB_GC_GUARD
#define RB_GC_GUARD(v)
Prevents premature destruction of local objects.
Definition memory.h:167
MEMMOVE
#define MEMMOVE(p1, p2, type, n)
Handy macro to call memmove.
Definition memory.h:384
ruby::backward::cxxanyargs::rb_block_call
VALUE rb_block_call(VALUE q, ID w, int e, const VALUE *r, type *t, VALUE y)
Call a method with a block.
Definition cxxanyargs.hpp:232
ruby::backward::cxxanyargs::rb_hash_foreach
void rb_hash_foreach(VALUE q, int_type *w, VALUE e)
Iteration over the given hash.
Definition cxxanyargs.hpp:482
ruby::backward::cxxanyargs::rb_ensure
VALUE rb_ensure(type *q, VALUE w, type *e, VALUE r)
An equivalent of ensure clause.
Definition cxxanyargs.hpp:310
RARRAY_LEN
#define RARRAY_LEN
Just another name of rb_array_len.
Definition rarray.h:51
RARRAY
#define RARRAY(obj)
Convenient casting macro.
Definition rarray.h:44
RARRAY_ASET
static void RARRAY_ASET(VALUE ary, long i, VALUE v)
Assigns an object in an array.
Definition rarray.h:386
RARRAY_PTR_USE
#define RARRAY_PTR_USE(ary, ptr_name, expr)
Declares a section of code where raw pointers are used.
Definition rarray.h:348
RARRAY_PTR
static VALUE * RARRAY_PTR(VALUE ary)
Wild use of a C pointer.
Definition rarray.h:366
RARRAY_AREF
#define RARRAY_AREF(a, i)
Definition rarray.h:403
RARRAY_CONST_PTR
#define RARRAY_CONST_PTR
Just another name of rb_array_const_ptr.
Definition rarray.h:52
RBASIC
#define RBASIC(obj)
Convenient casting macro.
Definition rbasic.h:40
RUBY_DATA_FUNC
void(* RUBY_DATA_FUNC)(void *)
This is the type of callbacks registered to RData.
Definition rdata.h:104
RHASH_SIZE
#define RHASH_SIZE(h)
Queries the size of the hash.
Definition rhash.h:69
StringValue
#define StringValue(v)
Ensures that the parameter object is a String.
Definition rstring.h:66
RTYPEDDATA_DATA
#define RTYPEDDATA_DATA(v)
Convenient getter macro.
Definition rtypeddata.h:103
TypedData_Wrap_Struct
#define TypedData_Wrap_Struct(klass, data_type, sval)
Converts sval, a pointer to your struct, into a Ruby object.
Definition rtypeddata.h:461
rb_data_type_t
struct rb_data_type_struct rb_data_type_t
This is the struct that holds necessary info for a struct.
Definition rtypeddata.h:205
RB_PASS_CALLED_KEYWORDS
#define RB_PASS_CALLED_KEYWORDS
Pass keywords if current method is called with keywords, useful for argument delegation.
Definition scan_args.h:78
RTEST
#define RTEST
This is an old name of RB_TEST.
Definition special_consts.h:51
RArray
Ruby's array.
Definition rarray.h:128
RArray::heap
struct RArray::@045262372243116021320040343026053377105164277244::@107044055235071215233122207133305327077254253150 heap
Arrays that use separated memory region for elements use this pattern.
RArray::basic
struct RBasic basic
Basic part, including flags and class.
Definition rarray.h:131
RArray::shared_root
const VALUE shared_root
Parent of the array.
Definition rarray.h:166
RArray::ary
const VALUE ary[1]
Embedded elements.
Definition rarray.h:188
RArray::aux
union RArray::@045262372243116021320040343026053377105164277244::@107044055235071215233122207133305327077254253150::@305130333254331304137150213113061105025176332136 aux
Auxiliary info.
RArray::capa
long capa
Capacity of *ptr.
Definition rarray.h:153
RArray::as
union RArray::@045262372243116021320040343026053377105164277244 as
Array's specific fields.
RArray::len
long len
Number of elements of the array.
Definition rarray.h:143
RArray::ptr
const VALUE * ptr
Pointer to the C array that holds the elements of the array.
Definition rarray.h:175
RBasic::flags
VALUE flags
Per-object flags.
Definition rbasic.h:81
SIGNED_VALUE
intptr_t SIGNED_VALUE
A signed integer type that has the same width with VALUE.
Definition value.h:63
VALUE
uintptr_t VALUE
Type that represents a Ruby object.
Definition value.h:40
RB_FLOAT_TYPE_P
static bool RB_FLOAT_TYPE_P(VALUE obj)
Queries if the object is an instance of rb_cFloat.
Definition value_type.h:264
RB_TYPE_P
static bool RB_TYPE_P(VALUE obj, enum ruby_value_type t)
Queries if the given object is of given type.
Definition value_type.h:376