Ruby 4.1.0dev (2026-08-15 revision 75d53029986f6c95f3fd66d8b05c3222d63f21b2)
array.c (75d53029986f6c95f3fd66d8b05c3222d63f21b2)
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
2310rb_ary_splice(VALUE ary, long beg, long len, const VALUE *rptr, long rlen)
2311{
2312 long olen;
2313 long rofs;
2314
2315 if (len < 0) rb_raise(rb_eIndexError, "negative length (%ld)", len);
2316 olen = RARRAY_LEN(ary);
2317 if (beg < 0) {
2318 beg += olen;
2319 if (beg < 0) {
2320 rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
2321 beg - olen, -olen);
2322 }
2323 }
2324 if (olen < len || olen < beg + len) {
2325 len = olen - beg;
2326 }
2327
2328 {
2329 const VALUE *optr = RARRAY_CONST_PTR(ary);
2330 rofs = (rptr >= optr && rptr < optr + olen) ? rptr - optr : -1;
2331 }
2332
2333 if (beg >= olen) {
2334 VALUE target_ary;
2335 if (beg > ARY_MAX_SIZE - rlen) {
2336 rb_raise(rb_eIndexError, "index %ld too big", beg);
2337 }
2338 target_ary = ary_ensure_room_for_push(ary, rlen-len); /* len is 0 or negative */
2339 len = beg + rlen;
2340 ary_mem_clear(ary, olen, beg - olen);
2341 if (rlen > 0) {
2342 if (rofs != -1) rptr = RARRAY_CONST_PTR(ary) + rofs;
2343 ary_memcpy0(ary, beg, rlen, rptr, target_ary);
2344 }
2345 ARY_SET_LEN(ary, len);
2346 }
2347 else {
2348 long alen;
2349
2350 if (olen - len > ARY_MAX_SIZE - rlen) {
2351 rb_raise(rb_eIndexError, "index %ld too big", olen + rlen - len);
2352 }
2354 alen = olen + rlen - len;
2355 if (alen >= ARY_CAPA(ary)) {
2356 ary_double_capa(ary, alen);
2357 }
2358
2359 if (len != rlen) {
2361 MEMMOVE(ptr + beg + rlen, ptr + beg + len,
2362 VALUE, olen - (beg + len)));
2363 ARY_SET_LEN(ary, alen);
2364 }
2365 if (rlen > 0) {
2366 if (rofs == -1) {
2367 rb_gc_writebarrier_remember(ary);
2368 }
2369 else {
2370 /* In this case, we're copying from a region in this array, so
2371 * we don't need to fire the write barrier. */
2372 rptr = RARRAY_CONST_PTR(ary) + rofs;
2373 }
2374
2375 /* do not use RARRAY_PTR() because it can causes GC.
2376 * ary can contain T_NONE object because it is not cleared.
2377 */
2379 MEMMOVE(ptr + beg, rptr, VALUE, rlen));
2380 }
2381 }
2382}
2383
2384void
2385rb_ary_set_len(VALUE ary, long len)
2386{
2387 long capa;
2388
2389 rb_ary_modify_check(ary);
2390 if (ARY_SHARED_P(ary)) {
2391 rb_raise(rb_eRuntimeError, "can't set length of shared ");
2392 }
2393 if (len > (capa = (long)ARY_CAPA(ary))) {
2394 rb_bug("probable buffer overflow: %ld for %ld", len, capa);
2395 }
2396 ARY_SET_LEN(ary, len);
2397}
2398
2399VALUE
2400rb_ary_modify_expand(VALUE ary, long expand)
2401{
2402 long len = RARRAY_LEN(ary);
2403
2404 if (expand < 0) {
2405 rb_raise(rb_eArgError, "negative expanding array size");
2406 }
2407 if (expand >= ARY_MAX_SIZE - len) {
2408 rb_raise(rb_eArgError, " size too big");
2409 }
2410 rb_ary_modify_check(ary);
2411 if (len + expand > ARY_CAPA(ary)) {
2412 ary_resize_capa(ary, len + expand);
2413 }
2414 return ary;
2415}
2416
2417VALUE
2419{
2420 long olen;
2421
2423 olen = RARRAY_LEN(ary);
2424 if (len == olen) return ary;
2425 if (len > ARY_MAX_SIZE) {
2426 rb_raise(rb_eIndexError, "index %ld too big", len);
2427 }
2428 if (len > olen) {
2429 if (len > ARY_CAPA(ary)) {
2430 ary_double_capa(ary, len);
2431 }
2432 ary_mem_clear(ary, olen, len - olen);
2433 ARY_SET_LEN(ary, len);
2434 }
2435 else if (ARY_EMBED_P(ary)) {
2436 ARY_SET_EMBED_LEN(ary, len);
2437 }
2438 else if (len <= ary_embed_capa(ary)) {
2439 const VALUE *ptr = ARY_HEAP_PTR(ary);
2440 long ptr_capa = ARY_HEAP_SIZE(ary);
2441 bool is_malloc_ptr = !ARY_SHARED_P(ary);
2442
2443 FL_SET_EMBED(ary);
2444
2445 MEMCPY((VALUE *)ARY_EMBED_PTR(ary), ptr, VALUE, len); /* WB: no new reference */
2446 ARY_SET_EMBED_LEN(ary, len);
2447
2448 if (is_malloc_ptr) ruby_xfree_sized((void *)ptr, ptr_capa);
2449 }
2450 else {
2451 if (olen > len + ARY_DEFAULT_SIZE) {
2452 size_t new_capa = ary_heap_realloc(ary, len);
2453 ARY_SET_CAPA(ary, new_capa);
2454 }
2455 ARY_SET_HEAP_LEN(ary, len);
2456 }
2457 ary_verify(ary);
2458 return ary;
2459}
2460
2461static VALUE
2462ary_aset_by_rb_ary_store(VALUE ary, long key, VALUE val)
2463{
2464 rb_ary_store(ary, key, val);
2465 return val;
2466}
2467
2468static VALUE
2469ary_aset_by_rb_ary_splice(VALUE ary, long beg, long len, VALUE val)
2470{
2471 VALUE rpl = rb_ary_to_ary(val);
2472 rb_ary_splice(ary, beg, len, RARRAY_CONST_PTR(rpl), RARRAY_LEN(rpl));
2473 RB_GC_GUARD(rpl);
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 rb_ary_splice(ary, pos, 0, argv + 1, argc - 1);
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 for (i=0; i<RARRAY_LEN(ary); i++) {
2791 }
2792 return ary;
2793}
2794
2795/*
2796 * call-seq:
2797 * each_index {|index| ... } -> self
2798 * each_index -> new_enumerator
2799 *
2800 * With a block given, iterates over the elements of +self+,
2801 * passing each <i>array index</i> to the block;
2802 * returns +self+:
2803 *
2804 * a = [:foo, 'bar', 2]
2805 * a.each_index {|index| puts "#{index} #{a[index]}" }
2806 *
2807 * Output:
2808 *
2809 * 0 foo
2810 * 1 bar
2811 * 2 2
2812 *
2813 * Allows the array to be modified during iteration:
2814 *
2815 * a = [:foo, 'bar', 2]
2816 * a.each_index {|index| puts index; a.clear if index > 0 }
2817 * a # => []
2818 *
2819 * Output:
2820 *
2821 * 0
2822 * 1
2823 *
2824 * With no block given, returns a new Enumerator.
2825 *
2826 * Related: see {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
2827 */
2828
2829static VALUE
2830rb_ary_each_index(VALUE ary)
2831{
2832 long i;
2833 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
2834
2835 for (i=0; i<RARRAY_LEN(ary); i++) {
2836 rb_yield(LONG2NUM(i));
2837 }
2838 return ary;
2839}
2840
2841/*
2842 * call-seq:
2843 * reverse_each {|element| ... } -> self
2844 * reverse_each -> Enumerator
2845 *
2846 * When a block given, iterates backwards over the elements of +self+,
2847 * passing, in reverse order, each element to the block;
2848 * returns +self+:
2849 *
2850 * a = []
2851 * [0, 1, 2].reverse_each {|element| a.push(element) }
2852 * a # => [2, 1, 0]
2853 *
2854 * Allows the array to be modified during iteration:
2855 *
2856 * a = ['a', 'b', 'c']
2857 * a.reverse_each {|element| a.clear if element.start_with?('b') }
2858 * a # => []
2859 *
2860 * When no block given, returns a new Enumerator.
2861 *
2862 * Related: see {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
2863 */
2864
2865static VALUE
2866rb_ary_reverse_each(VALUE ary)
2867{
2868 long len;
2869
2870 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
2871 len = RARRAY_LEN(ary);
2872 while (len--) {
2873 long nlen;
2875 nlen = RARRAY_LEN(ary);
2876 if (nlen < len) {
2877 len = nlen;
2878 }
2879 }
2880 return ary;
2881}
2882
2883/*
2884 * call-seq:
2885 * length -> integer
2886 * size -> integer
2887 *
2888 * Returns the count of elements in +self+:
2889 *
2890 * [0, 1, 2].length # => 3
2891 * [].length # => 0
2892 *
2893 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
2894 */
2895
2896static VALUE
2897rb_ary_length(VALUE ary)
2898{
2899 long len = RARRAY_LEN(ary);
2900 return LONG2NUM(len);
2901}
2902
2903/*
2904 * call-seq:
2905 * empty? -> true or false
2906 *
2907 * Returns +true+ if the count of elements in +self+ is zero,
2908 * +false+ otherwise.
2909 *
2910 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
2911 */
2912
2913static VALUE
2914rb_ary_empty_p(VALUE ary)
2915{
2916 return RBOOL(RARRAY_LEN(ary) == 0);
2917}
2918
2919VALUE
2921{
2922 long len = RARRAY_LEN(ary);
2923 VALUE dup = rb_ary_new2(len);
2924 ary_memcpy(dup, 0, len, RARRAY_CONST_PTR(ary));
2925 ARY_SET_LEN(dup, len);
2926
2927 ary_verify(ary);
2928 ary_verify(dup);
2929 return dup;
2930}
2931
2932VALUE
2934{
2935 return ary_make_partial(ary, rb_cArray, 0, RARRAY_LEN(ary));
2936}
2937
2938#if USE_ZJIT
2939bool
2940rb_zjit_array_dup_can_fastpath(VALUE ary, size_t *alloc_size_out, VALUE *flags_out, long *len_out)
2941{
2942 long len = RARRAY_LEN(ary);
2943 long embed_capa = (sizeof(struct RArray) - offsetof(struct RArray, as.ary)) / sizeof(VALUE);
2944
2945 if (len > embed_capa) return false;
2946
2947 *alloc_size_out = sizeof(struct RArray);
2948 *flags_out = T_ARRAY | RARRAY_EMBED_FLAG | ((VALUE)len << RARRAY_EMBED_LEN_SHIFT);
2949 *len_out = len;
2950 return true;
2951}
2952
2953void
2954rb_zjit_array_new_fastpath(size_t *alloc_size_out, VALUE *flags_out)
2955{
2956 size_t size = sizeof(struct RArray);
2957 shape_id_t shape_id = rb_shape_transition_slot_size(ROOT_SHAPE_ID | SHAPE_ID_LAYOUT_OTHER,
2958 rb_gc_size_slot_size(size));
2959 *alloc_size_out = size;
2960 *flags_out = T_ARRAY | RARRAY_EMBED_FLAG | ((VALUE)shape_id << SHAPE_FLAG_SHIFT);
2961}
2962#endif
2963
2964extern VALUE rb_output_fs;
2965
2966static void ary_join_1(VALUE obj, VALUE ary, VALUE sep, long i, VALUE result, int *first);
2967
2968static VALUE
2969recursive_join(VALUE obj, VALUE argp, int recur)
2970{
2971 VALUE *arg = (VALUE *)argp;
2972 VALUE ary = arg[0];
2973 VALUE sep = arg[1];
2974 VALUE result = arg[2];
2975 int *first = (int *)arg[3];
2976
2977 if (recur) {
2978 rb_raise(rb_eArgError, "recursive array join");
2979 }
2980 else {
2981 ary_join_1(obj, ary, sep, 0, result, first);
2982 }
2983 return Qnil;
2984}
2985
2986static long
2987ary_join_0(VALUE ary, VALUE sep, long max, VALUE result)
2988{
2989 long i;
2990 VALUE val;
2991
2992 if (max > 0) rb_enc_copy(result, RARRAY_AREF(ary, 0));
2993 for (i=0; i<max; i++) {
2994 val = RARRAY_AREF(ary, i);
2995 if (!RB_TYPE_P(val, T_STRING)) break;
2996 if (i > 0 && !NIL_P(sep))
2997 rb_str_buf_append(result, sep);
2998 rb_str_buf_append(result, val);
2999 }
3000 return i;
3001}
3002
3003static void
3004ary_join_1_str(VALUE dst, VALUE src, int *first)
3005{
3006 rb_str_buf_append(dst, src);
3007 if (*first) {
3008 rb_enc_copy(dst, src);
3009 *first = FALSE;
3010 }
3011}
3012
3013static void
3014ary_join_1_ary(VALUE obj, VALUE ary, VALUE sep, VALUE result, VALUE val, int *first)
3015{
3016 if (val == ary) {
3017 rb_raise(rb_eArgError, "recursive array join");
3018 }
3019 else {
3020 VALUE args[4];
3021
3022 *first = FALSE;
3023 args[0] = val;
3024 args[1] = sep;
3025 args[2] = result;
3026 args[3] = (VALUE)first;
3027 rb_exec_recursive(recursive_join, obj, (VALUE)args);
3028 }
3029}
3030
3031static void
3032ary_join_1(VALUE obj, VALUE ary, VALUE sep, long i, VALUE result, int *first)
3033{
3034 VALUE val, tmp;
3035
3036 for (; i<RARRAY_LEN(ary); i++) {
3037 if (i > 0 && !NIL_P(sep))
3038 rb_str_buf_append(result, sep);
3039
3040 val = RARRAY_AREF(ary, i);
3041 if (RB_TYPE_P(val, T_STRING)) {
3042 ary_join_1_str(result, val, first);
3043 }
3044 else if (RB_TYPE_P(val, T_ARRAY)) {
3045 ary_join_1_ary(val, ary, sep, result, val, first);
3046 }
3047 else if (!NIL_P(tmp = rb_check_string_type(val))) {
3048 ary_join_1_str(result, tmp, first);
3049 }
3050 else if (!NIL_P(tmp = rb_check_array_type(val))) {
3051 ary_join_1_ary(val, ary, sep, result, tmp, first);
3052 }
3053 else {
3054 ary_join_1_str(result, rb_obj_as_string(val), first);
3055 }
3056 }
3057}
3058
3059/* Fast path for Array#join: when every element is a String in one fast-path encoding
3060 * (UTF-8 / US-ASCII / ASCII-8BIT) and the separator is byte-compatible, the result can
3061 * be produced with a single memcpy pass instead of appending each element through
3062 * rb_str_buf_append. Returns the joined String, or Qundef when any of those invariants
3063 * does not hold -- the caller then uses the general path. No user code runs here, so
3064 * the array cannot be mutated underneath us. */
3065static VALUE
3066ary_join_fast(VALUE ary, VALUE sep)
3067{
3068 long n = RARRAY_LEN(ary);
3069 if (n == 0) return Qundef;
3070
3071 VALUE first = RARRAY_AREF(ary, 0);
3072 if (!RB_TYPE_P(first, T_STRING)) return Qundef;
3073 int encidx = ENCODING_GET(first);
3074 if (!rb_str_encindex_fastpath(encidx)) return Qundef;
3075
3076 /* cr accumulates the result code range exactly as rb_str_buf_append would. */
3078 long sep_len = 0;
3079 const char *sep_ptr = NULL;
3080 if (!NIL_P(sep)) {
3081 int sep_cr = rb_enc_str_coderange(sep);
3082 /* The separator must share the element encoding, or be 7-bit (encidx is
3083 ASCII-compatible, so a 7-bit separator concatenates without negotiation). */
3084 if (ENCODING_GET(sep) != encidx && sep_cr != ENC_CODERANGE_7BIT) return Qundef;
3085 sep_ptr = RSTRING_PTR(sep);
3086 sep_len = RSTRING_LEN(sep);
3087 if (n > 1) cr = ENC_CODERANGE_AND(cr, sep_cr);
3088 }
3089
3090 /* One pass: confirm the shared encoding, measure the length, merge code ranges. */
3091 long len = 1 + sep_len * (n - 1);
3092 for (long i = 0; i < n; i++) {
3093 VALUE s = RARRAY_AREF(ary, i);
3094 if (!RB_TYPE_P(s, T_STRING) || ENCODING_GET(s) != encidx) return Qundef;
3095 len += RSTRING_LEN(s);
3096 cr = ENC_CODERANGE_AND(cr, rb_enc_str_coderange(s));
3097 }
3098
3099 VALUE result = rb_str_buf_new(len);
3100 rb_enc_associate_index(result, encidx);
3101 char *const buf = RSTRING_PTR(result);
3102 char *p = buf;
3103 for (long i = 0; i < n; i++) {
3104 VALUE s = RARRAY_AREF(ary, i);
3105 long slen = RSTRING_LEN(s);
3106 if (i > 0 && sep_len) {
3107 memcpy(p, sep_ptr, sep_len);
3108 p += sep_len;
3109 }
3110 memcpy(p, RSTRING_PTR(s), slen);
3111 p += slen;
3112 }
3113
3114 ENC_CODERANGE_CLEAR(result); /* keep rb_str_set_len from rescanning the bytes */
3115 rb_str_set_len(result, p - buf);
3116 ENC_CODERANGE_SET(result, cr);
3117 return result;
3118}
3119
3120VALUE
3122{
3123 long len = 1, i;
3124 VALUE val, tmp, result;
3125
3126 if (RARRAY_LEN(ary) == 0) return rb_usascii_str_new(0, 0);
3127
3128 if (!NIL_P(sep)) StringValue(sep);
3129
3130 result = ary_join_fast(ary, sep);
3131 if (!UNDEF_P(result)) return result;
3132
3133 if (!NIL_P(sep)) {
3134 len += RSTRING_LEN(sep) * (RARRAY_LEN(ary) - 1);
3135 }
3136 long len_memo = RARRAY_LEN(ary);
3137 for (i=0; i < len_memo; i++) {
3138 val = RARRAY_AREF(ary, i);
3139 if (RB_UNLIKELY(!RB_TYPE_P(val, T_STRING))) {
3140 tmp = rb_check_string_type(val);
3141 if (NIL_P(tmp) || tmp != val) {
3142 int first;
3143 long n = RARRAY_LEN(ary);
3144 if (i > n) i = n;
3145 result = rb_str_buf_new(len + (n-i)*10);
3146 rb_enc_associate(result, rb_usascii_encoding());
3147 i = ary_join_0(ary, sep, i, result);
3148 first = i == 0;
3149 ary_join_1(ary, ary, sep, i, result, &first);
3150 return result;
3151 }
3152 len += RSTRING_LEN(tmp);
3153 len_memo = RARRAY_LEN(ary);
3154 }
3155 else {
3156 len += RSTRING_LEN(val);
3157 }
3158 }
3159
3160 result = rb_str_new(0, len);
3161 rb_str_set_len(result, 0);
3162
3163 ary_join_0(ary, sep, RARRAY_LEN(ary), result);
3164
3165 return result;
3166}
3167
3168/*
3169 * call-seq:
3170 * join(separator = $,) -> new_string
3171 *
3172 * Returns the new string formed by joining the string-converted elements of +self+
3173 * with the given +separator+ (defaults to <tt>$,</tt>):
3174 *
3175 * $, # => nil
3176 * %w[].join # => ""
3177 * %w[foo].join # => "foo"
3178 * a = %w[foo bar baz] # => ["foo", "bar", "baz"]
3179 * a.join # => "foobarbaz"
3180 * a.join('|') # => "foo|bar|baz"
3181 * a.join(' :|: ') # => "foo :|: bar :|: baz"
3182 *
3183 * Flattens and joins nested arrays:
3184 *
3185 * [:foo, [:bar, [:baz, :bat]]].join # => "foobarbazbat"
3186 *
3187 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3188 */
3189static VALUE
3190rb_ary_join_m(int argc, VALUE *argv, VALUE ary)
3191{
3192 VALUE sep;
3193
3194 if (rb_check_arity(argc, 0, 1) == 0 || NIL_P(sep = argv[0])) {
3195 sep = rb_output_fs;
3196 if (!NIL_P(sep)) {
3197 rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "$, is set to non-nil value");
3198 }
3199 }
3200
3201 return rb_ary_join(ary, sep);
3202}
3203
3204static VALUE
3205inspect_ary(VALUE ary, VALUE dummy, int recur)
3206{
3207 long i;
3208 VALUE s, str;
3209
3210 if (recur) return rb_usascii_str_new_cstr("[...]");
3211 str = rb_str_buf_new2("[");
3212 for (i=0; i<RARRAY_LEN(ary); i++) {
3213 s = rb_inspect(RARRAY_AREF(ary, i));
3214 if (i > 0) rb_str_buf_cat2(str, ", ");
3215 else rb_enc_copy(str, s);
3216 rb_str_buf_append(str, s);
3217 }
3218 rb_str_buf_cat2(str, "]");
3219 return str;
3220}
3221
3222/*
3223 * call-seq:
3224 * inspect -> new_string
3225 * to_s -> new_string
3226 *
3227 * Returns the new string formed by calling method <tt>#inspect</tt>
3228 * on each array element:
3229 *
3230 * a = [:foo, 'bar', 2]
3231 * a.inspect # => "[:foo, \"bar\", 2]"
3232 *
3233 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3234 */
3235
3236static VALUE
3237rb_ary_inspect(VALUE ary)
3238{
3239 if (RARRAY_LEN(ary) == 0) return rb_usascii_str_new2("[]");
3240 return rb_exec_recursive(inspect_ary, ary, 0);
3241}
3242
3243VALUE
3245{
3246 return rb_ary_inspect(ary);
3247}
3248
3249/*
3250 * call-seq:
3251 * to_a -> self or new_array
3252 *
3253 * When +self+ is an instance of \Array, returns +self+.
3254 *
3255 * Otherwise, returns a new array containing the elements of +self+:
3256 *
3257 * class MyArray < Array; end
3258 * my_a = MyArray.new(['foo', 'bar', 'two'])
3259 * a = my_a.to_a
3260 * a # => ["foo", "bar", "two"]
3261 * a.class # => Array # Not MyArray.
3262 *
3263 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3264 */
3265
3266static VALUE
3267rb_ary_to_a(VALUE ary)
3268{
3269 if (rb_obj_class(ary) != rb_cArray) {
3271 rb_ary_replace(dup, ary);
3272 return dup;
3273 }
3274 return ary;
3275}
3276
3277/*
3278 * call-seq:
3279 * to_h -> new_hash
3280 * to_h {|element| ... } -> new_hash
3281 *
3282 * Returns a new hash formed from +self+.
3283 *
3284 * With no block given, each element of +self+ must be a 2-element sub-array;
3285 * forms each sub-array into a key-value pair in the new hash:
3286 *
3287 * a = [['foo', 'zero'], ['bar', 'one'], ['baz', 'two']]
3288 * a.to_h # => {"foo" => "zero", "bar" => "one", "baz" => "two"}
3289 * [].to_h # => {}
3290 *
3291 * With a block given, the block must return a 2-element array;
3292 * calls the block with each element of +self+;
3293 * forms each returned array into a key-value pair in the returned hash:
3294 *
3295 * a = ['foo', :bar, 1, [2, 3], {baz: 4}]
3296 * a.to_h {|element| [element, element.class] }
3297 * # => {"foo" => String, bar: Symbol, 1 => Integer, [2, 3] => Array, {baz: 4} => Hash}
3298 *
3299 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3300 */
3301
3302static VALUE
3303rb_ary_to_h(VALUE ary)
3304{
3305 long i;
3306 VALUE hash = rb_hash_new_with_size(RARRAY_LEN(ary));
3307 int block_given = rb_block_given_p();
3308
3309 for (i=0; i<RARRAY_LEN(ary); i++) {
3310 const VALUE e = rb_ary_elt(ary, i);
3311 const VALUE elt = block_given ? rb_yield_force_blockarg(e) : e;
3312 const VALUE key_value_pair = rb_check_array_type(elt);
3313 if (NIL_P(key_value_pair)) {
3314 rb_raise(rb_eTypeError, "wrong element type %"PRIsVALUE" at %ld (expected array)",
3315 rb_obj_class(elt), i);
3316 }
3317 if (RARRAY_LEN(key_value_pair) != 2) {
3318 rb_raise(rb_eArgError, "wrong array length at %ld (expected 2, was %ld)",
3319 i, RARRAY_LEN(key_value_pair));
3320 }
3321 rb_hash_aset(hash, RARRAY_AREF(key_value_pair, 0), RARRAY_AREF(key_value_pair, 1));
3322 }
3323 return hash;
3324}
3325
3326/*
3327 * call-seq:
3328 * to_ary -> self
3329 *
3330 * Returns +self+.
3331 */
3332
3333static VALUE
3334rb_ary_to_ary_m(VALUE ary)
3335{
3336 return ary;
3337}
3338
3339static void
3340ary_reverse(VALUE *p1, VALUE *p2)
3341{
3342 while (p1 < p2) {
3343 VALUE tmp = *p1;
3344 *p1++ = *p2;
3345 *p2-- = tmp;
3346 }
3347}
3348
3349VALUE
3351{
3352 VALUE *p2;
3353 long len = RARRAY_LEN(ary);
3354
3356 if (len > 1) {
3357 RARRAY_PTR_USE(ary, p1, {
3358 p2 = p1 + len - 1; /* points last item */
3359 ary_reverse(p1, p2);
3360 }); /* WB: no new reference */
3361 }
3362 return ary;
3363}
3364
3365/*
3366 * call-seq:
3367 * reverse! -> self
3368 *
3369 * Reverses the order of the elements of +self+;
3370 * returns +self+:
3371 *
3372 * a = [0, 1, 2]
3373 * a.reverse! # => [2, 1, 0]
3374 * a # => [2, 1, 0]
3375 *
3376 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
3377 */
3378
3379static VALUE
3380rb_ary_reverse_bang(VALUE ary)
3381{
3382 return rb_ary_reverse(ary);
3383}
3384
3385/*
3386 * call-seq:
3387 * reverse -> new_array
3388 *
3389 * Returns a new array containing the elements of +self+ in reverse order:
3390 *
3391 * [0, 1, 2].reverse # => [2, 1, 0]
3392 *
3393 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
3394 */
3395
3396static VALUE
3397rb_ary_reverse_m(VALUE ary)
3398{
3399 long len = RARRAY_LEN(ary);
3400 VALUE dup = rb_ary_new2(len);
3401
3402 if (len > 0) {
3403 const VALUE *p1 = RARRAY_CONST_PTR(ary);
3404 VALUE *p2 = (VALUE *)RARRAY_CONST_PTR(dup) + len - 1;
3405 do *p2-- = *p1++; while (--len > 0);
3406 rb_gc_writebarrier_remember(dup);
3407 }
3408 ARY_SET_LEN(dup, RARRAY_LEN(ary));
3409 return dup;
3410}
3411
3412static inline long
3413rotate_count(long cnt, long len)
3414{
3415 return (cnt < 0) ? (len - (~cnt % len) - 1) : (cnt % len);
3416}
3417
3418static void
3419ary_rotate_ptr(VALUE *ptr, long len, long cnt)
3420{
3421 if (cnt == 1) {
3422 VALUE tmp = *ptr;
3423 memmove(ptr, ptr + 1, sizeof(VALUE)*(len - 1));
3424 *(ptr + len - 1) = tmp;
3425 }
3426 else if (cnt == len - 1) {
3427 VALUE tmp = *(ptr + len - 1);
3428 memmove(ptr + 1, ptr, sizeof(VALUE)*(len - 1));
3429 *ptr = tmp;
3430 }
3431 else {
3432 --len;
3433 if (cnt < len) ary_reverse(ptr + cnt, ptr + len);
3434 if (--cnt > 0) ary_reverse(ptr, ptr + cnt);
3435 if (len > 0) ary_reverse(ptr, ptr + len);
3436 }
3437}
3438
3439VALUE
3440rb_ary_rotate(VALUE ary, long cnt)
3441{
3443
3444 if (cnt != 0) {
3445 long len = RARRAY_LEN(ary);
3446 if (len > 1 && (cnt = rotate_count(cnt, len)) > 0) {
3447 RARRAY_PTR_USE(ary, ptr, ary_rotate_ptr(ptr, len, cnt));
3448 return ary;
3449 }
3450 }
3451 return Qnil;
3452}
3453
3454/*
3455 * call-seq:
3456 * rotate!(count = 1) -> self
3457 *
3458 * Rotates +self+ in place by moving elements from one end to the other; returns +self+.
3459 *
3460 * With non-negative numeric +count+,
3461 * rotates +count+ elements from the beginning to the end:
3462 *
3463 * [0, 1, 2, 3].rotate!(2) # => [2, 3, 0, 1]
3464 [0, 1, 2, 3].rotate!(2.1) # => [2, 3, 0, 1]
3465 *
3466 * If +count+ is large, uses <tt>count % array.size</tt> as the count:
3467 *
3468 * [0, 1, 2, 3].rotate!(21) # => [1, 2, 3, 0]
3469 *
3470 * If +count+ is zero, rotates no elements:
3471 *
3472 * [0, 1, 2, 3].rotate!(0) # => [0, 1, 2, 3]
3473 *
3474 * With a negative numeric +count+, rotates in the opposite direction,
3475 * from end to beginning:
3476 *
3477 * [0, 1, 2, 3].rotate!(-1) # => [3, 0, 1, 2]
3478 *
3479 * If +count+ is small (far from zero), uses <tt>count % array.size</tt> as the count:
3480 *
3481 * [0, 1, 2, 3].rotate!(-21) # => [3, 0, 1, 2]
3482 *
3483 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
3484 */
3485
3486static VALUE
3487rb_ary_rotate_bang(int argc, VALUE *argv, VALUE ary)
3488{
3489 long n = (rb_check_arity(argc, 0, 1) ? NUM2LONG(argv[0]) : 1);
3490 rb_ary_rotate(ary, n);
3491 return ary;
3492}
3493
3494/*
3495 * call-seq:
3496 * rotate(count = 1) -> new_array
3497 *
3498 * Returns a new array formed from +self+ with elements
3499 * rotated from one end to the other.
3500 *
3501 * With non-negative numeric +count+,
3502 * rotates elements from the beginning to the end:
3503 *
3504 * [0, 1, 2, 3].rotate(2) # => [2, 3, 0, 1]
3505 * [0, 1, 2, 3].rotate(2.1) # => [2, 3, 0, 1]
3506 *
3507 * If +count+ is large, uses <tt>count % array.size</tt> as the count:
3508 *
3509 * [0, 1, 2, 3].rotate(22) # => [2, 3, 0, 1]
3510 *
3511 * With a +count+ of zero, rotates no elements:
3512 *
3513 * [0, 1, 2, 3].rotate(0) # => [0, 1, 2, 3]
3514 *
3515 * With negative numeric +count+, rotates in the opposite direction,
3516 * from the end to the beginning:
3517 *
3518 * [0, 1, 2, 3].rotate(-1) # => [3, 0, 1, 2]
3519 *
3520 * If +count+ is small (far from zero), uses <tt>count % array.size</tt> as the count:
3521 *
3522 * [0, 1, 2, 3].rotate(-21) # => [3, 0, 1, 2]
3523 *
3524 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3525 */
3526
3527static VALUE
3528rb_ary_rotate_m(int argc, VALUE *argv, VALUE ary)
3529{
3530 VALUE rotated;
3531 const VALUE *ptr;
3532 long len;
3533 long cnt = (rb_check_arity(argc, 0, 1) ? NUM2LONG(argv[0]) : 1);
3534
3535 len = RARRAY_LEN(ary);
3536 rotated = rb_ary_new2(len);
3537 if (len > 0) {
3538 cnt = rotate_count(cnt, len);
3540 len -= cnt;
3541 ary_memcpy(rotated, 0, len, ptr + cnt);
3542 ary_memcpy(rotated, len, cnt, ptr);
3543 }
3544 ARY_SET_LEN(rotated, RARRAY_LEN(ary));
3545 return rotated;
3546}
3547
3548struct ary_sort_data {
3549 VALUE ary;
3550 VALUE receiver;
3551};
3552
3553static VALUE
3554sort_reentered(VALUE ary)
3555{
3556 if (RBASIC(ary)->klass) {
3557 rb_raise(rb_eRuntimeError, "sort reentered");
3558 }
3559 return Qnil;
3560}
3561
3562static void
3563sort_returned(struct ary_sort_data *data)
3564{
3565 if (rb_obj_frozen_p(data->receiver)) {
3566 rb_raise(rb_eFrozenError, "array frozen during sort");
3567 }
3568 sort_reentered(data->ary);
3569}
3570
3571static int
3572sort_1(const void *ap, const void *bp, void *dummy)
3573{
3574 struct ary_sort_data *data = dummy;
3575 VALUE retval = sort_reentered(data->ary);
3576 VALUE a = *(const VALUE *)ap, b = *(const VALUE *)bp;
3577 VALUE args[2];
3578 int n;
3579
3580 args[0] = a;
3581 args[1] = b;
3582 retval = rb_yield_values2(2, args);
3583 n = rb_cmpint(retval, a, b);
3584 sort_returned(data);
3585 return n;
3586}
3587
3588static int
3589sort_2(const void *ap, const void *bp, void *dummy)
3590{
3591 struct ary_sort_data *data = dummy;
3592 VALUE retval = sort_reentered(data->ary);
3593 VALUE a = *(const VALUE *)ap, b = *(const VALUE *)bp;
3594 int n;
3595
3596 if (FIXNUM_P(a) && FIXNUM_P(b) && CMP_OPTIMIZABLE(INTEGER)) {
3597 if ((long)a > (long)b) return 1;
3598 if ((long)a < (long)b) return -1;
3599 return 0;
3600 }
3601 if (STRING_P(a) && STRING_P(b) && CMP_OPTIMIZABLE(STRING)) {
3602 return rb_str_cmp(a, b);
3603 }
3604 if (RB_FLOAT_TYPE_P(a) && CMP_OPTIMIZABLE(FLOAT)) {
3605 return rb_float_cmp(a, b);
3606 }
3607
3608 retval = rb_funcallv(a, id_cmp, 1, &b);
3609 n = rb_cmpint(retval, a, b);
3610 sort_returned(data);
3611
3612 return n;
3613}
3614
3615/*
3616 * call-seq:
3617 * sort! -> self
3618 * sort! {|a, b| ... } -> self
3619 *
3620 * Like Array#sort, but returns +self+ with its elements sorted in place.
3621 *
3622 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
3623 */
3624
3625VALUE
3627{
3628 rb_ary_modify(ary);
3629 RUBY_ASSERT(!ARY_SHARED_P(ary));
3630 if (RARRAY_LEN(ary) > 1) {
3631 VALUE tmp = ary_make_substitution(ary); /* only ary refers tmp */
3632 struct ary_sort_data data;
3633 long len = RARRAY_LEN(ary);
3634 RBASIC_CLEAR_CLASS(tmp);
3635 data.ary = tmp;
3636 data.receiver = ary;
3637 RARRAY_PTR_USE(tmp, ptr, {
3638 ruby_qsort(ptr, len, sizeof(VALUE),
3639 rb_block_given_p()?sort_1:sort_2, &data);
3640 }); /* WB: no new reference */
3641 rb_ary_modify(ary);
3642 if (ARY_EMBED_P(tmp)) {
3643 if (ARY_SHARED_P(ary)) { /* ary might be destructively operated in the given block */
3644 rb_ary_unshare(ary);
3645 FL_SET_EMBED(ary);
3646 }
3647 if (ARY_EMBED_LEN(tmp) > ARY_CAPA(ary)) {
3648 ary_resize_capa(ary, ARY_EMBED_LEN(tmp));
3649 }
3650 ary_memcpy(ary, 0, ARY_EMBED_LEN(tmp), ARY_EMBED_PTR(tmp));
3651 ARY_SET_LEN(ary, ARY_EMBED_LEN(tmp));
3652 }
3653 else {
3654 if (!ARY_EMBED_P(ary) && ARY_HEAP_PTR(ary) == ARY_HEAP_PTR(tmp)) {
3655 FL_UNSET_SHARED(ary);
3656 ARY_SET_CAPA(ary, RARRAY_LEN(tmp));
3657 }
3658 else {
3659 RUBY_ASSERT(!ARY_SHARED_P(tmp));
3660 if (ARY_EMBED_P(ary)) {
3661 FL_UNSET_EMBED(ary);
3662 }
3663 else if (ARY_SHARED_P(ary)) {
3664 /* ary might be destructively operated in the given block */
3665 rb_ary_unshare(ary);
3666 }
3667 else {
3668 ary_heap_free(ary);
3669 }
3670 ARY_SET_PTR(ary, ARY_HEAP_PTR(tmp));
3671 ARY_SET_HEAP_LEN(ary, len);
3672 ARY_SET_CAPA(ary, ARY_HEAP_LEN(tmp));
3673 }
3674 /* tmp was lost ownership for the ptr */
3675 FL_SET_EMBED(tmp);
3676 ARY_SET_EMBED_LEN(tmp, 0);
3677 OBJ_FREEZE(tmp);
3678 }
3679 /* tmp will be GC'ed. */
3680 RBASIC_SET_CLASS_RAW(tmp, rb_cArray); /* rb_cArray must be marked */
3681 }
3682 ary_verify(ary);
3683 return ary;
3684}
3685
3686/*
3687 * call-seq:
3688 * sort -> new_array
3689 * sort {|a, b| ... } -> new_array
3690 *
3691 * Returns a new array containing the elements of +self+, sorted.
3692 *
3693 * With no block given, compares elements using operator <tt>#<=></tt>
3694 * (see Object#<=>):
3695 *
3696 * [0, 2, 3, 1].sort # => [0, 1, 2, 3]
3697 *
3698 * With a block given, calls the block with each combination of pairs of elements from +self+;
3699 * for each pair +a+ and +b+, the block should return a numeric:
3700 *
3701 * - Negative when +b+ is to follow +a+.
3702 * - Zero when +a+ and +b+ are equivalent.
3703 * - Positive when +a+ is to follow +b+.
3704 *
3705 * Example:
3706 *
3707 * a = [3, 2, 0, 1]
3708 * a.sort {|a, b| a <=> b } # => [0, 1, 2, 3]
3709 * a.sort {|a, b| b <=> a } # => [3, 2, 1, 0]
3710 *
3711 * When the block returns zero, the order for +a+ and +b+ is indeterminate,
3712 * and may be unstable.
3713 *
3714 * See an example in Numeric#nonzero? for the idiom to sort more
3715 * complex structure.
3716 *
3717 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3718 */
3719
3720VALUE
3721rb_ary_sort(VALUE ary)
3722{
3723 ary = rb_ary_dup(ary);
3724 rb_ary_sort_bang(ary);
3725 return ary;
3726}
3727
3728static VALUE rb_ary_bsearch_index(VALUE ary);
3729
3730/*
3731 * call-seq:
3732 * bsearch {|element| ... } -> found_element or nil
3733 * bsearch -> new_enumerator
3734 *
3735 * Returns the element from +self+ found by a binary search,
3736 * or +nil+ if the search found no suitable element.
3737 *
3738 * See {Binary Searching}[rdoc-ref:language/bsearch.rdoc].
3739 *
3740 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3741 */
3742
3743static VALUE
3744rb_ary_bsearch(VALUE ary)
3745{
3746 VALUE index_result = rb_ary_bsearch_index(ary);
3747
3748 if (FIXNUM_P(index_result)) {
3749 return rb_ary_entry(ary, FIX2LONG(index_result));
3750 }
3751 return index_result;
3752}
3753
3754/*
3755 * call-seq:
3756 * bsearch_index {|element| ... } -> integer or nil
3757 * bsearch_index -> new_enumerator
3758 *
3759 * Returns the integer index of the element from +self+ found by a binary search,
3760 * or +nil+ if the search found no suitable element.
3761 *
3762 * See {Binary Searching}[rdoc-ref:language/bsearch.rdoc].
3763 *
3764 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3765 */
3766
3767static VALUE
3768rb_ary_bsearch_index(VALUE ary)
3769{
3770 long low = 0, high = RARRAY_LEN(ary), mid;
3771 int smaller = 0, satisfied = 0;
3772 VALUE v, val;
3773
3774 RETURN_ENUMERATOR(ary, 0, 0);
3775 while (low < high) {
3776 mid = low + ((high - low) / 2);
3777 val = rb_ary_entry(ary, mid);
3778 v = rb_yield(val);
3779 if (FIXNUM_P(v)) {
3780 if (v == INT2FIX(0)) return INT2FIX(mid);
3781 smaller = (SIGNED_VALUE)v < 0; /* Fixnum preserves its sign-bit */
3782 }
3783 else if (v == Qtrue) {
3784 satisfied = 1;
3785 smaller = 1;
3786 }
3787 else if (!RTEST(v)) {
3788 smaller = 0;
3789 }
3790 else if (rb_obj_is_kind_of(v, rb_cNumeric)) {
3791 const VALUE zero = INT2FIX(0);
3792 switch (rb_cmpint(rb_funcallv(v, id_cmp, 1, &zero), v, zero)) {
3793 case 0: return INT2FIX(mid);
3794 case 1: smaller = 0; break;
3795 case -1: smaller = 1;
3796 }
3797 }
3798 else {
3799 rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE
3800 " (must be numeric, true, false or nil)",
3801 rb_obj_class(v));
3802 }
3803 if (smaller) {
3804 high = mid;
3805 }
3806 else {
3807 low = mid + 1;
3808 }
3809 }
3810 if (!satisfied) return Qnil;
3811 return INT2FIX(low);
3812}
3813
3814
3815static VALUE
3816sort_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, dummy))
3817{
3818 return rb_yield(i);
3819}
3820
3821/*
3822 * call-seq:
3823 * sort_by! {|element| ... } -> self
3824 * sort_by! -> new_enumerator
3825 *
3826 * With a block given, sorts the elements of +self+ in place;
3827 * returns self.
3828 *
3829 * Calls the block with each successive element;
3830 * sorts elements based on the values returned from the block:
3831 *
3832 * a = ['aaaa', 'bbb', 'cc', 'd']
3833 * a.sort_by! {|element| element.size }
3834 * a # => ["d", "cc", "bbb", "aaaa"]
3835 *
3836 * For duplicate values returned by the block, the ordering is indeterminate, and may be unstable.
3837 *
3838 * With no block given, returns a new Enumerator.
3839 *
3840 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
3841 */
3842
3843static VALUE
3844rb_ary_sort_by_bang(VALUE ary)
3845{
3846 VALUE sorted;
3847
3848 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3849 rb_ary_modify(ary);
3850 if (RARRAY_LEN(ary) > 1) {
3851 sorted = rb_block_call(ary, rb_intern("sort_by"), 0, 0, sort_by_i, 0);
3852 rb_ary_replace(ary, sorted);
3853 }
3854 return ary;
3855}
3856
3857
3858/*
3859 * call-seq:
3860 * collect {|element| ... } -> new_array
3861 * collect -> new_enumerator
3862 * map {|element| ... } -> new_array
3863 * map -> new_enumerator
3864 *
3865 * With a block given, calls the block with each element of +self+;
3866 * returns a new array whose elements are the return values from the block:
3867 *
3868 * a = [:foo, 'bar', 2]
3869 * a1 = a.map {|element| element.class }
3870 * a1 # => [Symbol, String, Integer]
3871 *
3872 * With no block given, returns a new Enumerator.
3873 *
3874 * Related: #collect!;
3875 * see also {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3876 */
3877
3878static VALUE
3879rb_ary_collect(VALUE ary)
3880{
3881 long i;
3882 VALUE collect;
3883
3884 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3885 collect = rb_ary_new2(RARRAY_LEN(ary));
3886 for (i = 0; i < RARRAY_LEN(ary); i++) {
3887 rb_ary_push(collect, rb_yield(RARRAY_AREF(ary, i)));
3888 }
3889 return collect;
3890}
3891
3892
3893/*
3894 * call-seq:
3895 * collect! {|element| ... } -> self
3896 * collect! -> new_enumerator
3897 * map! {|element| ... } -> self
3898 * map! -> new_enumerator
3899 *
3900 * With a block given, calls the block with each element of +self+
3901 * and replaces the element with the block's return value;
3902 * returns +self+:
3903 *
3904 * a = [:foo, 'bar', 2]
3905 * a.map! { |element| element.class } # => [Symbol, String, Integer]
3906 *
3907 * With no block given, returns a new Enumerator.
3908 *
3909 * Related: #collect;
3910 * see also {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3911 */
3912
3913static VALUE
3914rb_ary_collect_bang(VALUE ary)
3915{
3916 long i;
3917
3918 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3919 rb_ary_modify(ary);
3920 for (i = 0; i < RARRAY_LEN(ary); i++) {
3921 rb_ary_store(ary, i, rb_yield(RARRAY_AREF(ary, i)));
3922 }
3923 return ary;
3924}
3925
3926VALUE
3927rb_get_values_at(VALUE obj, long olen, int argc, const VALUE *argv, VALUE (*func) (VALUE, long))
3928{
3929 VALUE result = rb_ary_new2(argc);
3930 long beg, len, i, j;
3931
3932 for (i=0; i<argc; i++) {
3933 if (FIXNUM_P(argv[i])) {
3934 rb_ary_push(result, (*func)(obj, FIX2LONG(argv[i])));
3935 continue;
3936 }
3937 /* check if idx is Range */
3938 if (rb_range_beg_len(argv[i], &beg, &len, olen, 1)) {
3939 long end = olen < beg+len ? olen : beg+len;
3940 for (j = beg; j < end; j++) {
3941 rb_ary_push(result, (*func)(obj, j));
3942 }
3943 if (beg + len > j)
3944 rb_ary_resize(result, RARRAY_LEN(result) + (beg + len) - j);
3945 continue;
3946 }
3947 rb_ary_push(result, (*func)(obj, NUM2LONG(argv[i])));
3948 }
3949 return result;
3950}
3951
3952static VALUE
3953append_values_at_single(VALUE result, VALUE ary, long olen, VALUE idx)
3954{
3955 long beg, len;
3956 if (FIXNUM_P(idx)) {
3957 beg = FIX2LONG(idx);
3958 }
3959 /* check if idx is Range */
3960 else if (rb_range_beg_len(idx, &beg, &len, olen, 1)) {
3961 if (len > 0) {
3962 const VALUE *const src = RARRAY_CONST_PTR(ary);
3963 const long end = beg + len;
3964 const long prevlen = RARRAY_LEN(result);
3965 if (beg < olen) {
3966 rb_ary_cat(result, src + beg, end > olen ? olen-beg : len);
3967 }
3968 if (end > olen) {
3969 rb_ary_store(result, prevlen + len - 1, Qnil);
3970 }
3971 }
3972 return result;
3973 }
3974 else {
3975 beg = NUM2LONG(idx);
3976 }
3977 return rb_ary_push(result, rb_ary_entry(ary, beg));
3978}
3979
3980/*
3981 * call-seq:
3982 * values_at(*specifiers) -> new_array
3983 *
3984 * Returns elements from +self+ in a new array; does not modify +self+.
3985 *
3986 * The objects included in the returned array are the elements of +self+
3987 * selected by the given +specifiers+,
3988 * each of which must be a numeric index or a Range.
3989 *
3990 * In brief:
3991 *
3992 * a = ['a', 'b', 'c', 'd']
3993 *
3994 * # Index specifiers.
3995 * a.values_at(2, 0, 2, 0) # => ["c", "a", "c", "a"] # May repeat.
3996 * a.values_at(-4, -3, -2, -1) # => ["a", "b", "c", "d"] # Counts backwards if negative.
3997 * a.values_at(-50, 50) # => [nil, nil] # Outside of self.
3998 *
3999 * # Range specifiers.
4000 * a.values_at(1..3) # => ["b", "c", "d"] # From range.begin to range.end.
4001 * a.values_at(1...3) # => ["b", "c"] # End excluded.
4002 * a.values_at(3..1) # => [] # No such elements.
4003 *
4004 * a.values_at(-3..3) # => ["b", "c", "d"] # Negative range.begin counts backwards.
4005 * a.values_at(-50..3) # Raises RangeError.
4006 *
4007 * a.values_at(1..-2) # => ["b", "c"] # Negative range.end counts backwards.
4008 * a.values_at(1..-50) # => [] # No such elements.
4009 *
4010 * # Mixture of specifiers.
4011 * a.values_at(2..3, 3, 0..1, 0) # => ["c", "d", "d", "a", "b", "a"]
4012 *
4013 * With no +specifiers+ given, returns a new empty array:
4014 *
4015 * a = ['a', 'b', 'c', 'd']
4016 * a.values_at # => []
4017 *
4018 * For each numeric specifier +index+, includes an element:
4019 *
4020 * - For each non-negative numeric specifier +index+ that is in-range (less than <tt>self.size</tt>),
4021 * includes the element at offset +index+:
4022 *
4023 * a.values_at(0, 2) # => ["a", "c"]
4024 * a.values_at(0.1, 2.9) # => ["a", "c"]
4025 *
4026 * - For each negative numeric +index+ that is in-range (greater than or equal to <tt>- self.size</tt>),
4027 * counts backwards from the end of +self+:
4028 *
4029 * a.values_at(-1, -4) # => ["d", "a"]
4030 *
4031 * The given indexes may be in any order, and may repeat:
4032 *
4033 * a.values_at(2, 0, 1, 0, 2) # => ["c", "a", "b", "a", "c"]
4034 *
4035 * For each +index+ that is out-of-range, includes +nil+:
4036 *
4037 * a.values_at(4, -5) # => [nil, nil]
4038 *
4039 * For each Range specifier +range+, includes elements
4040 * according to <tt>range.begin</tt> and <tt>range.end</tt>:
4041 *
4042 * - If both <tt>range.begin</tt> and <tt>range.end</tt>
4043 * are non-negative and in-range (less than <tt>self.size</tt>),
4044 * includes elements from index <tt>range.begin</tt>
4045 * through <tt>range.end - 1</tt> (if <tt>range.exclude_end?</tt>),
4046 * or through <tt>range.end</tt> (otherwise):
4047 *
4048 * a.values_at(1..2) # => ["b", "c"]
4049 * a.values_at(1...2) # => ["b"]
4050 *
4051 * - If <tt>range.begin</tt> is negative and in-range (greater than or equal to <tt>- self.size</tt>),
4052 * counts backwards from the end of +self+:
4053 *
4054 * a.values_at(-2..3) # => ["c", "d"]
4055 *
4056 * - If <tt>range.begin</tt> is negative and out-of-range, raises an exception:
4057 *
4058 * a.values_at(-5..3) # Raises RangeError.
4059 *
4060 * - If <tt>range.end</tt> is positive and out-of-range,
4061 * extends the returned array with +nil+ elements:
4062 *
4063 * a.values_at(1..5) # => ["b", "c", "d", nil, nil]
4064 *
4065 * - If <tt>range.end</tt> is negative and in-range,
4066 * counts backwards from the end of +self+:
4067 *
4068 * a.values_at(1..-2) # => ["b", "c"]
4069 *
4070 * - If <tt>range.end</tt> is negative and out-of-range,
4071 * returns an empty array:
4072 *
4073 * a.values_at(1..-5) # => []
4074 *
4075 * The given ranges may be in any order and may repeat:
4076 *
4077 * a.values_at(2..3, 0..1, 2..3) # => ["c", "d", "a", "b", "c", "d"]
4078 *
4079 * The given specifiers may be any mixture of indexes and ranges:
4080 *
4081 * a.values_at(3, 1..2, 0, 2..3) # => ["d", "b", "c", "a", "c", "d"]
4082 *
4083 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
4084 */
4085
4086static VALUE
4087rb_ary_values_at(int argc, VALUE *argv, VALUE ary)
4088{
4089 long i, olen = RARRAY_LEN(ary);
4090 VALUE result = rb_ary_new_capa(argc);
4091 for (i = 0; i < argc; ++i) {
4092 append_values_at_single(result, ary, olen, argv[i]);
4093 }
4094 RB_GC_GUARD(ary);
4095 return result;
4096}
4097
4098
4099/*
4100 * call-seq:
4101 * select {|element| ... } -> new_array
4102 * select -> new_enumerator
4103 * filter {|element| ... } -> new_array
4104 * filter -> new_enumerator
4105 *
4106 * With a block given, calls the block with each element of +self+;
4107 * returns a new array containing those elements of +self+
4108 * for which the block returns a truthy value:
4109 *
4110 * a = [:foo, 'bar', 2, :bam]
4111 * a.select {|element| element.to_s.start_with?('b') }
4112 * # => ["bar", :bam]
4113 *
4114 * With no block given, returns a new Enumerator.
4115 *
4116 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
4117 */
4118
4119static VALUE
4120rb_ary_select(VALUE ary)
4121{
4122 VALUE result;
4123 long i;
4124
4125 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
4126 result = rb_ary_new2(RARRAY_LEN(ary));
4127 for (i = 0; i < RARRAY_LEN(ary); i++) {
4128 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) {
4129 rb_ary_push(result, rb_ary_elt(ary, i));
4130 }
4131 }
4132 return result;
4133}
4134
4135struct select_bang_arg {
4136 VALUE ary;
4137 long len[2];
4138};
4139
4140static VALUE
4141select_bang_i(VALUE a)
4142{
4143 volatile struct select_bang_arg *arg = (void *)a;
4144 VALUE ary = arg->ary;
4145 long i1, i2;
4146
4147 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); arg->len[0] = ++i1) {
4148 VALUE v = RARRAY_AREF(ary, i1);
4149 if (!RTEST(rb_yield(v))) continue;
4150 if (i1 != i2) {
4151 rb_ary_store(ary, i2, v);
4152 }
4153 arg->len[1] = ++i2;
4154 }
4155 return (i1 == i2) ? Qnil : ary;
4156}
4157
4158static VALUE
4159select_bang_ensure(VALUE a)
4160{
4161 volatile struct select_bang_arg *arg = (void *)a;
4162 VALUE ary = arg->ary;
4163 long len = RARRAY_LEN(ary);
4164 long i1 = arg->len[0], i2 = arg->len[1];
4165
4166 if (i2 < len && i2 < i1) {
4167 long tail = 0;
4168 rb_ary_modify(ary);
4169 if (i1 < len) {
4170 tail = len - i1;
4171 RARRAY_PTR_USE(ary, ptr, {
4172 MEMMOVE(ptr + i2, ptr + i1, VALUE, tail);
4173 });
4174 }
4175 ARY_SET_LEN(ary, i2 + tail);
4176 }
4177 return ary;
4178}
4179
4180/*
4181 * call-seq:
4182 * select! {|element| ... } -> self or nil
4183 * select! -> new_enumerator
4184 * filter! {|element| ... } -> self or nil
4185 * filter! -> new_enumerator
4186 *
4187 * With a block given, calls the block with each element of +self+;
4188 * removes from +self+ those elements for which the block returns +false+ or +nil+.
4189 *
4190 * Returns +self+ if any elements were removed:
4191 *
4192 * a = [:foo, 'bar', 2, :bam]
4193 * a.select! {|element| element.to_s.start_with?('b') } # => ["bar", :bam]
4194 *
4195 * Returns +nil+ if no elements were removed.
4196 *
4197 * With no block given, returns a new Enumerator.
4198 *
4199 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4200 */
4201
4202static VALUE
4203rb_ary_select_bang(VALUE ary)
4204{
4205 struct select_bang_arg args;
4206
4207 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
4208 rb_ary_modify(ary);
4209
4210 args.ary = ary;
4211 args.len[0] = args.len[1] = 0;
4212 return rb_ensure(select_bang_i, (VALUE)&args, select_bang_ensure, (VALUE)&args);
4213}
4214
4215/*
4216 * call-seq:
4217 * keep_if {|element| ... } -> self
4218 * keep_if -> new_enumerator
4219 *
4220 * With a block given, calls the block with each element of +self+;
4221 * removes the element from +self+ if the block does not return a truthy value:
4222 *
4223 * a = [:foo, 'bar', 2, :bam]
4224 * a.keep_if {|element| element.to_s.start_with?('b') } # => ["bar", :bam]
4225 *
4226 * With no block given, returns a new Enumerator.
4227 *
4228 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4229 */
4230
4231static VALUE
4232rb_ary_keep_if(VALUE ary)
4233{
4234 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
4235 rb_ary_select_bang(ary);
4236 return ary;
4237}
4238
4239static void
4240ary_resize_smaller(VALUE ary, long len)
4241{
4242 rb_ary_modify(ary);
4243 if (RARRAY_LEN(ary) > len) {
4244 ARY_SET_LEN(ary, len);
4245 if (len * 2 < ARY_CAPA(ary) &&
4246 ARY_CAPA(ary) > ARY_DEFAULT_SIZE) {
4247 ary_resize_capa(ary, len * 2);
4248 }
4249 }
4250}
4251
4252/*
4253 * call-seq:
4254 * delete(object) -> last_removed_object
4255 * delete(object) {|element| ... } -> last_removed_object or block_return
4256 *
4257 * Removes zero or more elements from +self+.
4258 *
4259 * With no block given,
4260 * removes from +self+ each element +ele+ such that <tt>ele == object</tt>;
4261 * returns the last removed element:
4262 *
4263 * a = [0, 1, 2, 2.0]
4264 * a.delete(2) # => 2.0
4265 * a # => [0, 1]
4266 *
4267 * Returns +nil+ if no elements removed:
4268 *
4269 * a.delete(2) # => nil
4270 *
4271 * With a block given,
4272 * removes from +self+ each element +ele+ such that <tt>ele == object</tt>.
4273 *
4274 * If any such elements are found, ignores the block
4275 * and returns the last removed element:
4276 *
4277 * a = [0, 1, 2, 2.0]
4278 * a.delete(2) {|element| fail 'Cannot happen' } # => 2.0
4279 * a # => [0, 1]
4280 *
4281 * If no such element is found, returns the block's return value:
4282 *
4283 * a.delete(2) {|element| "Element #{element} not found." }
4284 * # => "Element 2 not found."
4285 *
4286 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4287 */
4288
4289VALUE
4290rb_ary_delete(VALUE ary, VALUE item)
4291{
4292 VALUE v = item;
4293 long i1, i2;
4294
4295 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
4296 VALUE e = RARRAY_AREF(ary, i1);
4297
4298 if (rb_equal(e, item)) {
4299 v = e;
4300 continue;
4301 }
4302 if (i1 != i2) {
4303 rb_ary_store(ary, i2, e);
4304 }
4305 i2++;
4306 }
4307 if (RARRAY_LEN(ary) == i2) {
4308 if (rb_block_given_p()) {
4309 return rb_yield(item);
4310 }
4311 return Qnil;
4312 }
4313
4314 ary_resize_smaller(ary, i2);
4315
4316 ary_verify(ary);
4317 return v;
4318}
4319
4320void
4321rb_ary_delete_same(VALUE ary, VALUE item)
4322{
4323 long i1, i2;
4324
4325 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
4326 VALUE e = RARRAY_AREF(ary, i1);
4327
4328 if (e == item) {
4329 continue;
4330 }
4331 if (i1 != i2) {
4332 rb_ary_store(ary, i2, e);
4333 }
4334 i2++;
4335 }
4336 if (RARRAY_LEN(ary) == i2) {
4337 return;
4338 }
4339
4340 ary_resize_smaller(ary, i2);
4341}
4342
4343VALUE
4344rb_ary_delete_at(VALUE ary, long pos)
4345{
4346 long len = RARRAY_LEN(ary);
4347 VALUE del;
4348
4349 if (pos >= len) return Qnil;
4350 if (pos < 0) {
4351 pos += len;
4352 if (pos < 0) return Qnil;
4353 }
4354
4355 rb_ary_modify(ary);
4356 del = RARRAY_AREF(ary, pos);
4357 RARRAY_PTR_USE(ary, ptr, {
4358 MEMMOVE(ptr+pos, ptr+pos+1, VALUE, len-pos-1);
4359 });
4360 ARY_INCREASE_LEN(ary, -1);
4361 ary_verify(ary);
4362 return del;
4363}
4364
4365/*
4366 * call-seq:
4367 * delete_at(index) -> removed_object or nil
4368 *
4369 * Removes the element of +self+ at the given +index+, which must be an
4370 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
4371 *
4372 * When +index+ is non-negative, deletes the element at offset +index+:
4373 *
4374 * a = [:foo, 'bar', 2]
4375 * a.delete_at(1) # => "bar"
4376 * a # => [:foo, 2]
4377 *
4378 * When +index+ is negative, counts backward from the end of the array:
4379 *
4380 * a = [:foo, 'bar', 2]
4381 * a.delete_at(-2) # => "bar"
4382 * a # => [:foo, 2]
4383 *
4384 * When +index+ is out of range, returns +nil+.
4385 *
4386 * a = [:foo, 'bar', 2]
4387 * a.delete_at(3) # => nil
4388 * a.delete_at(-4) # => nil
4389 *
4390 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4391 */
4392
4393static VALUE
4394rb_ary_delete_at_m(VALUE ary, VALUE pos)
4395{
4396 return rb_ary_delete_at(ary, NUM2LONG(pos));
4397}
4398
4399static VALUE
4400ary_slice_bang_by_rb_ary_splice(VALUE ary, long pos, long len)
4401{
4402 const long orig_len = RARRAY_LEN(ary);
4403
4404 if (len < 0) {
4405 return Qnil;
4406 }
4407 else if (pos < -orig_len) {
4408 return Qnil;
4409 }
4410 else if (pos < 0) {
4411 pos += orig_len;
4412 }
4413 else if (orig_len < pos) {
4414 return Qnil;
4415 }
4416 if (orig_len < pos + len) {
4417 len = orig_len - pos;
4418 }
4419 if (len == 0) {
4420 return rb_ary_new2(0);
4421 }
4422 else {
4423 VALUE arg2 = rb_ary_new4(len, RARRAY_CONST_PTR(ary)+pos);
4424 rb_ary_splice(ary, pos, len, 0, 0);
4425 return arg2;
4426 }
4427}
4428
4429/*
4430 * call-seq:
4431 * slice!(index) -> object or nil
4432 * slice!(start, length) -> new_array or nil
4433 * slice!(range) -> new_array or nil
4434 *
4435 * Removes and returns elements from +self+.
4436 *
4437 * With numeric argument +index+ given,
4438 * removes and returns the element at offset +index+:
4439 *
4440 * a = ['a', 'b', 'c', 'd']
4441 * a.slice!(2) # => "c"
4442 * a # => ["a", "b", "d"]
4443 * a.slice!(2.1) # => "d"
4444 * a # => ["a", "b"]
4445 *
4446 * If +index+ is negative, counts backwards from the end of +self+:
4447 *
4448 * a = ['a', 'b', 'c', 'd']
4449 * a.slice!(-2) # => "c"
4450 * a # => ["a", "b", "d"]
4451 *
4452 * If +index+ is out of range, returns +nil+.
4453 *
4454 * With numeric arguments +start+ and +length+ given,
4455 * removes +length+ elements from +self+ beginning at zero-based offset +start+;
4456 * returns the removed objects in a new array:
4457 *
4458 * a = ['a', 'b', 'c', 'd']
4459 * a.slice!(1, 2) # => ["b", "c"]
4460 * a # => ["a", "d"]
4461 * a.slice!(0.1, 1.1) # => ["a"]
4462 * a # => ["d"]
4463 *
4464 * If +start+ is negative, counts backwards from the end of +self+:
4465 *
4466 * a = ['a', 'b', 'c', 'd']
4467 * a.slice!(-2, 1) # => ["c"]
4468 * a # => ["a", "b", "d"]
4469 *
4470 * If +start+ is out-of-range, returns +nil+:
4471 *
4472 * a = ['a', 'b', 'c', 'd']
4473 * a.slice!(5, 1) # => nil
4474 * a.slice!(-5, 1) # => nil
4475 *
4476 * If <tt>start + length</tt> exceeds the array size,
4477 * removes and returns all elements from offset +start+ to the end:
4478 *
4479 * a = ['a', 'b', 'c', 'd']
4480 * a.slice!(2, 50) # => ["c", "d"]
4481 * a # => ["a", "b"]
4482 *
4483 * If <tt>start == a.size</tt> and +length+ is non-negative,
4484 * returns a new empty array.
4485 *
4486 * If +length+ is negative, returns +nil+.
4487 *
4488 * With Range argument +range+ given,
4489 * treats <tt>range.min</tt> as +start+ (as above)
4490 * and <tt>range.size</tt> as +length+ (as above):
4491 *
4492 * a = ['a', 'b', 'c', 'd']
4493 * a.slice!(1..2) # => ["b", "c"]
4494 * a # => ["a", "d"]
4495 *
4496 * If <tt>range.start == a.size</tt>, returns a new empty array:
4497 *
4498 * a = ['a', 'b', 'c', 'd']
4499 * a.slice!(4..5) # => []
4500 *
4501 * If <tt>range.start</tt> is larger than the array size, returns +nil+:
4502 *
4503 * a = ['a', 'b', 'c', 'd']
4504 a.slice!(5..6) # => nil
4505 *
4506 * If <tt>range.start</tt> is negative,
4507 * calculates the start index by counting backwards from the end of +self+:
4508 *
4509 * a = ['a', 'b', 'c', 'd']
4510 * a.slice!(-2..2) # => ["c"]
4511 *
4512 * If <tt>range.end</tt> is negative,
4513 * calculates the end index by counting backwards from the end of +self+:
4514 *
4515 * a = ['a', 'b', 'c', 'd']
4516 * a.slice!(0..-2) # => ["a", "b", "c"]
4517 *
4518 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4519 */
4520
4521static VALUE
4522rb_ary_slice_bang(int argc, VALUE *argv, VALUE ary)
4523{
4524 VALUE arg1;
4525 long pos, len;
4526
4527 rb_ary_modify_check(ary);
4528 rb_check_arity(argc, 1, 2);
4529 arg1 = argv[0];
4530
4531 if (argc == 2) {
4532 pos = NUM2LONG(argv[0]);
4533 len = NUM2LONG(argv[1]);
4534 return ary_slice_bang_by_rb_ary_splice(ary, pos, len);
4535 }
4536
4537 if (!FIXNUM_P(arg1)) {
4538 switch (rb_range_beg_len(arg1, &pos, &len, RARRAY_LEN(ary), 0)) {
4539 case Qtrue:
4540 /* valid range */
4541 return ary_slice_bang_by_rb_ary_splice(ary, pos, len);
4542 case Qnil:
4543 /* invalid range */
4544 return Qnil;
4545 default:
4546 /* not a range */
4547 break;
4548 }
4549 }
4550
4551 return rb_ary_delete_at(ary, NUM2LONG(arg1));
4552}
4553
4554static VALUE
4555ary_reject(VALUE orig, VALUE result)
4556{
4557 long i;
4558
4559 for (i = 0; i < RARRAY_LEN(orig); i++) {
4560 VALUE v = RARRAY_AREF(orig, i);
4561
4562 if (!RTEST(rb_yield(v))) {
4563 rb_ary_push(result, v);
4564 }
4565 }
4566 return result;
4567}
4568
4569static VALUE
4570reject_bang_i(VALUE a)
4571{
4572 volatile struct select_bang_arg *arg = (void *)a;
4573 VALUE ary = arg->ary;
4574 long i1, i2;
4575
4576 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); arg->len[0] = ++i1) {
4577 VALUE v = RARRAY_AREF(ary, i1);
4578 if (RTEST(rb_yield(v))) continue;
4579 if (i1 != i2) {
4580 rb_ary_store(ary, i2, v);
4581 }
4582 arg->len[1] = ++i2;
4583 }
4584 return (i1 == i2) ? Qnil : ary;
4585}
4586
4587static VALUE
4588ary_reject_bang(VALUE ary)
4589{
4590 struct select_bang_arg args;
4591 rb_ary_modify_check(ary);
4592 args.ary = ary;
4593 args.len[0] = args.len[1] = 0;
4594 return rb_ensure(reject_bang_i, (VALUE)&args, select_bang_ensure, (VALUE)&args);
4595}
4596
4597/*
4598 * call-seq:
4599 * reject! {|element| ... } -> self or nil
4600 * reject! -> new_enumerator
4601 *
4602 * With a block given, calls the block with each element of +self+;
4603 * removes each element for which the block returns a truthy value.
4604 *
4605 * Returns +self+ if any elements removed:
4606 *
4607 * a = [:foo, 'bar', 2, 'bat']
4608 * a.reject! {|element| element.to_s.start_with?('b') } # => [:foo, 2]
4609 *
4610 * Returns +nil+ if no elements removed.
4611 *
4612 * With no block given, returns a new Enumerator.
4613 *
4614 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4615 */
4616
4617static VALUE
4618rb_ary_reject_bang(VALUE ary)
4619{
4620 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
4621 rb_ary_modify(ary);
4622 return ary_reject_bang(ary);
4623}
4624
4625/*
4626 * call-seq:
4627 * reject {|element| ... } -> new_array
4628 * reject -> new_enumerator
4629 *
4630 * With a block given, returns a new array whose elements are all those from +self+
4631 * for which the block returns +false+ or +nil+:
4632 *
4633 * a = [:foo, 'bar', 2, 'bat']
4634 * a1 = a.reject {|element| element.to_s.start_with?('b') }
4635 * a1 # => [:foo, 2]
4636 *
4637 * With no block given, returns a new Enumerator.
4638 *
4639 * Related: {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
4640 */
4641
4642static VALUE
4643rb_ary_reject(VALUE ary)
4644{
4645 VALUE rejected_ary;
4646
4647 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
4648 rejected_ary = rb_ary_new();
4649 ary_reject(ary, rejected_ary);
4650 return rejected_ary;
4651}
4652
4653/*
4654 * call-seq:
4655 * delete_if {|element| ... } -> self
4656 * delete_if -> new_numerator
4657 *
4658 * With a block given, calls the block with each element of +self+;
4659 * removes the element if the block returns a truthy value;
4660 * returns +self+:
4661 *
4662 * a = [:foo, 'bar', 2, 'bat']
4663 * a.delete_if {|element| element.to_s.start_with?('b') } # => [:foo, 2]
4664 *
4665 * With no block given, returns a new Enumerator.
4666 *
4667 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4668 */
4669
4670static VALUE
4671rb_ary_delete_if(VALUE ary)
4672{
4673 ary_verify(ary);
4674 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
4675 ary_reject_bang(ary);
4676 return ary;
4677}
4678
4679static VALUE
4680take_i(RB_BLOCK_CALL_FUNC_ARGLIST(val, cbarg))
4681{
4682 VALUE *args = (VALUE *)cbarg;
4683 if (argc > 1) val = rb_ary_new4(argc, argv);
4684 rb_ary_push(args[0], val);
4685 if (--args[1] == 0) rb_iter_break();
4686 return Qnil;
4687}
4688
4689static VALUE
4690take_items(VALUE obj, long n)
4691{
4692 VALUE result = rb_check_array_type(obj);
4693 VALUE args[2];
4694
4695 if (n == 0) return result;
4696 if (!NIL_P(result)) return rb_ary_subseq(result, 0, n);
4697 result = rb_ary_new2(n);
4698 args[0] = result; args[1] = (VALUE)n;
4699 if (UNDEF_P(rb_check_block_call(obj, idEach, 0, 0, take_i, (VALUE)args)))
4700 rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (must respond to :each)",
4701 rb_obj_class(obj));
4702 return result;
4703}
4704
4705
4706/*
4707 * call-seq:
4708 * zip(*other_arrays) -> new_array
4709 * zip(*other_arrays) {|sub_array| ... } -> nil
4710 *
4711 * With no block given, combines +self+ with the collection of +other_arrays+;
4712 * returns a new array of sub-arrays:
4713 *
4714 * [0, 1].zip(['zero', 'one'], [:zero, :one])
4715 * # => [[0, "zero", :zero], [1, "one", :one]]
4716 *
4717 * Returned:
4718 *
4719 * - The outer array is of size <tt>self.size</tt>.
4720 * - Each sub-array is of size <tt>other_arrays.size + 1</tt>.
4721 * - The _nth_ sub-array contains (in order):
4722 *
4723 * - The _nth_ element of +self+.
4724 * - The _nth_ element of each of the other arrays, as available.
4725 *
4726 * Example:
4727 *
4728 * a = [0, 1]
4729 * zipped = a.zip(['zero', 'one'], [:zero, :one])
4730 * # => [[0, "zero", :zero], [1, "one", :one]]
4731 * zipped.size # => 2 # Same size as a.
4732 * zipped.first.size # => 3 # Size of other arrays plus 1.
4733 *
4734 * When the other arrays are all the same size as +self+,
4735 * the returned sub-arrays are a rearrangement containing exactly elements of all the arrays
4736 * (including +self+), with no omissions or additions:
4737 *
4738 * a = [:a0, :a1, :a2, :a3]
4739 * b = [:b0, :b1, :b2, :b3]
4740 * c = [:c0, :c1, :c2, :c3]
4741 * d = a.zip(b, c)
4742 * pp d
4743 * # =>
4744 * [[:a0, :b0, :c0],
4745 * [:a1, :b1, :c1],
4746 * [:a2, :b2, :c2],
4747 * [:a3, :b3, :c3]]
4748 *
4749 * When one of the other arrays is smaller than +self+,
4750 * pads the corresponding sub-array with +nil+ elements:
4751 *
4752 * a = [:a0, :a1, :a2, :a3]
4753 * b = [:b0, :b1, :b2]
4754 * c = [:c0, :c1]
4755 * d = a.zip(b, c)
4756 * pp d
4757 * # =>
4758 * [[:a0, :b0, :c0],
4759 * [:a1, :b1, :c1],
4760 * [:a2, :b2, nil],
4761 * [:a3, nil, nil]]
4762 *
4763 * When one of the other arrays is larger than +self+,
4764 * _ignores_ its trailing elements:
4765 *
4766 * a = [:a0, :a1, :a2, :a3]
4767 * b = [:b0, :b1, :b2, :b3, :b4]
4768 * c = [:c0, :c1, :c2, :c3, :c4, :c5]
4769 * d = a.zip(b, c)
4770 * pp d
4771 * # =>
4772 * [[:a0, :b0, :c0],
4773 * [:a1, :b1, :c1],
4774 * [:a2, :b2, :c2],
4775 * [:a3, :b3, :c3]]
4776 *
4777 * With a block given, calls the block with each of the other arrays;
4778 * returns +nil+:
4779 *
4780 * d = []
4781 * a = [:a0, :a1, :a2, :a3]
4782 * b = [:b0, :b1, :b2, :b3]
4783 * c = [:c0, :c1, :c2, :c3]
4784 * a.zip(b, c) {|sub_array| d.push(sub_array.reverse) } # => nil
4785 * pp d
4786 * # =>
4787 * [[:c0, :b0, :a0],
4788 * [:c1, :b1, :a1],
4789 * [:c2, :b2, :a2],
4790 * [:c3, :b3, :a3]]
4791 *
4792 * For an *object* in *other_arrays* that is not actually an array,
4793 * forms the "other array" as <tt>object.to_ary</tt>, if defined,
4794 * or as <tt>object.each.to_a</tt> otherwise.
4795 *
4796 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
4797 */
4798
4799static VALUE
4800rb_ary_zip(int argc, VALUE *argv, VALUE ary)
4801{
4802 int i, j;
4803 long len = RARRAY_LEN(ary);
4804 VALUE result = Qnil;
4805
4806 for (i=0; i<argc; i++) {
4807 argv[i] = take_items(argv[i], len);
4808 }
4809
4810 if (rb_block_given_p()) {
4811 int arity = rb_block_arity();
4812
4813 if (arity > 1) {
4814 VALUE work, *tmp;
4815
4816 tmp = ALLOCV_N(VALUE, work, argc+1);
4817
4818 for (i=0; i<RARRAY_LEN(ary); i++) {
4819 tmp[0] = RARRAY_AREF(ary, i);
4820 for (j=0; j<argc; j++) {
4821 tmp[j+1] = rb_ary_elt(argv[j], i);
4822 }
4823 rb_yield_values2(argc+1, tmp);
4824 }
4825
4826 if (work) ALLOCV_END(work);
4827 }
4828 else {
4829 for (i=0; i<RARRAY_LEN(ary); i++) {
4830 VALUE tmp = rb_ary_new2(argc+1);
4831
4832 rb_ary_push(tmp, RARRAY_AREF(ary, i));
4833 for (j=0; j<argc; j++) {
4834 rb_ary_push(tmp, rb_ary_elt(argv[j], i));
4835 }
4836 rb_yield(tmp);
4837 }
4838 }
4839 }
4840 else {
4841 result = rb_ary_new_capa(len);
4842
4843 for (i=0; i<len; i++) {
4844 VALUE tmp = rb_ary_new_capa(argc+1);
4845
4846 rb_ary_push(tmp, RARRAY_AREF(ary, i));
4847 for (j=0; j<argc; j++) {
4848 rb_ary_push(tmp, rb_ary_elt(argv[j], i));
4849 }
4850 rb_ary_push(result, tmp);
4851 }
4852 }
4853
4854 return result;
4855}
4856
4857/*
4858 * call-seq:
4859 * transpose -> new_array
4860 *
4861 * Returns a new array that is +self+
4862 * as a {transposed matrix}[https://en.wikipedia.org/wiki/Transpose]:
4863 *
4864 * a = [[:a0, :a1], [:b0, :b1], [:c0, :c1]]
4865 * a.transpose # => [[:a0, :b0, :c0], [:a1, :b1, :c1]]
4866 *
4867 * The elements of +self+ must all be the same size.
4868 *
4869 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
4870 */
4871
4872static VALUE
4873rb_ary_transpose(VALUE ary)
4874{
4875 long elen = -1, alen, i, j;
4876 VALUE tmp, result = 0;
4877
4878 alen = RARRAY_LEN(ary);
4879 if (alen == 0) return rb_ary_dup(ary);
4880 for (i=0; i<alen; i++) {
4881 tmp = to_ary(rb_ary_elt(ary, i));
4882 if (elen < 0) { /* first element */
4883 elen = RARRAY_LEN(tmp);
4884 result = rb_ary_new2(elen);
4885 for (j=0; j<elen; j++) {
4886 rb_ary_store(result, j, rb_ary_new2(alen));
4887 }
4888 }
4889 else if (elen != RARRAY_LEN(tmp)) {
4890 rb_raise(rb_eIndexError, "element size differs (%ld should be %ld)",
4891 RARRAY_LEN(tmp), elen);
4892 }
4893 for (j=0; j<elen; j++) {
4894 rb_ary_store(rb_ary_elt(result, j), i, rb_ary_elt(tmp, j));
4895 }
4896 }
4897 return result;
4898}
4899
4900/*
4901 * call-seq:
4902 * initialize_copy(other_array) -> self
4903 * replace(other_array) -> self
4904 *
4905 * Replaces the elements of +self+ with the elements of +other_array+, which must be an
4906 * {array-convertible object}[rdoc-ref:implicit_conversion.rdoc@Array-Convertible+Objects];
4907 * returns +self+:
4908 *
4909 * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
4910 * a.replace(['d', 'e']) # => ["d", "e"]
4911 *
4912 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
4913 */
4914
4915VALUE
4916rb_ary_replace(VALUE copy, VALUE orig)
4917{
4918 rb_ary_modify_check(copy);
4919 orig = to_ary(orig);
4920 if (copy == orig) return copy;
4921
4922 rb_ary_reset(copy);
4923
4924 /* orig has enough space to embed the contents of orig. */
4925 if (RARRAY_LEN(orig) <= ary_embed_capa(copy)) {
4926 RUBY_ASSERT(ARY_EMBED_P(copy));
4927 ary_memcpy(copy, 0, RARRAY_LEN(orig), RARRAY_CONST_PTR(orig));
4928 ARY_SET_EMBED_LEN(copy, RARRAY_LEN(orig));
4929 }
4930 /* orig is embedded but copy does not have enough space to embed the
4931 * contents of orig. */
4932 else if (ARY_EMBED_P(orig)) {
4933 long len = ARY_EMBED_LEN(orig);
4934 VALUE *ptr = ary_heap_alloc_buffer(len);
4935
4936 FL_UNSET_EMBED(copy);
4937 ARY_SET_PTR(copy, ptr);
4938 ARY_SET_LEN(copy, len);
4939 ARY_SET_CAPA(copy, len);
4940
4941 // No allocation and exception expected that could leave `copy` in a
4942 // bad state from the edits above.
4943 ary_memcpy(copy, 0, len, RARRAY_CONST_PTR(orig));
4944 }
4945 /* Otherwise, orig is on heap and copy does not have enough space to embed
4946 * the contents of orig. */
4947 else {
4948 VALUE shared_root = ary_make_shared(orig);
4949 FL_UNSET_EMBED(copy);
4950 ARY_SET_PTR(copy, ARY_HEAP_PTR(orig));
4951 ARY_SET_LEN(copy, ARY_HEAP_LEN(orig));
4952 rb_ary_set_shared(copy, shared_root);
4953
4954 RUBY_ASSERT(RB_OBJ_SHAREABLE_P(copy) ? RB_OBJ_SHAREABLE_P(shared_root) : 1);
4955 }
4956 ary_verify(copy);
4957 return copy;
4958}
4959
4960/*
4961 * call-seq:
4962 * clear -> self
4963 *
4964 * Removes all elements from +self+; returns +self+:
4965 *
4966 * a = [:foo, 'bar', 2]
4967 * a.clear # => []
4968 *
4969 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4970 */
4971
4972VALUE
4974{
4975 rb_ary_modify_check(ary);
4976 if (ARY_SHARED_P(ary)) {
4977 rb_ary_unshare(ary);
4978 FL_SET_EMBED(ary);
4979 ARY_SET_EMBED_LEN(ary, 0);
4980 }
4981 else {
4982 ARY_SET_LEN(ary, 0);
4983 if (ARY_DEFAULT_SIZE * 2 < ARY_CAPA(ary)) {
4984 ary_resize_capa(ary, ARY_DEFAULT_SIZE * 2);
4985 }
4986 }
4987 ary_verify(ary);
4988 return ary;
4989}
4990
4991/*
4992 * call-seq:
4993 * fill(object, start = nil, count = nil) -> self
4994 * fill(object, range) -> self
4995 * fill(start = nil, count = nil) {|element| ... } -> self
4996 * fill(range) {|element| ... } -> self
4997 *
4998 * Replaces selected elements in +self+;
4999 * may add elements to +self+;
5000 * always returns +self+ (never a new array).
5001 *
5002 * In brief:
5003 *
5004 * # Non-negative start.
5005 * ['a', 'b', 'c', 'd'].fill('-', 1, 2) # => ["a", "-", "-", "d"]
5006 * ['a', 'b', 'c', 'd'].fill(1, 2) {|e| e.to_s } # => ["a", "1", "2", "d"]
5007 *
5008 * # Extends with specified values if necessary.
5009 * ['a', 'b', 'c', 'd'].fill('-', 3, 2) # => ["a", "b", "c", "-", "-"]
5010 * ['a', 'b', 'c', 'd'].fill(3, 2) {|e| e.to_s } # => ["a", "b", "c", "3", "4"]
5011 *
5012 * # Fills with nils if necessary.
5013 * ['a', 'b', 'c', 'd'].fill('-', 6, 2) # => ["a", "b", "c", "d", nil, nil, "-", "-"]
5014 * ['a', 'b', 'c', 'd'].fill(6, 2) {|e| e.to_s } # => ["a", "b", "c", "d", nil, nil, "6", "7"]
5015 *
5016 * # For negative start, counts backwards from the end.
5017 * ['a', 'b', 'c', 'd'].fill('-', -3, 3) # => ["a", "-", "-", "-"]
5018 * ['a', 'b', 'c', 'd'].fill(-3, 3) {|e| e.to_s } # => ["a", "1", "2", "3"]
5019 *
5020 * # Range.
5021 * ['a', 'b', 'c', 'd'].fill('-', 1..2) # => ["a", "-", "-", "d"]
5022 * ['a', 'b', 'c', 'd'].fill(1..2) {|e| e.to_s } # => ["a", "1", "2", "d"]
5023 *
5024 * When arguments +start+ and +count+ are given,
5025 * they select the elements of +self+ to be replaced;
5026 * each must be an
5027 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]
5028 * (or +nil+):
5029 *
5030 * - +start+ specifies the zero-based offset of the first element to be replaced;
5031 * +nil+ means zero.
5032 * - +count+ is the number of consecutive elements to be replaced;
5033 * +nil+ means "all the rest."
5034 *
5035 * With argument +object+ given,
5036 * that one object is used for all replacements:
5037 *
5038 * o = Object.new # => #<Object:0x0000014e7bff7600>
5039 * a = ['a', 'b', 'c', 'd'] # => ["a", "b", "c", "d"]
5040 * a.fill(o, 1, 2)
5041 * # => ["a", #<Object:0x0000014e7bff7600>, #<Object:0x0000014e7bff7600>, "d"]
5042 *
5043 * With a block given, the block is called once for each element to be replaced;
5044 * the value passed to the block is the _index_ of the element to be replaced
5045 * (not the element itself);
5046 * the block's return value replaces the element:
5047 *
5048 * a = ['a', 'b', 'c', 'd'] # => ["a", "b", "c", "d"]
5049 * a.fill(1, 2) {|element| element.to_s } # => ["a", "1", "2", "d"]
5050 *
5051 * For arguments +start+ and +count+:
5052 *
5053 * - If +start+ is non-negative,
5054 * replaces +count+ elements beginning at offset +start+:
5055 *
5056 * ['a', 'b', 'c', 'd'].fill('-', 0, 2) # => ["-", "-", "c", "d"]
5057 * ['a', 'b', 'c', 'd'].fill('-', 1, 2) # => ["a", "-", "-", "d"]
5058 * ['a', 'b', 'c', 'd'].fill('-', 2, 2) # => ["a", "b", "-", "-"]
5059 *
5060 * ['a', 'b', 'c', 'd'].fill(0, 2) {|e| e.to_s } # => ["0", "1", "c", "d"]
5061 * ['a', 'b', 'c', 'd'].fill(1, 2) {|e| e.to_s } # => ["a", "1", "2", "d"]
5062 * ['a', 'b', 'c', 'd'].fill(2, 2) {|e| e.to_s } # => ["a", "b", "2", "3"]
5063 *
5064 * Extends +self+ if necessary:
5065 *
5066 * ['a', 'b', 'c', 'd'].fill('-', 3, 2) # => ["a", "b", "c", "-", "-"]
5067 * ['a', 'b', 'c', 'd'].fill('-', 4, 2) # => ["a", "b", "c", "d", "-", "-"]
5068 *
5069 * ['a', 'b', 'c', 'd'].fill(3, 2) {|e| e.to_s } # => ["a", "b", "c", "3", "4"]
5070 * ['a', 'b', 'c', 'd'].fill(4, 2) {|e| e.to_s } # => ["a", "b", "c", "d", "4", "5"]
5071 *
5072 * Fills with +nil+ if necessary:
5073 *
5074 * ['a', 'b', 'c', 'd'].fill('-', 5, 2) # => ["a", "b", "c", "d", nil, "-", "-"]
5075 * ['a', 'b', 'c', 'd'].fill('-', 6, 2) # => ["a", "b", "c", "d", nil, nil, "-", "-"]
5076 *
5077 * ['a', 'b', 'c', 'd'].fill(5, 2) {|e| e.to_s } # => ["a", "b", "c", "d", nil, "5", "6"]
5078 * ['a', 'b', 'c', 'd'].fill(6, 2) {|e| e.to_s } # => ["a", "b", "c", "d", nil, nil, "6", "7"]
5079 *
5080 * Does nothing if +count+ is non-positive:
5081 *
5082 * ['a', 'b', 'c', 'd'].fill('-', 2, 0) # => ["a", "b", "c", "d"]
5083 * ['a', 'b', 'c', 'd'].fill('-', 2, -100) # => ["a", "b", "c", "d"]
5084 * ['a', 'b', 'c', 'd'].fill('-', 6, -100) # => ["a", "b", "c", "d"]
5085 *
5086 * ['a', 'b', 'c', 'd'].fill(2, 0) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
5087 * ['a', 'b', 'c', 'd'].fill(2, -100) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
5088 * ['a', 'b', 'c', 'd'].fill(6, -100) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
5089 *
5090 * - If +start+ is negative, counts backwards from the end of +self+:
5091 *
5092 * ['a', 'b', 'c', 'd'].fill('-', -4, 3) # => ["-", "-", "-", "d"]
5093 * ['a', 'b', 'c', 'd'].fill('-', -3, 3) # => ["a", "-", "-", "-"]
5094 *
5095 * ['a', 'b', 'c', 'd'].fill(-4, 3) {|e| e.to_s } # => ["0", "1", "2", "d"]
5096 * ['a', 'b', 'c', 'd'].fill(-3, 3) {|e| e.to_s } # => ["a", "1", "2", "3"]
5097 *
5098 * Extends +self+ if necessary:
5099 *
5100 * ['a', 'b', 'c', 'd'].fill('-', -2, 3) # => ["a", "b", "-", "-", "-"]
5101 * ['a', 'b', 'c', 'd'].fill('-', -1, 3) # => ["a", "b", "c", "-", "-", "-"]
5102 *
5103 * ['a', 'b', 'c', 'd'].fill(-2, 3) {|e| e.to_s } # => ["a", "b", "2", "3", "4"]
5104 * ['a', 'b', 'c', 'd'].fill(-1, 3) {|e| e.to_s } # => ["a", "b", "c", "3", "4", "5"]
5105 *
5106 * Starts at the beginning of +self+ if +start+ is negative and out-of-range:
5107 *
5108 * ['a', 'b', 'c', 'd'].fill('-', -5, 2) # => ["-", "-", "c", "d"]
5109 * ['a', 'b', 'c', 'd'].fill('-', -6, 2) # => ["-", "-", "c", "d"]
5110 *
5111 * ['a', 'b', 'c', 'd'].fill(-5, 2) {|e| e.to_s } # => ["0", "1", "c", "d"]
5112 * ['a', 'b', 'c', 'd'].fill(-6, 2) {|e| e.to_s } # => ["0", "1", "c", "d"]
5113 *
5114 * Does nothing if +count+ is non-positive:
5115 *
5116 * ['a', 'b', 'c', 'd'].fill('-', -2, 0) # => ["a", "b", "c", "d"]
5117 * ['a', 'b', 'c', 'd'].fill('-', -2, -1) # => ["a", "b", "c", "d"]
5118 *
5119 * ['a', 'b', 'c', 'd'].fill(-2, 0) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
5120 * ['a', 'b', 'c', 'd'].fill(-2, -1) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
5121 *
5122 * When argument +range+ is given,
5123 * it must be a Range object whose members are numeric;
5124 * its +begin+ and +end+ values determine the elements of +self+
5125 * to be replaced:
5126 *
5127 * - If both +begin+ and +end+ are positive, they specify the first and last elements
5128 * to be replaced:
5129 *
5130 * ['a', 'b', 'c', 'd'].fill('-', 1..2) # => ["a", "-", "-", "d"]
5131 * ['a', 'b', 'c', 'd'].fill(1..2) {|e| e.to_s } # => ["a", "1", "2", "d"]
5132 *
5133 * If +end+ is smaller than +begin+, replaces no elements:
5134 *
5135 * ['a', 'b', 'c', 'd'].fill('-', 2..1) # => ["a", "b", "c", "d"]
5136 * ['a', 'b', 'c', 'd'].fill(2..1) {|e| e.to_s } # => ["a", "b", "c", "d"]
5137 *
5138 * - If either is negative (or both are negative), counts backwards from the end of +self+:
5139 *
5140 * ['a', 'b', 'c', 'd'].fill('-', -3..2) # => ["a", "-", "-", "d"]
5141 * ['a', 'b', 'c', 'd'].fill('-', 1..-2) # => ["a", "-", "-", "d"]
5142 * ['a', 'b', 'c', 'd'].fill('-', -3..-2) # => ["a", "-", "-", "d"]
5143 *
5144 * ['a', 'b', 'c', 'd'].fill(-3..2) {|e| e.to_s } # => ["a", "1", "2", "d"]
5145 * ['a', 'b', 'c', 'd'].fill(1..-2) {|e| e.to_s } # => ["a", "1", "2", "d"]
5146 * ['a', 'b', 'c', 'd'].fill(-3..-2) {|e| e.to_s } # => ["a", "1", "2", "d"]
5147 *
5148 * - If the +end+ value is excluded (see Range#exclude_end?), omits the last replacement:
5149 *
5150 * ['a', 'b', 'c', 'd'].fill('-', 1...2) # => ["a", "-", "c", "d"]
5151 * ['a', 'b', 'c', 'd'].fill('-', 1...-2) # => ["a", "-", "c", "d"]
5152 *
5153 * ['a', 'b', 'c', 'd'].fill(1...2) {|e| e.to_s } # => ["a", "1", "c", "d"]
5154 * ['a', 'b', 'c', 'd'].fill(1...-2) {|e| e.to_s } # => ["a", "1", "c", "d"]
5155 *
5156 * - If the range is endless (see {Endless Ranges}[rdoc-ref:Range@Endless+Ranges]),
5157 * replaces elements to the end of +self+:
5158 *
5159 * ['a', 'b', 'c', 'd'].fill('-', 1..) # => ["a", "-", "-", "-"]
5160 * ['a', 'b', 'c', 'd'].fill(1..) {|e| e.to_s } # => ["a", "1", "2", "3"]
5161 *
5162 * - If the range is beginless (see {Beginless Ranges}[rdoc-ref:Range@Beginless+Ranges]),
5163 * replaces elements from the beginning of +self+:
5164 *
5165 * ['a', 'b', 'c', 'd'].fill('-', ..2) # => ["-", "-", "-", "d"]
5166 * ['a', 'b', 'c', 'd'].fill(..2) {|e| e.to_s } # => ["0", "1", "2", "d"]
5167 *
5168 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
5169 */
5170
5171static VALUE
5172rb_ary_fill(int argc, VALUE *argv, VALUE ary)
5173{
5174 VALUE item = Qundef, arg1, arg2;
5175 long beg = 0, end = 0, len = 0;
5176
5177 if (rb_block_given_p()) {
5178 rb_scan_args(argc, argv, "02", &arg1, &arg2);
5179 argc += 1; /* hackish */
5180 }
5181 else {
5182 rb_scan_args(argc, argv, "12", &item, &arg1, &arg2);
5183 }
5184 switch (argc) {
5185 case 1:
5186 beg = 0;
5187 len = RARRAY_LEN(ary);
5188 break;
5189 case 2:
5190 if (rb_range_beg_len(arg1, &beg, &len, RARRAY_LEN(ary), 1)) {
5191 break;
5192 }
5193 /* fall through */
5194 case 3:
5195 beg = NIL_P(arg1) ? 0 : NUM2LONG(arg1);
5196 if (beg < 0) {
5197 beg = RARRAY_LEN(ary) + beg;
5198 if (beg < 0) beg = 0;
5199 }
5200 len = NIL_P(arg2) ? RARRAY_LEN(ary) - beg : NUM2LONG(arg2);
5201 break;
5202 }
5203 rb_ary_modify(ary);
5204 if (len < 0) {
5205 return ary;
5206 }
5207 if (beg >= ARY_MAX_SIZE || len > ARY_MAX_SIZE - beg) {
5208 rb_raise(rb_eArgError, "argument too big");
5209 }
5210 end = beg + len;
5211 if (RARRAY_LEN(ary) < end) {
5212 if (end >= ARY_CAPA(ary)) {
5213 ary_resize_capa(ary, end);
5214 }
5215 ary_mem_clear(ary, RARRAY_LEN(ary), end - RARRAY_LEN(ary));
5216 ARY_SET_LEN(ary, end);
5217 }
5218
5219 if (UNDEF_P(item)) {
5220 VALUE v;
5221 long i;
5222
5223 for (i=beg; i<end; i++) {
5224 v = rb_yield(LONG2NUM(i));
5225 if (i>=RARRAY_LEN(ary)) break;
5226 ARY_SET(ary, i, v);
5227 }
5228 }
5229 else {
5230 ary_memfill(ary, beg, len, item);
5231 }
5232 return ary;
5233}
5234
5235/*
5236 * call-seq:
5237 * self + other_array -> new_array
5238 *
5239 * Returns a new array containing all elements of +self+
5240 * followed by all elements of +other_array+:
5241 *
5242 * a = [0, 1] + [2, 3]
5243 * a # => [0, 1, 2, 3]
5244 *
5245 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5246 */
5247
5248VALUE
5250{
5251 VALUE z;
5252 long len, xlen, ylen;
5253
5254 y = to_ary(y);
5255 xlen = RARRAY_LEN(x);
5256 ylen = RARRAY_LEN(y);
5257 len = xlen + ylen;
5258 z = rb_ary_new2(len);
5259
5260 ary_memcpy(z, 0, xlen, RARRAY_CONST_PTR(x));
5261 ary_memcpy(z, xlen, ylen, RARRAY_CONST_PTR(y));
5262 ARY_SET_LEN(z, len);
5263 return z;
5264}
5265
5266static VALUE
5267ary_append(VALUE x, VALUE y)
5268{
5269 long n = RARRAY_LEN(y);
5270 if (n > 0) {
5271 rb_ary_splice(x, RARRAY_LEN(x), 0, RARRAY_CONST_PTR(y), n);
5272 }
5273 RB_GC_GUARD(y);
5274 return x;
5275}
5276
5277/*
5278 * call-seq:
5279 * concat(*other_arrays) -> self
5280 *
5281 * Adds to +self+ all elements from each array in +other_arrays+; returns +self+:
5282 *
5283 * a = [0, 1]
5284 * a.concat(['two', 'three'], [:four, :five], a)
5285 * # => [0, 1, "two", "three", :four, :five, 0, 1]
5286 *
5287 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
5288 */
5289
5290static VALUE
5291rb_ary_concat_multi(int argc, VALUE *argv, VALUE ary)
5292{
5293 rb_ary_modify_check(ary);
5294
5295 if (argc == 1) {
5296 rb_ary_concat(ary, argv[0]);
5297 }
5298 else if (argc > 1) {
5299 int i;
5300 VALUE args = rb_ary_hidden_new(argc);
5301 for (i = 0; i < argc; i++) {
5302 rb_ary_concat(args, argv[i]);
5303 }
5304 ary_append(ary, args);
5305 }
5306
5307 ary_verify(ary);
5308 return ary;
5309}
5310
5311VALUE
5313{
5314 return ary_append(x, to_ary(y));
5315}
5316
5317/*
5318 * call-seq:
5319 * self * n -> new_array
5320 * self * string_separator -> new_string
5321 *
5322 * When non-negative integer argument +n+ is given,
5323 * returns a new array built by concatenating +n+ copies of +self+:
5324 *
5325 * a = ['x', 'y']
5326 * a * 3 # => ["x", "y", "x", "y", "x", "y"]
5327 *
5328 * When string argument +string_separator+ is given,
5329 * equivalent to <tt>self.join(string_separator)</tt>:
5330 *
5331 * [0, [0, 1], {foo: 0}] * ', ' # => "0, 0, 1, {foo: 0}"
5332 *
5333 */
5334
5335static VALUE
5336rb_ary_times(VALUE ary, VALUE times)
5337{
5338 VALUE ary2, tmp;
5339 const VALUE *ptr;
5340 long t, len;
5341
5342 tmp = rb_check_string_type(times);
5343 if (!NIL_P(tmp)) {
5344 return rb_ary_join(ary, tmp);
5345 }
5346
5347 len = NUM2LONG(times);
5348 if (len == 0) {
5349 ary2 = ary_new(rb_cArray, 0);
5350 goto out;
5351 }
5352 if (len < 0) {
5353 rb_raise(rb_eArgError, "negative argument");
5354 }
5355 if (ARY_MAX_SIZE/len < RARRAY_LEN(ary)) {
5356 rb_raise(rb_eArgError, "argument too big");
5357 }
5358 len *= RARRAY_LEN(ary);
5359
5360 ary2 = ary_new(rb_cArray, len);
5361 ARY_SET_LEN(ary2, len);
5362
5363 ptr = RARRAY_CONST_PTR(ary);
5364 t = RARRAY_LEN(ary);
5365 if (0 < t) {
5366 ary_memcpy(ary2, 0, t, ptr);
5367 while (t <= len/2) {
5368 ary_memcpy(ary2, t, t, RARRAY_CONST_PTR(ary2));
5369 t *= 2;
5370 }
5371 if (t < len) {
5372 ary_memcpy(ary2, t, len-t, RARRAY_CONST_PTR(ary2));
5373 }
5374 }
5375 out:
5376 return ary2;
5377}
5378
5379/*
5380 * call-seq:
5381 * assoc(object) -> found_array or nil
5382 *
5383 * Returns the first element +ele+ in +self+ such that +ele+ is an array
5384 * and <tt>ele[0] == object</tt>:
5385 *
5386 * a = [{foo: 0}, [2, 4], [4, 5, 6], [4, 5]]
5387 * a.assoc(4) # => [4, 5, 6]
5388 *
5389 * Returns +nil+ if no such element is found.
5390 *
5391 * Related: Array#rassoc;
5392 * see also {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
5393 */
5394
5395VALUE
5396rb_ary_assoc(VALUE ary, VALUE key)
5397{
5398 long i;
5399 VALUE v;
5400
5401 for (i = 0; i < RARRAY_LEN(ary); ++i) {
5402 v = rb_check_array_type(RARRAY_AREF(ary, i));
5403 if (!NIL_P(v) && RARRAY_LEN(v) > 0 &&
5404 rb_equal(RARRAY_AREF(v, 0), key))
5405 return v;
5406 }
5407 return Qnil;
5408}
5409
5410/*
5411 * call-seq:
5412 * rassoc(object) -> found_array or nil
5413 *
5414 * Returns the first element +ele+ in +self+ such that +ele+ is an array
5415 * and <tt>ele[1] == object</tt>:
5416 *
5417 * a = [{foo: 0}, [2, 4], [4, 5, 6], [4, 5]]
5418 * a.rassoc(4) # => [2, 4]
5419 * a.rassoc(5) # => [4, 5, 6]
5420 *
5421 * Returns +nil+ if no such element is found.
5422 *
5423 * Related: Array#assoc;
5424 * see also {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
5425 */
5426
5427VALUE
5428rb_ary_rassoc(VALUE ary, VALUE value)
5429{
5430 long i;
5431 VALUE v;
5432
5433 for (i = 0; i < RARRAY_LEN(ary); ++i) {
5434 v = rb_check_array_type(RARRAY_AREF(ary, i));
5435 if (RB_TYPE_P(v, T_ARRAY) &&
5436 RARRAY_LEN(v) > 1 &&
5437 rb_equal(RARRAY_AREF(v, 1), value))
5438 return v;
5439 }
5440 return Qnil;
5441}
5442
5443static VALUE
5444recursive_equal(VALUE ary1, VALUE ary2, int recur)
5445{
5446 long i, len1;
5447 const VALUE *p1, *p2;
5448
5449 if (recur) return Qtrue; /* Subtle! */
5450
5451 /* rb_equal() can evacuate ptrs */
5452 p1 = RARRAY_CONST_PTR(ary1);
5453 p2 = RARRAY_CONST_PTR(ary2);
5454 len1 = RARRAY_LEN(ary1);
5455
5456 for (i = 0; i < len1; i++) {
5457 if (*p1 != *p2) {
5458 if (rb_equal(*p1, *p2)) {
5459 len1 = RARRAY_LEN(ary1);
5460 if (len1 != RARRAY_LEN(ary2))
5461 return Qfalse;
5462 if (len1 < i)
5463 return Qtrue;
5464 p1 = RARRAY_CONST_PTR(ary1) + i;
5465 p2 = RARRAY_CONST_PTR(ary2) + i;
5466 }
5467 else {
5468 return Qfalse;
5469 }
5470 }
5471 p1++;
5472 p2++;
5473 }
5474 return Qtrue;
5475}
5476
5477/*
5478 * call-seq:
5479 * self == other_array -> true or false
5480 *
5481 * Returns whether both:
5482 *
5483 * - +self+ and +other_array+ are the same size.
5484 * - Their corresponding elements are the same;
5485 * that is, for each index +i+ in <tt>(0...self.size)</tt>,
5486 * <tt>self[i] == other_array[i]</tt>.
5487 *
5488 * Examples:
5489 *
5490 * [:foo, 'bar', 2] == [:foo, 'bar', 2] # => true
5491 * [:foo, 'bar', 2] == [:foo, 'bar', 2.0] # => true
5492 * [:foo, 'bar', 2] == [:foo, 'bar'] # => false # Different sizes.
5493 * [:foo, 'bar', 2] == [:foo, 'bar', 3] # => false # Different elements.
5494 *
5495 * This method is different from method Array#eql?,
5496 * which compares elements using <tt>Object#eql?</tt>.
5497 *
5498 * Related: see {Methods for Comparing}[rdoc-ref:Array@Methods+for+Comparing].
5499 */
5500
5501static VALUE
5502rb_ary_equal(VALUE ary1, VALUE ary2)
5503{
5504 if (ary1 == ary2) return Qtrue;
5505 if (!RB_TYPE_P(ary2, T_ARRAY)) {
5506 if (!rb_respond_to(ary2, idTo_ary)) {
5507 return Qfalse;
5508 }
5509 return rb_equal(ary2, ary1);
5510 }
5511 if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return Qfalse;
5512 if (RARRAY_CONST_PTR(ary1) == RARRAY_CONST_PTR(ary2)) return Qtrue;
5513 return rb_exec_recursive_paired(recursive_equal, ary1, ary2, ary2);
5514}
5515
5516static VALUE
5517recursive_eql(VALUE ary1, VALUE ary2, int recur)
5518{
5519 long i;
5520
5521 if (recur) return Qtrue; /* Subtle! */
5522 for (i=0; i<RARRAY_LEN(ary1); i++) {
5523 if (!rb_eql(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i)))
5524 return Qfalse;
5525 }
5526 return Qtrue;
5527}
5528
5529/*
5530 * call-seq:
5531 * eql?(other_array) -> true or false
5532 *
5533 * Returns +true+ if +self+ and +other_array+ are the same size,
5534 * and if, for each index +i+ in +self+, <tt>self[i].eql?(other_array[i])</tt>:
5535 *
5536 * a0 = [:foo, 'bar', 2]
5537 * a1 = [:foo, 'bar', 2]
5538 * a1.eql?(a0) # => true
5539 *
5540 * Otherwise, returns +false+.
5541 *
5542 * This method is different from method Array#==,
5543 * which compares using method <tt>Object#==</tt>.
5544 *
5545 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
5546 */
5547
5548static VALUE
5549rb_ary_eql(VALUE ary1, VALUE ary2)
5550{
5551 if (ary1 == ary2) return Qtrue;
5552 if (!RB_TYPE_P(ary2, T_ARRAY)) return Qfalse;
5553 if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return Qfalse;
5554 if (RARRAY_CONST_PTR(ary1) == RARRAY_CONST_PTR(ary2)) return Qtrue;
5555 return rb_exec_recursive_paired(recursive_eql, ary1, ary2, ary2);
5556}
5557
5558static VALUE
5559ary_hash_values(long len, const VALUE *elements, const VALUE ary)
5560{
5561 long i;
5562 st_index_t h;
5563 VALUE n;
5564
5565 h = rb_hash_start(len);
5566 h = rb_hash_uint(h, (st_index_t)rb_ary_hash_values);
5567 for (i=0; i<len; i++) {
5568 n = rb_hash(elements[i]);
5569 h = rb_hash_uint(h, NUM2LONG(n));
5570 if (ary) {
5571 len = RARRAY_LEN(ary);
5572 elements = RARRAY_CONST_PTR(ary);
5573 }
5574 }
5575 h = rb_hash_end(h);
5576 return ST2FIX(h);
5577}
5578
5579VALUE
5580rb_ary_hash_values(long len, const VALUE *elements)
5581{
5582 return ary_hash_values(len, elements, 0);
5583}
5584
5585/*
5586 * call-seq:
5587 * hash -> integer
5588 *
5589 * Returns the integer hash value for +self+.
5590 *
5591 * Two arrays with the same content will have the same hash value
5592 * (and will compare using eql?):
5593 *
5594 * ['a', 'b'].hash == ['a', 'b'].hash # => true
5595 * ['a', 'b'].hash == ['a', 'c'].hash # => false
5596 * ['a', 'b'].hash == ['a'].hash # => false
5597 *
5598 */
5599
5600static VALUE
5601rb_ary_hash(VALUE ary)
5602{
5604 return ary_hash_values(RARRAY_LEN(ary), RARRAY_CONST_PTR(ary), ary);
5605}
5606
5607/*
5608 * call-seq:
5609 * include?(object) -> true or false
5610 *
5611 * Returns whether for some element +element+ in +self+,
5612 * <tt>object == element</tt>:
5613 *
5614 * [0, 1, 2].include?(2) # => true
5615 * [0, 1, 2].include?(2.0) # => true
5616 * [0, 1, 2].include?(2.1) # => false
5617 *
5618 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
5619 */
5620
5621VALUE
5622rb_ary_includes(VALUE ary, VALUE item)
5623{
5624 long i;
5625 VALUE e;
5626
5627 for (i=0; i<RARRAY_LEN(ary); i++) {
5628 e = RARRAY_AREF(ary, i);
5629 if (rb_equal(e, item)) {
5630 return Qtrue;
5631 }
5632 }
5633 return Qfalse;
5634}
5635
5636static VALUE
5637rb_ary_includes_by_eql(VALUE ary, VALUE item)
5638{
5639 long i;
5640 VALUE e;
5641
5642 for (i=0; i<RARRAY_LEN(ary); i++) {
5643 e = RARRAY_AREF(ary, i);
5644 if (rb_eql(item, e)) {
5645 return Qtrue;
5646 }
5647 }
5648 return Qfalse;
5649}
5650
5651static VALUE
5652recursive_cmp(VALUE ary1, VALUE ary2, int recur)
5653{
5654 long i, len;
5655
5656 if (recur) return Qundef; /* Subtle! */
5657 len = RARRAY_LEN(ary1);
5658 if (len > RARRAY_LEN(ary2)) {
5659 len = RARRAY_LEN(ary2);
5660 }
5661 for (i=0; i<len; i++) {
5662 VALUE e1 = rb_ary_elt(ary1, i), e2 = rb_ary_elt(ary2, i);
5663 VALUE v = rb_funcallv(e1, id_cmp, 1, &e2);
5664 if (v != INT2FIX(0)) {
5665 return v;
5666 }
5667 }
5668 return Qundef;
5669}
5670
5671/*
5672 * call-seq:
5673 * self <=> other_array -> -1, 0, or 1
5674 *
5675 * Returns -1, 0, or 1 as +self+ is determined
5676 * to be less than, equal to, or greater than +other_array+.
5677 *
5678 * Iterates over each index +i+ in <tt>(0...self.size)</tt>:
5679 *
5680 * - Computes <tt>result[i]</tt> as <tt>self[i] <=> other_array[i]</tt>.
5681 * - Immediately returns 1 if <tt>result[i]</tt> is 1:
5682 *
5683 * [0, 1, 2] <=> [0, 0, 2] # => 1
5684 *
5685 * - Immediately returns -1 if <tt>result[i]</tt> is -1:
5686 *
5687 * [0, 1, 2] <=> [0, 2, 2] # => -1
5688 *
5689 * - Continues if <tt>result[i]</tt> is 0.
5690 *
5691 * When every +result+ is 0,
5692 * returns <tt>self.size <=> other_array.size</tt>
5693 * (see Integer#<=>):
5694 *
5695 * [0, 1, 2] <=> [0, 1] # => 1
5696 * [0, 1, 2] <=> [0, 1, 2] # => 0
5697 * [0, 1, 2] <=> [0, 1, 2, 3] # => -1
5698 *
5699 * Note that when +other_array+ is larger than +self+,
5700 * its trailing elements do not affect the result:
5701 *
5702 * [0, 1, 2] <=> [0, 1, 2, -3] # => -1
5703 * [0, 1, 2] <=> [0, 1, 2, 0] # => -1
5704 * [0, 1, 2] <=> [0, 1, 2, 3] # => -1
5705 *
5706 * Related: see {Methods for Comparing}[rdoc-ref:Array@Methods+for+Comparing].
5707 */
5708
5709VALUE
5710rb_ary_cmp(VALUE ary1, VALUE ary2)
5711{
5712 long len;
5713 VALUE v;
5714
5715 ary2 = rb_check_array_type(ary2);
5716 if (NIL_P(ary2)) return Qnil;
5717 if (ary1 == ary2) return INT2FIX(0);
5718 v = rb_exec_recursive_paired(recursive_cmp, ary1, ary2, ary2);
5719 if (!UNDEF_P(v)) return v;
5720 len = RARRAY_LEN(ary1) - RARRAY_LEN(ary2);
5721 if (len == 0) return INT2FIX(0);
5722 if (len > 0) return INT2FIX(1);
5723 return INT2FIX(-1);
5724}
5725
5726static VALUE
5727ary_add_hash(VALUE hash, VALUE ary)
5728{
5729 long i;
5730
5731 for (i=0; i<RARRAY_LEN(ary); i++) {
5732 VALUE elt = RARRAY_AREF(ary, i);
5733 rb_hash_add_new_element(hash, elt, elt);
5734 }
5735 return hash;
5736}
5737
5738static inline VALUE
5739ary_tmp_hash_new(VALUE ary)
5740{
5741 long size = RARRAY_LEN(ary);
5742 VALUE hash = rb_hash_new_with_size(size);
5743
5744 RBASIC_CLEAR_CLASS(hash);
5745 return hash;
5746}
5747
5748static VALUE
5749ary_make_hash(VALUE ary)
5750{
5751 VALUE hash = ary_tmp_hash_new(ary);
5752 return ary_add_hash(hash, ary);
5753}
5754
5755static VALUE
5756ary_add_hash_by(VALUE hash, VALUE ary)
5757{
5758 long i;
5759
5760 for (i = 0; i < RARRAY_LEN(ary); ++i) {
5761 VALUE v = rb_ary_elt(ary, i), k = rb_yield(v);
5762 rb_hash_add_new_element(hash, k, v);
5763 }
5764 return hash;
5765}
5766
5767static VALUE
5768ary_make_hash_by(VALUE ary)
5769{
5770 VALUE hash = ary_tmp_hash_new(ary);
5771 return ary_add_hash_by(hash, ary);
5772}
5773
5774/*
5775 * call-seq:
5776 * self - other_array -> new_array
5777 *
5778 * Returns a new array containing only those elements of +self+
5779 * that are not found in +other_array+;
5780 * the order from +self+ is preserved:
5781 *
5782 * [0, 1, 1, 2, 1, 1, 3, 1, 1] - [1] # => [0, 2, 3]
5783 * [0, 1, 1, 2, 1, 1, 3, 1, 1] - [3, 2, 0, :foo] # => [1, 1, 1, 1, 1, 1]
5784 * [0, 1, 2] - [:foo] # => [0, 1, 2]
5785 *
5786 * Element are compared using method <tt>#eql?</tt>
5787 * (as defined in each element of +self+).
5788 *
5789 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5790 */
5791
5792VALUE
5793rb_ary_diff(VALUE ary1, VALUE ary2)
5794{
5795 VALUE ary3;
5796 VALUE hash;
5797 long i;
5798
5799 ary2 = to_ary(ary2);
5800 if (RARRAY_LEN(ary2) == 0) { return ary_make_shared_copy(ary1); }
5801 ary3 = rb_ary_new();
5802
5803 if (RARRAY_LEN(ary1) <= SMALL_ARRAY_LEN || RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
5804 for (i=0; i<RARRAY_LEN(ary1); i++) {
5805 VALUE elt = rb_ary_elt(ary1, i);
5806 if (rb_ary_includes_by_eql(ary2, elt)) continue;
5807 rb_ary_push(ary3, elt);
5808 }
5809 return ary3;
5810 }
5811
5812 hash = ary_make_hash(ary2);
5813 for (i=0; i<RARRAY_LEN(ary1); i++) {
5814 if (rb_hash_stlike_lookup(hash, RARRAY_AREF(ary1, i), NULL)) continue;
5815 rb_ary_push(ary3, rb_ary_elt(ary1, i));
5816 }
5817
5818 return ary3;
5819}
5820
5821/*
5822 * call-seq:
5823 * difference(*other_arrays = []) -> new_array
5824 *
5825 * Returns a new array containing only those elements from +self+
5826 * that are not found in any of the given +other_arrays+;
5827 * items are compared using <tt>eql?</tt>; order from +self+ is preserved:
5828 *
5829 * [0, 1, 1, 2, 1, 1, 3, 1, 1].difference([1]) # => [0, 2, 3]
5830 * [0, 1, 2, 3].difference([3, 0], [1, 3]) # => [2]
5831 * [0, 1, 2].difference([4]) # => [0, 1, 2]
5832 * [0, 1, 2].difference # => [0, 1, 2]
5833 *
5834 * Returns a copy of +self+ if no arguments are given.
5835 *
5836 * Related: Array#-;
5837 * see also {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5838 */
5839
5840static VALUE
5841rb_ary_difference_multi(int argc, VALUE *argv, VALUE ary)
5842{
5843 VALUE ary_diff;
5844 long i, length;
5845 volatile VALUE t0;
5846 bool *is_hash = ALLOCV_N(bool, t0, argc);
5847 ary_diff = rb_ary_new();
5848 length = RARRAY_LEN(ary);
5849
5850 for (i = 0; i < argc; i++) {
5851 argv[i] = to_ary(argv[i]);
5852 is_hash[i] = (length > SMALL_ARRAY_LEN && RARRAY_LEN(argv[i]) > SMALL_ARRAY_LEN);
5853 if (is_hash[i]) argv[i] = ary_make_hash(argv[i]);
5854 }
5855
5856 for (i = 0; i < RARRAY_LEN(ary); i++) {
5857 int j;
5858 VALUE elt = rb_ary_elt(ary, i);
5859 for (j = 0; j < argc; j++) {
5860 if (is_hash[j]) {
5861 if (rb_hash_stlike_lookup(argv[j], elt, NULL))
5862 break;
5863 }
5864 else {
5865 if (rb_ary_includes_by_eql(argv[j], elt)) break;
5866 }
5867 }
5868 if (j == argc) rb_ary_push(ary_diff, elt);
5869 }
5870
5871 ALLOCV_END(t0);
5872
5873 return ary_diff;
5874}
5875
5876
5877/*
5878 * call-seq:
5879 * self & other_array -> new_array
5880 *
5881 * Returns a new array containing the _intersection_ of +self+ and +other_array+;
5882 * that is, containing those elements found in both +self+ and +other_array+:
5883 *
5884 * [0, 1, 2, 3] & [1, 2] # => [1, 2]
5885 *
5886 * Omits duplicates:
5887 *
5888 * [0, 1, 1, 0] & [0, 1] # => [0, 1]
5889 *
5890 * Preserves order from +self+:
5891 *
5892 * [0, 1, 2] & [3, 2, 1, 0] # => [0, 1, 2]
5893 *
5894 * Identifies common elements using method <tt>#eql?</tt>
5895 * (as defined in each element of +self+).
5896 *
5897 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5898 */
5899
5900
5901static VALUE
5902rb_ary_and(VALUE ary1, VALUE ary2)
5903{
5904 VALUE hash, ary3, v;
5905 st_data_t vv;
5906 long i;
5907
5908 ary2 = to_ary(ary2);
5909 ary3 = rb_ary_new();
5910 if (RARRAY_LEN(ary1) == 0 || RARRAY_LEN(ary2) == 0) return ary3;
5911
5912 if (RARRAY_LEN(ary1) <= SMALL_ARRAY_LEN && RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
5913 for (i=0; i<RARRAY_LEN(ary1); i++) {
5914 v = RARRAY_AREF(ary1, i);
5915 if (!rb_ary_includes_by_eql(ary2, v)) continue;
5916 if (rb_ary_includes_by_eql(ary3, v)) continue;
5917 rb_ary_push(ary3, v);
5918 }
5919 return ary3;
5920 }
5921
5922 hash = ary_make_hash(ary2);
5923
5924 for (i=0; i<RARRAY_LEN(ary1); i++) {
5925 v = RARRAY_AREF(ary1, i);
5926 vv = (st_data_t)v;
5927 if (rb_hash_stlike_delete(hash, &vv, 0)) {
5928 rb_ary_push(ary3, v);
5929 }
5930 }
5931
5932 return ary3;
5933}
5934
5935/*
5936 * call-seq:
5937 * intersection(*other_arrays) -> new_array
5938 *
5939 * Returns a new array containing each element in +self+ that is +#eql?+
5940 * to at least one element in each of the given +other_arrays+;
5941 * duplicates are omitted:
5942 *
5943 * [0, 0, 1, 1, 2, 3].intersection([0, 1, 2], [0, 1, 3]) # => [0, 1]
5944 *
5945 * Each element must correctly implement method <tt>#hash</tt>.
5946 *
5947 * Order from +self+ is preserved:
5948 *
5949 * [0, 1, 2].intersection([2, 1, 0]) # => [0, 1, 2]
5950 *
5951 * Returns a copy of +self+ if no arguments are given.
5952 *
5953 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5954 */
5955
5956static VALUE
5957rb_ary_intersection_multi(int argc, VALUE *argv, VALUE ary)
5958{
5959 VALUE result = rb_ary_dup(ary);
5960 int i;
5961
5962 for (i = 0; i < argc; i++) {
5963 result = rb_ary_and(result, argv[i]);
5964 }
5965
5966 return result;
5967}
5968
5969static int
5970ary_hash_orset(st_data_t *key, st_data_t *value, st_data_t arg, int existing)
5971{
5972 if (existing) return ST_STOP;
5973 *key = *value = (VALUE)arg;
5974 return ST_CONTINUE;
5975}
5976
5977static void
5978rb_ary_union(VALUE ary_union, VALUE ary)
5979{
5980 long i;
5981 for (i = 0; i < RARRAY_LEN(ary); i++) {
5982 VALUE elt = rb_ary_elt(ary, i);
5983 if (rb_ary_includes_by_eql(ary_union, elt)) continue;
5984 rb_ary_push(ary_union, elt);
5985 }
5986}
5987
5988static void
5989rb_ary_union_hash(VALUE hash, VALUE ary2)
5990{
5991 long i;
5992 for (i = 0; i < RARRAY_LEN(ary2); i++) {
5993 VALUE elt = RARRAY_AREF(ary2, i);
5994 if (!rb_hash_stlike_update(hash, (st_data_t)elt, ary_hash_orset, (st_data_t)elt)) {
5995 RB_OBJ_WRITTEN(hash, Qundef, elt);
5996 }
5997 }
5998}
5999
6000/*
6001 * call-seq:
6002 * self | other_array -> new_array
6003 *
6004 * Returns the union of +self+ and +other_array+;
6005 * duplicates are removed; order is preserved;
6006 * items are compared using <tt>eql?</tt> and <tt>hash</tt>:
6007 *
6008 * [0, 1] | [2, 3] # => [0, 1, 2, 3]
6009 * [0, 1, 1] | [2, 2, 3] # => [0, 1, 2, 3]
6010 * [0, 1, 2] | [3, 2, 1, 0] # => [0, 1, 2, 3]
6011 *
6012 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
6013 */
6014
6015static VALUE
6016rb_ary_or(VALUE ary1, VALUE ary2)
6017{
6018 VALUE hash;
6019
6020 ary2 = to_ary(ary2);
6021 if (RARRAY_LEN(ary1) + RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
6022 VALUE ary3 = rb_ary_new();
6023 rb_ary_union(ary3, ary1);
6024 rb_ary_union(ary3, ary2);
6025 return ary3;
6026 }
6027
6028 hash = ary_make_hash(ary1);
6029 rb_ary_union_hash(hash, ary2);
6030
6031 return rb_hash_values(hash);
6032}
6033
6034/*
6035 * call-seq:
6036 * union(*other_arrays) -> new_array
6037 *
6038 * Returns a new array that is the union of the elements of +self+
6039 * and all given arrays +other_arrays+;
6040 * items are compared using <tt>eql?</tt> and <tt>hash</tt>:
6041 *
6042 * [0, 1, 2, 3].union([4, 5], [6, 7]) # => [0, 1, 2, 3, 4, 5, 6, 7]
6043 *
6044 * Removes duplicates (preserving the first found):
6045 *
6046 * [0, 1, 1].union([2, 1], [3, 1]) # => [0, 1, 2, 3]
6047 *
6048 * Preserves order (preserving the position of the first found):
6049 *
6050 * [3, 2, 1, 0].union([5, 3], [4, 2]) # => [3, 2, 1, 0, 5, 4]
6051 *
6052 * With no arguments given, returns a copy of +self+.
6053 *
6054 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
6055 */
6056
6057static VALUE
6058rb_ary_union_multi(int argc, VALUE *argv, VALUE ary)
6059{
6060 int i;
6061 long sum;
6062 VALUE hash;
6063
6064 sum = RARRAY_LEN(ary);
6065 for (i = 0; i < argc; i++) {
6066 argv[i] = to_ary(argv[i]);
6067 sum += RARRAY_LEN(argv[i]);
6068 }
6069
6070 if (sum <= SMALL_ARRAY_LEN) {
6071 VALUE ary_union = rb_ary_new();
6072
6073 rb_ary_union(ary_union, ary);
6074 for (i = 0; i < argc; i++) rb_ary_union(ary_union, argv[i]);
6075
6076 return ary_union;
6077 }
6078
6079 hash = ary_make_hash(ary);
6080 for (i = 0; i < argc; i++) rb_ary_union_hash(hash, argv[i]);
6081
6082 return rb_hash_values(hash);
6083}
6084
6085/*
6086 * call-seq:
6087 * intersect?(other_array) -> true or false
6088 *
6089 * Returns whether +other_array+ has at least one element that is +#eql?+ to some element of +self+:
6090 *
6091 * [1, 2, 3].intersect?([3, 4, 5]) # => true
6092 * [1, 2, 3].intersect?([4, 5, 6]) # => false
6093 *
6094 * Each element must correctly implement method <tt>#hash</tt>.
6095 *
6096 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
6097 */
6098
6099static VALUE
6100rb_ary_intersect_p(VALUE ary1, VALUE ary2)
6101{
6102 VALUE hash, v, result, shorter, longer;
6103 st_data_t vv;
6104 long i;
6105
6106 ary2 = to_ary(ary2);
6107 if (RARRAY_LEN(ary1) == 0 || RARRAY_LEN(ary2) == 0) return Qfalse;
6108
6109 if (RARRAY_LEN(ary1) <= SMALL_ARRAY_LEN && RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
6110 for (i=0; i<RARRAY_LEN(ary1); i++) {
6111 v = RARRAY_AREF(ary1, i);
6112 if (rb_ary_includes_by_eql(ary2, v)) return Qtrue;
6113 }
6114 return Qfalse;
6115 }
6116
6117 shorter = ary1;
6118 longer = ary2;
6119 if (RARRAY_LEN(ary1) > RARRAY_LEN(ary2)) {
6120 longer = ary1;
6121 shorter = ary2;
6122 }
6123
6124 hash = ary_make_hash(shorter);
6125 result = Qfalse;
6126
6127 for (i=0; i<RARRAY_LEN(longer); i++) {
6128 v = RARRAY_AREF(longer, i);
6129 vv = (st_data_t)v;
6130 if (rb_hash_stlike_lookup(hash, vv, 0)) {
6131 result = Qtrue;
6132 break;
6133 }
6134 }
6135
6136 return result;
6137}
6138
6139static VALUE
6140ary_max_generic(VALUE ary, long i, VALUE vmax)
6141{
6142 RUBY_ASSERT(i > 0 && i < RARRAY_LEN(ary));
6143
6144 VALUE v;
6145 for (; i < RARRAY_LEN(ary); ++i) {
6146 v = RARRAY_AREF(ary, i);
6147
6148 if (rb_cmpint(rb_funcallv(vmax, id_cmp, 1, &v), vmax, v) < 0) {
6149 vmax = v;
6150 }
6151 }
6152
6153 return vmax;
6154}
6155
6156static VALUE
6157ary_max_opt_fixnum(VALUE ary, long i, VALUE vmax)
6158{
6159 const long n = RARRAY_LEN(ary);
6160 RUBY_ASSERT(i > 0 && i < n);
6161 RUBY_ASSERT(FIXNUM_P(vmax));
6162
6163 VALUE v;
6164 for (; i < n; ++i) {
6165 v = RARRAY_AREF(ary, i);
6166
6167 if (FIXNUM_P(v)) {
6168 if ((long)vmax < (long)v) {
6169 vmax = v;
6170 }
6171 }
6172 else {
6173 return ary_max_generic(ary, i, vmax);
6174 }
6175 }
6176
6177 return vmax;
6178}
6179
6180static VALUE
6181ary_max_opt_float(VALUE ary, long i, VALUE vmax)
6182{
6183 const long n = RARRAY_LEN(ary);
6184 RUBY_ASSERT(i > 0 && i < n);
6186
6187 VALUE v;
6188 for (; i < n; ++i) {
6189 v = RARRAY_AREF(ary, i);
6190
6191 if (RB_FLOAT_TYPE_P(v)) {
6192 if (rb_float_cmp(vmax, v) < 0) {
6193 vmax = v;
6194 }
6195 }
6196 else {
6197 return ary_max_generic(ary, i, vmax);
6198 }
6199 }
6200
6201 return vmax;
6202}
6203
6204static VALUE
6205ary_max_opt_string(VALUE ary, long i, VALUE vmax)
6206{
6207 const long n = RARRAY_LEN(ary);
6208 RUBY_ASSERT(i > 0 && i < n);
6209 RUBY_ASSERT(STRING_P(vmax));
6210
6211 VALUE v;
6212 for (; i < n; ++i) {
6213 v = RARRAY_AREF(ary, i);
6214
6215 if (STRING_P(v)) {
6216 if (rb_str_cmp(vmax, v) < 0) {
6217 vmax = v;
6218 }
6219 }
6220 else {
6221 return ary_max_generic(ary, i, vmax);
6222 }
6223 }
6224
6225 return vmax;
6226}
6227
6228/*
6229 * call-seq:
6230 * max -> element
6231 * max(count) -> new_array
6232 * max {|a, b| ... } -> element
6233 * max(count) {|a, b| ... } -> new_array
6234 *
6235 * Returns one of the following:
6236 *
6237 * - The maximum-valued element from +self+.
6238 * - A new array of maximum-valued elements from +self+.
6239 *
6240 * Does not modify +self+.
6241 *
6242 * With no block given, each element in +self+ must respond to method <tt>#<=></tt>
6243 * with a numeric.
6244 *
6245 * With no argument and no block, returns the element in +self+
6246 * having the maximum value per method <tt>#<=></tt>:
6247 *
6248 * [1, 0, 3, 2].max # => 3
6249 *
6250 * With non-negative numeric argument +count+ and no block,
6251 * returns a new array with at most +count+ elements,
6252 * in descending order, per method <tt>#<=></tt>:
6253 *
6254 * [1, 0, 3, 2].max(3) # => [3, 2, 1]
6255 * [1, 0, 3, 2].max(3.0) # => [3, 2, 1]
6256 * [1, 0, 3, 2].max(9) # => [3, 2, 1, 0]
6257 * [1, 0, 3, 2].max(0) # => []
6258 *
6259 * With a block given, the block must return a numeric.
6260 *
6261 * With a block and no argument, calls the block <tt>self.size - 1</tt> times to compare elements;
6262 * returns the element having the maximum value per the block:
6263 *
6264 * ['0', '', '000', '00'].max {|a, b| a.size <=> b.size }
6265 * # => "000"
6266 *
6267 * With non-negative numeric argument +count+ and a block,
6268 * returns a new array with at most +count+ elements,
6269 * in descending order, per the block:
6270 *
6271 * ['0', '', '000', '00'].max(2) {|a, b| a.size <=> b.size }
6272 * # => ["000", "00"]
6273 *
6274 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
6275 */
6276static VALUE
6277rb_ary_max(int argc, VALUE *argv, VALUE ary)
6278{
6279 VALUE result = Qundef, v;
6280 VALUE num;
6281 long i;
6282
6283 if (rb_check_arity(argc, 0, 1) && !NIL_P(num = argv[0]))
6284 return rb_nmin_run(ary, num, 0, 1, 1);
6285
6286 const long n = RARRAY_LEN(ary);
6287 if (rb_block_given_p()) {
6288 for (i = 0; i < RARRAY_LEN(ary); i++) {
6289 v = RARRAY_AREF(ary, i);
6290 if (UNDEF_P(result) || rb_cmpint(rb_yield_values(2, v, result), v, result) > 0) {
6291 result = v;
6292 }
6293 }
6294 }
6295 else if (n > 0) {
6296 result = RARRAY_AREF(ary, 0);
6297 if (n > 1) {
6298 if (FIXNUM_P(result) && CMP_OPTIMIZABLE(INTEGER)) {
6299 return ary_max_opt_fixnum(ary, 1, result);
6300 }
6301 else if (STRING_P(result) && CMP_OPTIMIZABLE(STRING)) {
6302 return ary_max_opt_string(ary, 1, result);
6303 }
6304 else if (RB_FLOAT_TYPE_P(result) && CMP_OPTIMIZABLE(FLOAT)) {
6305 return ary_max_opt_float(ary, 1, result);
6306 }
6307 else {
6308 return ary_max_generic(ary, 1, result);
6309 }
6310 }
6311 }
6312 if (UNDEF_P(result)) return Qnil;
6313 return result;
6314}
6315
6316static VALUE
6317ary_min_generic(VALUE ary, long i, VALUE vmin)
6318{
6319 RUBY_ASSERT(i > 0 && i < RARRAY_LEN(ary));
6320
6321 VALUE v;
6322 for (; i < RARRAY_LEN(ary); ++i) {
6323 v = RARRAY_AREF(ary, i);
6324
6325 if (rb_cmpint(rb_funcallv(vmin, id_cmp, 1, &v), vmin, v) > 0) {
6326 vmin = v;
6327 }
6328 }
6329
6330 return vmin;
6331}
6332
6333static VALUE
6334ary_min_opt_fixnum(VALUE ary, long i, VALUE vmin)
6335{
6336 const long n = RARRAY_LEN(ary);
6337 RUBY_ASSERT(i > 0 && i < n);
6338 RUBY_ASSERT(FIXNUM_P(vmin));
6339
6340 VALUE a;
6341 for (; i < n; ++i) {
6342 a = RARRAY_AREF(ary, i);
6343
6344 if (FIXNUM_P(a)) {
6345 if ((long)vmin > (long)a) {
6346 vmin = a;
6347 }
6348 }
6349 else {
6350 return ary_min_generic(ary, i, vmin);
6351 }
6352 }
6353
6354 return vmin;
6355}
6356
6357static VALUE
6358ary_min_opt_float(VALUE ary, long i, VALUE vmin)
6359{
6360 const long n = RARRAY_LEN(ary);
6361 RUBY_ASSERT(i > 0 && i < n);
6363
6364 VALUE a;
6365 for (; i < n; ++i) {
6366 a = RARRAY_AREF(ary, i);
6367
6368 if (RB_FLOAT_TYPE_P(a)) {
6369 if (rb_float_cmp(vmin, a) > 0) {
6370 vmin = a;
6371 }
6372 }
6373 else {
6374 return ary_min_generic(ary, i, vmin);
6375 }
6376 }
6377
6378 return vmin;
6379}
6380
6381static VALUE
6382ary_min_opt_string(VALUE ary, long i, VALUE vmin)
6383{
6384 const long n = RARRAY_LEN(ary);
6385 RUBY_ASSERT(i > 0 && i < n);
6386 RUBY_ASSERT(STRING_P(vmin));
6387
6388 VALUE a;
6389 for (; i < n; ++i) {
6390 a = RARRAY_AREF(ary, i);
6391
6392 if (STRING_P(a)) {
6393 if (rb_str_cmp(vmin, a) > 0) {
6394 vmin = a;
6395 }
6396 }
6397 else {
6398 return ary_min_generic(ary, i, vmin);
6399 }
6400 }
6401
6402 return vmin;
6403}
6404
6405/*
6406 * call-seq:
6407 * min -> element
6408 * min(count) -> new_array
6409 * min {|a, b| ... } -> element
6410 * min(count) {|a, b| ... } -> new_array
6411 *
6412 * Returns one of the following:
6413 *
6414 * - The minimum-valued element from +self+.
6415 * - A new array of minimum-valued elements from +self+.
6416 *
6417 * Does not modify +self+.
6418 *
6419 * With no block given, each element in +self+ must respond to method <tt>#<=></tt>
6420 * with a numeric.
6421 *
6422 * With no argument and no block, returns the element in +self+
6423 * having the minimum value per method <tt>#<=></tt>:
6424 *
6425 * [1, 0, 3, 2].min # => 0
6426 *
6427 * With non-negative numeric argument +count+ and no block,
6428 * returns a new array with at most +count+ elements,
6429 * in ascending order, per method <tt>#<=></tt>:
6430 *
6431 * [1, 0, 3, 2].min(3) # => [0, 1, 2]
6432 * [1, 0, 3, 2].min(3.0) # => [0, 1, 2]
6433 * [1, 0, 3, 2].min(9) # => [0, 1, 2, 3]
6434 * [1, 0, 3, 2].min(0) # => []
6435 *
6436 * With a block given, the block must return a numeric.
6437 *
6438 * With a block and no argument, calls the block <tt>self.size - 1</tt> times to compare elements;
6439 * returns the element having the minimum value per the block:
6440 *
6441 * ['0', '', '000', '00'].min {|a, b| a.size <=> b.size }
6442 * # => ""
6443 *
6444 * With non-negative numeric argument +count+ and a block,
6445 * returns a new array with at most +count+ elements,
6446 * in ascending order, per the block:
6447 *
6448 * ['0', '', '000', '00'].min(2) {|a, b| a.size <=> b.size }
6449 * # => ["", "0"]
6450 *
6451 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
6452 */
6453static VALUE
6454rb_ary_min(int argc, VALUE *argv, VALUE ary)
6455{
6456 VALUE result = Qundef, v;
6457 VALUE num;
6458 long i;
6459
6460 if (rb_check_arity(argc, 0, 1) && !NIL_P(num = argv[0]))
6461 return rb_nmin_run(ary, num, 0, 0, 1);
6462
6463 const long n = RARRAY_LEN(ary);
6464 if (rb_block_given_p()) {
6465 for (i = 0; i < RARRAY_LEN(ary); i++) {
6466 v = RARRAY_AREF(ary, i);
6467 if (UNDEF_P(result) || rb_cmpint(rb_yield_values(2, v, result), v, result) < 0) {
6468 result = v;
6469 }
6470 }
6471 }
6472 else if (n > 0) {
6473 result = RARRAY_AREF(ary, 0);
6474 if (n > 1) {
6475 if (FIXNUM_P(result) && CMP_OPTIMIZABLE(INTEGER)) {
6476 return ary_min_opt_fixnum(ary, 1, result);
6477 }
6478 else if (STRING_P(result) && CMP_OPTIMIZABLE(STRING)) {
6479 return ary_min_opt_string(ary, 1, result);
6480 }
6481 else if (RB_FLOAT_TYPE_P(result) && CMP_OPTIMIZABLE(FLOAT)) {
6482 return ary_min_opt_float(ary, 1, result);
6483 }
6484 else {
6485 return ary_min_generic(ary, 1, result);
6486 }
6487 }
6488 }
6489 if (UNDEF_P(result)) return Qnil;
6490 return result;
6491}
6492
6493/*
6494 * call-seq:
6495 * minmax -> array
6496 * minmax {|a, b| ... } -> array
6497 *
6498 * Returns a 2-element array containing the minimum-valued and maximum-valued
6499 * elements from +self+;
6500 * does not modify +self+.
6501 *
6502 * With no block given, the minimum and maximum values are determined using method <tt>#<=></tt>:
6503 *
6504 * [1, 0, 3, 2].minmax # => [0, 3]
6505 *
6506 * With a block given, the block must return a numeric;
6507 * the block is called <tt>self.size - 1</tt> times to compare elements;
6508 * returns the elements having the minimum and maximum values per the block:
6509 *
6510 * ['0', '', '000', '00'].minmax {|a, b| a.size <=> b.size }
6511 * # => ["", "000"]
6512 *
6513 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
6514 */
6515static VALUE
6516rb_ary_minmax(VALUE ary)
6517{
6518 if (rb_block_given_p()) {
6519 return rb_call_super(0, NULL);
6520 }
6521 return rb_assoc_new(rb_ary_min(0, 0, ary), rb_ary_max(0, 0, ary));
6522}
6523
6524static int
6525push_value(st_data_t key, st_data_t val, st_data_t ary)
6526{
6527 rb_ary_push((VALUE)ary, (VALUE)val);
6528 return ST_CONTINUE;
6529}
6530
6531/*
6532 * call-seq:
6533 * uniq! -> self or nil
6534 * uniq! {|element| ... } -> self or nil
6535 *
6536 * Removes duplicate elements from +self+, the first occurrence always being retained;
6537 * returns +self+ if any elements removed, +nil+ otherwise.
6538 *
6539 * With no block given, identifies and removes elements using method <tt>eql?</tt>
6540 * and <tt>hash</tt> to compare elements:
6541 *
6542 * a = [0, 0, 1, 1, 2, 2]
6543 * a.uniq! # => [0, 1, 2]
6544 * a.uniq! # => nil
6545 *
6546 * With a block given, calls the block for each element;
6547 * identifies and omits "duplicate" elements using method <tt>eql?</tt>
6548 * and <tt>hash</tt> to compare <i>block return values</i>;
6549 * that is, an element is a duplicate if its block return value
6550 * is the same as that of a previous element:
6551 *
6552 * a = ['a', 'aa', 'aaa', 'b', 'bb', 'bbb']
6553 * a.uniq! {|element| element.size } # => ["a", "aa", "aaa"]
6554 * a.uniq! {|element| element.size } # => nil
6555 *
6556 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
6557 */
6558static VALUE
6559rb_ary_uniq_bang(VALUE ary)
6560{
6561 VALUE hash;
6562 long hash_size;
6563
6564 rb_ary_modify_check(ary);
6565 if (RARRAY_LEN(ary) <= 1)
6566 return Qnil;
6567 if (rb_block_given_p())
6568 hash = ary_make_hash_by(ary);
6569 else
6570 hash = ary_make_hash(ary);
6571
6572 hash_size = RHASH_SIZE(hash);
6573 if (RARRAY_LEN(ary) == hash_size) {
6574 return Qnil;
6575 }
6576 rb_ary_modify_check(ary);
6577 ARY_SET_LEN(ary, 0);
6578 if (ARY_SHARED_P(ary)) {
6579 rb_ary_unshare(ary);
6580 FL_SET_EMBED(ary);
6581 }
6582 ary_resize_capa(ary, hash_size);
6583 rb_hash_foreach(hash, push_value, ary);
6584
6585 return ary;
6586}
6587
6588/*
6589 * call-seq:
6590 * uniq -> new_array
6591 * uniq {|element| ... } -> new_array
6592 *
6593 * Returns a new array containing those elements from +self+ that are not duplicates,
6594 * the first occurrence always being retained.
6595 *
6596 * With no block given, identifies and omits duplicate elements using method <tt>eql?</tt>
6597 * and <tt>hash</tt> to compare elements:
6598 *
6599 * a = [0, 0, 1, 1, 2, 2]
6600 * a.uniq # => [0, 1, 2]
6601 *
6602 * With a block given, calls the block for each element;
6603 * identifies and omits "duplicate" elements using method <tt>eql?</tt>
6604 * and <tt>hash</tt> to compare <i>block return values</i>;
6605 * that is, an element is a duplicate if its block return value
6606 * is the same as that of a previous element:
6607 *
6608 * a = ['a', 'aa', 'aaa', 'b', 'bb', 'bbb']
6609 * a.uniq {|element| element.size } # => ["a", "aa", "aaa"]
6610 *
6611 * Related: {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
6612 */
6613
6614static VALUE
6615rb_ary_uniq(VALUE ary)
6616{
6617 VALUE hash, uniq;
6618
6619 if (RARRAY_LEN(ary) <= 1) {
6620 hash = 0;
6621 uniq = rb_ary_dup(ary);
6622 }
6623 else if (rb_block_given_p()) {
6624 hash = ary_make_hash_by(ary);
6625 uniq = rb_hash_values(hash);
6626 }
6627 else {
6628 hash = ary_make_hash(ary);
6629 uniq = rb_hash_values(hash);
6630 }
6631
6632 return uniq;
6633}
6634
6635/*
6636 * call-seq:
6637 * compact! -> self or nil
6638 *
6639 * Removes all +nil+ elements from +self+;
6640 * Returns +self+ if any elements are removed, +nil+ otherwise:
6641 *
6642 * a = [nil, 0, nil, false, nil, '', nil, [], nil, {}]
6643 * a.compact! # => [0, false, "", [], {}]
6644 * a # => [0, false, "", [], {}]
6645 * a.compact! # => nil
6646 *
6647 * Related: Array#compact;
6648 * see also {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
6649 */
6650
6651VALUE
6652rb_ary_compact_bang(VALUE ary)
6653{
6654 VALUE *p, *t, *end;
6655 long n;
6656
6657 rb_ary_modify(ary);
6658 p = t = (VALUE *)RARRAY_CONST_PTR(ary); /* WB: no new reference */
6659 end = p + RARRAY_LEN(ary);
6660
6661 while (t < end) {
6662 if (NIL_P(*t)) t++;
6663 else *p++ = *t++;
6664 }
6665 n = p - RARRAY_CONST_PTR(ary);
6666 if (RARRAY_LEN(ary) == n) {
6667 return Qnil;
6668 }
6669 ary_resize_smaller(ary, n);
6670
6671 return ary;
6672}
6673
6674/*
6675 * call-seq:
6676 * compact -> new_array
6677 *
6678 * Returns a new array containing only the non-+nil+ elements from +self+;
6679 * element order is preserved:
6680 *
6681 * a = [nil, 0, nil, false, nil, '', nil, [], nil, {}]
6682 * a.compact # => [0, false, "", [], {}]
6683 *
6684 * Related: Array#compact!;
6685 * see also {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
6686 */
6687
6688static VALUE
6689rb_ary_compact(VALUE ary)
6690{
6691 ary = rb_ary_dup(ary);
6692 rb_ary_compact_bang(ary);
6693 return ary;
6694}
6695
6696/*
6697 * call-seq:
6698 * count -> integer
6699 * count(object) -> integer
6700 * count {|element| ... } -> integer
6701 *
6702 * Returns a count of specified elements.
6703 *
6704 * With no argument and no block, returns the count of all elements:
6705 *
6706 * [0, :one, 'two', 3, 3.0].count # => 5
6707 *
6708 * With argument +object+ given, returns the count of elements <tt>==</tt> to +object+:
6709 *
6710 * [0, :one, 'two', 3, 3.0].count(3) # => 2
6711 *
6712 * With no argument and a block given, calls the block with each element;
6713 * returns the count of elements for which the block returns a truthy value:
6714 *
6715 * [0, 1, 2, 3].count {|element| element > 1 } # => 2
6716 *
6717 * With argument +object+ and a block given, issues a warning, ignores the block,
6718 * and returns the count of elements <tt>==</tt> to +object+.
6719 *
6720 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
6721 */
6722
6723static VALUE
6724rb_ary_count(int argc, VALUE *argv, VALUE ary)
6725{
6726 long i, n = 0;
6727
6728 if (rb_check_arity(argc, 0, 1) == 0) {
6729 VALUE v;
6730
6731 if (!rb_block_given_p())
6732 return LONG2NUM(RARRAY_LEN(ary));
6733
6734 for (i = 0; i < RARRAY_LEN(ary); i++) {
6735 v = RARRAY_AREF(ary, i);
6736 if (RTEST(rb_yield(v))) n++;
6737 }
6738 }
6739 else {
6740 VALUE obj = argv[0];
6741
6742 if (rb_block_given_p()) {
6743 rb_warn("given block not used");
6744 }
6745 for (i = 0; i < RARRAY_LEN(ary); i++) {
6746 if (rb_equal(RARRAY_AREF(ary, i), obj)) n++;
6747 }
6748 }
6749
6750 return LONG2NUM(n);
6751}
6752
6753static VALUE
6754flatten(VALUE ary, int level)
6755{
6756 long i;
6757 VALUE stack, result, tmp = 0, elt;
6758 VALUE memo = Qfalse;
6759
6760 for (i = 0; i < RARRAY_LEN(ary); i++) {
6761 elt = RARRAY_AREF(ary, i);
6762 tmp = rb_check_array_type(elt);
6763 if (!NIL_P(tmp)) {
6764 break;
6765 }
6766 }
6767 if (i == RARRAY_LEN(ary)) {
6768 return ary;
6769 }
6770
6771 result = ary_new(0, RARRAY_LEN(ary));
6772 ary_memcpy(result, 0, i, RARRAY_CONST_PTR(ary));
6773 ARY_SET_LEN(result, i);
6774
6775 stack = ary_new(0, ARY_DEFAULT_SIZE);
6776 rb_ary_push(stack, ary);
6777 rb_ary_push(stack, LONG2NUM(i + 1));
6778
6779 if (level < 0) {
6780 memo = rb_obj_hide(rb_ident_hash_new());
6781 rb_hash_aset(memo, ary, Qtrue);
6782 rb_hash_aset(memo, tmp, Qtrue);
6783 }
6784
6785 ary = tmp;
6786 i = 0;
6787
6788 while (1) {
6789 while (i < RARRAY_LEN(ary)) {
6790 elt = RARRAY_AREF(ary, i++);
6791 if (level >= 0 && RARRAY_LEN(stack) / 2 >= level) {
6792 rb_ary_push(result, elt);
6793 continue;
6794 }
6795 tmp = rb_check_array_type(elt);
6796 if (RBASIC(result)->klass) {
6797 if (RTEST(memo)) {
6798 rb_hash_clear(memo);
6799 }
6800 rb_raise(rb_eRuntimeError, "flatten reentered");
6801 }
6802 if (NIL_P(tmp)) {
6803 rb_ary_push(result, elt);
6804 }
6805 else {
6806 if (memo) {
6807 if (rb_hash_aref(memo, tmp) == Qtrue) {
6808 rb_hash_clear(memo);
6809 rb_raise(rb_eArgError, "tried to flatten recursive array");
6810 }
6811 rb_hash_aset(memo, tmp, Qtrue);
6812 }
6813 rb_ary_push(stack, ary);
6814 rb_ary_push(stack, LONG2NUM(i));
6815 ary = tmp;
6816 i = 0;
6817 }
6818 }
6819 if (RARRAY_LEN(stack) == 0) {
6820 break;
6821 }
6822 if (memo) {
6823 rb_hash_delete(memo, ary);
6824 }
6825 tmp = rb_ary_pop(stack);
6826 i = NUM2LONG(tmp);
6827 ary = rb_ary_pop(stack);
6828 }
6829
6830 if (memo) {
6831 rb_hash_clear(memo);
6832 }
6833
6834 RBASIC_SET_CLASS(result, rb_cArray);
6835 return result;
6836}
6837
6838/*
6839 * call-seq:
6840 * flatten!(depth = nil) -> self or nil
6841 *
6842 * Returns +self+ as a recursively flattening of +self+ to +depth+ levels of recursion;
6843 * +depth+ must be an
6844 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects],
6845 * or +nil+.
6846 * At each level of recursion:
6847 *
6848 * - Each element that is an array is "flattened"
6849 * (that is, replaced by its individual array elements).
6850 * - Each element that is not an array is unchanged
6851 * (even if the element is an object that has instance method +flatten+).
6852 *
6853 * Returns +nil+ if no elements were flattened.
6854 *
6855 * With non-negative integer argument +depth+, flattens recursively through +depth+ levels:
6856 *
6857 * a = [ 0, [ 1, [2, 3], 4 ], 5, {foo: 0}, Set.new([6, 7]) ]
6858 * a # => [0, [1, [2, 3], 4], 5, {foo: 0}, #<Set: {6, 7}>]
6859 * a.dup.flatten!(1) # => [0, 1, [2, 3], 4, 5, {foo: 0}, #<Set: {6, 7}>]
6860 * a.dup.flatten!(1.1) # => [0, 1, [2, 3], 4, 5, {foo: 0}, #<Set: {6, 7}>]
6861 * a.dup.flatten!(2) # => [0, 1, 2, 3, 4, 5, {foo: 0}, #<Set: {6, 7}>]
6862 * a.dup.flatten!(3) # => [0, 1, 2, 3, 4, 5, {foo: 0}, #<Set: {6, 7}>]
6863 *
6864 * With +nil+ or negative argument +depth+, flattens all levels:
6865 *
6866 * a.dup.flatten! # => [0, 1, 2, 3, 4, 5, {foo: 0}, #<Set: {6, 7}>]
6867 * a.dup.flatten!(-1) # => [0, 1, 2, 3, 4, 5, {foo: 0}, #<Set: {6, 7}>]
6868 *
6869 * Related: Array#flatten;
6870 * see also {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
6871 */
6872
6873static VALUE
6874rb_ary_flatten_bang(int argc, VALUE *argv, VALUE ary)
6875{
6876 int mod = 0, level = -1;
6877 VALUE result, lv;
6878
6879 lv = (rb_check_arity(argc, 0, 1) ? argv[0] : Qnil);
6880 rb_ary_modify_check(ary);
6881 if (!NIL_P(lv)) level = NUM2INT(lv);
6882 if (level == 0) return Qnil;
6883
6884 result = flatten(ary, level);
6885 if (result == ary) {
6886 return Qnil;
6887 }
6888 if (!(mod = ARY_EMBED_P(result))) rb_ary_freeze(result);
6889 rb_ary_replace(ary, result);
6890 if (mod) ARY_SET_EMBED_LEN(result, 0);
6891
6892 return ary;
6893}
6894
6895/*
6896 * call-seq:
6897 * flatten(depth = nil) -> new_array
6898 *
6899 * Returns a new array that is a recursive flattening of +self+
6900 * to +depth+ levels of recursion;
6901 * +depth+ must be an
6902 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]
6903 * or +nil+.
6904 * At each level of recursion:
6905 *
6906 * - Each element that is an array is "flattened"
6907 * (that is, replaced by its individual array elements).
6908 * - Each element that is not an array is unchanged
6909 * (even if the element is an object that has instance method +flatten+).
6910 *
6911 * With non-negative integer argument +depth+, flattens recursively through +depth+ levels:
6912 *
6913 * a = [ 0, [ 1, [2, 3], 4 ], 5, {foo: 0}, Set.new([6, 7]) ]
6914 * a # => [0, [1, [2, 3], 4], 5, {foo: 0}, #<Set: {6, 7}>]
6915 * a.flatten(0) # => [0, [1, [2, 3], 4], 5, {foo: 0}, #<Set: {6, 7}>]
6916 * a.flatten(1 ) # => [0, 1, [2, 3], 4, 5, {foo: 0}, #<Set: {6, 7}>]
6917 * a.flatten(1.1) # => [0, 1, [2, 3], 4, 5, {foo: 0}, #<Set: {6, 7}>]
6918 * a.flatten(2) # => [0, 1, 2, 3, 4, 5, {foo: 0}, #<Set: {6, 7}>]
6919 * a.flatten(3) # => [0, 1, 2, 3, 4, 5, {foo: 0}, #<Set: {6, 7}>]
6920 *
6921 * With +nil+ or negative +depth+, flattens all levels.
6922 *
6923 * a.flatten # => [0, 1, 2, 3, 4, 5, {foo: 0}, #<Set: {6, 7}>]
6924 * a.flatten(-1) # => [0, 1, 2, 3, 4, 5, {foo: 0}, #<Set: {6, 7}>]
6925 *
6926 * Related: Array#flatten!;
6927 * see also {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
6928 */
6929
6930static VALUE
6931rb_ary_flatten(int argc, VALUE *argv, VALUE ary)
6932{
6933 int level = -1;
6934 VALUE result;
6935
6936 if (rb_check_arity(argc, 0, 1) && !NIL_P(argv[0])) {
6937 level = NUM2INT(argv[0]);
6938 if (level == 0) return ary_make_shared_copy(ary);
6939 }
6940
6941 result = flatten(ary, level);
6942 if (result == ary) {
6943 result = ary_make_shared_copy(ary);
6944 }
6945
6946 return result;
6947}
6948
6949#define RAND_UPTO(max) (long)rb_random_ulong_limited((randgen), (max)-1)
6950
6951static VALUE
6952rb_ary_shuffle_bang(rb_execution_context_t *ec, VALUE ary, VALUE randgen)
6953{
6954 long i, len;
6955
6956 rb_ary_modify(ary);
6957 i = len = RARRAY_LEN(ary);
6958 RARRAY_PTR_USE(ary, ptr, {
6959 while (i > 1) {
6960 long j = RAND_UPTO(i);
6961 VALUE tmp;
6962 if (len != RARRAY_LEN(ary) || ptr != RARRAY_CONST_PTR(ary)) {
6963 rb_raise(rb_eRuntimeError, "modified during shuffle");
6964 }
6965 tmp = ptr[--i];
6966 ptr[i] = ptr[j];
6967 ptr[j] = tmp;
6968 }
6969 }); /* WB: no new reference */
6970 return ary;
6971}
6972
6973static VALUE
6974rb_ary_shuffle(rb_execution_context_t *ec, VALUE ary, VALUE randgen)
6975{
6976 ary = rb_ary_dup(ary);
6977 rb_ary_shuffle_bang(ec, ary, randgen);
6978 return ary;
6979}
6980
6981static const rb_data_type_t ary_sample_memo_type = {
6982 .wrap_struct_name = "ary_sample_memo",
6983 .function = {
6984 .dfree = (RUBY_DATA_FUNC)st_free_table,
6985 },
6986 .flags = RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_THREAD_SAFE_FREE
6987};
6988
6989static VALUE
6990ary_sample(rb_execution_context_t *ec, VALUE ary, VALUE randgen, VALUE nv, VALUE to_array)
6991{
6992 VALUE result;
6993 long n, len, i, j, k, idx[10];
6994 long rnds[numberof(idx)];
6995 long memo_threshold;
6996
6997 len = RARRAY_LEN(ary);
6998 if (!to_array) {
6999 if (len < 2)
7000 i = 0;
7001 else
7002 i = RAND_UPTO(len);
7003
7004 return rb_ary_elt(ary, i);
7005 }
7006 n = NUM2LONG(nv);
7007 if (n < 0) rb_raise(rb_eArgError, "negative sample number");
7008 if (n > len) n = len;
7009 if (n <= numberof(idx)) {
7010 for (i = 0; i < n; ++i) {
7011 rnds[i] = RAND_UPTO(len - i);
7012 }
7013 }
7014 k = len;
7015 len = RARRAY_LEN(ary);
7016 if (len < k && n <= numberof(idx)) {
7017 for (i = 0; i < n; ++i) {
7018 if (rnds[i] >= len) return rb_ary_new_capa(0);
7019 }
7020 }
7021 if (n > len) n = len;
7022 switch (n) {
7023 case 0:
7024 return rb_ary_new_capa(0);
7025 case 1:
7026 i = rnds[0];
7027 return rb_ary_new_from_args(1, RARRAY_AREF(ary, i));
7028 case 2:
7029 i = rnds[0];
7030 j = rnds[1];
7031 if (j >= i) j++;
7032 return rb_ary_new_from_args(2, RARRAY_AREF(ary, i), RARRAY_AREF(ary, j));
7033 case 3:
7034 i = rnds[0];
7035 j = rnds[1];
7036 k = rnds[2];
7037 {
7038 long l = j, g = i;
7039 if (j >= i) l = i, g = ++j;
7040 if (k >= l && (++k >= g)) ++k;
7041 }
7042 return rb_ary_new_from_args(3, RARRAY_AREF(ary, i), RARRAY_AREF(ary, j), RARRAY_AREF(ary, k));
7043 }
7044 memo_threshold =
7045 len < 2560 ? len / 128 :
7046 len < 5120 ? len / 64 :
7047 len < 10240 ? len / 32 :
7048 len / 16;
7049 if (n <= numberof(idx)) {
7050 long sorted[numberof(idx)];
7051 sorted[0] = idx[0] = rnds[0];
7052 for (i=1; i<n; i++) {
7053 k = rnds[i];
7054 for (j = 0; j < i; ++j) {
7055 if (k < sorted[j]) break;
7056 ++k;
7057 }
7058 memmove(&sorted[j+1], &sorted[j], sizeof(sorted[0])*(i-j));
7059 sorted[j] = idx[i] = k;
7060 }
7061 result = rb_ary_new_capa(n);
7062 RARRAY_PTR_USE(result, ptr_result, {
7063 for (i=0; i<n; i++) {
7064 ptr_result[i] = RARRAY_AREF(ary, idx[i]);
7065 }
7066 });
7067 }
7068 else if (n <= memo_threshold / 2) {
7069 long max_idx = 0;
7070 VALUE vmemo = TypedData_Wrap_Struct(0, &ary_sample_memo_type, 0);
7071 st_table *memo = st_init_numtable_with_size(n);
7072 RTYPEDDATA_DATA(vmemo) = memo;
7073 result = rb_ary_new_capa(n);
7074 RARRAY_PTR_USE(result, ptr_result, {
7075 for (i=0; i<n; i++) {
7076 long r = RAND_UPTO(len-i) + i;
7077 ptr_result[i] = r;
7078 if (r > max_idx) max_idx = r;
7079 }
7080 len = RARRAY_LEN(ary);
7081 if (len <= max_idx) n = 0;
7082 else if (n > len) n = len;
7083 RARRAY_PTR_USE(ary, ptr_ary, {
7084 for (i=0; i<n; i++) {
7085 long j2 = j = ptr_result[i];
7086 long i2 = i;
7087 st_data_t value;
7088 if (st_lookup(memo, (st_data_t)i, &value)) i2 = (long)value;
7089 if (st_lookup(memo, (st_data_t)j, &value)) j2 = (long)value;
7090 st_insert(memo, (st_data_t)j, (st_data_t)i2);
7091 ptr_result[i] = ptr_ary[j2];
7092 }
7093 });
7094 });
7095 RTYPEDDATA_DATA(vmemo) = 0;
7096 st_free_table(memo);
7097 RB_GC_GUARD(vmemo);
7098 }
7099 else {
7100 result = rb_ary_dup(ary);
7101 RBASIC_CLEAR_CLASS(result);
7102 RB_GC_GUARD(ary);
7103 RARRAY_PTR_USE(result, ptr_result, {
7104 for (i=0; i<n; i++) {
7105 j = RAND_UPTO(len-i) + i;
7106 nv = ptr_result[j];
7107 ptr_result[j] = ptr_result[i];
7108 ptr_result[i] = nv;
7109 }
7110 });
7111 RBASIC_SET_CLASS_RAW(result, rb_cArray);
7112 }
7113 ARY_SET_LEN(result, n);
7114
7115 return result;
7116}
7117
7118static VALUE
7119ary_sized_alloc(rb_execution_context_t *ec, VALUE self)
7120{
7121 return rb_ary_new2(RARRAY_LEN(self));
7122}
7123
7124static VALUE
7125ary_sample0(rb_execution_context_t *ec, VALUE ary)
7126{
7127 return ary_sample(ec, ary, rb_cRandom, Qfalse, Qfalse);
7128}
7129
7130static VALUE
7131rb_ary_cycle_size(VALUE self, VALUE args, VALUE eobj)
7132{
7133 long mul;
7134 VALUE n = Qnil;
7135 if (args && (RARRAY_LEN(args) > 0)) {
7136 n = RARRAY_AREF(args, 0);
7137 }
7138 if (RARRAY_LEN(self) == 0) return INT2FIX(0);
7139 if (NIL_P(n)) return DBL2NUM(HUGE_VAL);
7140 mul = NUM2LONG(n);
7141 if (mul <= 0) return INT2FIX(0);
7142 n = LONG2FIX(mul);
7143 return rb_fix_mul_fix(rb_ary_length(self), n);
7144}
7145
7146/*
7147 * call-seq:
7148 * cycle(count = nil) {|element| ... } -> nil
7149 * cycle(count = nil) -> new_enumerator
7150 *
7151 * With a block given, may call the block, depending on the value of argument +count+;
7152 * +count+ must be an
7153 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects],
7154 * or +nil+.
7155 *
7156 * When +count+ is positive,
7157 * calls the block with each element, then does so repeatedly,
7158 * until it has done so +count+ times; returns +nil+:
7159 *
7160 * output = []
7161 * [0, 1].cycle(2) {|element| output.push(element) } # => nil
7162 * output # => [0, 1, 0, 1]
7163 *
7164 * When +count+ is zero or negative, does not call the block:
7165 *
7166 * [0, 1].cycle(0) {|element| fail 'Cannot happen' } # => nil
7167 * [0, 1].cycle(-1) {|element| fail 'Cannot happen' } # => nil
7168 *
7169 * When +count+ is +nil+, cycles forever:
7170 *
7171 * # Prints 0 and 1 forever.
7172 * [0, 1].cycle {|element| puts element }
7173 * [0, 1].cycle(nil) {|element| puts element }
7174 *
7175 * With no block given, returns a new Enumerator.
7176 *
7177 * Related: see {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
7178 */
7179static VALUE
7180rb_ary_cycle(int argc, VALUE *argv, VALUE ary)
7181{
7182 long n, i;
7183
7184 rb_check_arity(argc, 0, 1);
7185
7186 RETURN_SIZED_ENUMERATOR(ary, argc, argv, rb_ary_cycle_size);
7187 if (argc == 0 || NIL_P(argv[0])) {
7188 n = -1;
7189 }
7190 else {
7191 n = NUM2LONG(argv[0]);
7192 if (n <= 0) return Qnil;
7193 }
7194
7195 while (RARRAY_LEN(ary) > 0 && (n < 0 || 0 < n--)) {
7196 for (i=0; i<RARRAY_LEN(ary); i++) {
7197 rb_yield(RARRAY_AREF(ary, i));
7198 }
7199 }
7200 return Qnil;
7201}
7202
7203/*
7204 * Build a ruby array of the corresponding values and yield it to the
7205 * associated block.
7206 * Return the class of +values+ for reentry check.
7207 */
7208static int
7209yield_indexed_values(const VALUE values, const long r, const long *const p)
7210{
7211 const VALUE result = rb_ary_new2(r);
7212 long i;
7213
7214 for (i = 0; i < r; i++) ARY_SET(result, i, RARRAY_AREF(values, p[i]));
7215 ARY_SET_LEN(result, r);
7216 rb_yield(result);
7217 return !RBASIC(values)->klass;
7218}
7219
7220/*
7221 * Compute permutations of +r+ elements of the set <code>[0..n-1]</code>.
7222 *
7223 * When we have a complete permutation of array indices, copy the values
7224 * at those indices into a new array and yield that array.
7225 *
7226 * n: the size of the set
7227 * r: the number of elements in each permutation
7228 * p: the array (of size r) that we're filling in
7229 * used: an array of booleans: whether a given index is already used
7230 * values: the Ruby array that holds the actual values to permute
7231 */
7232static void
7233permute0(const long n, const long r, long *const p, char *const used, const VALUE values)
7234{
7235 long i = 0, index = 0;
7236
7237 for (;;) {
7238 const char *const unused = memchr(&used[i], 0, n-i);
7239 if (!unused) {
7240 if (!index) break;
7241 i = p[--index]; /* pop index */
7242 used[i++] = 0; /* index unused */
7243 }
7244 else {
7245 i = unused - used;
7246 p[index] = i;
7247 used[i] = 1; /* mark index used */
7248 ++index;
7249 if (index < r-1) { /* if not done yet */
7250 p[index] = i = 0;
7251 continue;
7252 }
7253 for (i = 0; i < n; ++i) {
7254 if (used[i]) continue;
7255 p[index] = i;
7256 if (!yield_indexed_values(values, r, p)) {
7257 rb_raise(rb_eRuntimeError, "permute reentered");
7258 }
7259 }
7260 i = p[--index]; /* pop index */
7261 used[i] = 0; /* index unused */
7262 p[index] = ++i;
7263 }
7264 }
7265}
7266
7267/*
7268 * Returns the product of from, from-1, ..., from - how_many + 1.
7269 * https://en.wikipedia.org/wiki/Pochhammer_symbol
7270 */
7271static VALUE
7272descending_factorial(long from, long how_many)
7273{
7274 VALUE cnt;
7275 if (how_many > 0) {
7276 cnt = LONG2FIX(from);
7277 while (--how_many > 0) {
7278 long v = --from;
7279 cnt = rb_int_mul(cnt, LONG2FIX(v));
7280 }
7281 }
7282 else {
7283 cnt = LONG2FIX(how_many == 0);
7284 }
7285 return cnt;
7286}
7287
7288static VALUE
7289binomial_coefficient(long comb, long size)
7290{
7291 VALUE r;
7292 long i;
7293 if (comb > size-comb) {
7294 comb = size-comb;
7295 }
7296 if (comb < 0) {
7297 return LONG2FIX(0);
7298 }
7299 else if (comb == 0) {
7300 return LONG2FIX(1);
7301 }
7302 r = LONG2FIX(size);
7303 for (i = 1; i < comb; ++i) {
7304 r = rb_int_mul(r, LONG2FIX(size - i));
7305 r = rb_int_idiv(r, LONG2FIX(i + 1));
7306 }
7307 return r;
7308}
7309
7310static VALUE
7311rb_ary_permutation_size(VALUE ary, VALUE args, VALUE eobj)
7312{
7313 long n = RARRAY_LEN(ary);
7314 long k = (args && (RARRAY_LEN(args) > 0)) ? NUM2LONG(RARRAY_AREF(args, 0)) : n;
7315
7316 return descending_factorial(n, k);
7317}
7318
7319/*
7320 * call-seq:
7321 * permutation(count = self.size) {|permutation| ... } -> self
7322 * permutation(count = self.size) -> new_enumerator
7323 *
7324 * Iterates over permutations of the elements of +self+;
7325 * the order of permutations is indeterminate.
7326 *
7327 * With a block and an in-range positive integer argument +count+ (<tt>0 < count <= self.size</tt>) given,
7328 * calls the block with each permutation of +self+ of size +count+;
7329 * returns +self+:
7330 *
7331 * a = [0, 1, 2]
7332 * perms = []
7333 * a.permutation(1) {|perm| perms.push(perm) }
7334 * perms # => [[0], [1], [2]]
7335 *
7336 * perms = []
7337 * a.permutation(2) {|perm| perms.push(perm) }
7338 * perms # => [[0, 1], [0, 2], [1, 0], [1, 2], [2, 0], [2, 1]]
7339 *
7340 * perms = []
7341 * a.permutation(3) {|perm| perms.push(perm) }
7342 * perms # => [[0, 1, 2], [0, 2, 1], [1, 0, 2], [1, 2, 0], [2, 0, 1], [2, 1, 0]]
7343 *
7344 * When +count+ is zero, calls the block once with a new empty array:
7345 *
7346 * perms = []
7347 * a.permutation(0) {|perm| perms.push(perm) }
7348 * perms # => [[]]
7349 *
7350 * When +count+ is out of range (negative or larger than <tt>self.size</tt>),
7351 * does not call the block:
7352 *
7353 * a.permutation(-1) {|permutation| fail 'Cannot happen' }
7354 * a.permutation(4) {|permutation| fail 'Cannot happen' }
7355 *
7356 * With no block given, returns a new Enumerator.
7357 *
7358 * Related: {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
7359 */
7360
7361static VALUE
7362rb_ary_permutation(int argc, VALUE *argv, VALUE ary)
7363{
7364 long r, n, i;
7365
7366 n = RARRAY_LEN(ary); /* Array length */
7367 RETURN_SIZED_ENUMERATOR(ary, argc, argv, rb_ary_permutation_size); /* Return enumerator if no block */
7368 r = n;
7369 if (rb_check_arity(argc, 0, 1) && !NIL_P(argv[0]))
7370 r = NUM2LONG(argv[0]); /* Permutation size from argument */
7371
7372 if (r < 0 || n < r) {
7373 /* no permutations: yield nothing */
7374 }
7375 else if (r == 0) { /* exactly one permutation: the zero-length array */
7377 }
7378 else if (r == 1) { /* this is a special, easy case */
7379 for (i = 0; i < RARRAY_LEN(ary); i++) {
7380 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
7381 }
7382 }
7383 else { /* this is the general case */
7384 volatile VALUE t0;
7385 long *p = ALLOCV_N(long, t0, r+roomof(n, sizeof(long)));
7386 char *used = (char*)(p + r);
7387 VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
7388 RBASIC_CLEAR_CLASS(ary0);
7389
7390 MEMZERO(used, char, n); /* initialize array */
7391
7392 permute0(n, r, p, used, ary0); /* compute and yield permutations */
7393 ALLOCV_END(t0);
7394 RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
7395 }
7396 return ary;
7397}
7398
7399static void
7400combinate0(const long len, const long n, long *const stack, const VALUE values)
7401{
7402 long lev = 0;
7403
7404 MEMZERO(stack+1, long, n);
7405 stack[0] = -1;
7406 for (;;) {
7407 for (lev++; lev < n; lev++) {
7408 stack[lev+1] = stack[lev]+1;
7409 }
7410 if (!yield_indexed_values(values, n, stack+1)) {
7411 rb_raise(rb_eRuntimeError, "combination reentered");
7412 }
7413 do {
7414 if (lev == 0) return;
7415 stack[lev--]++;
7416 } while (stack[lev+1]+n == len+lev+1);
7417 }
7418}
7419
7420static VALUE
7421rb_ary_combination_size(VALUE ary, VALUE args, VALUE eobj)
7422{
7423 long n = RARRAY_LEN(ary);
7424 long k = NUM2LONG(RARRAY_AREF(args, 0));
7425
7426 return binomial_coefficient(k, n);
7427}
7428
7429/*
7430 * call-seq:
7431 * combination(count) {|element| ... } -> self
7432 * combination(count) -> new_enumerator
7433 *
7434 * When a block and a positive
7435 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]
7436 * argument +count+ (<tt>0 < count <= self.size</tt>)
7437 * are given, calls the block with each combination of +self+ of size +count+;
7438 * returns +self+:
7439 *
7440 * a = %w[a b c] # => ["a", "b", "c"]
7441 * a.combination(2) {|combination| p combination } # => ["a", "b", "c"]
7442 *
7443 * Output:
7444 *
7445 * ["a", "b"]
7446 * ["a", "c"]
7447 * ["b", "c"]
7448 *
7449 * The order of the yielded combinations is not guaranteed.
7450 *
7451 * When +count+ is zero, calls the block once with a new empty array:
7452 *
7453 * a.combination(0) {|combination| p combination }
7454 * [].combination(0) {|combination| p combination }
7455 *
7456 * Output:
7457 *
7458 * []
7459 * []
7460 *
7461 * When +count+ is negative or larger than +self.size+ and +self+ is non-empty,
7462 * does not call the block:
7463 *
7464 * a.combination(-1) {|combination| fail 'Cannot happen' } # => ["a", "b", "c"]
7465 * a.combination(4) {|combination| fail 'Cannot happen' } # => ["a", "b", "c"]
7466 *
7467 * With no block given, returns a new Enumerator.
7468 *
7469 * Related: Array#permutation;
7470 * see also {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
7471 */
7472
7473static VALUE
7474rb_ary_combination(VALUE ary, VALUE num)
7475{
7476 long i, n, len;
7477
7478 n = NUM2LONG(num);
7479 RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_combination_size);
7480 len = RARRAY_LEN(ary);
7481 if (n < 0 || len < n) {
7482 /* yield nothing */
7483 }
7484 else if (n == 0) {
7486 }
7487 else if (n == 1) {
7488 for (i = 0; i < RARRAY_LEN(ary); i++) {
7489 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
7490 }
7491 }
7492 else {
7493 VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
7494 volatile VALUE t0;
7495 long *stack = ALLOCV_N(long, t0, n+1);
7496
7497 RBASIC_CLEAR_CLASS(ary0);
7498 combinate0(len, n, stack, ary0);
7499 ALLOCV_END(t0);
7500 RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
7501 }
7502 return ary;
7503}
7504
7505/*
7506 * Compute repeated permutations of +r+ elements of the set
7507 * <code>[0..n-1]</code>.
7508 *
7509 * When we have a complete repeated permutation of array indices, copy the
7510 * values at those indices into a new array and yield that array.
7511 *
7512 * n: the size of the set
7513 * r: the number of elements in each permutation
7514 * p: the array (of size r) that we're filling in
7515 * values: the Ruby array that holds the actual values to permute
7516 */
7517static void
7518rpermute0(const long n, const long r, long *const p, const VALUE values)
7519{
7520 long i = 0, index = 0;
7521
7522 p[index] = i;
7523 for (;;) {
7524 if (++index < r-1) {
7525 p[index] = i = 0;
7526 continue;
7527 }
7528 for (i = 0; i < n; ++i) {
7529 p[index] = i;
7530 if (!yield_indexed_values(values, r, p)) {
7531 rb_raise(rb_eRuntimeError, "repeated permute reentered");
7532 }
7533 }
7534 do {
7535 if (index <= 0) return;
7536 } while ((i = ++p[--index]) >= n);
7537 }
7538}
7539
7540static VALUE
7541rb_ary_repeated_permutation_size(VALUE ary, VALUE args, VALUE eobj)
7542{
7543 long n = RARRAY_LEN(ary);
7544 long k = NUM2LONG(RARRAY_AREF(args, 0));
7545
7546 if (k < 0) {
7547 return LONG2FIX(0);
7548 }
7549 if (n <= 0) {
7550 return LONG2FIX(!k);
7551 }
7552 return rb_int_positive_pow(n, (unsigned long)k);
7553}
7554
7555/*
7556 * call-seq:
7557 * repeated_permutation(size) {|permutation| ... } -> self
7558 * repeated_permutation(size) -> new_enumerator
7559 *
7560 * With a block given, calls the block with each repeated permutation of length +size+
7561 * of the elements of +self+;
7562 * each permutation is an array;
7563 * returns +self+. The order of the permutations is indeterminate.
7564 *
7565 * If a positive integer argument +size+ is given,
7566 * calls the block with each +size+-tuple repeated permutation of the elements of +self+.
7567 * The number of permutations is <tt>self.size**size</tt>.
7568 *
7569 * Examples:
7570 *
7571 * - +size+ is 1:
7572 *
7573 * p = []
7574 * [0, 1, 2].repeated_permutation(1) {|permutation| p.push(permutation) }
7575 * p # => [[0], [1], [2]]
7576 *
7577 * - +size+ is 2:
7578 *
7579 * p = []
7580 * [0, 1, 2].repeated_permutation(2) {|permutation| p.push(permutation) }
7581 * p # => [[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2], [2, 0], [2, 1], [2, 2]]
7582 *
7583 * If +size+ is zero, calls the block once with an empty array.
7584 *
7585 * If +size+ is negative, does not call the block:
7586 *
7587 * [0, 1, 2].repeated_permutation(-1) {|permutation| fail 'Cannot happen' }
7588 *
7589 * With no block given, returns a new Enumerator.
7590 *
7591 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
7592 */
7593static VALUE
7594rb_ary_repeated_permutation(VALUE ary, VALUE num)
7595{
7596 long r, n, i;
7597
7598 n = RARRAY_LEN(ary); /* Array length */
7599 RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_repeated_permutation_size); /* Return Enumerator if no block */
7600 r = NUM2LONG(num); /* Permutation size from argument */
7601
7602 if (r < 0) {
7603 /* no permutations: yield nothing */
7604 }
7605 else if (r == 0) { /* exactly one permutation: the zero-length array */
7607 }
7608 else if (r == 1) { /* this is a special, easy case */
7609 for (i = 0; i < RARRAY_LEN(ary); i++) {
7610 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
7611 }
7612 }
7613 else { /* this is the general case */
7614 volatile VALUE t0;
7615 long *p = ALLOCV_N(long, t0, r);
7616 VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
7617 RBASIC_CLEAR_CLASS(ary0);
7618
7619 rpermute0(n, r, p, ary0); /* compute and yield repeated permutations */
7620 ALLOCV_END(t0);
7621 RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
7622 }
7623 return ary;
7624}
7625
7626static void
7627rcombinate0(const long n, const long r, long *const p, const long rest, const VALUE values)
7628{
7629 long i = 0, index = 0;
7630
7631 p[index] = i;
7632 for (;;) {
7633 if (++index < r-1) {
7634 p[index] = i;
7635 continue;
7636 }
7637 for (; i < n; ++i) {
7638 p[index] = i;
7639 if (!yield_indexed_values(values, r, p)) {
7640 rb_raise(rb_eRuntimeError, "repeated combination reentered");
7641 }
7642 }
7643 do {
7644 if (index <= 0) return;
7645 } while ((i = ++p[--index]) >= n);
7646 }
7647}
7648
7649static VALUE
7650rb_ary_repeated_combination_size(VALUE ary, VALUE args, VALUE eobj)
7651{
7652 long n = RARRAY_LEN(ary);
7653 long k = NUM2LONG(RARRAY_AREF(args, 0));
7654 if (k == 0) {
7655 return LONG2FIX(1);
7656 }
7657 return binomial_coefficient(k, n + k - 1);
7658}
7659
7660/*
7661 * call-seq:
7662 * repeated_combination(size) {|combination| ... } -> self
7663 * repeated_combination(size) -> new_enumerator
7664 *
7665 * With a block given, calls the block with each repeated combination of length +size+
7666 * of the elements of +self+;
7667 * each combination is an array;
7668 * returns +self+. The order of the combinations is indeterminate.
7669 *
7670 * If a positive integer argument +size+ is given,
7671 * calls the block with each +size+-tuple repeated combination of the elements of +self+.
7672 * The number of combinations is <tt>(size+1)(size+2)/2</tt>.
7673 *
7674 * Examples:
7675 *
7676 * - +size+ is 1:
7677 *
7678 * c = []
7679 * [0, 1, 2].repeated_combination(1) {|combination| c.push(combination) }
7680 * c # => [[0], [1], [2]]
7681 *
7682 * - +size+ is 2:
7683 *
7684 * c = []
7685 * [0, 1, 2].repeated_combination(2) {|combination| c.push(combination) }
7686 * c # => [[0, 0], [0, 1], [0, 2], [1, 1], [1, 2], [2, 2]]
7687 *
7688 * If +size+ is zero, calls the block once with an empty array.
7689 *
7690 * If +size+ is negative, does not call the block:
7691 *
7692 * [0, 1, 2].repeated_combination(-1) {|combination| fail 'Cannot happen' }
7693 *
7694 * With no block given, returns a new Enumerator.
7695 *
7696 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
7697 */
7698
7699static VALUE
7700rb_ary_repeated_combination(VALUE ary, VALUE num)
7701{
7702 long n, i, len;
7703
7704 n = NUM2LONG(num); /* Combination size from argument */
7705 RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_repeated_combination_size); /* Return enumerator if no block */
7706 len = RARRAY_LEN(ary);
7707 if (n < 0) {
7708 /* yield nothing */
7709 }
7710 else if (n == 0) {
7712 }
7713 else if (n == 1) {
7714 for (i = 0; i < RARRAY_LEN(ary); i++) {
7715 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
7716 }
7717 }
7718 else if (len == 0) {
7719 /* yield nothing */
7720 }
7721 else {
7722 volatile VALUE t0;
7723 long *p = ALLOCV_N(long, t0, n);
7724 VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
7725 RBASIC_CLEAR_CLASS(ary0);
7726
7727 rcombinate0(len, n, p, n, ary0); /* compute and yield repeated combinations */
7728 ALLOCV_END(t0);
7729 RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
7730 }
7731 return ary;
7732}
7733
7734/*
7735 * call-seq:
7736 * product(*other_arrays) -> new_array
7737 * product(*other_arrays) {|combination| ... } -> self
7738 *
7739 * Computes all combinations of elements from all the arrays,
7740 * including both +self+ and +other_arrays+:
7741 *
7742 * - The number of combinations is the product of the sizes of all the arrays,
7743 * including both +self+ and +other_arrays+.
7744 * - The order of the returned combinations is indeterminate.
7745 *
7746 * With no block given, returns the combinations as an array of arrays:
7747 *
7748 * p = [0, 1].product([2, 3])
7749 * # => [[0, 2], [0, 3], [1, 2], [1, 3]]
7750 * p.size # => 4
7751 * p = [0, 1].product([2, 3], [4, 5])
7752 * # => [[0, 2, 4], [0, 2, 5], [0, 3, 4], [0, 3, 5], [1, 2, 4], [1, 2, 5], [1, 3, 4], [1, 3,...
7753 * p.size # => 8
7754 *
7755 * If +self+ or any argument is empty, returns an empty array:
7756 *
7757 * [].product([2, 3], [4, 5]) # => []
7758 * [0, 1].product([2, 3], []) # => []
7759 *
7760 * If no argument is given, returns an array of 1-element arrays,
7761 * each containing an element of +self+:
7762 *
7763 * [0, 1, 2].product # => [[0], [1], [2]]
7764 *
7765 * With a block given, calls the block with each combination; returns +self+:
7766 *
7767 * p = []
7768 * [0, 1].product([2, 3]) {|combination| p.push(combination) }
7769 * p # => [[0, 2], [0, 3], [1, 2], [1, 3]]
7770 *
7771 * If +self+ or any argument is empty, does not call the block:
7772 *
7773 * [].product([2, 3], [4, 5]) {|combination| fail 'Cannot happen' }
7774 * # => []
7775 * [0, 1].product([2, 3], []) {|combination| fail 'Cannot happen' }
7776 * # => [0, 1]
7777 *
7778 * If no argument is given, calls the block with each element of +self+ as a 1-element array:
7779 *
7780 * p = []
7781 * [0, 1].product {|combination| p.push(combination) }
7782 * p # => [[0], [1]]
7783 *
7784 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
7785 */
7786
7787static VALUE
7788rb_ary_product(int argc, VALUE *argv, VALUE ary)
7789{
7790 int n = argc+1; /* How many arrays we're operating on */
7791 volatile VALUE t0 = rb_ary_hidden_new(n);
7792 volatile VALUE t1 = Qundef;
7793 VALUE *arrays = RARRAY_PTR(t0); /* The arrays we're computing the product of */
7794 int *counters = ALLOCV_N(int, t1, n); /* The current position in each one */
7795 VALUE result = Qnil; /* The array we'll be returning, when no block given */
7796 long i,j;
7797 long resultlen = 1;
7798
7799 RBASIC_CLEAR_CLASS(t0);
7800
7801 /* initialize the arrays of arrays */
7802 ARY_SET_LEN(t0, n);
7803 arrays[0] = ary;
7804 for (i = 1; i < n; i++) arrays[i] = Qnil;
7805 for (i = 1; i < n; i++) arrays[i] = to_ary(argv[i-1]);
7806
7807 /* initialize the counters for the arrays */
7808 for (i = 0; i < n; i++) counters[i] = 0;
7809
7810 /* Otherwise, allocate and fill in an array of results */
7811 if (rb_block_given_p()) {
7812 /* Make defensive copies of arrays; exit if any is empty */
7813 for (i = 0; i < n; i++) {
7814 if (RARRAY_LEN(arrays[i]) == 0) goto done;
7815 arrays[i] = ary_make_shared_copy(arrays[i]);
7816 }
7817 }
7818 else {
7819 /* Compute the length of the result array; return [] if any is empty */
7820 for (i = 0; i < n; i++) {
7821 long k = RARRAY_LEN(arrays[i]);
7822 if (k == 0) {
7823 result = rb_ary_new2(0);
7824 goto done;
7825 }
7826 if (MUL_OVERFLOW_LONG_P(resultlen, k))
7827 rb_raise(rb_eRangeError, "too big to product");
7828 resultlen *= k;
7829 }
7830 result = rb_ary_new2(resultlen);
7831 }
7832 for (;;) {
7833 int m;
7834 /* fill in one subarray */
7835 VALUE subarray = rb_ary_new2(n);
7836 for (j = 0; j < n; j++) {
7837 rb_ary_push(subarray, rb_ary_entry(arrays[j], counters[j]));
7838 }
7839
7840 /* put it on the result array */
7841 if (NIL_P(result)) {
7842 FL_SET(t0, RARRAY_SHARED_ROOT_FLAG);
7843 rb_yield(subarray);
7844 if (!FL_TEST(t0, RARRAY_SHARED_ROOT_FLAG)) {
7845 rb_raise(rb_eRuntimeError, "product reentered");
7846 }
7847 else {
7848 FL_UNSET(t0, RARRAY_SHARED_ROOT_FLAG);
7849 }
7850 }
7851 else {
7852 rb_ary_push(result, subarray);
7853 }
7854
7855 /*
7856 * Increment the last counter. If it overflows, reset to 0
7857 * and increment the one before it.
7858 */
7859 m = n-1;
7860 counters[m]++;
7861 while (counters[m] == RARRAY_LEN(arrays[m])) {
7862 counters[m] = 0;
7863 /* If the first counter overflows, we are done */
7864 if (--m < 0) goto done;
7865 counters[m]++;
7866 }
7867 }
7868
7869done:
7870 ALLOCV_END(t1);
7871
7872 return NIL_P(result) ? ary : result;
7873}
7874
7875/*
7876 * call-seq:
7877 * take(count) -> new_array
7878 *
7879 * Returns a new array containing the first +count+ element of +self+
7880 * (as available);
7881 * +count+ must be a non-negative numeric;
7882 * does not modify +self+:
7883 *
7884 * a = ['a', 'b', 'c', 'd']
7885 * a.take(2) # => ["a", "b"]
7886 * a.take(2.1) # => ["a", "b"]
7887 * a.take(50) # => ["a", "b", "c", "d"]
7888 * a.take(0) # => []
7889 *
7890 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
7891 */
7892
7893static VALUE
7894rb_ary_take(VALUE obj, VALUE n)
7895{
7896 long len = NUM2LONG(n);
7897 if (len < 0) {
7898 rb_raise(rb_eArgError, "attempt to take negative size");
7899 }
7900 return rb_ary_subseq(obj, 0, len);
7901}
7902
7903/*
7904 * call-seq:
7905 * take_while {|element| ... } -> new_array
7906 * take_while -> new_enumerator
7907 *
7908 * With a block given, calls the block with each successive element of +self+;
7909 * stops iterating if the block returns +false+ or +nil+;
7910 * returns a new array containing those elements for which the block returned a truthy value:
7911 *
7912 * a = [0, 1, 2, 3, 4, 5]
7913 * a.take_while {|element| element < 3 } # => [0, 1, 2]
7914 * a.take_while {|element| true } # => [0, 1, 2, 3, 4, 5]
7915 * a.take_while {|element| false } # => []
7916 *
7917 * With no block given, returns a new Enumerator.
7918 *
7919 * Does not modify +self+.
7920 *
7921 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
7922 */
7923
7924static VALUE
7925rb_ary_take_while(VALUE ary)
7926{
7927 long i;
7928
7929 RETURN_ENUMERATOR(ary, 0, 0);
7930 for (i = 0; i < RARRAY_LEN(ary); i++) {
7931 if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) break;
7932 }
7933 return rb_ary_take(ary, LONG2FIX(i));
7934}
7935
7936/*
7937 * call-seq:
7938 * drop(count) -> new_array
7939 *
7940 * Returns a new array containing all but the first +count+ element of +self+,
7941 * where +count+ is a non-negative integer;
7942 * does not modify +self+.
7943 *
7944 * Examples:
7945 *
7946 * a = [0, 1, 2, 3, 4, 5]
7947 * a.drop(0) # => [0, 1, 2, 3, 4, 5]
7948 * a.drop(1) # => [1, 2, 3, 4, 5]
7949 * a.drop(2) # => [2, 3, 4, 5]
7950 * a.drop(9) # => []
7951 *
7952 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
7953 */
7954
7955static VALUE
7956rb_ary_drop(VALUE ary, VALUE n)
7957{
7958 VALUE result;
7959 long pos = NUM2LONG(n);
7960 if (pos < 0) {
7961 rb_raise(rb_eArgError, "attempt to drop negative size");
7962 }
7963
7964 result = rb_ary_subseq(ary, pos, RARRAY_LEN(ary));
7965 if (NIL_P(result)) result = rb_ary_new();
7966 return result;
7967}
7968
7969/*
7970 * call-seq:
7971 * drop_while {|element| ... } -> new_array
7972 * drop_while -> new_enumerator
7973 *
7974 * With a block given, calls the block with each successive element of +self+;
7975 * stops if the block returns +false+ or +nil+;
7976 * returns a new array _omitting_ those elements for which the block returned a truthy value;
7977 * does not modify +self+:
7978 *
7979 * a = [0, 1, 2, 3, 4, 5]
7980 * a.drop_while {|element| element < 3 } # => [3, 4, 5]
7981 *
7982 * With no block given, returns a new Enumerator.
7983 *
7984 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
7985 */
7986
7987static VALUE
7988rb_ary_drop_while(VALUE ary)
7989{
7990 long i;
7991
7992 RETURN_ENUMERATOR(ary, 0, 0);
7993 for (i = 0; i < RARRAY_LEN(ary); i++) {
7994 if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) break;
7995 }
7996 return rb_ary_drop(ary, LONG2FIX(i));
7997}
7998
7999/*
8000 * call-seq:
8001 * any? -> true or false
8002 * any?(object) -> true or false
8003 * any? {|element| ... } -> true or false
8004 *
8005 * Returns whether for any element of +self+, a given criterion is satisfied.
8006 *
8007 * With no block and no argument, returns whether any element of +self+ is truthy:
8008 *
8009 * [nil, false, []].any? # => true # Array object is truthy.
8010 * [nil, false, {}].any? # => true # Hash object is truthy.
8011 * [nil, false, ''].any? # => true # String object is truthy.
8012 * [nil, false].any? # => false # Nil and false are not truthy.
8013 *
8014 * With argument +object+ given,
8015 * returns whether <tt>object === ele</tt> for any element +ele+ in +self+:
8016 *
8017 * [nil, false, 0].any?(0) # => true
8018 * [nil, false, 1].any?(0) # => false
8019 * [nil, false, 'food'].any?(/foo/) # => true
8020 * [nil, false, 'food'].any?(/bar/) # => false
8021 *
8022 * With a block given,
8023 * calls the block with each element in +self+;
8024 * returns whether the block returns any truthy value:
8025 *
8026 * [0, 1, 2].any? {|ele| ele < 1 } # => true
8027 * [0, 1, 2].any? {|ele| ele < 0 } # => false
8028 *
8029 * With both a block and argument +object+ given,
8030 * ignores the block and uses +object+ as above.
8031 *
8032 * <b>Special case</b>: returns +false+ if +self+ is empty
8033 * (regardless of any given argument or block).
8034 *
8035 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
8036 */
8037
8038static VALUE
8039rb_ary_any_p(int argc, VALUE *argv, VALUE ary)
8040{
8041 long i, len = RARRAY_LEN(ary);
8042
8043 rb_check_arity(argc, 0, 1);
8044 if (!len) return Qfalse;
8045 if (argc) {
8046 if (rb_block_given_p()) {
8047 rb_warn("given block not used");
8048 }
8049 for (i = 0; i < RARRAY_LEN(ary); ++i) {
8050 if (RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) return Qtrue;
8051 }
8052 }
8053 else if (!rb_block_given_p()) {
8054 for (i = 0; i < len; ++i) {
8055 if (RTEST(RARRAY_AREF(ary, i))) return Qtrue;
8056 }
8057 }
8058 else {
8059 for (i = 0; i < RARRAY_LEN(ary); ++i) {
8060 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) return Qtrue;
8061 }
8062 }
8063 return Qfalse;
8064}
8065
8066/*
8067 * call-seq:
8068 * all? -> true or false
8069 * all?(object) -> true or false
8070 * all? {|element| ... } -> true or false
8071 *
8072 * Returns whether for every element of +self+,
8073 * a given criterion is satisfied.
8074 *
8075 * With no block and no argument,
8076 * returns whether every element of +self+ is truthy:
8077 *
8078 * [[], {}, '', 0, 0.0, Object.new].all? # => true # All truthy objects.
8079 * [[], {}, '', 0, 0.0, nil].all? # => false # nil is not truthy.
8080 * [[], {}, '', 0, 0.0, false].all? # => false # false is not truthy.
8081 *
8082 * With argument +object+ given, returns whether <tt>object === ele</tt>
8083 * for every element +ele+ in +self+:
8084 *
8085 * [0, 0, 0].all?(0) # => true
8086 * [0, 1, 2].all?(1) # => false
8087 * ['food', 'fool', 'foot'].all?(/foo/) # => true
8088 * ['food', 'drink'].all?(/foo/) # => false
8089 *
8090 * With a block given, calls the block with each element in +self+;
8091 * returns whether the block returns only truthy values:
8092 *
8093 * [0, 1, 2].all? { |ele| ele < 3 } # => true
8094 * [0, 1, 2].all? { |ele| ele < 2 } # => false
8095 *
8096 * With both a block and argument +object+ given,
8097 * ignores the block and uses +object+ as above.
8098 *
8099 * <b>Special case</b>: returns +true+ if +self+ is empty
8100 * (regardless of any given argument or block).
8101 *
8102 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
8103 */
8104
8105static VALUE
8106rb_ary_all_p(int argc, VALUE *argv, VALUE ary)
8107{
8108 long i, len = RARRAY_LEN(ary);
8109
8110 rb_check_arity(argc, 0, 1);
8111 if (!len) return Qtrue;
8112 if (argc) {
8113 if (rb_block_given_p()) {
8114 rb_warn("given block not used");
8115 }
8116 for (i = 0; i < RARRAY_LEN(ary); ++i) {
8117 if (!RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) return Qfalse;
8118 }
8119 }
8120 else if (!rb_block_given_p()) {
8121 for (i = 0; i < len; ++i) {
8122 if (!RTEST(RARRAY_AREF(ary, i))) return Qfalse;
8123 }
8124 }
8125 else {
8126 for (i = 0; i < RARRAY_LEN(ary); ++i) {
8127 if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) return Qfalse;
8128 }
8129 }
8130 return Qtrue;
8131}
8132
8133/*
8134 * call-seq:
8135 * none? -> true or false
8136 * none?(object) -> true or false
8137 * none? {|element| ... } -> true or false
8138 *
8139 * Returns +true+ if no element of +self+ meets a given criterion, +false+ otherwise.
8140 *
8141 * With no block given and no argument, returns +true+ if +self+ has no truthy elements,
8142 * +false+ otherwise:
8143 *
8144 * [nil, false].none? # => true
8145 * [nil, 0, false].none? # => false
8146 * [].none? # => true
8147 *
8148 * With argument +object+ given, returns +false+ if for any element +element+,
8149 * <tt>object === element</tt>; +true+ otherwise:
8150 *
8151 * ['food', 'drink'].none?(/bar/) # => true
8152 * ['food', 'drink'].none?(/foo/) # => false
8153 * [].none?(/foo/) # => true
8154 * [0, 1, 2].none?(3) # => true
8155 * [0, 1, 2].none?(1) # => false
8156 *
8157 * With a block given, calls the block with each element in +self+;
8158 * returns +true+ if the block returns no truthy value, +false+ otherwise:
8159 *
8160 * [0, 1, 2].none? {|element| element > 3 } # => true
8161 * [0, 1, 2].none? {|element| element > 1 } # => false
8162 *
8163 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
8164 */
8165
8166static VALUE
8167rb_ary_none_p(int argc, VALUE *argv, VALUE ary)
8168{
8169 long i, len = RARRAY_LEN(ary);
8170
8171 rb_check_arity(argc, 0, 1);
8172 if (!len) return Qtrue;
8173 if (argc) {
8174 if (rb_block_given_p()) {
8175 rb_warn("given block not used");
8176 }
8177 for (i = 0; i < RARRAY_LEN(ary); ++i) {
8178 if (RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) return Qfalse;
8179 }
8180 }
8181 else if (!rb_block_given_p()) {
8182 for (i = 0; i < len; ++i) {
8183 if (RTEST(RARRAY_AREF(ary, i))) return Qfalse;
8184 }
8185 }
8186 else {
8187 for (i = 0; i < RARRAY_LEN(ary); ++i) {
8188 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) return Qfalse;
8189 }
8190 }
8191 return Qtrue;
8192}
8193
8194/*
8195 * call-seq:
8196 * one? -> true or false
8197 * one? {|element| ... } -> true or false
8198 * one?(object) -> true or false
8199 *
8200 * Returns +true+ if exactly one element of +self+ meets a given criterion.
8201 *
8202 * With no block given and no argument, returns +true+ if +self+ has exactly one truthy element,
8203 * +false+ otherwise:
8204 *
8205 * [nil, 0].one? # => true
8206 * [0, 0].one? # => false
8207 * [nil, nil].one? # => false
8208 * [].one? # => false
8209 *
8210 * With a block given, calls the block with each element in +self+;
8211 * returns +true+ if the block a truthy value for exactly one element, +false+ otherwise:
8212 *
8213 * [0, 1, 2].one? {|element| element > 0 } # => false
8214 * [0, 1, 2].one? {|element| element > 1 } # => true
8215 * [0, 1, 2].one? {|element| element > 2 } # => false
8216 *
8217 * With argument +object+ given, returns +true+ if for exactly one element +element+, <tt>object === element</tt>;
8218 * +false+ otherwise:
8219 *
8220 * [0, 1, 2].one?(0) # => true
8221 * [0, 0, 1].one?(0) # => false
8222 * [1, 1, 2].one?(0) # => false
8223 * ['food', 'drink'].one?(/bar/) # => false
8224 * ['food', 'drink'].one?(/foo/) # => true
8225 * [].one?(/foo/) # => false
8226 *
8227 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
8228 */
8229
8230static VALUE
8231rb_ary_one_p(int argc, VALUE *argv, VALUE ary)
8232{
8233 long i, len = RARRAY_LEN(ary);
8234 VALUE result = Qfalse;
8235
8236 rb_check_arity(argc, 0, 1);
8237 if (!len) return Qfalse;
8238 if (argc) {
8239 if (rb_block_given_p()) {
8240 rb_warn("given block not used");
8241 }
8242 for (i = 0; i < RARRAY_LEN(ary); ++i) {
8243 if (RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) {
8244 if (result) return Qfalse;
8245 result = Qtrue;
8246 }
8247 }
8248 }
8249 else if (!rb_block_given_p()) {
8250 for (i = 0; i < len; ++i) {
8251 if (RTEST(RARRAY_AREF(ary, i))) {
8252 if (result) return Qfalse;
8253 result = Qtrue;
8254 }
8255 }
8256 }
8257 else {
8258 for (i = 0; i < RARRAY_LEN(ary); ++i) {
8259 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) {
8260 if (result) return Qfalse;
8261 result = Qtrue;
8262 }
8263 }
8264 }
8265 return result;
8266}
8267
8268/*
8269 * call-seq:
8270 * dig(index, *identifiers) -> object
8271 *
8272 * Finds and returns the object in nested object
8273 * specified by +index+ and +identifiers+;
8274 * the nested objects may be instances of various classes.
8275 * See {Dig Methods}[rdoc-ref:dig_methods.rdoc].
8276 *
8277 * Examples:
8278 *
8279 * a = [:foo, [:bar, :baz, [:bat, :bam]]]
8280 * a.dig(1) # => [:bar, :baz, [:bat, :bam]]
8281 * a.dig(1, 2) # => [:bat, :bam]
8282 * a.dig(1, 2, 0) # => :bat
8283 * a.dig(1, 2, 3) # => nil
8284 *
8285 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
8286 */
8287
8288static VALUE
8289rb_ary_dig(int argc, VALUE *argv, VALUE self)
8290{
8292 self = rb_ary_at(self, *argv);
8293 if (!--argc) return self;
8294 ++argv;
8295 return rb_obj_dig(argc, argv, self, Qnil);
8296}
8297
8298static inline VALUE
8299finish_exact_sum(long n, VALUE r, VALUE v, int z)
8300{
8301 if (n != 0)
8302 v = rb_fix_plus(LONG2FIX(n), v);
8303 if (!UNDEF_P(r)) {
8304 v = rb_rational_plus(r, v);
8305 }
8306 else if (!n && z) {
8307 v = rb_fix_plus(LONG2FIX(0), v);
8308 }
8309 return v;
8310}
8311
8312/*
8313 * call-seq:
8314 * sum(init = 0) -> object
8315 * sum(init = 0) {|element| ... } -> object
8316 *
8317 * With no block given, returns the sum of +init+ and all elements of +self+;
8318 * for array +array+ and value +init+, equivalent to:
8319 *
8320 * sum = init
8321 * array.each {|element| sum += element }
8322 * sum
8323 *
8324 * For example, <tt>[e0, e1, e2].sum</tt> returns <tt>init + e0 + e1 + e2</tt>.
8325 *
8326 * Examples:
8327 *
8328 * [0, 1, 2, 3].sum # => 6
8329 * [0, 1, 2, 3].sum(100) # => 106
8330 * ['abc', 'def', 'ghi'].sum('jkl') # => "jklabcdefghi"
8331 * [[:foo, :bar], ['foo', 'bar']].sum([2, 3])
8332 * # => [2, 3, :foo, :bar, "foo", "bar"]
8333 *
8334 * The +init+ value and elements need not be numeric, but must all be <tt>+</tt>-compatible:
8335 *
8336 * # Raises TypeError: Array can't be coerced into Integer.
8337 * [[:foo, :bar], ['foo', 'bar']].sum(2)
8338 *
8339 * With a block given, calls the block with each element of +self+;
8340 * the block's return value (instead of the element itself) is used as the addend:
8341 *
8342 * ['zero', 1, :two].sum('Coerced and concatenated: ') {|element| element.to_s }
8343 * # => "Coerced and concatenated: zero1two"
8344 *
8345 * Notes:
8346 *
8347 * - Array#join and Array#flatten may be faster than Array#sum
8348 * for an array of strings or an array of arrays.
8349 * - Array#sum method may not respect method redefinition of "+" methods such as Integer#+.
8350 *
8351 */
8352
8353static VALUE
8354rb_ary_sum(int argc, VALUE *argv, VALUE ary)
8355{
8356 VALUE e, v, r;
8357 long i, n;
8358 int block_given;
8359
8360 v = (rb_check_arity(argc, 0, 1) ? argv[0] : LONG2FIX(0));
8361
8362 block_given = rb_block_given_p();
8363
8364 if (RARRAY_LEN(ary) == 0)
8365 return v;
8366
8367 n = 0;
8368 r = Qundef;
8369
8370 bool init_is_float = RB_FLOAT_TYPE_P(v);
8371 if (init_is_float) {
8372 v = LONG2FIX(0);
8373 }
8374 else if (!RB_INTEGER_TYPE_P(v) && !RB_TYPE_P(v, T_RATIONAL)) {
8375 i = 0;
8376 goto init_is_a_value;
8377 }
8378
8379 for (i = 0; i < RARRAY_LEN(ary); i++) {
8380 e = RARRAY_AREF(ary, i);
8381 if (block_given)
8382 e = rb_yield(e);
8383 if (FIXNUM_P(e)) {
8384 n += FIX2LONG(e); /* should not overflow long type */
8385 if (!FIXABLE(n)) {
8386 v = rb_big_plus(LONG2NUM(n), v);
8387 n = 0;
8388 }
8389 }
8390 else if (RB_BIGNUM_TYPE_P(e))
8391 v = rb_big_plus(e, v);
8392 else if (RB_TYPE_P(e, T_RATIONAL)) {
8393 if (UNDEF_P(r))
8394 r = e;
8395 else
8396 r = rb_rational_plus(r, e);
8397 }
8398 else
8399 goto not_exact;
8400 }
8401 v = finish_exact_sum(n, r, v, argc!=0);
8402 if (init_is_float) v = rb_float_plus(argv[0], v);
8403 return v;
8404
8405 not_exact:
8406 v = finish_exact_sum(n, r, v, i!=0);
8407
8408 if (init_is_float ? (--i, e = argv[0], true) : RB_FLOAT_TYPE_P(e)) {
8409 /*
8410 * Kahan-Babuska balancing compensated summation algorithm
8411 * See https://link.springer.com/article/10.1007/s00607-005-0139-x
8412 */
8413 double f, c;
8414 double x, t;
8415
8416 f = NUM2DBL(v);
8417 c = 0.0;
8418 goto has_float_value;
8419 for (; i < RARRAY_LEN(ary); i++) {
8420 e = RARRAY_AREF(ary, i);
8421 if (block_given)
8422 e = rb_yield(e);
8423 if (RB_FLOAT_TYPE_P(e))
8424 has_float_value:
8425 x = RFLOAT_VALUE(e);
8426 else if (FIXNUM_P(e))
8427 x = FIX2LONG(e);
8428 else if (RB_BIGNUM_TYPE_P(e))
8429 x = rb_big2dbl(e);
8430 else if (RB_TYPE_P(e, T_RATIONAL))
8431 x = rb_num2dbl(e);
8432 else
8433 goto not_float;
8434
8435 if (isnan(f)) continue;
8436 if (isnan(x)) {
8437 f = x;
8438 continue;
8439 }
8440 if (isinf(x)) {
8441 if (isinf(f) && signbit(x) != signbit(f))
8442 f = NAN;
8443 else
8444 f = x;
8445 continue;
8446 }
8447 if (isinf(f)) continue;
8448
8449 t = f + x;
8450 if (fabs(f) >= fabs(x))
8451 c += ((f - t) + x);
8452 else
8453 c += ((x - t) + f);
8454 f = t;
8455 }
8456 f += c;
8457 return DBL2NUM(f);
8458
8459 not_float:
8460 v = DBL2NUM(f);
8461 }
8462
8463 goto has_some_value;
8464 init_is_a_value:
8465 for (; i < RARRAY_LEN(ary); i++) {
8466 e = RARRAY_AREF(ary, i);
8467 if (block_given)
8468 e = rb_yield(e);
8469 has_some_value:
8470 v = rb_funcall(v, idPLUS, 1, e);
8471 }
8472 return v;
8473}
8474
8475/* :nodoc: */
8476static VALUE
8477rb_ary_deconstruct(VALUE ary)
8478{
8479 return ary;
8480}
8481
8482/*
8483 * An \Array object is an ordered, integer-indexed collection of objects,
8484 * called _elements_;
8485 * the object represents
8486 * an {array data structure}[https://en.wikipedia.org/wiki/Array_(data_structure)].
8487 *
8488 * An element may be any object (even another array);
8489 * elements may be any mixture of objects of different types.
8490 *
8491 * Important data structures that use arrays include:
8492 *
8493 * - {Coordinate vector}[https://en.wikipedia.org/wiki/Coordinate_vector].
8494 * - {Matrix}[https://en.wikipedia.org/wiki/Matrix_(mathematics)].
8495 * - {Heap}[https://en.wikipedia.org/wiki/Heap_(data_structure)].
8496 * - {Hash table}[https://en.wikipedia.org/wiki/Hash_table].
8497 * - {Deque (double-ended queue)}[https://en.wikipedia.org/wiki/Double-ended_queue].
8498 * - {Queue}[https://en.wikipedia.org/wiki/Queue_(abstract_data_type)].
8499 * - {Stack}[https://en.wikipedia.org/wiki/Stack_(abstract_data_type)].
8500 *
8501 * There are also array-like data structures:
8502 *
8503 * - {Associative array}[https://en.wikipedia.org/wiki/Associative_array] (see Hash).
8504 * - {Directory}[https://en.wikipedia.org/wiki/Directory_(computing)] (see Dir).
8505 * - {Environment}[https://en.wikipedia.org/wiki/Environment_variable] (see ENV).
8506 * - {Set}[https://en.wikipedia.org/wiki/Set_(abstract_data_type)] (see Set).
8507 * - {String}[https://en.wikipedia.org/wiki/String_(computer_science)] (see String).
8508 *
8509 * == \Array Indexes
8510 *
8511 * \Array indexing starts at 0, as in C or Java.
8512 *
8513 * A non-negative index is an offset from the first element:
8514 *
8515 * - Index 0 indicates the first element.
8516 * - Index 1 indicates the second element.
8517 * - ...
8518 *
8519 * A negative index is an offset, backwards, from the end of the array:
8520 *
8521 * - Index -1 indicates the last element.
8522 * - Index -2 indicates the next-to-last element.
8523 * - ...
8524 *
8525 *
8526 * === In-Range and Out-of-Range Indexes
8527 *
8528 * A non-negative index is <i>in range</i> if and only if it is smaller than
8529 * the size of the array. For a 3-element array:
8530 *
8531 * - Indexes 0 through 2 are in range.
8532 * - Index 3 is out of range.
8533 *
8534 * A negative index is <i>in range</i> if and only if its absolute value is
8535 * not larger than the size of the array. For a 3-element array:
8536 *
8537 * - Indexes -1 through -3 are in range.
8538 * - Index -4 is out of range.
8539 *
8540 * === Effective Index
8541 *
8542 * Although the effective index into an array is always an integer,
8543 * some methods (both within class \Array and elsewhere)
8544 * accept one or more non-integer arguments that are
8545 * {integer-convertible objects}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
8546 *
8547 * == Creating Arrays
8548 *
8549 * You can create an \Array object explicitly with:
8550 *
8551 * - An {array literal}[rdoc-ref:syntax/literals.rdoc@Array+Literals]:
8552 *
8553 * [1, 'one', :one, [2, 'two', :two]]
8554 *
8555 * - A {%w or %W string-array Literal}[rdoc-ref:syntax/literals.rdoc@w-and-w-String-Array-Literals]:
8556 *
8557 * %w[foo bar baz] # => ["foo", "bar", "baz"]
8558 * %w[1 % *] # => ["1", "%", "*"]
8559 *
8560 * - A {%i or %I symbol-array Literal}[rdoc-ref:syntax/literals.rdoc@i+and-I-Symbol-Array+Literals]:
8561 *
8562 * %i[foo bar baz] # => [:foo, :bar, :baz]
8563 * %i[1 % *] # => [:"1", :%, :*]
8564 *
8565 * - Method Kernel#Array:
8566 *
8567 * Array(["a", "b"]) # => ["a", "b"]
8568 * Array(1..5) # => [1, 2, 3, 4, 5]
8569 * Array(key: :value) # => [[:key, :value]]
8570 * Array(nil) # => []
8571 * Array(1) # => [1]
8572 * Array({:a => "a", :b => "b"}) # => [[:a, "a"], [:b, "b"]]
8573 *
8574 * - Method Array.new:
8575 *
8576 * Array.new # => []
8577 * Array.new(3) # => [nil, nil, nil]
8578 * Array.new(4) {Hash.new} # => [{}, {}, {}, {}]
8579 * Array.new(3, true) # => [true, true, true]
8580 *
8581 * Note that the last example above populates the array
8582 * with references to the same object.
8583 * This is recommended only in cases where that object is a natively immutable object
8584 * such as a symbol, a numeric, +nil+, +true+, or +false+.
8585 *
8586 * Another way to create an array with various objects, using a block;
8587 * this usage is safe for mutable objects such as hashes, strings or
8588 * other arrays:
8589 *
8590 * Array.new(4) {|i| i.to_s } # => ["0", "1", "2", "3"]
8591 *
8592 * Here is a way to create a multi-dimensional array:
8593 *
8594 * Array.new(3) {Array.new(3)}
8595 * # => [[nil, nil, nil], [nil, nil, nil], [nil, nil, nil]]
8596 *
8597 * A number of Ruby methods, both in the core and in the standard library,
8598 * provide instance method +to_a+, which converts an object to an array.
8599 *
8600 * - ARGF#to_a
8601 * - Array#to_a
8602 * - Enumerable#to_a
8603 * - Hash#to_a
8604 * - MatchData#to_a
8605 * - NilClass#to_a
8606 * - OptionParser#to_a
8607 * - Range#to_a
8608 * - Set#to_a
8609 * - Struct#to_a
8610 * - Time#to_a
8611 * - Benchmark::Tms#to_a
8612 * - CSV::Table#to_a
8613 * - Enumerator::Lazy#to_a
8614 * - Gem::List#to_a
8615 * - Gem::NameTuple#to_a
8616 * - Gem::Platform#to_a
8617 * - Gem::RequestSet::Lockfile::Tokenizer#to_a
8618 * - Gem::SourceList#to_a
8619 * - OpenSSL::X509::Extension#to_a
8620 * - OpenSSL::X509::Name#to_a
8621 * - Racc::ISet#to_a
8622 * - Rinda::RingFinger#to_a
8623 * - Ripper::Lexer::Elem#to_a
8624 * - RubyVM::InstructionSequence#to_a
8625 * - YAML::DBM#to_a
8626 *
8627 * == Example Usage
8628 *
8629 * In addition to the methods it mixes in through the Enumerable module,
8630 * class \Array has proprietary methods for accessing, searching and otherwise
8631 * manipulating arrays.
8632 *
8633 * Some of the more common ones are illustrated below.
8634 *
8635 * == Accessing Elements
8636 *
8637 * Elements in an array can be retrieved using the Array#[] method. It can
8638 * take a single integer argument (a numeric index), a pair of arguments
8639 * (start and length) or a range. Negative indices start counting from the end,
8640 * with -1 being the last element.
8641 *
8642 * arr = [1, 2, 3, 4, 5, 6]
8643 * arr[2] #=> 3
8644 * arr[100] #=> nil
8645 * arr[-3] #=> 4
8646 * arr[2, 3] #=> [3, 4, 5]
8647 * arr[1..4] #=> [2, 3, 4, 5]
8648 * arr[1..-3] #=> [2, 3, 4]
8649 *
8650 * Another way to access a particular array element is by using the #at method
8651 *
8652 * arr.at(0) #=> 1
8653 *
8654 * The #slice method works in an identical manner to Array#[].
8655 *
8656 * To raise an error for indices outside of the array bounds or else to
8657 * provide a default value when that happens, you can use #fetch.
8658 *
8659 * arr = ['a', 'b', 'c', 'd', 'e', 'f']
8660 * arr.fetch(100) #=> IndexError: index 100 outside of array bounds: -6...6
8661 * arr.fetch(100, "oops") #=> "oops"
8662 *
8663 * The special methods #first and #last will return the first and last
8664 * elements of an array, respectively.
8665 *
8666 * arr.first #=> 1
8667 * arr.last #=> 6
8668 *
8669 * To return the first +n+ elements of an array, use #take
8670 *
8671 * arr.take(3) #=> [1, 2, 3]
8672 *
8673 * #drop does the opposite of #take, by returning the elements after +n+
8674 * elements have been dropped:
8675 *
8676 * arr.drop(3) #=> [4, 5, 6]
8677 *
8678 * == Obtaining Information about an \Array
8679 *
8680 * An array keeps track of its own length at all times. To query an array
8681 * about the number of elements it contains, use #length, #count or #size.
8682 *
8683 * browsers = ['Chrome', 'Firefox', 'Safari', 'Opera', 'IE']
8684 * browsers.length #=> 5
8685 * browsers.count #=> 5
8686 *
8687 * To check whether an array contains any elements at all
8688 *
8689 * browsers.empty? #=> false
8690 *
8691 * To check whether a particular item is included in the array
8692 *
8693 * browsers.include?('Konqueror') #=> false
8694 *
8695 * == Adding Items to an \Array
8696 *
8697 * Items can be added to the end of an array by using either #push or #<<
8698 *
8699 * arr = [1, 2, 3, 4]
8700 * arr.push(5) #=> [1, 2, 3, 4, 5]
8701 * arr << 6 #=> [1, 2, 3, 4, 5, 6]
8702 *
8703 * #unshift will add a new item to the beginning of an array.
8704 *
8705 * arr.unshift(0) #=> [0, 1, 2, 3, 4, 5, 6]
8706 *
8707 * With #insert you can add a new element to an array at any position.
8708 *
8709 * arr.insert(3, 'apple') #=> [0, 1, 2, 'apple', 3, 4, 5, 6]
8710 *
8711 * Using the #insert method, you can also insert multiple values at once:
8712 *
8713 * arr.insert(3, 'orange', 'pear', 'grapefruit')
8714 * #=> [0, 1, 2, "orange", "pear", "grapefruit", "apple", 3, 4, 5, 6]
8715 *
8716 * == Removing Items from an \Array
8717 *
8718 * The method #pop removes the last element in an array and returns it:
8719 *
8720 * arr = [1, 2, 3, 4, 5, 6]
8721 * arr.pop #=> 6
8722 * arr #=> [1, 2, 3, 4, 5]
8723 *
8724 * To retrieve and at the same time remove the first item, use #shift:
8725 *
8726 * arr.shift #=> 1
8727 * arr #=> [2, 3, 4, 5]
8728 *
8729 * To delete an element at a particular index:
8730 *
8731 * arr.delete_at(2) #=> 4
8732 * arr #=> [2, 3, 5]
8733 *
8734 * To delete a particular element anywhere in an array, use #delete:
8735 *
8736 * arr = [1, 2, 2, 3]
8737 * arr.delete(2) #=> 2
8738 * arr #=> [1,3]
8739 *
8740 * A useful method if you need to remove +nil+ values from an array is
8741 * #compact:
8742 *
8743 * arr = ['foo', 0, nil, 'bar', 7, 'baz', nil]
8744 * arr.compact #=> ['foo', 0, 'bar', 7, 'baz']
8745 * arr #=> ['foo', 0, nil, 'bar', 7, 'baz', nil]
8746 * arr.compact! #=> ['foo', 0, 'bar', 7, 'baz']
8747 * arr #=> ['foo', 0, 'bar', 7, 'baz']
8748 *
8749 * Another common need is to remove duplicate elements from an array.
8750 *
8751 * It has the non-destructive #uniq, and destructive method #uniq!
8752 *
8753 * arr = [2, 5, 6, 556, 6, 6, 8, 9, 0, 123, 556]
8754 * arr.uniq #=> [2, 5, 6, 556, 8, 9, 0, 123]
8755 *
8756 * == Iterating over an \Array
8757 *
8758 * Like all classes that include the Enumerable module, class \Array has an each
8759 * method, which defines what elements should be iterated over and how. In
8760 * case of Array#each, all elements in +self+ are yielded to
8761 * the supplied block in sequence.
8762 *
8763 * Note that this operation leaves the array unchanged.
8764 *
8765 * arr = [1, 2, 3, 4, 5]
8766 * arr.each {|a| print a -= 10, " "}
8767 * # prints: -9 -8 -7 -6 -5
8768 * #=> [1, 2, 3, 4, 5]
8769 *
8770 * Another sometimes useful iterator is #reverse_each which will iterate over
8771 * the elements in the array in reverse order.
8772 *
8773 * words = %w[first second third fourth fifth sixth]
8774 * str = ""
8775 * words.reverse_each {|word| str += "#{word} "}
8776 * p str #=> "sixth fifth fourth third second first "
8777 *
8778 * The #map method can be used to create a new array based on the original
8779 * array, but with the values modified by the supplied block:
8780 *
8781 * arr.map {|a| 2*a} #=> [2, 4, 6, 8, 10]
8782 * arr #=> [1, 2, 3, 4, 5]
8783 * arr.map! {|a| a**2} #=> [1, 4, 9, 16, 25]
8784 * arr #=> [1, 4, 9, 16, 25]
8785 *
8786 *
8787 * == Selecting Items from an \Array
8788 *
8789 * Elements can be selected from an array according to criteria defined in a
8790 * block. The selection can happen in a destructive or a non-destructive
8791 * manner. While the destructive operations will modify the array they were
8792 * called on, the non-destructive methods usually return a new array with the
8793 * selected elements, but leave the original array unchanged.
8794 *
8795 * === Non-destructive Selection
8796 *
8797 * arr = [1, 2, 3, 4, 5, 6]
8798 * arr.select {|a| a > 3} #=> [4, 5, 6]
8799 * arr.reject {|a| a < 3} #=> [3, 4, 5, 6]
8800 * arr.drop_while {|a| a < 4} #=> [4, 5, 6]
8801 * arr #=> [1, 2, 3, 4, 5, 6]
8802 *
8803 * === Destructive Selection
8804 *
8805 * #select! and #reject! are the corresponding destructive methods to #select
8806 * and #reject
8807 *
8808 * Similar to #select vs. #reject, #delete_if and #keep_if have the exact
8809 * opposite result when supplied with the same block:
8810 *
8811 * arr.delete_if {|a| a < 4} #=> [4, 5, 6]
8812 * arr #=> [4, 5, 6]
8813 *
8814 * arr = [1, 2, 3, 4, 5, 6]
8815 * arr.keep_if {|a| a < 4} #=> [1, 2, 3]
8816 * arr #=> [1, 2, 3]
8817 *
8818 * == What's Here
8819 *
8820 * First, what's elsewhere. Class \Array:
8821 *
8822 * - Inherits from {class Object}[rdoc-ref:Object@Whats-Here].
8823 * - Includes {module Enumerable}[rdoc-ref:Enumerable@Whats-Here],
8824 * which provides dozens of additional methods.
8825 *
8826 * Here, class \Array provides methods that are useful for:
8827 *
8828 * - {Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array]
8829 * - {Querying}[rdoc-ref:Array@Methods+for+Querying]
8830 * - {Comparing}[rdoc-ref:Array@Methods+for+Comparing]
8831 * - {Fetching}[rdoc-ref:Array@Methods+for+Fetching]
8832 * - {Assigning}[rdoc-ref:Array@Methods+for+Assigning]
8833 * - {Deleting}[rdoc-ref:Array@Methods+for+Deleting]
8834 * - {Combining}[rdoc-ref:Array@Methods+for+Combining]
8835 * - {Iterating}[rdoc-ref:Array@Methods+for+Iterating]
8836 * - {Converting}[rdoc-ref:Array@Methods+for+Converting]
8837 * - {And more....}[rdoc-ref:Array@Other+Methods]
8838 *
8839 * === Methods for Creating an \Array
8840 *
8841 * - ::[]: Returns a new array populated with given objects.
8842 * - ::new: Returns a new array.
8843 * - ::try_convert: Returns a new array created from a given object.
8844 *
8845 * See also {Creating Arrays}[rdoc-ref:Array@Creating+Arrays].
8846 *
8847 * === Methods for Querying
8848 *
8849 * - #all?: Returns whether all elements meet a given criterion.
8850 * - #any?: Returns whether any element meets a given criterion.
8851 * - #count: Returns the count of elements that meet a given criterion.
8852 * - #empty?: Returns whether there are no elements.
8853 * - #find_index (aliased as #index): Returns the index of the first element that meets a given criterion.
8854 * - #hash: Returns the integer hash code.
8855 * - #include?: Returns whether any element <tt>==</tt> a given object.
8856 * - #length (aliased as #size): Returns the count of elements.
8857 * - #none?: Returns whether no element <tt>==</tt> a given object.
8858 * - #one?: Returns whether exactly one element <tt>==</tt> a given object.
8859 * - #rindex: Returns the index of the last element that meets a given criterion.
8860 *
8861 * === Methods for Comparing
8862 *
8863 * - #<=>: Returns -1, 0, or 1, as +self+ is less than, equal to, or greater than a given object.
8864 * - #==: Returns whether each element in +self+ is <tt>==</tt> to the corresponding element in a given object.
8865 * - #eql?: Returns whether each element in +self+ is <tt>eql?</tt> to the corresponding element in a given object.
8866
8867 * === Methods for Fetching
8868 *
8869 * These methods do not modify +self+.
8870 *
8871 * - #[] (aliased as #slice): Returns consecutive elements as determined by a given argument.
8872 * - #assoc: Returns the first element that is an array whose first element <tt>==</tt> a given object.
8873 * - #at: Returns the element at a given offset.
8874 * - #bsearch: Returns an element selected via a binary search as determined by a given block.
8875 * - #bsearch_index: Returns the index of an element selected via a binary search as determined by a given block.
8876 * - #compact: Returns an array containing all non-+nil+ elements.
8877 * - #dig: Returns the object in nested objects that is specified by a given index and additional arguments.
8878 * - #drop: Returns trailing elements as determined by a given index.
8879 * - #drop_while: Returns trailing elements as determined by a given block.
8880 * - #fetch: Returns the element at a given offset.
8881 * - #fetch_values: Returns elements at given offsets.
8882 * - #first: Returns one or more leading elements.
8883 * - #last: Returns one or more trailing elements.
8884 * - #max: Returns one or more maximum-valued elements, as determined by <tt>#<=></tt> or a given block.
8885 * - #min: Returns one or more minimum-valued elements, as determined by <tt>#<=></tt> or a given block.
8886 * - #minmax: Returns the minimum-valued and maximum-valued elements, as determined by <tt>#<=></tt> or a given block.
8887 * - #rassoc: Returns the first element that is an array whose second element <tt>==</tt> a given object.
8888 * - #reject: Returns an array containing elements not rejected by a given block.
8889 * - #reverse: Returns all elements in reverse order.
8890 * - #rotate: Returns all elements with some rotated from one end to the other.
8891 * - #sample: Returns one or more random elements.
8892 * - #select (aliased as #filter): Returns an array containing elements selected by a given block.
8893 * - #shuffle: Returns elements in a random order.
8894 * - #sort: Returns all elements in an order determined by <tt>#<=></tt> or a given block.
8895 * - #take: Returns leading elements as determined by a given index.
8896 * - #take_while: Returns leading elements as determined by a given block.
8897 * - #uniq: Returns an array containing non-duplicate elements.
8898 * - #values_at: Returns the elements at given offsets.
8899 *
8900 * === Methods for Assigning
8901 *
8902 * These methods add, replace, or reorder elements in +self+.
8903 *
8904 * - #<<: Appends an element.
8905 * - #[]=: Assigns specified elements with a given object.
8906 * - #concat: Appends all elements from given arrays.
8907 * - #fill: Replaces specified elements with specified objects.
8908 * - #flatten!: Replaces each nested array in +self+ with the elements from that array.
8909 * - #initialize_copy (aliased as #replace): Replaces the content of +self+ with the content of a given array.
8910 * - #insert: Inserts given objects at a given offset; does not replace elements.
8911 * - #push (aliased as #append): Appends elements.
8912 * - #reverse!: Replaces +self+ with its elements reversed.
8913 * - #rotate!: Replaces +self+ with its elements rotated.
8914 * - #shuffle!: Replaces +self+ with its elements in random order.
8915 * - #sort!: Replaces +self+ with its elements sorted, as determined by <tt>#<=></tt> or a given block.
8916 * - #sort_by!: Replaces +self+ with its elements sorted, as determined by a given block.
8917 * - #unshift (aliased as #prepend): Prepends leading elements.
8918 *
8919 * === Methods for Deleting
8920 *
8921 * Each of these methods removes elements from +self+:
8922 *
8923 * - #clear: Removes all elements.
8924 * - #compact!: Removes all +nil+ elements.
8925 * - #delete: Removes elements equal to a given object.
8926 * - #delete_at: Removes the element at a given offset.
8927 * - #delete_if: Removes elements specified by a given block.
8928 * - #keep_if: Removes elements not specified by a given block.
8929 * - #pop: Removes and returns the last element.
8930 * - #reject!: Removes elements specified by a given block.
8931 * - #select! (aliased as #filter!): Removes elements not specified by a given block.
8932 * - #shift: Removes and returns the first element.
8933 * - #slice!: Removes and returns a sequence of elements.
8934 * - #uniq!: Removes duplicates.
8935 *
8936 * === Methods for Combining
8937 *
8938 * - #&: Returns an array containing elements found both in +self+ and a given array.
8939 * - #+: Returns an array containing all elements of +self+ followed by all elements of a given array.
8940 * - #-: Returns an array containing all elements of +self+ that are not found in a given array.
8941 * - #|: Returns an array containing all element of +self+ and all elements of a given array, duplicates removed.
8942 * - #difference: Returns an array containing all elements of +self+ that are not found in any of the given arrays..
8943 * - #intersection: Returns an array containing elements found both in +self+ and in each given array.
8944 * - #product: Returns or yields all combinations of elements from +self+ and given arrays.
8945 * - #reverse: Returns an array containing all elements of +self+ in reverse order.
8946 * - #union: Returns an array containing all elements of +self+ and all elements of given arrays, duplicates removed.
8947 *
8948 * === Methods for Iterating
8949 *
8950 * - #combination: Calls a given block with combinations of elements of +self+; a combination does not use the same element more than once.
8951 * - #cycle: Calls a given block with each element, then does so again, for a specified number of times, or forever.
8952 * - #each: Passes each element to a given block.
8953 * - #each_index: Passes each element index to a given block.
8954 * - #permutation: Calls a given block with permutations of elements of +self+; a permutation does not use the same element more than once.
8955 * - #repeated_combination: Calls a given block with combinations of elements of +self+; a combination may use the same element more than once.
8956 * - #repeated_permutation: Calls a given block with permutations of elements of +self+; a permutation may use the same element more than once.
8957 * - #reverse_each: Passes each element, in reverse order, to a given block.
8958 *
8959 * === Methods for Converting
8960 *
8961 * - #collect (aliased as #map): Returns an array containing the block return-value for each element.
8962 * - #collect! (aliased as #map!): Replaces each element with a block return-value.
8963 * - #flatten: Returns an array that is a recursive flattening of +self+.
8964 * - #inspect (aliased as #to_s): Returns a new String containing the elements.
8965 * - #join: Returns a new String containing the elements joined by the field separator.
8966 * - #to_a: Returns +self+ or a new array containing all elements.
8967 * - #to_ary: Returns +self+.
8968 * - #to_h: Returns a new hash formed from the elements.
8969 * - #transpose: Transposes +self+, which must be an array of arrays.
8970 * - #zip: Returns a new array of arrays containing +self+ and given arrays.
8971 *
8972 * === Other Methods
8973 *
8974 * - #*: Returns one of the following:
8975 *
8976 * - With integer argument +n+, a new array that is the concatenation
8977 * of +n+ copies of +self+.
8978 * - With string argument +field_separator+, a new string that is equivalent to
8979 * <tt>join(field_separator)</tt>.
8980 *
8981 * - #pack: Packs the elements into a binary sequence.
8982 * - #sum: Returns a sum of elements according to either <tt>+</tt> or a given block.
8983 */
8984
8985void
8986Init_Array(void)
8987{
8988 fake_ary_flags = init_fake_ary_flags();
8989
8990 rb_cArray = rb_define_class("Array", rb_cObject);
8992
8993 rb_define_alloc_func(rb_cArray, empty_ary_alloc);
8994 rb_define_singleton_method(rb_cArray, "new", rb_ary_s_new, -1);
8995 rb_define_singleton_method(rb_cArray, "[]", rb_ary_s_create, -1);
8996 rb_define_singleton_method(rb_cArray, "try_convert", rb_ary_s_try_convert, 1);
8997 rb_define_method(rb_cArray, "initialize", rb_ary_initialize, -1);
8998 rb_define_method(rb_cArray, "initialize_copy", rb_ary_replace, 1);
8999
9000 rb_define_method(rb_cArray, "inspect", rb_ary_inspect, 0);
9001 rb_define_alias(rb_cArray, "to_s", "inspect");
9002 rb_define_method(rb_cArray, "to_a", rb_ary_to_a, 0);
9003 rb_define_method(rb_cArray, "to_h", rb_ary_to_h, 0);
9004 rb_define_method(rb_cArray, "to_ary", rb_ary_to_ary_m, 0);
9005
9006 rb_define_method(rb_cArray, "==", rb_ary_equal, 1);
9007 rb_define_method(rb_cArray, "eql?", rb_ary_eql, 1);
9008 rb_define_method(rb_cArray, "hash", rb_ary_hash, 0);
9009
9011 rb_define_method(rb_cArray, "[]=", rb_ary_aset, -1);
9012 rb_define_method(rb_cArray, "at", rb_ary_at, 1);
9013 rb_define_method(rb_cArray, "fetch", rb_ary_fetch, -1);
9014 rb_define_method(rb_cArray, "concat", rb_ary_concat_multi, -1);
9015 rb_define_method(rb_cArray, "union", rb_ary_union_multi, -1);
9016 rb_define_method(rb_cArray, "difference", rb_ary_difference_multi, -1);
9017 rb_define_method(rb_cArray, "intersection", rb_ary_intersection_multi, -1);
9018 rb_define_method(rb_cArray, "intersect?", rb_ary_intersect_p, 1);
9020 rb_define_method(rb_cArray, "push", rb_ary_push_m, -1);
9021 rb_define_alias(rb_cArray, "append", "push");
9022 rb_define_method(rb_cArray, "pop", rb_ary_pop_m, -1);
9023 rb_define_method(rb_cArray, "shift", rb_ary_shift_m, -1);
9024 rb_define_method(rb_cArray, "unshift", rb_ary_unshift_m, -1);
9025 rb_define_alias(rb_cArray, "prepend", "unshift");
9026 rb_define_method(rb_cArray, "insert", rb_ary_insert, -1);
9028 rb_define_method(rb_cArray, "each_index", rb_ary_each_index, 0);
9029 rb_define_method(rb_cArray, "reverse_each", rb_ary_reverse_each, 0);
9030 rb_define_method(rb_cArray, "length", rb_ary_length, 0);
9031 rb_define_method(rb_cArray, "size", rb_ary_length, 0);
9032 rb_define_method(rb_cArray, "empty?", rb_ary_empty_p, 0);
9033 rb_define_method(rb_cArray, "find", rb_ary_find, -1);
9034 rb_define_method(rb_cArray, "detect", rb_ary_find, -1);
9035 rb_define_method(rb_cArray, "rfind", rb_ary_rfind, -1);
9036 rb_define_method(rb_cArray, "find_index", rb_ary_index, -1);
9037 rb_define_method(rb_cArray, "index", rb_ary_index, -1);
9038 rb_define_method(rb_cArray, "rindex", rb_ary_rindex, -1);
9039 rb_define_method(rb_cArray, "join", rb_ary_join_m, -1);
9040 rb_define_method(rb_cArray, "reverse", rb_ary_reverse_m, 0);
9041 rb_define_method(rb_cArray, "reverse!", rb_ary_reverse_bang, 0);
9042 rb_define_method(rb_cArray, "rotate", rb_ary_rotate_m, -1);
9043 rb_define_method(rb_cArray, "rotate!", rb_ary_rotate_bang, -1);
9046 rb_define_method(rb_cArray, "sort_by!", rb_ary_sort_by_bang, 0);
9047 rb_define_method(rb_cArray, "collect", rb_ary_collect, 0);
9048 rb_define_method(rb_cArray, "collect!", rb_ary_collect_bang, 0);
9049 rb_define_method(rb_cArray, "map", rb_ary_collect, 0);
9050 rb_define_method(rb_cArray, "map!", rb_ary_collect_bang, 0);
9051 rb_define_method(rb_cArray, "select", rb_ary_select, 0);
9052 rb_define_method(rb_cArray, "select!", rb_ary_select_bang, 0);
9053 rb_define_method(rb_cArray, "filter", rb_ary_select, 0);
9054 rb_define_method(rb_cArray, "filter!", rb_ary_select_bang, 0);
9055 rb_define_method(rb_cArray, "keep_if", rb_ary_keep_if, 0);
9056 rb_define_method(rb_cArray, "values_at", rb_ary_values_at, -1);
9058 rb_define_method(rb_cArray, "delete_at", rb_ary_delete_at_m, 1);
9059 rb_define_method(rb_cArray, "delete_if", rb_ary_delete_if, 0);
9060 rb_define_method(rb_cArray, "reject", rb_ary_reject, 0);
9061 rb_define_method(rb_cArray, "reject!", rb_ary_reject_bang, 0);
9062 rb_define_method(rb_cArray, "zip", rb_ary_zip, -1);
9063 rb_define_method(rb_cArray, "transpose", rb_ary_transpose, 0);
9066 rb_define_method(rb_cArray, "fill", rb_ary_fill, -1);
9069
9070 rb_define_method(rb_cArray, "slice", rb_ary_aref, -1);
9071 rb_define_method(rb_cArray, "slice!", rb_ary_slice_bang, -1);
9072
9075
9077 rb_define_method(rb_cArray, "*", rb_ary_times, 1);
9078
9079 rb_define_method(rb_cArray, "-", rb_ary_diff, 1);
9080 rb_define_method(rb_cArray, "&", rb_ary_and, 1);
9081 rb_define_method(rb_cArray, "|", rb_ary_or, 1);
9082
9083 rb_define_method(rb_cArray, "max", rb_ary_max, -1);
9084 rb_define_method(rb_cArray, "min", rb_ary_min, -1);
9085 rb_define_method(rb_cArray, "minmax", rb_ary_minmax, 0);
9086
9087 rb_define_method(rb_cArray, "uniq", rb_ary_uniq, 0);
9088 rb_define_method(rb_cArray, "uniq!", rb_ary_uniq_bang, 0);
9089 rb_define_method(rb_cArray, "compact", rb_ary_compact, 0);
9090 rb_define_method(rb_cArray, "compact!", rb_ary_compact_bang, 0);
9091 rb_define_method(rb_cArray, "flatten", rb_ary_flatten, -1);
9092 rb_define_method(rb_cArray, "flatten!", rb_ary_flatten_bang, -1);
9093 rb_define_method(rb_cArray, "count", rb_ary_count, -1);
9094 rb_define_method(rb_cArray, "cycle", rb_ary_cycle, -1);
9095 rb_define_method(rb_cArray, "permutation", rb_ary_permutation, -1);
9096 rb_define_method(rb_cArray, "combination", rb_ary_combination, 1);
9097 rb_define_method(rb_cArray, "repeated_permutation", rb_ary_repeated_permutation, 1);
9098 rb_define_method(rb_cArray, "repeated_combination", rb_ary_repeated_combination, 1);
9099 rb_define_method(rb_cArray, "product", rb_ary_product, -1);
9100
9101 rb_define_method(rb_cArray, "take", rb_ary_take, 1);
9102 rb_define_method(rb_cArray, "take_while", rb_ary_take_while, 0);
9103 rb_define_method(rb_cArray, "drop", rb_ary_drop, 1);
9104 rb_define_method(rb_cArray, "drop_while", rb_ary_drop_while, 0);
9105 rb_define_method(rb_cArray, "bsearch", rb_ary_bsearch, 0);
9106 rb_define_method(rb_cArray, "bsearch_index", rb_ary_bsearch_index, 0);
9107 rb_define_method(rb_cArray, "any?", rb_ary_any_p, -1);
9108 rb_define_method(rb_cArray, "all?", rb_ary_all_p, -1);
9109 rb_define_method(rb_cArray, "none?", rb_ary_none_p, -1);
9110 rb_define_method(rb_cArray, "one?", rb_ary_one_p, -1);
9111 rb_define_method(rb_cArray, "dig", rb_ary_dig, -1);
9112 rb_define_method(rb_cArray, "sum", rb_ary_sum, -1);
9114
9115 rb_define_method(rb_cArray, "deconstruct", rb_ary_deconstruct, 0);
9116
9117 rb_cArray_empty_frozen = RB_OBJ_SET_SHAREABLE(rb_ary_freeze(rb_ary_new()));
9118 rb_vm_register_global_object(rb_cArray_empty_frozen);
9119}
9120
9121#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:1608
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
Definition class.c:2897
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:3187
int rb_block_given_p(void)
Determines if the current method is given a block.
Definition eval.c:1029
#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 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:2341
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:58
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:92
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:2257
VALUE rb_obj_frozen_p(VALUE obj)
Just calls RB_OBJ_FROZEN() inside.
Definition object.c:1309
int rb_eql(VALUE lhs, VALUE rhs)
Checks for equality of the passed objects, in terms of Object#eql?.
Definition object.c:151
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:232
VALUE rb_inspect(VALUE obj)
Generates a human-readable textual representation of the given object.
Definition object.c:657
double rb_num2dbl(VALUE num)
Converts an instance of rb_cNumeric into C's double.
Definition object.c:3823
VALUE rb_equal(VALUE lhs, VALUE rhs)
This function is an optimised version of calling #==.
Definition object.c:138
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:894
VALUE rb_obj_freeze(VALUE obj)
Just calls rb_obj_freeze_inline() inside.
Definition object.c:1297
#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:3846
void rb_str_set_len(VALUE str, long len)
Overwrites the length of the string.
Definition string.c:3467
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:4297
VALUE rb_check_string_type(VALUE obj)
Try converting an object to its stringised representation using its to_str method,...
Definition string.c:3014
VALUE rb_str_buf_new(long capa)
Allocates a "string buffer".
Definition string.c:1737
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:1869
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:3552
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
#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