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