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