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