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