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