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