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