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