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