Ruby 3.5.0dev (2025-04-24 revision bbd5d3348b519035a5d2cdf777e7c8d5c143055c)
array.c (bbd5d3348b519035a5d2cdf777e7c8d5c143055c)
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
573rb_ary_modify(VALUE ary)
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 */
602 rb_ary_modify(ary);
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);
613 rb_ary_modify(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
645rb_ary_freeze(VALUE ary)
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
666rb_ary_shared_with_p(VALUE ary1, VALUE ary2)
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
740rb_ary_new_capa(long capa)
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
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
858rb_ary_hidden_new(long capa)
859{
860 VALUE ary = ary_new(0, capa);
861 return ary;
862}
863
864VALUE
865rb_ary_hidden_new_fill(long capa)
866{
867 VALUE ary = rb_ary_hidden_new(capa);
868 ary_memfill(ary, 0, capa, Qnil);
869 ARY_SET_LEN(ary, capa);
870 return ary;
871}
872
873void
874rb_ary_free(VALUE ary)
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;
906 rb_ary_freeze(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
1013rb_check_array_type(VALUE ary)
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
1135 rb_ary_modify(ary);
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 */
1163 rb_ary_modify(ary);
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++) {
1172 rb_ary_store(ary, i, rb_yield(LONG2NUM(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
1221 rb_ary_modify(ary);
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
1383rb_ary_push(VALUE ary, VALUE item)
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
1430rb_ary_pop(VALUE ary)
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
1495rb_ary_shift(VALUE ary)
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
1626 rb_ary_modify(ary);
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
2196rb_ary_to_ary(VALUE obj)
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 }
2248 rb_ary_modify(ary);
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
2295rb_ary_resize(VALUE ary, long len)
2296{
2297 long olen;
2298
2299 rb_ary_modify(ary);
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
2640rb_ary_each(VALUE ary)
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
2776rb_ary_dup(VALUE ary)
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
2789rb_ary_resurrect(VALUE ary)
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
2890rb_ary_join(VALUE ary, VALUE sep)
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
3012rb_ary_to_s(VALUE ary)
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
3118rb_ary_reverse(VALUE ary)
3119{
3120 VALUE *p2;
3121 long len = RARRAY_LEN(ary);
3122
3123 rb_ary_modify(ary);
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{
3209 rb_ary_modify(ary);
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
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
3393rb_ary_sort_bang(VALUE ary)
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
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
4739rb_ary_clear(VALUE ary)
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
5015rb_ary_plus(VALUE x, VALUE y)
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
5078rb_ary_concat(VALUE x, VALUE y)
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
5324VALUE
5325rb_ary_hash_values(long len, const VALUE *elements)
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 }
5337 h = rb_hash_end(h);
5338 return ST2FIX(h);
5339}
5340
5341/*
5342 * call-seq:
5343 * hash -> integer
5344 *
5345 * Returns the integer hash value for +self+.
5346 *
5347 * Two arrays with the same content will have the same hash value
5348 * (and will compare using eql?):
5349 *
5350 * ['a', 'b'].hash == ['a', 'b'].hash # => true
5351 * ['a', 'b'].hash == ['a', 'c'].hash # => false
5352 * ['a', 'b'].hash == ['a'].hash # => false
5353 *
5354 */
5355
5356static VALUE
5357rb_ary_hash(VALUE ary)
5358{
5359 return rb_ary_hash_values(RARRAY_LEN(ary), RARRAY_CONST_PTR(ary));
5360}
5361
5362/*
5363 * call-seq:
5364 * include?(object) -> true or false
5365 *
5366 * Returns whether for some element +element+ in +self+,
5367 * <tt>object == element</tt>:
5368 *
5369 * [0, 1, 2].include?(2) # => true
5370 * [0, 1, 2].include?(2.0) # => true
5371 * [0, 1, 2].include?(2.1) # => false
5372 *
5373 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
5374 */
5375
5376VALUE
5377rb_ary_includes(VALUE ary, VALUE item)
5378{
5379 long i;
5380 VALUE e;
5381
5382 for (i=0; i<RARRAY_LEN(ary); i++) {
5383 e = RARRAY_AREF(ary, i);
5384 if (rb_equal(e, item)) {
5385 return Qtrue;
5386 }
5387 }
5388 return Qfalse;
5389}
5390
5391static VALUE
5392rb_ary_includes_by_eql(VALUE ary, VALUE item)
5393{
5394 long i;
5395 VALUE e;
5396
5397 for (i=0; i<RARRAY_LEN(ary); i++) {
5398 e = RARRAY_AREF(ary, i);
5399 if (rb_eql(item, e)) {
5400 return Qtrue;
5401 }
5402 }
5403 return Qfalse;
5404}
5405
5406static VALUE
5407recursive_cmp(VALUE ary1, VALUE ary2, int recur)
5408{
5409 long i, len;
5410
5411 if (recur) return Qundef; /* Subtle! */
5412 len = RARRAY_LEN(ary1);
5413 if (len > RARRAY_LEN(ary2)) {
5414 len = RARRAY_LEN(ary2);
5415 }
5416 for (i=0; i<len; i++) {
5417 VALUE e1 = rb_ary_elt(ary1, i), e2 = rb_ary_elt(ary2, i);
5418 VALUE v = rb_funcallv(e1, id_cmp, 1, &e2);
5419 if (v != INT2FIX(0)) {
5420 return v;
5421 }
5422 }
5423 return Qundef;
5424}
5425
5426/*
5427 * call-seq:
5428 * self <=> other_array -> -1, 0, or 1
5429 *
5430 * Returns -1, 0, or 1 as +self+ is determined
5431 * to be less than, equal to, or greater than +other_array+.
5432 *
5433 * Iterates over each index +i+ in <tt>(0...self.size)</tt>:
5434 *
5435 * - Computes <tt>result[i]</tt> as <tt>self[i] <=> other_array[i]</tt>.
5436 * - Immediately returns 1 if <tt>result[i]</tt> is 1:
5437 *
5438 * [0, 1, 2] <=> [0, 0, 2] # => 1
5439 *
5440 * - Immediately returns -1 if <tt>result[i]</tt> is -1:
5441 *
5442 * [0, 1, 2] <=> [0, 2, 2] # => -1
5443 *
5444 * - Continues if <tt>result[i]</tt> is 0.
5445 *
5446 * When every +result+ is 0,
5447 * returns <tt>self.size <=> other_array.size</tt>
5448 * (see Integer#<=>):
5449 *
5450 * [0, 1, 2] <=> [0, 1] # => 1
5451 * [0, 1, 2] <=> [0, 1, 2] # => 0
5452 * [0, 1, 2] <=> [0, 1, 2, 3] # => -1
5453 *
5454 * Note that when +other_array+ is larger than +self+,
5455 * its trailing elements do not affect the result:
5456 *
5457 * [0, 1, 2] <=> [0, 1, 2, -3] # => -1
5458 * [0, 1, 2] <=> [0, 1, 2, 0] # => -1
5459 * [0, 1, 2] <=> [0, 1, 2, 3] # => -1
5460 *
5461 * Related: see {Methods for Comparing}[rdoc-ref:Array@Methods+for+Comparing].
5462 */
5463
5464VALUE
5465rb_ary_cmp(VALUE ary1, VALUE ary2)
5466{
5467 long len;
5468 VALUE v;
5469
5470 ary2 = rb_check_array_type(ary2);
5471 if (NIL_P(ary2)) return Qnil;
5472 if (ary1 == ary2) return INT2FIX(0);
5473 v = rb_exec_recursive_paired(recursive_cmp, ary1, ary2, ary2);
5474 if (!UNDEF_P(v)) return v;
5475 len = RARRAY_LEN(ary1) - RARRAY_LEN(ary2);
5476 if (len == 0) return INT2FIX(0);
5477 if (len > 0) return INT2FIX(1);
5478 return INT2FIX(-1);
5479}
5480
5481static VALUE
5482ary_add_hash(VALUE hash, VALUE ary)
5483{
5484 long i;
5485
5486 for (i=0; i<RARRAY_LEN(ary); i++) {
5487 VALUE elt = RARRAY_AREF(ary, i);
5488 rb_hash_add_new_element(hash, elt, elt);
5489 }
5490 return hash;
5491}
5492
5493static inline VALUE
5494ary_tmp_hash_new(VALUE ary)
5495{
5496 long size = RARRAY_LEN(ary);
5497 VALUE hash = rb_hash_new_with_size(size);
5498
5499 RBASIC_CLEAR_CLASS(hash);
5500 return hash;
5501}
5502
5503static VALUE
5504ary_make_hash(VALUE ary)
5505{
5506 VALUE hash = ary_tmp_hash_new(ary);
5507 return ary_add_hash(hash, ary);
5508}
5509
5510static VALUE
5511ary_add_hash_by(VALUE hash, VALUE ary)
5512{
5513 long i;
5514
5515 for (i = 0; i < RARRAY_LEN(ary); ++i) {
5516 VALUE v = rb_ary_elt(ary, i), k = rb_yield(v);
5517 rb_hash_add_new_element(hash, k, v);
5518 }
5519 return hash;
5520}
5521
5522static VALUE
5523ary_make_hash_by(VALUE ary)
5524{
5525 VALUE hash = ary_tmp_hash_new(ary);
5526 return ary_add_hash_by(hash, ary);
5527}
5528
5529/*
5530 * call-seq:
5531 * self - other_array -> new_array
5532 *
5533 * Returns a new array containing only those elements of +self+
5534 * that are not found in +other_array+;
5535 * the order from +self+ is preserved:
5536 *
5537 * [0, 1, 1, 2, 1, 1, 3, 1, 1] - [1] # => [0, 2, 3]
5538 * [0, 1, 1, 2, 1, 1, 3, 1, 1] - [3, 2, 0, :foo] # => [1, 1, 1, 1, 1, 1]
5539 * [0, 1, 2] - [:foo] # => [0, 1, 2]
5540 *
5541 * Element are compared using method <tt>#eql?</tt>
5542 * (as defined in each element of +self+).
5543 *
5544 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5545 */
5546
5547VALUE
5548rb_ary_diff(VALUE ary1, VALUE ary2)
5549{
5550 VALUE ary3;
5551 VALUE hash;
5552 long i;
5553
5554 ary2 = to_ary(ary2);
5555 if (RARRAY_LEN(ary2) == 0) { return ary_make_shared_copy(ary1); }
5556 ary3 = rb_ary_new();
5557
5558 if (RARRAY_LEN(ary1) <= SMALL_ARRAY_LEN || RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
5559 for (i=0; i<RARRAY_LEN(ary1); i++) {
5560 VALUE elt = rb_ary_elt(ary1, i);
5561 if (rb_ary_includes_by_eql(ary2, elt)) continue;
5562 rb_ary_push(ary3, elt);
5563 }
5564 return ary3;
5565 }
5566
5567 hash = ary_make_hash(ary2);
5568 for (i=0; i<RARRAY_LEN(ary1); i++) {
5569 if (rb_hash_stlike_lookup(hash, RARRAY_AREF(ary1, i), NULL)) continue;
5570 rb_ary_push(ary3, rb_ary_elt(ary1, i));
5571 }
5572
5573 return ary3;
5574}
5575
5576/*
5577 * call-seq:
5578 * difference(*other_arrays = []) -> new_array
5579 *
5580 * Returns a new array containing only those elements from +self+
5581 * that are not found in any of the given +other_arrays+;
5582 * items are compared using <tt>eql?</tt>; order from +self+ is preserved:
5583 *
5584 * [0, 1, 1, 2, 1, 1, 3, 1, 1].difference([1]) # => [0, 2, 3]
5585 * [0, 1, 2, 3].difference([3, 0], [1, 3]) # => [2]
5586 * [0, 1, 2].difference([4]) # => [0, 1, 2]
5587 * [0, 1, 2].difference # => [0, 1, 2]
5588 *
5589 * Returns a copy of +self+ if no arguments are given.
5590 *
5591 * Related: Array#-;
5592 * see also {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5593 */
5594
5595static VALUE
5596rb_ary_difference_multi(int argc, VALUE *argv, VALUE ary)
5597{
5598 VALUE ary_diff;
5599 long i, length;
5600 volatile VALUE t0;
5601 bool *is_hash = ALLOCV_N(bool, t0, argc);
5602 ary_diff = rb_ary_new();
5603 length = RARRAY_LEN(ary);
5604
5605 for (i = 0; i < argc; i++) {
5606 argv[i] = to_ary(argv[i]);
5607 is_hash[i] = (length > SMALL_ARRAY_LEN && RARRAY_LEN(argv[i]) > SMALL_ARRAY_LEN);
5608 if (is_hash[i]) argv[i] = ary_make_hash(argv[i]);
5609 }
5610
5611 for (i = 0; i < RARRAY_LEN(ary); i++) {
5612 int j;
5613 VALUE elt = rb_ary_elt(ary, i);
5614 for (j = 0; j < argc; j++) {
5615 if (is_hash[j]) {
5616 if (rb_hash_stlike_lookup(argv[j], RARRAY_AREF(ary, i), NULL))
5617 break;
5618 }
5619 else {
5620 if (rb_ary_includes_by_eql(argv[j], elt)) break;
5621 }
5622 }
5623 if (j == argc) rb_ary_push(ary_diff, elt);
5624 }
5625
5626 ALLOCV_END(t0);
5627
5628 return ary_diff;
5629}
5630
5631
5632/*
5633 * call-seq:
5634 * self & other_array -> new_array
5635 *
5636 * Returns a new array containing the _intersection_ of +self+ and +other_array+;
5637 * that is, containing those elements found in both +self+ and +other_array+:
5638 *
5639 * [0, 1, 2, 3] & [1, 2] # => [1, 2]
5640 *
5641 * Omits duplicates:
5642 *
5643 * [0, 1, 1, 0] & [0, 1] # => [0, 1]
5644 *
5645 * Preserves order from +self+:
5646 *
5647 * [0, 1, 2] & [3, 2, 1, 0] # => [0, 1, 2]
5648 *
5649 * Identifies common elements using method <tt>#eql?</tt>
5650 * (as defined in each element of +self+).
5651 *
5652 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5653 */
5654
5655
5656static VALUE
5657rb_ary_and(VALUE ary1, VALUE ary2)
5658{
5659 VALUE hash, ary3, v;
5660 st_data_t vv;
5661 long i;
5662
5663 ary2 = to_ary(ary2);
5664 ary3 = rb_ary_new();
5665 if (RARRAY_LEN(ary1) == 0 || RARRAY_LEN(ary2) == 0) return ary3;
5666
5667 if (RARRAY_LEN(ary1) <= SMALL_ARRAY_LEN && RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
5668 for (i=0; i<RARRAY_LEN(ary1); i++) {
5669 v = RARRAY_AREF(ary1, i);
5670 if (!rb_ary_includes_by_eql(ary2, v)) continue;
5671 if (rb_ary_includes_by_eql(ary3, v)) continue;
5672 rb_ary_push(ary3, v);
5673 }
5674 return ary3;
5675 }
5676
5677 hash = ary_make_hash(ary2);
5678
5679 for (i=0; i<RARRAY_LEN(ary1); i++) {
5680 v = RARRAY_AREF(ary1, i);
5681 vv = (st_data_t)v;
5682 if (rb_hash_stlike_delete(hash, &vv, 0)) {
5683 rb_ary_push(ary3, v);
5684 }
5685 }
5686
5687 return ary3;
5688}
5689
5690/*
5691 * call-seq:
5692 * intersection(*other_arrays) -> new_array
5693 *
5694 * Returns a new array containing each element in +self+ that is +#eql?+
5695 * to at least one element in each of the given +other_arrays+;
5696 * duplicates are omitted:
5697 *
5698 * [0, 0, 1, 1, 2, 3].intersection([0, 1, 2], [0, 1, 3]) # => [0, 1]
5699 *
5700 * Each element must correctly implement method <tt>#hash</tt>.
5701 *
5702 * Order from +self+ is preserved:
5703 *
5704 * [0, 1, 2].intersection([2, 1, 0]) # => [0, 1, 2]
5705 *
5706 * Returns a copy of +self+ if no arguments are given.
5707 *
5708 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5709 */
5710
5711static VALUE
5712rb_ary_intersection_multi(int argc, VALUE *argv, VALUE ary)
5713{
5714 VALUE result = rb_ary_dup(ary);
5715 int i;
5716
5717 for (i = 0; i < argc; i++) {
5718 result = rb_ary_and(result, argv[i]);
5719 }
5720
5721 return result;
5722}
5723
5724static int
5725ary_hash_orset(st_data_t *key, st_data_t *value, st_data_t arg, int existing)
5726{
5727 if (existing) return ST_STOP;
5728 *key = *value = (VALUE)arg;
5729 return ST_CONTINUE;
5730}
5731
5732static void
5733rb_ary_union(VALUE ary_union, VALUE ary)
5734{
5735 long i;
5736 for (i = 0; i < RARRAY_LEN(ary); i++) {
5737 VALUE elt = rb_ary_elt(ary, i);
5738 if (rb_ary_includes_by_eql(ary_union, elt)) continue;
5739 rb_ary_push(ary_union, elt);
5740 }
5741}
5742
5743static void
5744rb_ary_union_hash(VALUE hash, VALUE ary2)
5745{
5746 long i;
5747 for (i = 0; i < RARRAY_LEN(ary2); i++) {
5748 VALUE elt = RARRAY_AREF(ary2, i);
5749 if (!rb_hash_stlike_update(hash, (st_data_t)elt, ary_hash_orset, (st_data_t)elt)) {
5750 RB_OBJ_WRITTEN(hash, Qundef, elt);
5751 }
5752 }
5753}
5754
5755/*
5756 * call-seq:
5757 * self | other_array -> new_array
5758 *
5759 * Returns the union of +self+ and +other_array+;
5760 * duplicates are removed; order is preserved;
5761 * items are compared using <tt>eql?</tt>:
5762 *
5763 * [0, 1] | [2, 3] # => [0, 1, 2, 3]
5764 * [0, 1, 1] | [2, 2, 3] # => [0, 1, 2, 3]
5765 * [0, 1, 2] | [3, 2, 1, 0] # => [0, 1, 2, 3]
5766 *
5767 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5768 */
5769
5770static VALUE
5771rb_ary_or(VALUE ary1, VALUE ary2)
5772{
5773 VALUE hash;
5774
5775 ary2 = to_ary(ary2);
5776 if (RARRAY_LEN(ary1) + RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
5777 VALUE ary3 = rb_ary_new();
5778 rb_ary_union(ary3, ary1);
5779 rb_ary_union(ary3, ary2);
5780 return ary3;
5781 }
5782
5783 hash = ary_make_hash(ary1);
5784 rb_ary_union_hash(hash, ary2);
5785
5786 return rb_hash_values(hash);
5787}
5788
5789/*
5790 * call-seq:
5791 * union(*other_arrays) -> new_array
5792 *
5793 * Returns a new array that is the union of the elements of +self+
5794 * and all given arrays +other_arrays+;
5795 * items are compared using <tt>eql?</tt>:
5796 *
5797 * [0, 1, 2, 3].union([4, 5], [6, 7]) # => [0, 1, 2, 3, 4, 5, 6, 7]
5798 *
5799 * Removes duplicates (preserving the first found):
5800 *
5801 * [0, 1, 1].union([2, 1], [3, 1]) # => [0, 1, 2, 3]
5802 *
5803 * Preserves order (preserving the position of the first found):
5804 *
5805 * [3, 2, 1, 0].union([5, 3], [4, 2]) # => [3, 2, 1, 0, 5, 4]
5806 *
5807 * With no arguments given, returns a copy of +self+.
5808 *
5809 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5810 */
5811
5812static VALUE
5813rb_ary_union_multi(int argc, VALUE *argv, VALUE ary)
5814{
5815 int i;
5816 long sum;
5817 VALUE hash;
5818
5819 sum = RARRAY_LEN(ary);
5820 for (i = 0; i < argc; i++) {
5821 argv[i] = to_ary(argv[i]);
5822 sum += RARRAY_LEN(argv[i]);
5823 }
5824
5825 if (sum <= SMALL_ARRAY_LEN) {
5826 VALUE ary_union = rb_ary_new();
5827
5828 rb_ary_union(ary_union, ary);
5829 for (i = 0; i < argc; i++) rb_ary_union(ary_union, argv[i]);
5830
5831 return ary_union;
5832 }
5833
5834 hash = ary_make_hash(ary);
5835 for (i = 0; i < argc; i++) rb_ary_union_hash(hash, argv[i]);
5836
5837 return rb_hash_values(hash);
5838}
5839
5840/*
5841 * call-seq:
5842 * intersect?(other_array) -> true or false
5843 *
5844 * Returns whether +other_array+ has at least one element that is +#eql?+ to some element of +self+:
5845 *
5846 * [1, 2, 3].intersect?([3, 4, 5]) # => true
5847 * [1, 2, 3].intersect?([4, 5, 6]) # => false
5848 *
5849 * Each element must correctly implement method <tt>#hash</tt>.
5850 *
5851 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
5852 */
5853
5854static VALUE
5855rb_ary_intersect_p(VALUE ary1, VALUE ary2)
5856{
5857 VALUE hash, v, result, shorter, longer;
5858 st_data_t vv;
5859 long i;
5860
5861 ary2 = to_ary(ary2);
5862 if (RARRAY_LEN(ary1) == 0 || RARRAY_LEN(ary2) == 0) return Qfalse;
5863
5864 if (RARRAY_LEN(ary1) <= SMALL_ARRAY_LEN && RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
5865 for (i=0; i<RARRAY_LEN(ary1); i++) {
5866 v = RARRAY_AREF(ary1, i);
5867 if (rb_ary_includes_by_eql(ary2, v)) return Qtrue;
5868 }
5869 return Qfalse;
5870 }
5871
5872 shorter = ary1;
5873 longer = ary2;
5874 if (RARRAY_LEN(ary1) > RARRAY_LEN(ary2)) {
5875 longer = ary1;
5876 shorter = ary2;
5877 }
5878
5879 hash = ary_make_hash(shorter);
5880 result = Qfalse;
5881
5882 for (i=0; i<RARRAY_LEN(longer); i++) {
5883 v = RARRAY_AREF(longer, i);
5884 vv = (st_data_t)v;
5885 if (rb_hash_stlike_lookup(hash, vv, 0)) {
5886 result = Qtrue;
5887 break;
5888 }
5889 }
5890
5891 return result;
5892}
5893
5894static VALUE
5895ary_max_generic(VALUE ary, long i, VALUE vmax)
5896{
5897 RUBY_ASSERT(i > 0 && i < RARRAY_LEN(ary));
5898
5899 VALUE v;
5900 for (; i < RARRAY_LEN(ary); ++i) {
5901 v = RARRAY_AREF(ary, i);
5902
5903 if (rb_cmpint(rb_funcallv(vmax, id_cmp, 1, &v), vmax, v) < 0) {
5904 vmax = v;
5905 }
5906 }
5907
5908 return vmax;
5909}
5910
5911static VALUE
5912ary_max_opt_fixnum(VALUE ary, long i, VALUE vmax)
5913{
5914 const long n = RARRAY_LEN(ary);
5915 RUBY_ASSERT(i > 0 && i < n);
5916 RUBY_ASSERT(FIXNUM_P(vmax));
5917
5918 VALUE v;
5919 for (; i < n; ++i) {
5920 v = RARRAY_AREF(ary, i);
5921
5922 if (FIXNUM_P(v)) {
5923 if ((long)vmax < (long)v) {
5924 vmax = v;
5925 }
5926 }
5927 else {
5928 return ary_max_generic(ary, i, vmax);
5929 }
5930 }
5931
5932 return vmax;
5933}
5934
5935static VALUE
5936ary_max_opt_float(VALUE ary, long i, VALUE vmax)
5937{
5938 const long n = RARRAY_LEN(ary);
5939 RUBY_ASSERT(i > 0 && i < n);
5941
5942 VALUE v;
5943 for (; i < n; ++i) {
5944 v = RARRAY_AREF(ary, i);
5945
5946 if (RB_FLOAT_TYPE_P(v)) {
5947 if (rb_float_cmp(vmax, v) < 0) {
5948 vmax = v;
5949 }
5950 }
5951 else {
5952 return ary_max_generic(ary, i, vmax);
5953 }
5954 }
5955
5956 return vmax;
5957}
5958
5959static VALUE
5960ary_max_opt_string(VALUE ary, long i, VALUE vmax)
5961{
5962 const long n = RARRAY_LEN(ary);
5963 RUBY_ASSERT(i > 0 && i < n);
5964 RUBY_ASSERT(STRING_P(vmax));
5965
5966 VALUE v;
5967 for (; i < n; ++i) {
5968 v = RARRAY_AREF(ary, i);
5969
5970 if (STRING_P(v)) {
5971 if (rb_str_cmp(vmax, v) < 0) {
5972 vmax = v;
5973 }
5974 }
5975 else {
5976 return ary_max_generic(ary, i, vmax);
5977 }
5978 }
5979
5980 return vmax;
5981}
5982
5983/*
5984 * call-seq:
5985 * max -> element
5986 * max(count) -> new_array
5987 * max {|a, b| ... } -> element
5988 * max(count) {|a, b| ... } -> new_array
5989 *
5990 * Returns one of the following:
5991 *
5992 * - The maximum-valued element from +self+.
5993 * - A new array of maximum-valued elements from +self+.
5994 *
5995 * Does not modify +self+.
5996 *
5997 * With no block given, each element in +self+ must respond to method <tt>#<=></tt>
5998 * with a numeric.
5999 *
6000 * With no argument and no block, returns the element in +self+
6001 * having the maximum value per method <tt>#<=></tt>:
6002 *
6003 * [1, 0, 3, 2].max # => 3
6004 *
6005 * With non-negative numeric argument +count+ and no block,
6006 * returns a new array with at most +count+ elements,
6007 * in descending order, per method <tt>#<=></tt>:
6008 *
6009 * [1, 0, 3, 2].max(3) # => [3, 2, 1]
6010 * [1, 0, 3, 2].max(3.0) # => [3, 2, 1]
6011 * [1, 0, 3, 2].max(9) # => [3, 2, 1, 0]
6012 * [1, 0, 3, 2].max(0) # => []
6013 *
6014 * With a block given, the block must return a numeric.
6015 *
6016 * With a block and no argument, calls the block <tt>self.size - 1</tt> times to compare elements;
6017 * returns the element having the maximum value per the block:
6018 *
6019 * ['0', '', '000', '00'].max {|a, b| a.size <=> b.size }
6020 * # => "000"
6021 *
6022 * With non-negative numeric argument +count+ and a block,
6023 * returns a new array with at most +count+ elements,
6024 * in descending order, per the block:
6025 *
6026 * ['0', '', '000', '00'].max(2) {|a, b| a.size <=> b.size }
6027 * # => ["000", "00"]
6028 *
6029 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
6030 */
6031static VALUE
6032rb_ary_max(int argc, VALUE *argv, VALUE ary)
6033{
6034 VALUE result = Qundef, v;
6035 VALUE num;
6036 long i;
6037
6038 if (rb_check_arity(argc, 0, 1) && !NIL_P(num = argv[0]))
6039 return rb_nmin_run(ary, num, 0, 1, 1);
6040
6041 const long n = RARRAY_LEN(ary);
6042 if (rb_block_given_p()) {
6043 for (i = 0; i < RARRAY_LEN(ary); i++) {
6044 v = RARRAY_AREF(ary, i);
6045 if (UNDEF_P(result) || rb_cmpint(rb_yield_values(2, v, result), v, result) > 0) {
6046 result = v;
6047 }
6048 }
6049 }
6050 else if (n > 0) {
6051 result = RARRAY_AREF(ary, 0);
6052 if (n > 1) {
6053 if (FIXNUM_P(result) && CMP_OPTIMIZABLE(INTEGER)) {
6054 return ary_max_opt_fixnum(ary, 1, result);
6055 }
6056 else if (STRING_P(result) && CMP_OPTIMIZABLE(STRING)) {
6057 return ary_max_opt_string(ary, 1, result);
6058 }
6059 else if (RB_FLOAT_TYPE_P(result) && CMP_OPTIMIZABLE(FLOAT)) {
6060 return ary_max_opt_float(ary, 1, result);
6061 }
6062 else {
6063 return ary_max_generic(ary, 1, result);
6064 }
6065 }
6066 }
6067 if (UNDEF_P(result)) return Qnil;
6068 return result;
6069}
6070
6071static VALUE
6072ary_min_generic(VALUE ary, long i, VALUE vmin)
6073{
6074 RUBY_ASSERT(i > 0 && i < RARRAY_LEN(ary));
6075
6076 VALUE v;
6077 for (; i < RARRAY_LEN(ary); ++i) {
6078 v = RARRAY_AREF(ary, i);
6079
6080 if (rb_cmpint(rb_funcallv(vmin, id_cmp, 1, &v), vmin, v) > 0) {
6081 vmin = v;
6082 }
6083 }
6084
6085 return vmin;
6086}
6087
6088static VALUE
6089ary_min_opt_fixnum(VALUE ary, long i, VALUE vmin)
6090{
6091 const long n = RARRAY_LEN(ary);
6092 RUBY_ASSERT(i > 0 && i < n);
6093 RUBY_ASSERT(FIXNUM_P(vmin));
6094
6095 VALUE a;
6096 for (; i < n; ++i) {
6097 a = RARRAY_AREF(ary, i);
6098
6099 if (FIXNUM_P(a)) {
6100 if ((long)vmin > (long)a) {
6101 vmin = a;
6102 }
6103 }
6104 else {
6105 return ary_min_generic(ary, i, vmin);
6106 }
6107 }
6108
6109 return vmin;
6110}
6111
6112static VALUE
6113ary_min_opt_float(VALUE ary, long i, VALUE vmin)
6114{
6115 const long n = RARRAY_LEN(ary);
6116 RUBY_ASSERT(i > 0 && i < n);
6118
6119 VALUE a;
6120 for (; i < n; ++i) {
6121 a = RARRAY_AREF(ary, i);
6122
6123 if (RB_FLOAT_TYPE_P(a)) {
6124 if (rb_float_cmp(vmin, a) > 0) {
6125 vmin = a;
6126 }
6127 }
6128 else {
6129 return ary_min_generic(ary, i, vmin);
6130 }
6131 }
6132
6133 return vmin;
6134}
6135
6136static VALUE
6137ary_min_opt_string(VALUE ary, long i, VALUE vmin)
6138{
6139 const long n = RARRAY_LEN(ary);
6140 RUBY_ASSERT(i > 0 && i < n);
6141 RUBY_ASSERT(STRING_P(vmin));
6142
6143 VALUE a;
6144 for (; i < n; ++i) {
6145 a = RARRAY_AREF(ary, i);
6146
6147 if (STRING_P(a)) {
6148 if (rb_str_cmp(vmin, a) > 0) {
6149 vmin = a;
6150 }
6151 }
6152 else {
6153 return ary_min_generic(ary, i, vmin);
6154 }
6155 }
6156
6157 return vmin;
6158}
6159
6160/*
6161 * call-seq:
6162 * min -> element
6163 * min(count) -> new_array
6164 * min {|a, b| ... } -> element
6165 * min(count) {|a, b| ... } -> new_array
6166 *
6167 * Returns one of the following:
6168 *
6169 * - The minimum-valued element from +self+.
6170 * - A new array of minimum-valued elements from +self+.
6171 *
6172 * Does not modify +self+.
6173 *
6174 * With no block given, each element in +self+ must respond to method <tt>#<=></tt>
6175 * with a numeric.
6176 *
6177 * With no argument and no block, returns the element in +self+
6178 * having the minimum value per method <tt>#<=></tt>:
6179 *
6180 * [1, 0, 3, 2].min # => 0
6181 *
6182 * With non-negative numeric argument +count+ and no block,
6183 * returns a new array with at most +count+ elements,
6184 * in ascending order, per method <tt>#<=></tt>:
6185 *
6186 * [1, 0, 3, 2].min(3) # => [0, 1, 2]
6187 * [1, 0, 3, 2].min(3.0) # => [0, 1, 2]
6188 * [1, 0, 3, 2].min(9) # => [0, 1, 2, 3]
6189 * [1, 0, 3, 2].min(0) # => []
6190 *
6191 * With a block given, the block must return a numeric.
6192 *
6193 * With a block and no argument, calls the block <tt>self.size - 1</tt> times to compare elements;
6194 * returns the element having the minimum value per the block:
6195 *
6196 * ['0', '', '000', '00'].min {|a, b| a.size <=> b.size }
6197 * # => ""
6198 *
6199 * With non-negative numeric argument +count+ and a block,
6200 * returns a new array with at most +count+ elements,
6201 * in ascending order, per the block:
6202 *
6203 * ['0', '', '000', '00'].min(2) {|a, b| a.size <=> b.size }
6204 * # => ["", "0"]
6205 *
6206 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
6207 */
6208static VALUE
6209rb_ary_min(int argc, VALUE *argv, VALUE ary)
6210{
6211 VALUE result = Qundef, v;
6212 VALUE num;
6213 long i;
6214
6215 if (rb_check_arity(argc, 0, 1) && !NIL_P(num = argv[0]))
6216 return rb_nmin_run(ary, num, 0, 0, 1);
6217
6218 const long n = RARRAY_LEN(ary);
6219 if (rb_block_given_p()) {
6220 for (i = 0; i < RARRAY_LEN(ary); i++) {
6221 v = RARRAY_AREF(ary, i);
6222 if (UNDEF_P(result) || rb_cmpint(rb_yield_values(2, v, result), v, result) < 0) {
6223 result = v;
6224 }
6225 }
6226 }
6227 else if (n > 0) {
6228 result = RARRAY_AREF(ary, 0);
6229 if (n > 1) {
6230 if (FIXNUM_P(result) && CMP_OPTIMIZABLE(INTEGER)) {
6231 return ary_min_opt_fixnum(ary, 1, result);
6232 }
6233 else if (STRING_P(result) && CMP_OPTIMIZABLE(STRING)) {
6234 return ary_min_opt_string(ary, 1, result);
6235 }
6236 else if (RB_FLOAT_TYPE_P(result) && CMP_OPTIMIZABLE(FLOAT)) {
6237 return ary_min_opt_float(ary, 1, result);
6238 }
6239 else {
6240 return ary_min_generic(ary, 1, result);
6241 }
6242 }
6243 }
6244 if (UNDEF_P(result)) return Qnil;
6245 return result;
6246}
6247
6248/*
6249 * call-seq:
6250 * minmax -> array
6251 * minmax {|a, b| ... } -> array
6252 *
6253 * Returns a 2-element array containing the minimum-valued and maximum-valued
6254 * elements from +self+;
6255 * does not modify +self+.
6256 *
6257 * With no block given, the minimum and maximum values are determined using method <tt>#<=></tt>:
6258 *
6259 * [1, 0, 3, 2].minmax # => [0, 3]
6260 *
6261 * With a block given, the block must return a numeric;
6262 * the block is called <tt>self.size - 1</tt> times to compare elements;
6263 * returns the elements having the minimum and maximum values per the block:
6264 *
6265 * ['0', '', '000', '00'].minmax {|a, b| a.size <=> b.size }
6266 * # => ["", "000"]
6267 *
6268 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
6269 */
6270static VALUE
6271rb_ary_minmax(VALUE ary)
6272{
6273 if (rb_block_given_p()) {
6274 return rb_call_super(0, NULL);
6275 }
6276 return rb_assoc_new(rb_ary_min(0, 0, ary), rb_ary_max(0, 0, ary));
6277}
6278
6279static int
6280push_value(st_data_t key, st_data_t val, st_data_t ary)
6281{
6282 rb_ary_push((VALUE)ary, (VALUE)val);
6283 return ST_CONTINUE;
6284}
6285
6286/*
6287 * call-seq:
6288 * uniq! -> self or nil
6289 * uniq! {|element| ... } -> self or nil
6290 *
6291 * Removes duplicate elements from +self+, the first occurrence always being retained;
6292 * returns +self+ if any elements removed, +nil+ otherwise.
6293 *
6294 * With no block given, identifies and removes elements using method <tt>eql?</tt>
6295 * to compare elements:
6296 *
6297 * a = [0, 0, 1, 1, 2, 2]
6298 * a.uniq! # => [0, 1, 2]
6299 * a.uniq! # => nil
6300 *
6301 * With a block given, calls the block for each element;
6302 * identifies and omits "duplicate" elements using method <tt>eql?</tt>
6303 * to compare <i>block return values</i>;
6304 * that is, an element is a duplicate if its block return value
6305 * is the same as that of a previous element:
6306 *
6307 * a = ['a', 'aa', 'aaa', 'b', 'bb', 'bbb']
6308 * a.uniq! {|element| element.size } # => ["a", "aa", "aaa"]
6309 * a.uniq! {|element| element.size } # => nil
6310 *
6311 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
6312 */
6313static VALUE
6314rb_ary_uniq_bang(VALUE ary)
6315{
6316 VALUE hash;
6317 long hash_size;
6318
6319 rb_ary_modify_check(ary);
6320 if (RARRAY_LEN(ary) <= 1)
6321 return Qnil;
6322 if (rb_block_given_p())
6323 hash = ary_make_hash_by(ary);
6324 else
6325 hash = ary_make_hash(ary);
6326
6327 hash_size = RHASH_SIZE(hash);
6328 if (RARRAY_LEN(ary) == hash_size) {
6329 return Qnil;
6330 }
6331 rb_ary_modify_check(ary);
6332 ARY_SET_LEN(ary, 0);
6333 if (ARY_SHARED_P(ary)) {
6334 rb_ary_unshare(ary);
6335 FL_SET_EMBED(ary);
6336 }
6337 ary_resize_capa(ary, hash_size);
6338 rb_hash_foreach(hash, push_value, ary);
6339
6340 return ary;
6341}
6342
6343/*
6344 * call-seq:
6345 * uniq -> new_array
6346 * uniq {|element| ... } -> new_array
6347 *
6348 * Returns a new array containing those elements from +self+ that are not duplicates,
6349 * the first occurrence always being retained.
6350 *
6351 * With no block given, identifies and omits duplicate elements using method <tt>eql?</tt>
6352 * to compare elements:
6353 *
6354 * a = [0, 0, 1, 1, 2, 2]
6355 * a.uniq # => [0, 1, 2]
6356 *
6357 * With a block given, calls the block for each element;
6358 * identifies and omits "duplicate" elements using method <tt>eql?</tt>
6359 * to compare <i>block return values</i>;
6360 * that is, an element is a duplicate if its block return value
6361 * is the same as that of a previous element:
6362 *
6363 * a = ['a', 'aa', 'aaa', 'b', 'bb', 'bbb']
6364 * a.uniq {|element| element.size } # => ["a", "aa", "aaa"]
6365 *
6366 * Related: {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
6367 */
6368
6369static VALUE
6370rb_ary_uniq(VALUE ary)
6371{
6372 VALUE hash, uniq;
6373
6374 if (RARRAY_LEN(ary) <= 1) {
6375 hash = 0;
6376 uniq = rb_ary_dup(ary);
6377 }
6378 else if (rb_block_given_p()) {
6379 hash = ary_make_hash_by(ary);
6380 uniq = rb_hash_values(hash);
6381 }
6382 else {
6383 hash = ary_make_hash(ary);
6384 uniq = rb_hash_values(hash);
6385 }
6386
6387 return uniq;
6388}
6389
6390/*
6391 * call-seq:
6392 * compact! -> self or nil
6393 *
6394 * Removes all +nil+ elements from +self+;
6395 * Returns +self+ if any elements are removed, +nil+ otherwise:
6396 *
6397 * a = [nil, 0, nil, false, nil, '', nil, [], nil, {}]
6398 * a.compact! # => [0, false, "", [], {}]
6399 * a # => [0, false, "", [], {}]
6400 * a.compact! # => nil
6401 *
6402 * Related: Array#compact;
6403 * see also {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
6404 */
6405
6406static VALUE
6407rb_ary_compact_bang(VALUE ary)
6408{
6409 VALUE *p, *t, *end;
6410 long n;
6411
6412 rb_ary_modify(ary);
6413 p = t = (VALUE *)RARRAY_CONST_PTR(ary); /* WB: no new reference */
6414 end = p + RARRAY_LEN(ary);
6415
6416 while (t < end) {
6417 if (NIL_P(*t)) t++;
6418 else *p++ = *t++;
6419 }
6420 n = p - RARRAY_CONST_PTR(ary);
6421 if (RARRAY_LEN(ary) == n) {
6422 return Qnil;
6423 }
6424 ary_resize_smaller(ary, n);
6425
6426 return ary;
6427}
6428
6429/*
6430 * call-seq:
6431 * compact -> new_array
6432 *
6433 * Returns a new array containing only the non-+nil+ elements from +self+;
6434 * element order is preserved:
6435 *
6436 * a = [nil, 0, nil, false, nil, '', nil, [], nil, {}]
6437 * a.compact # => [0, false, "", [], {}]
6438 *
6439 * Related: Array#compact!;
6440 * see also {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
6441 */
6442
6443static VALUE
6444rb_ary_compact(VALUE ary)
6445{
6446 ary = rb_ary_dup(ary);
6447 rb_ary_compact_bang(ary);
6448 return ary;
6449}
6450
6451/*
6452 * call-seq:
6453 * count -> integer
6454 * count(object) -> integer
6455 * count {|element| ... } -> integer
6456 *
6457 * Returns a count of specified elements.
6458 *
6459 * With no argument and no block, returns the count of all elements:
6460 *
6461 * [0, :one, 'two', 3, 3.0].count # => 5
6462 *
6463 * With argument +object+ given, returns the count of elements <tt>==</tt> to +object+:
6464 *
6465 * [0, :one, 'two', 3, 3.0].count(3) # => 2
6466 *
6467 * With no argument and a block given, calls the block with each element;
6468 * returns the count of elements for which the block returns a truthy value:
6469 *
6470 * [0, 1, 2, 3].count {|element| element > 1 } # => 2
6471 *
6472 * With argument +object+ and a block given, issues a warning, ignores the block,
6473 * and returns the count of elements <tt>==</tt> to +object+.
6474 *
6475 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
6476 */
6477
6478static VALUE
6479rb_ary_count(int argc, VALUE *argv, VALUE ary)
6480{
6481 long i, n = 0;
6482
6483 if (rb_check_arity(argc, 0, 1) == 0) {
6484 VALUE v;
6485
6486 if (!rb_block_given_p())
6487 return LONG2NUM(RARRAY_LEN(ary));
6488
6489 for (i = 0; i < RARRAY_LEN(ary); i++) {
6490 v = RARRAY_AREF(ary, i);
6491 if (RTEST(rb_yield(v))) n++;
6492 }
6493 }
6494 else {
6495 VALUE obj = argv[0];
6496
6497 if (rb_block_given_p()) {
6498 rb_warn("given block not used");
6499 }
6500 for (i = 0; i < RARRAY_LEN(ary); i++) {
6501 if (rb_equal(RARRAY_AREF(ary, i), obj)) n++;
6502 }
6503 }
6504
6505 return LONG2NUM(n);
6506}
6507
6508static VALUE
6509flatten(VALUE ary, int level)
6510{
6511 long i;
6512 VALUE stack, result, tmp = 0, elt;
6513 VALUE memo = Qfalse;
6514
6515 for (i = 0; i < RARRAY_LEN(ary); i++) {
6516 elt = RARRAY_AREF(ary, i);
6517 tmp = rb_check_array_type(elt);
6518 if (!NIL_P(tmp)) {
6519 break;
6520 }
6521 }
6522 if (i == RARRAY_LEN(ary)) {
6523 return ary;
6524 }
6525
6526 result = ary_new(0, RARRAY_LEN(ary));
6527 ary_memcpy(result, 0, i, RARRAY_CONST_PTR(ary));
6528 ARY_SET_LEN(result, i);
6529
6530 stack = ary_new(0, ARY_DEFAULT_SIZE);
6531 rb_ary_push(stack, ary);
6532 rb_ary_push(stack, LONG2NUM(i + 1));
6533
6534 if (level < 0) {
6535 memo = rb_obj_hide(rb_ident_hash_new());
6536 rb_hash_aset(memo, ary, Qtrue);
6537 rb_hash_aset(memo, tmp, Qtrue);
6538 }
6539
6540 ary = tmp;
6541 i = 0;
6542
6543 while (1) {
6544 while (i < RARRAY_LEN(ary)) {
6545 elt = RARRAY_AREF(ary, i++);
6546 if (level >= 0 && RARRAY_LEN(stack) / 2 >= level) {
6547 rb_ary_push(result, elt);
6548 continue;
6549 }
6550 tmp = rb_check_array_type(elt);
6551 if (RBASIC(result)->klass) {
6552 if (RTEST(memo)) {
6553 rb_hash_clear(memo);
6554 }
6555 rb_raise(rb_eRuntimeError, "flatten reentered");
6556 }
6557 if (NIL_P(tmp)) {
6558 rb_ary_push(result, elt);
6559 }
6560 else {
6561 if (memo) {
6562 if (rb_hash_aref(memo, tmp) == Qtrue) {
6563 rb_hash_clear(memo);
6564 rb_raise(rb_eArgError, "tried to flatten recursive array");
6565 }
6566 rb_hash_aset(memo, tmp, Qtrue);
6567 }
6568 rb_ary_push(stack, ary);
6569 rb_ary_push(stack, LONG2NUM(i));
6570 ary = tmp;
6571 i = 0;
6572 }
6573 }
6574 if (RARRAY_LEN(stack) == 0) {
6575 break;
6576 }
6577 if (memo) {
6578 rb_hash_delete(memo, ary);
6579 }
6580 tmp = rb_ary_pop(stack);
6581 i = NUM2LONG(tmp);
6582 ary = rb_ary_pop(stack);
6583 }
6584
6585 if (memo) {
6586 rb_hash_clear(memo);
6587 }
6588
6589 RBASIC_SET_CLASS(result, rb_cArray);
6590 return result;
6591}
6592
6593/*
6594 * call-seq:
6595 * flatten!(depth = nil) -> self or nil
6596 *
6597 * Returns +self+ as a recursively flattening of +self+ to +depth+ levels of recursion;
6598 * +depth+ must be an
6599 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects],
6600 * or +nil+.
6601 * At each level of recursion:
6602 *
6603 * - Each element that is an array is "flattened"
6604 * (that is, replaced by its individual array elements).
6605 * - Each element that is not an array is unchanged
6606 * (even if the element is an object that has instance method +flatten+).
6607 *
6608 * Returns +nil+ if no elements were flattened.
6609 *
6610 * With non-negative integer argument +depth+, flattens recursively through +depth+ levels:
6611 *
6612 * a = [ 0, [ 1, [2, 3], 4 ], 5, {foo: 0}, Set.new([6, 7]) ]
6613 * a # => [0, [1, [2, 3], 4], 5, {:foo=>0}, #<Set: {6, 7}>]
6614 * a.dup.flatten!(1) # => [0, 1, [2, 3], 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6615 * a.dup.flatten!(1.1) # => [0, 1, [2, 3], 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6616 * a.dup.flatten!(2) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6617 * a.dup.flatten!(3) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6618 *
6619 * With +nil+ or negative argument +depth+, flattens all levels:
6620 *
6621 * a.dup.flatten! # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6622 * a.dup.flatten!(-1) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6623 *
6624 * Related: Array#flatten;
6625 * see also {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
6626 */
6627
6628static VALUE
6629rb_ary_flatten_bang(int argc, VALUE *argv, VALUE ary)
6630{
6631 int mod = 0, level = -1;
6632 VALUE result, lv;
6633
6634 lv = (rb_check_arity(argc, 0, 1) ? argv[0] : Qnil);
6635 rb_ary_modify_check(ary);
6636 if (!NIL_P(lv)) level = NUM2INT(lv);
6637 if (level == 0) return Qnil;
6638
6639 result = flatten(ary, level);
6640 if (result == ary) {
6641 return Qnil;
6642 }
6643 if (!(mod = ARY_EMBED_P(result))) rb_ary_freeze(result);
6644 rb_ary_replace(ary, result);
6645 if (mod) ARY_SET_EMBED_LEN(result, 0);
6646
6647 return ary;
6648}
6649
6650/*
6651 * call-seq:
6652 * flatten(depth = nil) -> new_array
6653 *
6654 * Returns a new array that is a recursive flattening of +self+
6655 * to +depth+ levels of recursion;
6656 * +depth+ must be an
6657 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]
6658 * or +nil+.
6659 * At each level of recursion:
6660 *
6661 * - Each element that is an array is "flattened"
6662 * (that is, replaced by its individual array elements).
6663 * - Each element that is not an array is unchanged
6664 * (even if the element is an object that has instance method +flatten+).
6665 *
6666 * With non-negative integer argument +depth+, flattens recursively through +depth+ levels:
6667 *
6668 * a = [ 0, [ 1, [2, 3], 4 ], 5, {foo: 0}, Set.new([6, 7]) ]
6669 * a # => [0, [1, [2, 3], 4], 5, {:foo=>0}, #<Set: {6, 7}>]
6670 * a.flatten(0) # => [0, [1, [2, 3], 4], 5, {:foo=>0}, #<Set: {6, 7}>]
6671 * a.flatten(1 ) # => [0, 1, [2, 3], 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6672 * a.flatten(1.1) # => [0, 1, [2, 3], 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6673 * a.flatten(2) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6674 * a.flatten(3) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6675 *
6676 * With +nil+ or negative +depth+, flattens all levels.
6677 *
6678 * a.flatten # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6679 * a.flatten(-1) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6680 *
6681 * Related: Array#flatten!;
6682 * see also {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
6683 */
6684
6685static VALUE
6686rb_ary_flatten(int argc, VALUE *argv, VALUE ary)
6687{
6688 int level = -1;
6689 VALUE result;
6690
6691 if (rb_check_arity(argc, 0, 1) && !NIL_P(argv[0])) {
6692 level = NUM2INT(argv[0]);
6693 if (level == 0) return ary_make_shared_copy(ary);
6694 }
6695
6696 result = flatten(ary, level);
6697 if (result == ary) {
6698 result = ary_make_shared_copy(ary);
6699 }
6700
6701 return result;
6702}
6703
6704#define RAND_UPTO(max) (long)rb_random_ulong_limited((randgen), (max)-1)
6705
6706static VALUE
6707rb_ary_shuffle_bang(rb_execution_context_t *ec, VALUE ary, VALUE randgen)
6708{
6709 long i, len;
6710
6711 rb_ary_modify(ary);
6712 i = len = RARRAY_LEN(ary);
6713 RARRAY_PTR_USE(ary, ptr, {
6714 while (i > 1) {
6715 long j = RAND_UPTO(i);
6716 VALUE tmp;
6717 if (len != RARRAY_LEN(ary) || ptr != RARRAY_CONST_PTR(ary)) {
6718 rb_raise(rb_eRuntimeError, "modified during shuffle");
6719 }
6720 tmp = ptr[--i];
6721 ptr[i] = ptr[j];
6722 ptr[j] = tmp;
6723 }
6724 }); /* WB: no new reference */
6725 return ary;
6726}
6727
6728static VALUE
6729rb_ary_shuffle(rb_execution_context_t *ec, VALUE ary, VALUE randgen)
6730{
6731 ary = rb_ary_dup(ary);
6732 rb_ary_shuffle_bang(ec, ary, randgen);
6733 return ary;
6734}
6735
6736static const rb_data_type_t ary_sample_memo_type = {
6737 .wrap_struct_name = "ary_sample_memo",
6738 .function = {
6739 .dfree = (RUBY_DATA_FUNC)st_free_table,
6740 },
6741 .flags = RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY
6742};
6743
6744static VALUE
6745ary_sample(rb_execution_context_t *ec, VALUE ary, VALUE randgen, VALUE nv, VALUE to_array)
6746{
6747 VALUE result;
6748 long n, len, i, j, k, idx[10];
6749 long rnds[numberof(idx)];
6750 long memo_threshold;
6751
6752 len = RARRAY_LEN(ary);
6753 if (!to_array) {
6754 if (len < 2)
6755 i = 0;
6756 else
6757 i = RAND_UPTO(len);
6758
6759 return rb_ary_elt(ary, i);
6760 }
6761 n = NUM2LONG(nv);
6762 if (n < 0) rb_raise(rb_eArgError, "negative sample number");
6763 if (n > len) n = len;
6764 if (n <= numberof(idx)) {
6765 for (i = 0; i < n; ++i) {
6766 rnds[i] = RAND_UPTO(len - i);
6767 }
6768 }
6769 k = len;
6770 len = RARRAY_LEN(ary);
6771 if (len < k && n <= numberof(idx)) {
6772 for (i = 0; i < n; ++i) {
6773 if (rnds[i] >= len) return rb_ary_new_capa(0);
6774 }
6775 }
6776 if (n > len) n = len;
6777 switch (n) {
6778 case 0:
6779 return rb_ary_new_capa(0);
6780 case 1:
6781 i = rnds[0];
6782 return rb_ary_new_from_args(1, RARRAY_AREF(ary, i));
6783 case 2:
6784 i = rnds[0];
6785 j = rnds[1];
6786 if (j >= i) j++;
6787 return rb_ary_new_from_args(2, RARRAY_AREF(ary, i), RARRAY_AREF(ary, j));
6788 case 3:
6789 i = rnds[0];
6790 j = rnds[1];
6791 k = rnds[2];
6792 {
6793 long l = j, g = i;
6794 if (j >= i) l = i, g = ++j;
6795 if (k >= l && (++k >= g)) ++k;
6796 }
6797 return rb_ary_new_from_args(3, RARRAY_AREF(ary, i), RARRAY_AREF(ary, j), RARRAY_AREF(ary, k));
6798 }
6799 memo_threshold =
6800 len < 2560 ? len / 128 :
6801 len < 5120 ? len / 64 :
6802 len < 10240 ? len / 32 :
6803 len / 16;
6804 if (n <= numberof(idx)) {
6805 long sorted[numberof(idx)];
6806 sorted[0] = idx[0] = rnds[0];
6807 for (i=1; i<n; i++) {
6808 k = rnds[i];
6809 for (j = 0; j < i; ++j) {
6810 if (k < sorted[j]) break;
6811 ++k;
6812 }
6813 memmove(&sorted[j+1], &sorted[j], sizeof(sorted[0])*(i-j));
6814 sorted[j] = idx[i] = k;
6815 }
6816 result = rb_ary_new_capa(n);
6817 RARRAY_PTR_USE(result, ptr_result, {
6818 for (i=0; i<n; i++) {
6819 ptr_result[i] = RARRAY_AREF(ary, idx[i]);
6820 }
6821 });
6822 }
6823 else if (n <= memo_threshold / 2) {
6824 long max_idx = 0;
6825 VALUE vmemo = TypedData_Wrap_Struct(0, &ary_sample_memo_type, 0);
6826 st_table *memo = st_init_numtable_with_size(n);
6827 RTYPEDDATA_DATA(vmemo) = memo;
6828 result = rb_ary_new_capa(n);
6829 RARRAY_PTR_USE(result, ptr_result, {
6830 for (i=0; i<n; i++) {
6831 long r = RAND_UPTO(len-i) + i;
6832 ptr_result[i] = r;
6833 if (r > max_idx) max_idx = r;
6834 }
6835 len = RARRAY_LEN(ary);
6836 if (len <= max_idx) n = 0;
6837 else if (n > len) n = len;
6838 RARRAY_PTR_USE(ary, ptr_ary, {
6839 for (i=0; i<n; i++) {
6840 long j2 = j = ptr_result[i];
6841 long i2 = i;
6842 st_data_t value;
6843 if (st_lookup(memo, (st_data_t)i, &value)) i2 = (long)value;
6844 if (st_lookup(memo, (st_data_t)j, &value)) j2 = (long)value;
6845 st_insert(memo, (st_data_t)j, (st_data_t)i2);
6846 ptr_result[i] = ptr_ary[j2];
6847 }
6848 });
6849 });
6850 RTYPEDDATA_DATA(vmemo) = 0;
6851 st_free_table(memo);
6852 RB_GC_GUARD(vmemo);
6853 }
6854 else {
6855 result = rb_ary_dup(ary);
6856 RBASIC_CLEAR_CLASS(result);
6857 RB_GC_GUARD(ary);
6858 RARRAY_PTR_USE(result, ptr_result, {
6859 for (i=0; i<n; i++) {
6860 j = RAND_UPTO(len-i) + i;
6861 nv = ptr_result[j];
6862 ptr_result[j] = ptr_result[i];
6863 ptr_result[i] = nv;
6864 }
6865 });
6866 RBASIC_SET_CLASS_RAW(result, rb_cArray);
6867 }
6868 ARY_SET_LEN(result, n);
6869
6870 return result;
6871}
6872
6873static VALUE
6874ary_sized_alloc(rb_execution_context_t *ec, VALUE self)
6875{
6876 return rb_ary_new2(RARRAY_LEN(self));
6877}
6878
6879static VALUE
6880ary_sample0(rb_execution_context_t *ec, VALUE ary)
6881{
6882 return ary_sample(ec, ary, rb_cRandom, Qfalse, Qfalse);
6883}
6884
6885static VALUE
6886rb_ary_cycle_size(VALUE self, VALUE args, VALUE eobj)
6887{
6888 long mul;
6889 VALUE n = Qnil;
6890 if (args && (RARRAY_LEN(args) > 0)) {
6891 n = RARRAY_AREF(args, 0);
6892 }
6893 if (RARRAY_LEN(self) == 0) return INT2FIX(0);
6894 if (NIL_P(n)) return DBL2NUM(HUGE_VAL);
6895 mul = NUM2LONG(n);
6896 if (mul <= 0) return INT2FIX(0);
6897 n = LONG2FIX(mul);
6898 return rb_fix_mul_fix(rb_ary_length(self), n);
6899}
6900
6901/*
6902 * call-seq:
6903 * cycle(count = nil) {|element| ... } -> nil
6904 * cycle(count = nil) -> new_enumerator
6905 *
6906 * With a block given, may call the block, depending on the value of argument +count+;
6907 * +count+ must be an
6908 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects],
6909 * or +nil+.
6910 *
6911 * When +count+ is positive,
6912 * calls the block with each element, then does so repeatedly,
6913 * until it has done so +count+ times; returns +nil+:
6914 *
6915 * output = []
6916 * [0, 1].cycle(2) {|element| output.push(element) } # => nil
6917 * output # => [0, 1, 0, 1]
6918 *
6919 * When +count+ is zero or negative, does not call the block:
6920 *
6921 * [0, 1].cycle(0) {|element| fail 'Cannot happen' } # => nil
6922 * [0, 1].cycle(-1) {|element| fail 'Cannot happen' } # => nil
6923 *
6924 * When +count+ is +nil+, cycles forever:
6925 *
6926 * # Prints 0 and 1 forever.
6927 * [0, 1].cycle {|element| puts element }
6928 * [0, 1].cycle(nil) {|element| puts element }
6929 *
6930 * With no block given, returns a new Enumerator.
6931 *
6932 * Related: see {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
6933 */
6934static VALUE
6935rb_ary_cycle(int argc, VALUE *argv, VALUE ary)
6936{
6937 long n, i;
6938
6939 rb_check_arity(argc, 0, 1);
6940
6941 RETURN_SIZED_ENUMERATOR(ary, argc, argv, rb_ary_cycle_size);
6942 if (argc == 0 || NIL_P(argv[0])) {
6943 n = -1;
6944 }
6945 else {
6946 n = NUM2LONG(argv[0]);
6947 if (n <= 0) return Qnil;
6948 }
6949
6950 while (RARRAY_LEN(ary) > 0 && (n < 0 || 0 < n--)) {
6951 for (i=0; i<RARRAY_LEN(ary); i++) {
6952 rb_yield(RARRAY_AREF(ary, i));
6953 }
6954 }
6955 return Qnil;
6956}
6957
6958/*
6959 * Build a ruby array of the corresponding values and yield it to the
6960 * associated block.
6961 * Return the class of +values+ for reentry check.
6962 */
6963static int
6964yield_indexed_values(const VALUE values, const long r, const long *const p)
6965{
6966 const VALUE result = rb_ary_new2(r);
6967 long i;
6968
6969 for (i = 0; i < r; i++) ARY_SET(result, i, RARRAY_AREF(values, p[i]));
6970 ARY_SET_LEN(result, r);
6971 rb_yield(result);
6972 return !RBASIC(values)->klass;
6973}
6974
6975/*
6976 * Compute permutations of +r+ elements of the set <code>[0..n-1]</code>.
6977 *
6978 * When we have a complete permutation of array indices, copy the values
6979 * at those indices into a new array and yield that array.
6980 *
6981 * n: the size of the set
6982 * r: the number of elements in each permutation
6983 * p: the array (of size r) that we're filling in
6984 * used: an array of booleans: whether a given index is already used
6985 * values: the Ruby array that holds the actual values to permute
6986 */
6987static void
6988permute0(const long n, const long r, long *const p, char *const used, const VALUE values)
6989{
6990 long i = 0, index = 0;
6991
6992 for (;;) {
6993 const char *const unused = memchr(&used[i], 0, n-i);
6994 if (!unused) {
6995 if (!index) break;
6996 i = p[--index]; /* pop index */
6997 used[i++] = 0; /* index unused */
6998 }
6999 else {
7000 i = unused - used;
7001 p[index] = i;
7002 used[i] = 1; /* mark index used */
7003 ++index;
7004 if (index < r-1) { /* if not done yet */
7005 p[index] = i = 0;
7006 continue;
7007 }
7008 for (i = 0; i < n; ++i) {
7009 if (used[i]) continue;
7010 p[index] = i;
7011 if (!yield_indexed_values(values, r, p)) {
7012 rb_raise(rb_eRuntimeError, "permute reentered");
7013 }
7014 }
7015 i = p[--index]; /* pop index */
7016 used[i] = 0; /* index unused */
7017 p[index] = ++i;
7018 }
7019 }
7020}
7021
7022/*
7023 * Returns the product of from, from-1, ..., from - how_many + 1.
7024 * https://en.wikipedia.org/wiki/Pochhammer_symbol
7025 */
7026static VALUE
7027descending_factorial(long from, long how_many)
7028{
7029 VALUE cnt;
7030 if (how_many > 0) {
7031 cnt = LONG2FIX(from);
7032 while (--how_many > 0) {
7033 long v = --from;
7034 cnt = rb_int_mul(cnt, LONG2FIX(v));
7035 }
7036 }
7037 else {
7038 cnt = LONG2FIX(how_many == 0);
7039 }
7040 return cnt;
7041}
7042
7043static VALUE
7044binomial_coefficient(long comb, long size)
7045{
7046 VALUE r;
7047 long i;
7048 if (comb > size-comb) {
7049 comb = size-comb;
7050 }
7051 if (comb < 0) {
7052 return LONG2FIX(0);
7053 }
7054 else if (comb == 0) {
7055 return LONG2FIX(1);
7056 }
7057 r = LONG2FIX(size);
7058 for (i = 1; i < comb; ++i) {
7059 r = rb_int_mul(r, LONG2FIX(size - i));
7060 r = rb_int_idiv(r, LONG2FIX(i + 1));
7061 }
7062 return r;
7063}
7064
7065static VALUE
7066rb_ary_permutation_size(VALUE ary, VALUE args, VALUE eobj)
7067{
7068 long n = RARRAY_LEN(ary);
7069 long k = (args && (RARRAY_LEN(args) > 0)) ? NUM2LONG(RARRAY_AREF(args, 0)) : n;
7070
7071 return descending_factorial(n, k);
7072}
7073
7074/*
7075 * call-seq:
7076 * permutation(count = self.size) {|permutation| ... } -> self
7077 * permutation(count = self.size) -> new_enumerator
7078 *
7079 * Iterates over permutations of the elements of +self+;
7080 * the order of permutations is indeterminate.
7081 *
7082 * With a block and an in-range positive integer argument +count+ (<tt>0 < count <= self.size</tt>) given,
7083 * calls the block with each permutation of +self+ of size +count+;
7084 * returns +self+:
7085 *
7086 * a = [0, 1, 2]
7087 * perms = []
7088 * a.permutation(1) {|perm| perms.push(perm) }
7089 * perms # => [[0], [1], [2]]
7090 *
7091 * perms = []
7092 * a.permutation(2) {|perm| perms.push(perm) }
7093 * perms # => [[0, 1], [0, 2], [1, 0], [1, 2], [2, 0], [2, 1]]
7094 *
7095 * perms = []
7096 * a.permutation(3) {|perm| perms.push(perm) }
7097 * perms # => [[0, 1, 2], [0, 2, 1], [1, 0, 2], [1, 2, 0], [2, 0, 1], [2, 1, 0]]
7098 *
7099 * When +count+ is zero, calls the block once with a new empty array:
7100 *
7101 * perms = []
7102 * a.permutation(0) {|perm| perms.push(perm) }
7103 * perms # => [[]]
7104 *
7105 * When +count+ is out of range (negative or larger than <tt>self.size</tt>),
7106 * does not call the block:
7107 *
7108 * a.permutation(-1) {|permutation| fail 'Cannot happen' }
7109 * a.permutation(4) {|permutation| fail 'Cannot happen' }
7110 *
7111 * With no block given, returns a new Enumerator.
7112 *
7113 * Related: {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
7114 */
7115
7116static VALUE
7117rb_ary_permutation(int argc, VALUE *argv, VALUE ary)
7118{
7119 long r, n, i;
7120
7121 n = RARRAY_LEN(ary); /* Array length */
7122 RETURN_SIZED_ENUMERATOR(ary, argc, argv, rb_ary_permutation_size); /* Return enumerator if no block */
7123 r = n;
7124 if (rb_check_arity(argc, 0, 1) && !NIL_P(argv[0]))
7125 r = NUM2LONG(argv[0]); /* Permutation size from argument */
7126
7127 if (r < 0 || n < r) {
7128 /* no permutations: yield nothing */
7129 }
7130 else if (r == 0) { /* exactly one permutation: the zero-length array */
7132 }
7133 else if (r == 1) { /* this is a special, easy case */
7134 for (i = 0; i < RARRAY_LEN(ary); i++) {
7135 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
7136 }
7137 }
7138 else { /* this is the general case */
7139 volatile VALUE t0;
7140 long *p = ALLOCV_N(long, t0, r+roomof(n, sizeof(long)));
7141 char *used = (char*)(p + r);
7142 VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
7143 RBASIC_CLEAR_CLASS(ary0);
7144
7145 MEMZERO(used, char, n); /* initialize array */
7146
7147 permute0(n, r, p, used, ary0); /* compute and yield permutations */
7148 ALLOCV_END(t0);
7149 RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
7150 }
7151 return ary;
7152}
7153
7154static void
7155combinate0(const long len, const long n, long *const stack, const VALUE values)
7156{
7157 long lev = 0;
7158
7159 MEMZERO(stack+1, long, n);
7160 stack[0] = -1;
7161 for (;;) {
7162 for (lev++; lev < n; lev++) {
7163 stack[lev+1] = stack[lev]+1;
7164 }
7165 if (!yield_indexed_values(values, n, stack+1)) {
7166 rb_raise(rb_eRuntimeError, "combination reentered");
7167 }
7168 do {
7169 if (lev == 0) return;
7170 stack[lev--]++;
7171 } while (stack[lev+1]+n == len+lev+1);
7172 }
7173}
7174
7175static VALUE
7176rb_ary_combination_size(VALUE ary, VALUE args, VALUE eobj)
7177{
7178 long n = RARRAY_LEN(ary);
7179 long k = NUM2LONG(RARRAY_AREF(args, 0));
7180
7181 return binomial_coefficient(k, n);
7182}
7183
7184/*
7185 * call-seq:
7186 * combination(count) {|element| ... } -> self
7187 * combination(count) -> new_enumerator
7188 *
7189 * When a block and a positive
7190 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]
7191 * argument +count+ (<tt>0 < count <= self.size</tt>)
7192 * are given, calls the block with each combination of +self+ of size +count+;
7193 * returns +self+:
7194 *
7195 * a = %w[a b c] # => ["a", "b", "c"]
7196 * a.combination(2) {|combination| p combination } # => ["a", "b", "c"]
7197 *
7198 * Output:
7199 *
7200 * ["a", "b"]
7201 * ["a", "c"]
7202 * ["b", "c"]
7203 *
7204 * The order of the yielded combinations is not guaranteed.
7205 *
7206 * When +count+ is zero, calls the block once with a new empty array:
7207 *
7208 * a.combination(0) {|combination| p combination }
7209 * [].combination(0) {|combination| p combination }
7210 *
7211 * Output:
7212 *
7213 * []
7214 * []
7215 *
7216 * When +count+ is negative or larger than +self.size+ and +self+ is non-empty,
7217 * does not call the block:
7218 *
7219 * a.combination(-1) {|combination| fail 'Cannot happen' } # => ["a", "b", "c"]
7220 * a.combination(4) {|combination| fail 'Cannot happen' } # => ["a", "b", "c"]
7221 *
7222 * With no block given, returns a new Enumerator.
7223 *
7224 * Related: Array#permutation;
7225 * see also {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
7226 */
7227
7228static VALUE
7229rb_ary_combination(VALUE ary, VALUE num)
7230{
7231 long i, n, len;
7232
7233 n = NUM2LONG(num);
7234 RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_combination_size);
7235 len = RARRAY_LEN(ary);
7236 if (n < 0 || len < n) {
7237 /* yield nothing */
7238 }
7239 else if (n == 0) {
7241 }
7242 else if (n == 1) {
7243 for (i = 0; i < RARRAY_LEN(ary); i++) {
7244 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
7245 }
7246 }
7247 else {
7248 VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
7249 volatile VALUE t0;
7250 long *stack = ALLOCV_N(long, t0, n+1);
7251
7252 RBASIC_CLEAR_CLASS(ary0);
7253 combinate0(len, n, stack, ary0);
7254 ALLOCV_END(t0);
7255 RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
7256 }
7257 return ary;
7258}
7259
7260/*
7261 * Compute repeated permutations of +r+ elements of the set
7262 * <code>[0..n-1]</code>.
7263 *
7264 * When we have a complete repeated permutation of array indices, copy the
7265 * values at those indices into a new array and yield that array.
7266 *
7267 * n: the size of the set
7268 * r: the number of elements in each permutation
7269 * p: the array (of size r) that we're filling in
7270 * values: the Ruby array that holds the actual values to permute
7271 */
7272static void
7273rpermute0(const long n, const long r, long *const p, const VALUE values)
7274{
7275 long i = 0, index = 0;
7276
7277 p[index] = i;
7278 for (;;) {
7279 if (++index < r-1) {
7280 p[index] = i = 0;
7281 continue;
7282 }
7283 for (i = 0; i < n; ++i) {
7284 p[index] = i;
7285 if (!yield_indexed_values(values, r, p)) {
7286 rb_raise(rb_eRuntimeError, "repeated permute reentered");
7287 }
7288 }
7289 do {
7290 if (index <= 0) return;
7291 } while ((i = ++p[--index]) >= n);
7292 }
7293}
7294
7295static VALUE
7296rb_ary_repeated_permutation_size(VALUE ary, VALUE args, VALUE eobj)
7297{
7298 long n = RARRAY_LEN(ary);
7299 long k = NUM2LONG(RARRAY_AREF(args, 0));
7300
7301 if (k < 0) {
7302 return LONG2FIX(0);
7303 }
7304 if (n <= 0) {
7305 return LONG2FIX(!k);
7306 }
7307 return rb_int_positive_pow(n, (unsigned long)k);
7308}
7309
7310/*
7311 * call-seq:
7312 * repeated_permutation(size) {|permutation| ... } -> self
7313 * repeated_permutation(size) -> new_enumerator
7314 *
7315 * With a block given, calls the block with each repeated permutation of length +size+
7316 * of the elements of +self+;
7317 * each permutation is an array;
7318 * returns +self+. The order of the permutations is indeterminate.
7319 *
7320 * If a positive integer argument +size+ is given,
7321 * calls the block with each +size+-tuple repeated permutation of the elements of +self+.
7322 * The number of permutations is <tt>self.size**size</tt>.
7323 *
7324 * Examples:
7325 *
7326 * - +size+ is 1:
7327 *
7328 * p = []
7329 * [0, 1, 2].repeated_permutation(1) {|permutation| p.push(permutation) }
7330 * p # => [[0], [1], [2]]
7331 *
7332 * - +size+ is 2:
7333 *
7334 * p = []
7335 * [0, 1, 2].repeated_permutation(2) {|permutation| p.push(permutation) }
7336 * p # => [[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2], [2, 0], [2, 1], [2, 2]]
7337 *
7338 * If +size+ is zero, calls the block once with an empty array.
7339 *
7340 * If +size+ is negative, does not call the block:
7341 *
7342 * [0, 1, 2].repeated_permutation(-1) {|permutation| fail 'Cannot happen' }
7343 *
7344 * With no block given, returns a new Enumerator.
7345 *
7346 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
7347 */
7348static VALUE
7349rb_ary_repeated_permutation(VALUE ary, VALUE num)
7350{
7351 long r, n, i;
7352
7353 n = RARRAY_LEN(ary); /* Array length */
7354 RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_repeated_permutation_size); /* Return Enumerator if no block */
7355 r = NUM2LONG(num); /* Permutation size from argument */
7356
7357 if (r < 0) {
7358 /* no permutations: yield nothing */
7359 }
7360 else if (r == 0) { /* exactly one permutation: the zero-length array */
7362 }
7363 else if (r == 1) { /* this is a special, easy case */
7364 for (i = 0; i < RARRAY_LEN(ary); i++) {
7365 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
7366 }
7367 }
7368 else { /* this is the general case */
7369 volatile VALUE t0;
7370 long *p = ALLOCV_N(long, t0, r);
7371 VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
7372 RBASIC_CLEAR_CLASS(ary0);
7373
7374 rpermute0(n, r, p, ary0); /* compute and yield repeated permutations */
7375 ALLOCV_END(t0);
7376 RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
7377 }
7378 return ary;
7379}
7380
7381static void
7382rcombinate0(const long n, const long r, long *const p, const long rest, const VALUE values)
7383{
7384 long i = 0, index = 0;
7385
7386 p[index] = i;
7387 for (;;) {
7388 if (++index < r-1) {
7389 p[index] = i;
7390 continue;
7391 }
7392 for (; i < n; ++i) {
7393 p[index] = i;
7394 if (!yield_indexed_values(values, r, p)) {
7395 rb_raise(rb_eRuntimeError, "repeated combination reentered");
7396 }
7397 }
7398 do {
7399 if (index <= 0) return;
7400 } while ((i = ++p[--index]) >= n);
7401 }
7402}
7403
7404static VALUE
7405rb_ary_repeated_combination_size(VALUE ary, VALUE args, VALUE eobj)
7406{
7407 long n = RARRAY_LEN(ary);
7408 long k = NUM2LONG(RARRAY_AREF(args, 0));
7409 if (k == 0) {
7410 return LONG2FIX(1);
7411 }
7412 return binomial_coefficient(k, n + k - 1);
7413}
7414
7415/*
7416 * call-seq:
7417 * repeated_combination(size) {|combination| ... } -> self
7418 * repeated_combination(size) -> new_enumerator
7419 *
7420 * With a block given, calls the block with each repeated combination of length +size+
7421 * of the elements of +self+;
7422 * each combination is an array;
7423 * returns +self+. The order of the combinations is indeterminate.
7424 *
7425 * If a positive integer argument +size+ is given,
7426 * calls the block with each +size+-tuple repeated combination of the elements of +self+.
7427 * The number of combinations is <tt>(size+1)(size+2)/2</tt>.
7428 *
7429 * Examples:
7430 *
7431 * - +size+ is 1:
7432 *
7433 * c = []
7434 * [0, 1, 2].repeated_combination(1) {|combination| c.push(combination) }
7435 * c # => [[0], [1], [2]]
7436 *
7437 * - +size+ is 2:
7438 *
7439 * c = []
7440 * [0, 1, 2].repeated_combination(2) {|combination| c.push(combination) }
7441 * c # => [[0, 0], [0, 1], [0, 2], [1, 1], [1, 2], [2, 2]]
7442 *
7443 * If +size+ is zero, calls the block once with an empty array.
7444 *
7445 * If +size+ is negative, does not call the block:
7446 *
7447 * [0, 1, 2].repeated_combination(-1) {|combination| fail 'Cannot happen' }
7448 *
7449 * With no block given, returns a new Enumerator.
7450 *
7451 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
7452 */
7453
7454static VALUE
7455rb_ary_repeated_combination(VALUE ary, VALUE num)
7456{
7457 long n, i, len;
7458
7459 n = NUM2LONG(num); /* Combination size from argument */
7460 RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_repeated_combination_size); /* Return enumerator if no block */
7461 len = RARRAY_LEN(ary);
7462 if (n < 0) {
7463 /* yield nothing */
7464 }
7465 else if (n == 0) {
7467 }
7468 else if (n == 1) {
7469 for (i = 0; i < RARRAY_LEN(ary); i++) {
7470 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
7471 }
7472 }
7473 else if (len == 0) {
7474 /* yield nothing */
7475 }
7476 else {
7477 volatile VALUE t0;
7478 long *p = ALLOCV_N(long, t0, n);
7479 VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
7480 RBASIC_CLEAR_CLASS(ary0);
7481
7482 rcombinate0(len, n, p, n, ary0); /* compute and yield repeated combinations */
7483 ALLOCV_END(t0);
7484 RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
7485 }
7486 return ary;
7487}
7488
7489/*
7490 * call-seq:
7491 * product(*other_arrays) -> new_array
7492 * product(*other_arrays) {|combination| ... } -> self
7493 *
7494 * Computes all combinations of elements from all the arrays,
7495 * including both +self+ and +other_arrays+:
7496 *
7497 * - The number of combinations is the product of the sizes of all the arrays,
7498 * including both +self+ and +other_arrays+.
7499 * - The order of the returned combinations is indeterminate.
7500 *
7501 * With no block given, returns the combinations as an array of arrays:
7502 *
7503 * p = [0, 1].product([2, 3])
7504 * # => [[0, 2], [0, 3], [1, 2], [1, 3]]
7505 * p.size # => 4
7506 * p = [0, 1].product([2, 3], [4, 5])
7507 * # => [[0, 2, 4], [0, 2, 5], [0, 3, 4], [0, 3, 5], [1, 2, 4], [1, 2, 5], [1, 3, 4], [1, 3,...
7508 * p.size # => 8
7509 *
7510 * If +self+ or any argument is empty, returns an empty array:
7511 *
7512 * [].product([2, 3], [4, 5]) # => []
7513 * [0, 1].product([2, 3], []) # => []
7514 *
7515 * If no argument is given, returns an array of 1-element arrays,
7516 * each containing an element of +self+:
7517 *
7518 * a.product # => [[0], [1], [2]]
7519 *
7520 * With a block given, calls the block with each combination; returns +self+:
7521 *
7522 * p = []
7523 * [0, 1].product([2, 3]) {|combination| p.push(combination) }
7524 * p # => [[0, 2], [0, 3], [1, 2], [1, 3]]
7525 *
7526 * If +self+ or any argument is empty, does not call the block:
7527 *
7528 * [].product([2, 3], [4, 5]) {|combination| fail 'Cannot happen' }
7529 * # => []
7530 * [0, 1].product([2, 3], []) {|combination| fail 'Cannot happen' }
7531 * # => [0, 1]
7532 *
7533 * If no argument is given, calls the block with each element of +self+ as a 1-element array:
7534 *
7535 * p = []
7536 * [0, 1].product {|combination| p.push(combination) }
7537 * p # => [[0], [1]]
7538 *
7539 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
7540 */
7541
7542static VALUE
7543rb_ary_product(int argc, VALUE *argv, VALUE ary)
7544{
7545 int n = argc+1; /* How many arrays we're operating on */
7546 volatile VALUE t0 = rb_ary_hidden_new(n);
7547 volatile VALUE t1 = Qundef;
7548 VALUE *arrays = RARRAY_PTR(t0); /* The arrays we're computing the product of */
7549 int *counters = ALLOCV_N(int, t1, n); /* The current position in each one */
7550 VALUE result = Qnil; /* The array we'll be returning, when no block given */
7551 long i,j;
7552 long resultlen = 1;
7553
7554 RBASIC_CLEAR_CLASS(t0);
7555
7556 /* initialize the arrays of arrays */
7557 ARY_SET_LEN(t0, n);
7558 arrays[0] = ary;
7559 for (i = 1; i < n; i++) arrays[i] = Qnil;
7560 for (i = 1; i < n; i++) arrays[i] = to_ary(argv[i-1]);
7561
7562 /* initialize the counters for the arrays */
7563 for (i = 0; i < n; i++) counters[i] = 0;
7564
7565 /* Otherwise, allocate and fill in an array of results */
7566 if (rb_block_given_p()) {
7567 /* Make defensive copies of arrays; exit if any is empty */
7568 for (i = 0; i < n; i++) {
7569 if (RARRAY_LEN(arrays[i]) == 0) goto done;
7570 arrays[i] = ary_make_shared_copy(arrays[i]);
7571 }
7572 }
7573 else {
7574 /* Compute the length of the result array; return [] if any is empty */
7575 for (i = 0; i < n; i++) {
7576 long k = RARRAY_LEN(arrays[i]);
7577 if (k == 0) {
7578 result = rb_ary_new2(0);
7579 goto done;
7580 }
7581 if (MUL_OVERFLOW_LONG_P(resultlen, k))
7582 rb_raise(rb_eRangeError, "too big to product");
7583 resultlen *= k;
7584 }
7585 result = rb_ary_new2(resultlen);
7586 }
7587 for (;;) {
7588 int m;
7589 /* fill in one subarray */
7590 VALUE subarray = rb_ary_new2(n);
7591 for (j = 0; j < n; j++) {
7592 rb_ary_push(subarray, rb_ary_entry(arrays[j], counters[j]));
7593 }
7594
7595 /* put it on the result array */
7596 if (NIL_P(result)) {
7597 FL_SET(t0, RARRAY_SHARED_ROOT_FLAG);
7598 rb_yield(subarray);
7599 if (!FL_TEST(t0, RARRAY_SHARED_ROOT_FLAG)) {
7600 rb_raise(rb_eRuntimeError, "product reentered");
7601 }
7602 else {
7603 FL_UNSET(t0, RARRAY_SHARED_ROOT_FLAG);
7604 }
7605 }
7606 else {
7607 rb_ary_push(result, subarray);
7608 }
7609
7610 /*
7611 * Increment the last counter. If it overflows, reset to 0
7612 * and increment the one before it.
7613 */
7614 m = n-1;
7615 counters[m]++;
7616 while (counters[m] == RARRAY_LEN(arrays[m])) {
7617 counters[m] = 0;
7618 /* If the first counter overflows, we are done */
7619 if (--m < 0) goto done;
7620 counters[m]++;
7621 }
7622 }
7623
7624done:
7625 ALLOCV_END(t1);
7626
7627 return NIL_P(result) ? ary : result;
7628}
7629
7630/*
7631 * call-seq:
7632 * take(count) -> new_array
7633 *
7634 * Returns a new array containing the first +count+ element of +self+
7635 * (as available);
7636 * +count+ must be a non-negative numeric;
7637 * does not modify +self+:
7638 *
7639 * a = ['a', 'b', 'c', 'd']
7640 * a.take(2) # => ["a", "b"]
7641 * a.take(2.1) # => ["a", "b"]
7642 * a.take(50) # => ["a", "b", "c", "d"]
7643 * a.take(0) # => []
7644 *
7645 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
7646 */
7647
7648static VALUE
7649rb_ary_take(VALUE obj, VALUE n)
7650{
7651 long len = NUM2LONG(n);
7652 if (len < 0) {
7653 rb_raise(rb_eArgError, "attempt to take negative size");
7654 }
7655 return rb_ary_subseq(obj, 0, len);
7656}
7657
7658/*
7659 * call-seq:
7660 * take_while {|element| ... } -> new_array
7661 * take_while -> new_enumerator
7662 *
7663 * With a block given, calls the block with each successive element of +self+;
7664 * stops iterating if the block returns +false+ or +nil+;
7665 * returns a new array containing those elements for which the block returned a truthy value:
7666 *
7667 * a = [0, 1, 2, 3, 4, 5]
7668 * a.take_while {|element| element < 3 } # => [0, 1, 2]
7669 * a.take_while {|element| true } # => [0, 1, 2, 3, 4, 5]
7670 * a.take_while {|element| false } # => []
7671 *
7672 * With no block given, returns a new Enumerator.
7673 *
7674 * Does not modify +self+.
7675 *
7676 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
7677 */
7678
7679static VALUE
7680rb_ary_take_while(VALUE ary)
7681{
7682 long i;
7683
7684 RETURN_ENUMERATOR(ary, 0, 0);
7685 for (i = 0; i < RARRAY_LEN(ary); i++) {
7686 if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) break;
7687 }
7688 return rb_ary_take(ary, LONG2FIX(i));
7689}
7690
7691/*
7692 * call-seq:
7693 * drop(count) -> new_array
7694 *
7695 * Returns a new array containing all but the first +count+ element of +self+,
7696 * where +count+ is a non-negative integer;
7697 * does not modify +self+.
7698 *
7699 * Examples:
7700 *
7701 * a = [0, 1, 2, 3, 4, 5]
7702 * a.drop(0) # => [0, 1, 2, 3, 4, 5]
7703 * a.drop(1) # => [1, 2, 3, 4, 5]
7704 * a.drop(2) # => [2, 3, 4, 5]
7705 * a.drop(9) # => []
7706 *
7707 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
7708 */
7709
7710static VALUE
7711rb_ary_drop(VALUE ary, VALUE n)
7712{
7713 VALUE result;
7714 long pos = NUM2LONG(n);
7715 if (pos < 0) {
7716 rb_raise(rb_eArgError, "attempt to drop negative size");
7717 }
7718
7719 result = rb_ary_subseq(ary, pos, RARRAY_LEN(ary));
7720 if (NIL_P(result)) result = rb_ary_new();
7721 return result;
7722}
7723
7724/*
7725 * call-seq:
7726 * drop_while {|element| ... } -> new_array
7727 * drop_while -> new_enumerator
7728 *
7729 * With a block given, calls the block with each successive element of +self+;
7730 * stops if the block returns +false+ or +nil+;
7731 * returns a new array _omitting_ those elements for which the block returned a truthy value;
7732 * does not modify +self+:
7733 *
7734 * a = [0, 1, 2, 3, 4, 5]
7735 * a.drop_while {|element| element < 3 } # => [3, 4, 5]
7736 *
7737 * With no block given, returns a new Enumerator.
7738 *
7739 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
7740 */
7741
7742static VALUE
7743rb_ary_drop_while(VALUE ary)
7744{
7745 long i;
7746
7747 RETURN_ENUMERATOR(ary, 0, 0);
7748 for (i = 0; i < RARRAY_LEN(ary); i++) {
7749 if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) break;
7750 }
7751 return rb_ary_drop(ary, LONG2FIX(i));
7752}
7753
7754/*
7755 * call-seq:
7756 * any? -> true or false
7757 * any?(object) -> true or false
7758 * any? {|element| ... } -> true or false
7759 *
7760 * Returns whether for any element of +self+, a given criterion is satisfied.
7761 *
7762 * With no block and no argument, returns whether any element of +self+ is truthy:
7763 *
7764 * [nil, false, []].any? # => true # Array object is truthy.
7765 * [nil, false, {}].any? # => true # Hash object is truthy.
7766 * [nil, false, ''].any? # => true # String object is truthy.
7767 * [nil, false].any? # => false # Nil and false are not truthy.
7768 *
7769 * With argument +object+ given,
7770 * returns whether <tt>object === ele</tt> for any element +ele+ in +self+:
7771 *
7772 * [nil, false, 0].any?(0) # => true
7773 * [nil, false, 1].any?(0) # => false
7774 * [nil, false, 'food'].any?(/foo/) # => true
7775 * [nil, false, 'food'].any?(/bar/) # => false
7776 *
7777 * With a block given,
7778 * calls the block with each element in +self+;
7779 * returns whether the block returns any truthy value:
7780 *
7781 * [0, 1, 2].any? {|ele| ele < 1 } # => true
7782 * [0, 1, 2].any? {|ele| ele < 0 } # => false
7783 *
7784 * With both a block and argument +object+ given,
7785 * ignores the block and uses +object+ as above.
7786 *
7787 * <b>Special case</b>: returns +false+ if +self+ is empty
7788 * (regardless of any given argument or block).
7789 *
7790 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
7791 */
7792
7793static VALUE
7794rb_ary_any_p(int argc, VALUE *argv, VALUE ary)
7795{
7796 long i, len = RARRAY_LEN(ary);
7797
7798 rb_check_arity(argc, 0, 1);
7799 if (!len) return Qfalse;
7800 if (argc) {
7801 if (rb_block_given_p()) {
7802 rb_warn("given block not used");
7803 }
7804 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7805 if (RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) return Qtrue;
7806 }
7807 }
7808 else if (!rb_block_given_p()) {
7809 for (i = 0; i < len; ++i) {
7810 if (RTEST(RARRAY_AREF(ary, i))) return Qtrue;
7811 }
7812 }
7813 else {
7814 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7815 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) return Qtrue;
7816 }
7817 }
7818 return Qfalse;
7819}
7820
7821/*
7822 * call-seq:
7823 * all? -> true or false
7824 * all?(object) -> true or false
7825 * all? {|element| ... } -> true or false
7826 *
7827 * Returns whether for every element of +self+,
7828 * a given criterion is satisfied.
7829 *
7830 * With no block and no argument,
7831 * returns whether every element of +self+ is truthy:
7832 *
7833 * [[], {}, '', 0, 0.0, Object.new].all? # => true # All truthy objects.
7834 * [[], {}, '', 0, 0.0, nil].all? # => false # nil is not truthy.
7835 * [[], {}, '', 0, 0.0, false].all? # => false # false is not truthy.
7836 *
7837 * With argument +object+ given, returns whether <tt>object === ele</tt>
7838 * for every element +ele+ in +self+:
7839 *
7840 * [0, 0, 0].all?(0) # => true
7841 * [0, 1, 2].all?(1) # => false
7842 * ['food', 'fool', 'foot'].all?(/foo/) # => true
7843 * ['food', 'drink'].all?(/foo/) # => false
7844 *
7845 * With a block given, calls the block with each element in +self+;
7846 * returns whether the block returns only truthy values:
7847 *
7848 * [0, 1, 2].all? { |ele| ele < 3 } # => true
7849 * [0, 1, 2].all? { |ele| ele < 2 } # => false
7850 *
7851 * With both a block and argument +object+ given,
7852 * ignores the block and uses +object+ as above.
7853 *
7854 * <b>Special case</b>: returns +true+ if +self+ is empty
7855 * (regardless of any given argument or block).
7856 *
7857 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
7858 */
7859
7860static VALUE
7861rb_ary_all_p(int argc, VALUE *argv, VALUE ary)
7862{
7863 long i, len = RARRAY_LEN(ary);
7864
7865 rb_check_arity(argc, 0, 1);
7866 if (!len) return Qtrue;
7867 if (argc) {
7868 if (rb_block_given_p()) {
7869 rb_warn("given block not used");
7870 }
7871 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7872 if (!RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) return Qfalse;
7873 }
7874 }
7875 else if (!rb_block_given_p()) {
7876 for (i = 0; i < len; ++i) {
7877 if (!RTEST(RARRAY_AREF(ary, i))) return Qfalse;
7878 }
7879 }
7880 else {
7881 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7882 if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) return Qfalse;
7883 }
7884 }
7885 return Qtrue;
7886}
7887
7888/*
7889 * call-seq:
7890 * none? -> true or false
7891 * none?(object) -> true or false
7892 * none? {|element| ... } -> true or false
7893 *
7894 * Returns +true+ if no element of +self+ meets a given criterion, +false+ otherwise.
7895 *
7896 * With no block given and no argument, returns +true+ if +self+ has no truthy elements,
7897 * +false+ otherwise:
7898 *
7899 * [nil, false].none? # => true
7900 * [nil, 0, false].none? # => false
7901 * [].none? # => true
7902 *
7903 * With argument +object+ given, returns +false+ if for any element +element+,
7904 * <tt>object === element</tt>; +true+ otherwise:
7905 *
7906 * ['food', 'drink'].none?(/bar/) # => true
7907 * ['food', 'drink'].none?(/foo/) # => false
7908 * [].none?(/foo/) # => true
7909 * [0, 1, 2].none?(3) # => true
7910 * [0, 1, 2].none?(1) # => false
7911 *
7912 * With a block given, calls the block with each element in +self+;
7913 * returns +true+ if the block returns no truthy value, +false+ otherwise:
7914 *
7915 * [0, 1, 2].none? {|element| element > 3 } # => true
7916 * [0, 1, 2].none? {|element| element > 1 } # => false
7917 *
7918 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
7919 */
7920
7921static VALUE
7922rb_ary_none_p(int argc, VALUE *argv, VALUE ary)
7923{
7924 long i, len = RARRAY_LEN(ary);
7925
7926 rb_check_arity(argc, 0, 1);
7927 if (!len) return Qtrue;
7928 if (argc) {
7929 if (rb_block_given_p()) {
7930 rb_warn("given block not used");
7931 }
7932 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7933 if (RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) return Qfalse;
7934 }
7935 }
7936 else if (!rb_block_given_p()) {
7937 for (i = 0; i < len; ++i) {
7938 if (RTEST(RARRAY_AREF(ary, i))) return Qfalse;
7939 }
7940 }
7941 else {
7942 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7943 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) return Qfalse;
7944 }
7945 }
7946 return Qtrue;
7947}
7948
7949/*
7950 * call-seq:
7951 * one? -> true or false
7952 * one? {|element| ... } -> true or false
7953 * one?(object) -> true or false
7954 *
7955 * Returns +true+ if exactly one element of +self+ meets a given criterion.
7956 *
7957 * With no block given and no argument, returns +true+ if +self+ has exactly one truthy element,
7958 * +false+ otherwise:
7959 *
7960 * [nil, 0].one? # => true
7961 * [0, 0].one? # => false
7962 * [nil, nil].one? # => false
7963 * [].one? # => false
7964 *
7965 * With a block given, calls the block with each element in +self+;
7966 * returns +true+ if the block a truthy value for exactly one element, +false+ otherwise:
7967 *
7968 * [0, 1, 2].one? {|element| element > 0 } # => false
7969 * [0, 1, 2].one? {|element| element > 1 } # => true
7970 * [0, 1, 2].one? {|element| element > 2 } # => false
7971 *
7972 * With argument +object+ given, returns +true+ if for exactly one element +element+, <tt>object === element</tt>;
7973 * +false+ otherwise:
7974 *
7975 * [0, 1, 2].one?(0) # => true
7976 * [0, 0, 1].one?(0) # => false
7977 * [1, 1, 2].one?(0) # => false
7978 * ['food', 'drink'].one?(/bar/) # => false
7979 * ['food', 'drink'].one?(/foo/) # => true
7980 * [].one?(/foo/) # => false
7981 *
7982 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
7983 */
7984
7985static VALUE
7986rb_ary_one_p(int argc, VALUE *argv, VALUE ary)
7987{
7988 long i, len = RARRAY_LEN(ary);
7989 VALUE result = Qfalse;
7990
7991 rb_check_arity(argc, 0, 1);
7992 if (!len) return Qfalse;
7993 if (argc) {
7994 if (rb_block_given_p()) {
7995 rb_warn("given block not used");
7996 }
7997 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7998 if (RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) {
7999 if (result) return Qfalse;
8000 result = Qtrue;
8001 }
8002 }
8003 }
8004 else if (!rb_block_given_p()) {
8005 for (i = 0; i < len; ++i) {
8006 if (RTEST(RARRAY_AREF(ary, i))) {
8007 if (result) return Qfalse;
8008 result = Qtrue;
8009 }
8010 }
8011 }
8012 else {
8013 for (i = 0; i < RARRAY_LEN(ary); ++i) {
8014 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) {
8015 if (result) return Qfalse;
8016 result = Qtrue;
8017 }
8018 }
8019 }
8020 return result;
8021}
8022
8023/*
8024 * call-seq:
8025 * dig(index, *identifiers) -> object
8026 *
8027 * Finds and returns the object in nested object
8028 * specified by +index+ and +identifiers+;
8029 * the nested objects may be instances of various classes.
8030 * See {Dig Methods}[rdoc-ref:dig_methods.rdoc].
8031 *
8032 * Examples:
8033 *
8034 * a = [:foo, [:bar, :baz, [:bat, :bam]]]
8035 * a.dig(1) # => [:bar, :baz, [:bat, :bam]]
8036 * a.dig(1, 2) # => [:bat, :bam]
8037 * a.dig(1, 2, 0) # => :bat
8038 * a.dig(1, 2, 3) # => nil
8039 *
8040 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
8041 */
8042
8043static VALUE
8044rb_ary_dig(int argc, VALUE *argv, VALUE self)
8045{
8047 self = rb_ary_at(self, *argv);
8048 if (!--argc) return self;
8049 ++argv;
8050 return rb_obj_dig(argc, argv, self, Qnil);
8051}
8052
8053static inline VALUE
8054finish_exact_sum(long n, VALUE r, VALUE v, int z)
8055{
8056 if (n != 0)
8057 v = rb_fix_plus(LONG2FIX(n), v);
8058 if (!UNDEF_P(r)) {
8059 v = rb_rational_plus(r, v);
8060 }
8061 else if (!n && z) {
8062 v = rb_fix_plus(LONG2FIX(0), v);
8063 }
8064 return v;
8065}
8066
8067/*
8068 * call-seq:
8069 * sum(init = 0) -> object
8070 * sum(init = 0) {|element| ... } -> object
8071 *
8072 * With no block given, returns the sum of +init+ and all elements of +self+;
8073 * for array +array+ and value +init+, equivalent to:
8074 *
8075 * sum = init
8076 * array.each {|element| sum += element }
8077 * sum
8078 *
8079 * For example, <tt>[e0, e1, e2].sum</tt> returns <tt>init + e0 + e1 + e2</tt>.
8080 *
8081 * Examples:
8082 *
8083 * [0, 1, 2, 3].sum # => 6
8084 * [0, 1, 2, 3].sum(100) # => 106
8085 * ['abc', 'def', 'ghi'].sum('jkl') # => "jklabcdefghi"
8086 * [[:foo, :bar], ['foo', 'bar']].sum([2, 3])
8087 * # => [2, 3, :foo, :bar, "foo", "bar"]
8088 *
8089 * The +init+ value and elements need not be numeric, but must all be <tt>+</tt>-compatible:
8090 *
8091 * # Raises TypeError: Array can't be coerced into Integer.
8092 * [[:foo, :bar], ['foo', 'bar']].sum(2)
8093 *
8094 * With a block given, calls the block with each element of +self+;
8095 * the block's return value (instead of the element itself) is used as the addend:
8096 *
8097 * ['zero', 1, :two].sum('Coerced and concatenated: ') {|element| element.to_s }
8098 * # => "Coerced and concatenated: zero1two"
8099 *
8100 * Notes:
8101 *
8102 * - Array#join and Array#flatten may be faster than Array#sum
8103 * for an array of strings or an array of arrays.
8104 * - Array#sum method may not respect method redefinition of "+" methods such as Integer#+.
8105 *
8106 */
8107
8108static VALUE
8109rb_ary_sum(int argc, VALUE *argv, VALUE ary)
8110{
8111 VALUE e, v, r;
8112 long i, n;
8113 int block_given;
8114
8115 v = (rb_check_arity(argc, 0, 1) ? argv[0] : LONG2FIX(0));
8116
8117 block_given = rb_block_given_p();
8118
8119 if (RARRAY_LEN(ary) == 0)
8120 return v;
8121
8122 n = 0;
8123 r = Qundef;
8124
8125 if (!FIXNUM_P(v) && !RB_BIGNUM_TYPE_P(v) && !RB_TYPE_P(v, T_RATIONAL)) {
8126 i = 0;
8127 goto init_is_a_value;
8128 }
8129
8130 for (i = 0; i < RARRAY_LEN(ary); i++) {
8131 e = RARRAY_AREF(ary, i);
8132 if (block_given)
8133 e = rb_yield(e);
8134 if (FIXNUM_P(e)) {
8135 n += FIX2LONG(e); /* should not overflow long type */
8136 if (!FIXABLE(n)) {
8137 v = rb_big_plus(LONG2NUM(n), v);
8138 n = 0;
8139 }
8140 }
8141 else if (RB_BIGNUM_TYPE_P(e))
8142 v = rb_big_plus(e, v);
8143 else if (RB_TYPE_P(e, T_RATIONAL)) {
8144 if (UNDEF_P(r))
8145 r = e;
8146 else
8147 r = rb_rational_plus(r, e);
8148 }
8149 else
8150 goto not_exact;
8151 }
8152 v = finish_exact_sum(n, r, v, argc!=0);
8153 return v;
8154
8155 not_exact:
8156 v = finish_exact_sum(n, r, v, i!=0);
8157
8158 if (RB_FLOAT_TYPE_P(e)) {
8159 /*
8160 * Kahan-Babuska balancing compensated summation algorithm
8161 * See https://link.springer.com/article/10.1007/s00607-005-0139-x
8162 */
8163 double f, c;
8164 double x, t;
8165
8166 f = NUM2DBL(v);
8167 c = 0.0;
8168 goto has_float_value;
8169 for (; i < RARRAY_LEN(ary); i++) {
8170 e = RARRAY_AREF(ary, i);
8171 if (block_given)
8172 e = rb_yield(e);
8173 if (RB_FLOAT_TYPE_P(e))
8174 has_float_value:
8175 x = RFLOAT_VALUE(e);
8176 else if (FIXNUM_P(e))
8177 x = FIX2LONG(e);
8178 else if (RB_BIGNUM_TYPE_P(e))
8179 x = rb_big2dbl(e);
8180 else if (RB_TYPE_P(e, T_RATIONAL))
8181 x = rb_num2dbl(e);
8182 else
8183 goto not_float;
8184
8185 if (isnan(f)) continue;
8186 if (isnan(x)) {
8187 f = x;
8188 continue;
8189 }
8190 if (isinf(x)) {
8191 if (isinf(f) && signbit(x) != signbit(f))
8192 f = NAN;
8193 else
8194 f = x;
8195 continue;
8196 }
8197 if (isinf(f)) continue;
8198
8199 t = f + x;
8200 if (fabs(f) >= fabs(x))
8201 c += ((f - t) + x);
8202 else
8203 c += ((x - t) + f);
8204 f = t;
8205 }
8206 f += c;
8207 return DBL2NUM(f);
8208
8209 not_float:
8210 v = DBL2NUM(f);
8211 }
8212
8213 goto has_some_value;
8214 init_is_a_value:
8215 for (; i < RARRAY_LEN(ary); i++) {
8216 e = RARRAY_AREF(ary, i);
8217 if (block_given)
8218 e = rb_yield(e);
8219 has_some_value:
8220 v = rb_funcall(v, idPLUS, 1, e);
8221 }
8222 return v;
8223}
8224
8225/* :nodoc: */
8226static VALUE
8227rb_ary_deconstruct(VALUE ary)
8228{
8229 return ary;
8230}
8231
8232/*
8233 * An \Array object is an ordered, integer-indexed collection of objects,
8234 * called _elements_;
8235 * the object represents
8236 * an {array data structure}[https://en.wikipedia.org/wiki/Array_(data_structure)].
8237 *
8238 * An element may be any object (even another array);
8239 * elements may be any mixture of objects of different types.
8240 *
8241 * Important data structures that use arrays include:
8242 *
8243 * - {Coordinate vector}[https://en.wikipedia.org/wiki/Coordinate_vector].
8244 * - {Matrix}[https://en.wikipedia.org/wiki/Matrix_(mathematics)].
8245 * - {Heap}[https://en.wikipedia.org/wiki/Heap_(data_structure)].
8246 * - {Hash table}[https://en.wikipedia.org/wiki/Hash_table].
8247 * - {Deque (double-ended queue)}[https://en.wikipedia.org/wiki/Double-ended_queue].
8248 * - {Queue}[https://en.wikipedia.org/wiki/Queue_(abstract_data_type)].
8249 * - {Stack}[https://en.wikipedia.org/wiki/Stack_(abstract_data_type)].
8250 *
8251 * There are also array-like data structures:
8252 *
8253 * - {Associative array}[https://en.wikipedia.org/wiki/Associative_array] (see Hash).
8254 * - {Directory}[https://en.wikipedia.org/wiki/Directory_(computing)] (see Dir).
8255 * - {Environment}[https://en.wikipedia.org/wiki/Environment_variable] (see ENV).
8256 * - {Set}[https://en.wikipedia.org/wiki/Set_(abstract_data_type)] (see Set).
8257 * - {String}[https://en.wikipedia.org/wiki/String_(computer_science)] (see String).
8258 *
8259 * == \Array Indexes
8260 *
8261 * \Array indexing starts at 0, as in C or Java.
8262 *
8263 * A non-negative index is an offset from the first element:
8264 *
8265 * - Index 0 indicates the first element.
8266 * - Index 1 indicates the second element.
8267 * - ...
8268 *
8269 * A negative index is an offset, backwards, from the end of the array:
8270 *
8271 * - Index -1 indicates the last element.
8272 * - Index -2 indicates the next-to-last element.
8273 * - ...
8274 *
8275 *
8276 * === In-Range and Out-of-Range Indexes
8277 *
8278 * A non-negative index is <i>in range</i> if and only if it is smaller than
8279 * the size of the array. For a 3-element array:
8280 *
8281 * - Indexes 0 through 2 are in range.
8282 * - Index 3 is out of range.
8283 *
8284 * A negative index is <i>in range</i> if and only if its absolute value is
8285 * not larger than the size of the array. For a 3-element array:
8286 *
8287 * - Indexes -1 through -3 are in range.
8288 * - Index -4 is out of range.
8289 *
8290 * === Effective Index
8291 *
8292 * Although the effective index into an array is always an integer,
8293 * some methods (both within class \Array and elsewhere)
8294 * accept one or more non-integer arguments that are
8295 * {integer-convertible objects}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
8296 *
8297 * == Creating Arrays
8298 *
8299 * You can create an \Array object explicitly with:
8300 *
8301 * - An {array literal}[rdoc-ref:syntax/literals.rdoc@Array+Literals]:
8302 *
8303 * [1, 'one', :one, [2, 'two', :two]]
8304 *
8305 * - A {%w or %W string-array Literal}[rdoc-ref:syntax/literals.rdoc@25w+and+-25W-3A+String-Array+Literals]:
8306 *
8307 * %w[foo bar baz] # => ["foo", "bar", "baz"]
8308 * %w[1 % *] # => ["1", "%", "*"]
8309 *
8310 * - A {%i or %I symbol-array Literal}[rdoc-ref:syntax/literals.rdoc@25i+and+-25I-3A+Symbol-Array+Literals]:
8311 *
8312 * %i[foo bar baz] # => [:foo, :bar, :baz]
8313 * %i[1 % *] # => [:"1", :%, :*]
8314 *
8315 * - Method Kernel#Array:
8316 *
8317 * Array(["a", "b"]) # => ["a", "b"]
8318 * Array(1..5) # => [1, 2, 3, 4, 5]
8319 * Array(key: :value) # => [[:key, :value]]
8320 * Array(nil) # => []
8321 * Array(1) # => [1]
8322 * Array({:a => "a", :b => "b"}) # => [[:a, "a"], [:b, "b"]]
8323 *
8324 * - Method Array.new:
8325 *
8326 * Array.new # => []
8327 * Array.new(3) # => [nil, nil, nil]
8328 * Array.new(4) {Hash.new} # => [{}, {}, {}, {}]
8329 * Array.new(3, true) # => [true, true, true]
8330 *
8331 * Note that the last example above populates the array
8332 * with references to the same object.
8333 * This is recommended only in cases where that object is a natively immutable object
8334 * such as a symbol, a numeric, +nil+, +true+, or +false+.
8335 *
8336 * Another way to create an array with various objects, using a block;
8337 * this usage is safe for mutable objects such as hashes, strings or
8338 * other arrays:
8339 *
8340 * Array.new(4) {|i| i.to_s } # => ["0", "1", "2", "3"]
8341 *
8342 * Here is a way to create a multi-dimensional array:
8343 *
8344 * Array.new(3) {Array.new(3)}
8345 * # => [[nil, nil, nil], [nil, nil, nil], [nil, nil, nil]]
8346 *
8347 * A number of Ruby methods, both in the core and in the standard library,
8348 * provide instance method +to_a+, which converts an object to an array.
8349 *
8350 * - ARGF#to_a
8351 * - Array#to_a
8352 * - Enumerable#to_a
8353 * - Hash#to_a
8354 * - MatchData#to_a
8355 * - NilClass#to_a
8356 * - OptionParser#to_a
8357 * - Range#to_a
8358 * - Set#to_a
8359 * - Struct#to_a
8360 * - Time#to_a
8361 * - Benchmark::Tms#to_a
8362 * - CSV::Table#to_a
8363 * - Enumerator::Lazy#to_a
8364 * - Gem::List#to_a
8365 * - Gem::NameTuple#to_a
8366 * - Gem::Platform#to_a
8367 * - Gem::RequestSet::Lockfile::Tokenizer#to_a
8368 * - Gem::SourceList#to_a
8369 * - OpenSSL::X509::Extension#to_a
8370 * - OpenSSL::X509::Name#to_a
8371 * - Racc::ISet#to_a
8372 * - Rinda::RingFinger#to_a
8373 * - Ripper::Lexer::Elem#to_a
8374 * - RubyVM::InstructionSequence#to_a
8375 * - YAML::DBM#to_a
8376 *
8377 * == Example Usage
8378 *
8379 * In addition to the methods it mixes in through the Enumerable module,
8380 * class \Array has proprietary methods for accessing, searching and otherwise
8381 * manipulating arrays.
8382 *
8383 * Some of the more common ones are illustrated below.
8384 *
8385 * == Accessing Elements
8386 *
8387 * Elements in an array can be retrieved using the Array#[] method. It can
8388 * take a single integer argument (a numeric index), a pair of arguments
8389 * (start and length) or a range. Negative indices start counting from the end,
8390 * with -1 being the last element.
8391 *
8392 * arr = [1, 2, 3, 4, 5, 6]
8393 * arr[2] #=> 3
8394 * arr[100] #=> nil
8395 * arr[-3] #=> 4
8396 * arr[2, 3] #=> [3, 4, 5]
8397 * arr[1..4] #=> [2, 3, 4, 5]
8398 * arr[1..-3] #=> [2, 3, 4]
8399 *
8400 * Another way to access a particular array element is by using the #at method
8401 *
8402 * arr.at(0) #=> 1
8403 *
8404 * The #slice method works in an identical manner to Array#[].
8405 *
8406 * To raise an error for indices outside of the array bounds or else to
8407 * provide a default value when that happens, you can use #fetch.
8408 *
8409 * arr = ['a', 'b', 'c', 'd', 'e', 'f']
8410 * arr.fetch(100) #=> IndexError: index 100 outside of array bounds: -6...6
8411 * arr.fetch(100, "oops") #=> "oops"
8412 *
8413 * The special methods #first and #last will return the first and last
8414 * elements of an array, respectively.
8415 *
8416 * arr.first #=> 1
8417 * arr.last #=> 6
8418 *
8419 * To return the first +n+ elements of an array, use #take
8420 *
8421 * arr.take(3) #=> [1, 2, 3]
8422 *
8423 * #drop does the opposite of #take, by returning the elements after +n+
8424 * elements have been dropped:
8425 *
8426 * arr.drop(3) #=> [4, 5, 6]
8427 *
8428 * == Obtaining Information about an \Array
8429 *
8430 * An array keeps track of its own length at all times. To query an array
8431 * about the number of elements it contains, use #length, #count or #size.
8432 *
8433 * browsers = ['Chrome', 'Firefox', 'Safari', 'Opera', 'IE']
8434 * browsers.length #=> 5
8435 * browsers.count #=> 5
8436 *
8437 * To check whether an array contains any elements at all
8438 *
8439 * browsers.empty? #=> false
8440 *
8441 * To check whether a particular item is included in the array
8442 *
8443 * browsers.include?('Konqueror') #=> false
8444 *
8445 * == Adding Items to an \Array
8446 *
8447 * Items can be added to the end of an array by using either #push or #<<
8448 *
8449 * arr = [1, 2, 3, 4]
8450 * arr.push(5) #=> [1, 2, 3, 4, 5]
8451 * arr << 6 #=> [1, 2, 3, 4, 5, 6]
8452 *
8453 * #unshift will add a new item to the beginning of an array.
8454 *
8455 * arr.unshift(0) #=> [0, 1, 2, 3, 4, 5, 6]
8456 *
8457 * With #insert you can add a new element to an array at any position.
8458 *
8459 * arr.insert(3, 'apple') #=> [0, 1, 2, 'apple', 3, 4, 5, 6]
8460 *
8461 * Using the #insert method, you can also insert multiple values at once:
8462 *
8463 * arr.insert(3, 'orange', 'pear', 'grapefruit')
8464 * #=> [0, 1, 2, "orange", "pear", "grapefruit", "apple", 3, 4, 5, 6]
8465 *
8466 * == Removing Items from an \Array
8467 *
8468 * The method #pop removes the last element in an array and returns it:
8469 *
8470 * arr = [1, 2, 3, 4, 5, 6]
8471 * arr.pop #=> 6
8472 * arr #=> [1, 2, 3, 4, 5]
8473 *
8474 * To retrieve and at the same time remove the first item, use #shift:
8475 *
8476 * arr.shift #=> 1
8477 * arr #=> [2, 3, 4, 5]
8478 *
8479 * To delete an element at a particular index:
8480 *
8481 * arr.delete_at(2) #=> 4
8482 * arr #=> [2, 3, 5]
8483 *
8484 * To delete a particular element anywhere in an array, use #delete:
8485 *
8486 * arr = [1, 2, 2, 3]
8487 * arr.delete(2) #=> 2
8488 * arr #=> [1,3]
8489 *
8490 * A useful method if you need to remove +nil+ values from an array is
8491 * #compact:
8492 *
8493 * arr = ['foo', 0, nil, 'bar', 7, 'baz', nil]
8494 * arr.compact #=> ['foo', 0, 'bar', 7, 'baz']
8495 * arr #=> ['foo', 0, nil, 'bar', 7, 'baz', nil]
8496 * arr.compact! #=> ['foo', 0, 'bar', 7, 'baz']
8497 * arr #=> ['foo', 0, 'bar', 7, 'baz']
8498 *
8499 * Another common need is to remove duplicate elements from an array.
8500 *
8501 * It has the non-destructive #uniq, and destructive method #uniq!
8502 *
8503 * arr = [2, 5, 6, 556, 6, 6, 8, 9, 0, 123, 556]
8504 * arr.uniq #=> [2, 5, 6, 556, 8, 9, 0, 123]
8505 *
8506 * == Iterating over an \Array
8507 *
8508 * Like all classes that include the Enumerable module, class \Array has an each
8509 * method, which defines what elements should be iterated over and how. In
8510 * case of Array#each, all elements in +self+ are yielded to
8511 * the supplied block in sequence.
8512 *
8513 * Note that this operation leaves the array unchanged.
8514 *
8515 * arr = [1, 2, 3, 4, 5]
8516 * arr.each {|a| print a -= 10, " "}
8517 * # prints: -9 -8 -7 -6 -5
8518 * #=> [1, 2, 3, 4, 5]
8519 *
8520 * Another sometimes useful iterator is #reverse_each which will iterate over
8521 * the elements in the array in reverse order.
8522 *
8523 * words = %w[first second third fourth fifth sixth]
8524 * str = ""
8525 * words.reverse_each {|word| str += "#{word} "}
8526 * p str #=> "sixth fifth fourth third second first "
8527 *
8528 * The #map method can be used to create a new array based on the original
8529 * array, but with the values modified by the supplied block:
8530 *
8531 * arr.map {|a| 2*a} #=> [2, 4, 6, 8, 10]
8532 * arr #=> [1, 2, 3, 4, 5]
8533 * arr.map! {|a| a**2} #=> [1, 4, 9, 16, 25]
8534 * arr #=> [1, 4, 9, 16, 25]
8535 *
8536 *
8537 * == Selecting Items from an \Array
8538 *
8539 * Elements can be selected from an array according to criteria defined in a
8540 * block. The selection can happen in a destructive or a non-destructive
8541 * manner. While the destructive operations will modify the array they were
8542 * called on, the non-destructive methods usually return a new array with the
8543 * selected elements, but leave the original array unchanged.
8544 *
8545 * === Non-destructive Selection
8546 *
8547 * arr = [1, 2, 3, 4, 5, 6]
8548 * arr.select {|a| a > 3} #=> [4, 5, 6]
8549 * arr.reject {|a| a < 3} #=> [3, 4, 5, 6]
8550 * arr.drop_while {|a| a < 4} #=> [4, 5, 6]
8551 * arr #=> [1, 2, 3, 4, 5, 6]
8552 *
8553 * === Destructive Selection
8554 *
8555 * #select! and #reject! are the corresponding destructive methods to #select
8556 * and #reject
8557 *
8558 * Similar to #select vs. #reject, #delete_if and #keep_if have the exact
8559 * opposite result when supplied with the same block:
8560 *
8561 * arr.delete_if {|a| a < 4} #=> [4, 5, 6]
8562 * arr #=> [4, 5, 6]
8563 *
8564 * arr = [1, 2, 3, 4, 5, 6]
8565 * arr.keep_if {|a| a < 4} #=> [1, 2, 3]
8566 * arr #=> [1, 2, 3]
8567 *
8568 * == What's Here
8569 *
8570 * First, what's elsewhere. Class \Array:
8571 *
8572 * - Inherits from {class Object}[rdoc-ref:Object@What-27s+Here].
8573 * - Includes {module Enumerable}[rdoc-ref:Enumerable@What-27s+Here],
8574 * which provides dozens of additional methods.
8575 *
8576 * Here, class \Array provides methods that are useful for:
8577 *
8578 * - {Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array]
8579 * - {Querying}[rdoc-ref:Array@Methods+for+Querying]
8580 * - {Comparing}[rdoc-ref:Array@Methods+for+Comparing]
8581 * - {Fetching}[rdoc-ref:Array@Methods+for+Fetching]
8582 * - {Assigning}[rdoc-ref:Array@Methods+for+Assigning]
8583 * - {Deleting}[rdoc-ref:Array@Methods+for+Deleting]
8584 * - {Combining}[rdoc-ref:Array@Methods+for+Combining]
8585 * - {Iterating}[rdoc-ref:Array@Methods+for+Iterating]
8586 * - {Converting}[rdoc-ref:Array@Methods+for+Converting]
8587 * - {And more....}[rdoc-ref:Array@Other+Methods]
8588 *
8589 * === Methods for Creating an \Array
8590 *
8591 * - ::[]: Returns a new array populated with given objects.
8592 * - ::new: Returns a new array.
8593 * - ::try_convert: Returns a new array created from a given object.
8594 *
8595 * See also {Creating Arrays}[rdoc-ref:Array@Creating+Arrays].
8596 *
8597 * === Methods for Querying
8598 *
8599 * - #all?: Returns whether all elements meet a given criterion.
8600 * - #any?: Returns whether any element meets a given criterion.
8601 * - #count: Returns the count of elements that meet a given criterion.
8602 * - #empty?: Returns whether there are no elements.
8603 * - #find_index (aliased as #index): Returns the index of the first element that meets a given criterion.
8604 * - #hash: Returns the integer hash code.
8605 * - #include?: Returns whether any element <tt>==</tt> a given object.
8606 * - #length (aliased as #size): Returns the count of elements.
8607 * - #none?: Returns whether no element <tt>==</tt> a given object.
8608 * - #one?: Returns whether exactly one element <tt>==</tt> a given object.
8609 * - #rindex: Returns the index of the last element that meets a given criterion.
8610 *
8611 * === Methods for Comparing
8612 *
8613 * - #<=>: Returns -1, 0, or 1, as +self+ is less than, equal to, or greater than a given object.
8614 * - #==: Returns whether each element in +self+ is <tt>==</tt> to the corresponding element in a given object.
8615 * - #eql?: Returns whether each element in +self+ is <tt>eql?</tt> to the corresponding element in a given object.
8616
8617 * === Methods for Fetching
8618 *
8619 * These methods do not modify +self+.
8620 *
8621 * - #[] (aliased as #slice): Returns consecutive elements as determined by a given argument.
8622 * - #assoc: Returns the first element that is an array whose first element <tt>==</tt> a given object.
8623 * - #at: Returns the element at a given offset.
8624 * - #bsearch: Returns an element selected via a binary search as determined by a given block.
8625 * - #bsearch_index: Returns the index of an element selected via a binary search as determined by a given block.
8626 * - #compact: Returns an array containing all non-+nil+ elements.
8627 * - #dig: Returns the object in nested objects that is specified by a given index and additional arguments.
8628 * - #drop: Returns trailing elements as determined by a given index.
8629 * - #drop_while: Returns trailing elements as determined by a given block.
8630 * - #fetch: Returns the element at a given offset.
8631 * - #fetch_values: Returns elements at given offsets.
8632 * - #first: Returns one or more leading elements.
8633 * - #last: Returns one or more trailing elements.
8634 * - #max: Returns one or more maximum-valued elements, as determined by <tt>#<=></tt> or a given block.
8635 * - #min: Returns one or more minimum-valued elements, as determined by <tt>#<=></tt> or a given block.
8636 * - #minmax: Returns the minimum-valued and maximum-valued elements, as determined by <tt>#<=></tt> or a given block.
8637 * - #rassoc: Returns the first element that is an array whose second element <tt>==</tt> a given object.
8638 * - #reject: Returns an array containing elements not rejected by a given block.
8639 * - #reverse: Returns all elements in reverse order.
8640 * - #rotate: Returns all elements with some rotated from one end to the other.
8641 * - #sample: Returns one or more random elements.
8642 * - #select (aliased as #filter): Returns an array containing elements selected by a given block.
8643 * - #shuffle: Returns elements in a random order.
8644 * - #sort: Returns all elements in an order determined by <tt>#<=></tt> or a given block.
8645 * - #take: Returns leading elements as determined by a given index.
8646 * - #take_while: Returns leading elements as determined by a given block.
8647 * - #uniq: Returns an array containing non-duplicate elements.
8648 * - #values_at: Returns the elements at given offsets.
8649 *
8650 * === Methods for Assigning
8651 *
8652 * These methods add, replace, or reorder elements in +self+.
8653 *
8654 * - #<<: Appends an element.
8655 * - #[]=: Assigns specified elements with a given object.
8656 * - #concat: Appends all elements from given arrays.
8657 * - #fill: Replaces specified elements with specified objects.
8658 * - #flatten!: Replaces each nested array in +self+ with the elements from that array.
8659 * - #initialize_copy (aliased as #replace): Replaces the content of +self+ with the content of a given array.
8660 * - #insert: Inserts given objects at a given offset; does not replace elements.
8661 * - #push (aliased as #append): Appends elements.
8662 * - #reverse!: Replaces +self+ with its elements reversed.
8663 * - #rotate!: Replaces +self+ with its elements rotated.
8664 * - #shuffle!: Replaces +self+ with its elements in random order.
8665 * - #sort!: Replaces +self+ with its elements sorted, as determined by <tt>#<=></tt> or a given block.
8666 * - #sort_by!: Replaces +self+ with its elements sorted, as determined by a given block.
8667 * - #unshift (aliased as #prepend): Prepends leading elements.
8668 *
8669 * === Methods for Deleting
8670 *
8671 * Each of these methods removes elements from +self+:
8672 *
8673 * - #clear: Removes all elements.
8674 * - #compact!: Removes all +nil+ elements.
8675 * - #delete: Removes elements equal to a given object.
8676 * - #delete_at: Removes the element at a given offset.
8677 * - #delete_if: Removes elements specified by a given block.
8678 * - #keep_if: Removes elements not specified by a given block.
8679 * - #pop: Removes and returns the last element.
8680 * - #reject!: Removes elements specified by a given block.
8681 * - #select! (aliased as #filter!): Removes elements not specified by a given block.
8682 * - #shift: Removes and returns the first element.
8683 * - #slice!: Removes and returns a sequence of elements.
8684 * - #uniq!: Removes duplicates.
8685 *
8686 * === Methods for Combining
8687 *
8688 * - #&: Returns an array containing elements found both in +self+ and a given array.
8689 * - #+: Returns an array containing all elements of +self+ followed by all elements of a given array.
8690 * - #-: Returns an array containing all elements of +self+ that are not found in a given array.
8691 * - #|: Returns an array containing all element of +self+ and all elements of a given array, duplicates removed.
8692 * - #difference: Returns an array containing all elements of +self+ that are not found in any of the given arrays..
8693 * - #intersection: Returns an array containing elements found both in +self+ and in each given array.
8694 * - #product: Returns or yields all combinations of elements from +self+ and given arrays.
8695 * - #reverse: Returns an array containing all elements of +self+ in reverse order.
8696 * - #union: Returns an array containing all elements of +self+ and all elements of given arrays, duplicates removed.
8697 *
8698 * === Methods for Iterating
8699 *
8700 * - #combination: Calls a given block with combinations of elements of +self+; a combination does not use the same element more than once.
8701 * - #cycle: Calls a given block with each element, then does so again, for a specified number of times, or forever.
8702 * - #each: Passes each element to a given block.
8703 * - #each_index: Passes each element index to a given block.
8704 * - #permutation: Calls a given block with permutations of elements of +self+; a permutation does not use the same element more than once.
8705 * - #repeated_combination: Calls a given block with combinations of elements of +self+; a combination may use the same element more than once.
8706 * - #repeated_permutation: Calls a given block with permutations of elements of +self+; a permutation may use the same element more than once.
8707 * - #reverse_each: Passes each element, in reverse order, to a given block.
8708 *
8709 * === Methods for Converting
8710 *
8711 * - #collect (aliased as #map): Returns an array containing the block return-value for each element.
8712 * - #collect! (aliased as #map!): Replaces each element with a block return-value.
8713 * - #flatten: Returns an array that is a recursive flattening of +self+.
8714 * - #inspect (aliased as #to_s): Returns a new String containing the elements.
8715 * - #join: Returns a newsString containing the elements joined by the field separator.
8716 * - #to_a: Returns +self+ or a new array containing all elements.
8717 * - #to_ary: Returns +self+.
8718 * - #to_h: Returns a new hash formed from the elements.
8719 * - #transpose: Transposes +self+, which must be an array of arrays.
8720 * - #zip: Returns a new array of arrays containing +self+ and given arrays.
8721 *
8722 * === Other Methods
8723 *
8724 * - #*: Returns one of the following:
8725 *
8726 * - With integer argument +n+, a new array that is the concatenation
8727 * of +n+ copies of +self+.
8728 * - With string argument +field_separator+, a new string that is equivalent to
8729 * <tt>join(field_separator)</tt>.
8730 *
8731 * - #pack: Packs the elements into a binary sequence.
8732 * - #sum: Returns a sum of elements according to either <tt>+</tt> or a given block.
8733 */
8734
8735void
8736Init_Array(void)
8737{
8738 fake_ary_flags = init_fake_ary_flags();
8739
8740 rb_cArray = rb_define_class("Array", rb_cObject);
8742
8743 rb_define_alloc_func(rb_cArray, empty_ary_alloc);
8744 rb_define_singleton_method(rb_cArray, "new", rb_ary_s_new, -1);
8745 rb_define_singleton_method(rb_cArray, "[]", rb_ary_s_create, -1);
8746 rb_define_singleton_method(rb_cArray, "try_convert", rb_ary_s_try_convert, 1);
8747 rb_define_method(rb_cArray, "initialize", rb_ary_initialize, -1);
8748 rb_define_method(rb_cArray, "initialize_copy", rb_ary_replace, 1);
8749
8750 rb_define_method(rb_cArray, "inspect", rb_ary_inspect, 0);
8751 rb_define_alias(rb_cArray, "to_s", "inspect");
8752 rb_define_method(rb_cArray, "to_a", rb_ary_to_a, 0);
8753 rb_define_method(rb_cArray, "to_h", rb_ary_to_h, 0);
8754 rb_define_method(rb_cArray, "to_ary", rb_ary_to_ary_m, 0);
8755
8756 rb_define_method(rb_cArray, "==", rb_ary_equal, 1);
8757 rb_define_method(rb_cArray, "eql?", rb_ary_eql, 1);
8758 rb_define_method(rb_cArray, "hash", rb_ary_hash, 0);
8759
8760 rb_define_method(rb_cArray, "[]", rb_ary_aref, -1);
8761 rb_define_method(rb_cArray, "[]=", rb_ary_aset, -1);
8762 rb_define_method(rb_cArray, "at", rb_ary_at, 1);
8763 rb_define_method(rb_cArray, "fetch", rb_ary_fetch, -1);
8764 rb_define_method(rb_cArray, "concat", rb_ary_concat_multi, -1);
8765 rb_define_method(rb_cArray, "union", rb_ary_union_multi, -1);
8766 rb_define_method(rb_cArray, "difference", rb_ary_difference_multi, -1);
8767 rb_define_method(rb_cArray, "intersection", rb_ary_intersection_multi, -1);
8768 rb_define_method(rb_cArray, "intersect?", rb_ary_intersect_p, 1);
8769 rb_define_method(rb_cArray, "<<", rb_ary_push, 1);
8770 rb_define_method(rb_cArray, "push", rb_ary_push_m, -1);
8771 rb_define_alias(rb_cArray, "append", "push");
8772 rb_define_method(rb_cArray, "pop", rb_ary_pop_m, -1);
8773 rb_define_method(rb_cArray, "shift", rb_ary_shift_m, -1);
8774 rb_define_method(rb_cArray, "unshift", rb_ary_unshift_m, -1);
8775 rb_define_alias(rb_cArray, "prepend", "unshift");
8776 rb_define_method(rb_cArray, "insert", rb_ary_insert, -1);
8777 rb_define_method(rb_cArray, "each", rb_ary_each, 0);
8778 rb_define_method(rb_cArray, "each_index", rb_ary_each_index, 0);
8779 rb_define_method(rb_cArray, "reverse_each", rb_ary_reverse_each, 0);
8780 rb_define_method(rb_cArray, "length", rb_ary_length, 0);
8781 rb_define_method(rb_cArray, "size", rb_ary_length, 0);
8782 rb_define_method(rb_cArray, "empty?", rb_ary_empty_p, 0);
8783 rb_define_method(rb_cArray, "find_index", rb_ary_index, -1);
8784 rb_define_method(rb_cArray, "index", rb_ary_index, -1);
8785 rb_define_method(rb_cArray, "rindex", rb_ary_rindex, -1);
8786 rb_define_method(rb_cArray, "join", rb_ary_join_m, -1);
8787 rb_define_method(rb_cArray, "reverse", rb_ary_reverse_m, 0);
8788 rb_define_method(rb_cArray, "reverse!", rb_ary_reverse_bang, 0);
8789 rb_define_method(rb_cArray, "rotate", rb_ary_rotate_m, -1);
8790 rb_define_method(rb_cArray, "rotate!", rb_ary_rotate_bang, -1);
8791 rb_define_method(rb_cArray, "sort", rb_ary_sort, 0);
8792 rb_define_method(rb_cArray, "sort!", rb_ary_sort_bang, 0);
8793 rb_define_method(rb_cArray, "sort_by!", rb_ary_sort_by_bang, 0);
8794 rb_define_method(rb_cArray, "collect", rb_ary_collect, 0);
8795 rb_define_method(rb_cArray, "collect!", rb_ary_collect_bang, 0);
8796 rb_define_method(rb_cArray, "map", rb_ary_collect, 0);
8797 rb_define_method(rb_cArray, "map!", rb_ary_collect_bang, 0);
8798 rb_define_method(rb_cArray, "select", rb_ary_select, 0);
8799 rb_define_method(rb_cArray, "select!", rb_ary_select_bang, 0);
8800 rb_define_method(rb_cArray, "filter", rb_ary_select, 0);
8801 rb_define_method(rb_cArray, "filter!", rb_ary_select_bang, 0);
8802 rb_define_method(rb_cArray, "keep_if", rb_ary_keep_if, 0);
8803 rb_define_method(rb_cArray, "values_at", rb_ary_values_at, -1);
8804 rb_define_method(rb_cArray, "delete", rb_ary_delete, 1);
8805 rb_define_method(rb_cArray, "delete_at", rb_ary_delete_at_m, 1);
8806 rb_define_method(rb_cArray, "delete_if", rb_ary_delete_if, 0);
8807 rb_define_method(rb_cArray, "reject", rb_ary_reject, 0);
8808 rb_define_method(rb_cArray, "reject!", rb_ary_reject_bang, 0);
8809 rb_define_method(rb_cArray, "zip", rb_ary_zip, -1);
8810 rb_define_method(rb_cArray, "transpose", rb_ary_transpose, 0);
8811 rb_define_method(rb_cArray, "replace", rb_ary_replace, 1);
8812 rb_define_method(rb_cArray, "clear", rb_ary_clear, 0);
8813 rb_define_method(rb_cArray, "fill", rb_ary_fill, -1);
8814 rb_define_method(rb_cArray, "include?", rb_ary_includes, 1);
8815 rb_define_method(rb_cArray, "<=>", rb_ary_cmp, 1);
8816
8817 rb_define_method(rb_cArray, "slice", rb_ary_aref, -1);
8818 rb_define_method(rb_cArray, "slice!", rb_ary_slice_bang, -1);
8819
8820 rb_define_method(rb_cArray, "assoc", rb_ary_assoc, 1);
8821 rb_define_method(rb_cArray, "rassoc", rb_ary_rassoc, 1);
8822
8823 rb_define_method(rb_cArray, "+", rb_ary_plus, 1);
8824 rb_define_method(rb_cArray, "*", rb_ary_times, 1);
8825
8826 rb_define_method(rb_cArray, "-", rb_ary_diff, 1);
8827 rb_define_method(rb_cArray, "&", rb_ary_and, 1);
8828 rb_define_method(rb_cArray, "|", rb_ary_or, 1);
8829
8830 rb_define_method(rb_cArray, "max", rb_ary_max, -1);
8831 rb_define_method(rb_cArray, "min", rb_ary_min, -1);
8832 rb_define_method(rb_cArray, "minmax", rb_ary_minmax, 0);
8833
8834 rb_define_method(rb_cArray, "uniq", rb_ary_uniq, 0);
8835 rb_define_method(rb_cArray, "uniq!", rb_ary_uniq_bang, 0);
8836 rb_define_method(rb_cArray, "compact", rb_ary_compact, 0);
8837 rb_define_method(rb_cArray, "compact!", rb_ary_compact_bang, 0);
8838 rb_define_method(rb_cArray, "flatten", rb_ary_flatten, -1);
8839 rb_define_method(rb_cArray, "flatten!", rb_ary_flatten_bang, -1);
8840 rb_define_method(rb_cArray, "count", rb_ary_count, -1);
8841 rb_define_method(rb_cArray, "cycle", rb_ary_cycle, -1);
8842 rb_define_method(rb_cArray, "permutation", rb_ary_permutation, -1);
8843 rb_define_method(rb_cArray, "combination", rb_ary_combination, 1);
8844 rb_define_method(rb_cArray, "repeated_permutation", rb_ary_repeated_permutation, 1);
8845 rb_define_method(rb_cArray, "repeated_combination", rb_ary_repeated_combination, 1);
8846 rb_define_method(rb_cArray, "product", rb_ary_product, -1);
8847
8848 rb_define_method(rb_cArray, "take", rb_ary_take, 1);
8849 rb_define_method(rb_cArray, "take_while", rb_ary_take_while, 0);
8850 rb_define_method(rb_cArray, "drop", rb_ary_drop, 1);
8851 rb_define_method(rb_cArray, "drop_while", rb_ary_drop_while, 0);
8852 rb_define_method(rb_cArray, "bsearch", rb_ary_bsearch, 0);
8853 rb_define_method(rb_cArray, "bsearch_index", rb_ary_bsearch_index, 0);
8854 rb_define_method(rb_cArray, "any?", rb_ary_any_p, -1);
8855 rb_define_method(rb_cArray, "all?", rb_ary_all_p, -1);
8856 rb_define_method(rb_cArray, "none?", rb_ary_none_p, -1);
8857 rb_define_method(rb_cArray, "one?", rb_ary_one_p, -1);
8858 rb_define_method(rb_cArray, "dig", rb_ary_dig, -1);
8859 rb_define_method(rb_cArray, "sum", rb_ary_sum, -1);
8860 rb_define_method(rb_cArray, "freeze", rb_ary_freeze, 0);
8861
8862 rb_define_method(rb_cArray, "deconstruct", rb_ary_deconstruct, 0);
8863
8864 rb_cArray_empty_frozen = rb_ary_freeze(rb_ary_new());
8865 rb_vm_register_global_object(rb_cArray_empty_frozen);
8866}
8867
8868#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 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:1187
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition class.c:980
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
Definition class.c:2345
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:2635
int rb_block_given_p(void)
Determines if the current method is given a block.
Definition eval.c:937
#define FL_UNSET_RAW
Old name of RB_FL_UNSET_RAW.
Definition fl_type.h:134
#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:137
#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:129
#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:131
#define FL_FREEZE
Old name of RUBY_FL_FREEZE.
Definition fl_type.h:67
#define NUM2LONG
Old name of RB_NUM2LONG.
Definition long.h:51
#define FL_UNSET
Old name of RB_FL_UNSET.
Definition fl_type.h:133
#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:130
#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:2108
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.
Definition array.c:41
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:2139
VALUE rb_obj_frozen_p(VALUE obj)
Just calls RB_OBJ_FROZEN() inside.
Definition object.c:1296
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:680
double rb_num2dbl(VALUE num)
Converts an instance of rb_cNumeric into C's double.
Definition object.c:3739
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:865
VALUE rb_obj_freeze(VALUE obj)
Just calls rb_obj_freeze_inline() inside.
Definition object.c:1284
#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:1099
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
Defines RBIMPL_HAS_BUILTIN.
#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_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:4034
void rb_str_set_len(VALUE str, long len)
Overwrites the length of the string.
Definition string.c:3658
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:4493
VALUE rb_check_string_type(VALUE obj)
Try converting an object to its stringised representation using its to_str method,...
Definition string.c:3238
VALUE rb_str_buf_new(long capa)
Allocates a "string buffer".
Definition string.c:2021
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:2153
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:2958
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:1366
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:1388
VALUE rb_yield(VALUE val)
Yields the block.
Definition vm_eval.c:1354
#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:449
#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:200
const char * wrap_struct_name
Name of structs of this kind.
Definition rtypeddata.h:207
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