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