Ruby 4.1.0dev (2026-10-28 revision 637bd7cba1bd5a89b4128eac4cb389a8e236b5b3)
array.c (637bd7cba1bd5a89b4128eac4cb389a8e236b5b3)
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 = FIX2LONG(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, FIX2LONG(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 = FIX2LONG(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// FIX2LONG 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 FIX2LONG(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, FIX2LONG(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 LONG2FIX(FIX2LONG(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 * each_index {|index| ... } -> self
2856 * each_index -> new_enumerator
2857 *
2858 * With a block given, iterates over the elements of +self+,
2859 * passing each <i>array index</i> to the block;
2860 * returns +self+:
2861 *
2862 * a = [:foo, 'bar', 2]
2863 * a.each_index {|index| puts "#{index} #{a[index]}" }
2864 *
2865 * Output:
2866 *
2867 * 0 foo
2868 * 1 bar
2869 * 2 2
2870 *
2871 * Allows the array to be modified during iteration:
2872 *
2873 * a = [:foo, 'bar', 2]
2874 * a.each_index {|index| puts index; a.clear if index > 0 }
2875 * a # => []
2876 *
2877 * Output:
2878 *
2879 * 0
2880 * 1
2881 *
2882 * With no block given, returns a new Enumerator.
2883 *
2884 * Related: see {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
2885 */
2886
2887static VALUE
2888rb_ary_each_index(VALUE ary)
2889{
2890 rb_len_t i;
2891 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
2892
2893 for (i=0; i<RARRAY_LEN(ary); i++) {
2894 rb_yield(LEN2NUM(i));
2895 }
2896 return ary;
2897}
2898
2899/*
2900 * call-seq:
2901 * reverse_each {|element| ... } -> self
2902 * reverse_each -> Enumerator
2903 *
2904 * When a block given, iterates backwards over the elements of +self+,
2905 * passing, in reverse order, each element to the block;
2906 * returns +self+:
2907 *
2908 * a = []
2909 * [0, 1, 2].reverse_each {|element| a.push(element) }
2910 * a # => [2, 1, 0]
2911 *
2912 * Allows the array to be modified during iteration:
2913 *
2914 * a = ['a', 'b', 'c']
2915 * a.reverse_each {|element| a.clear if element.start_with?('b') }
2916 * a # => []
2917 *
2918 * When no block given, returns a new Enumerator.
2919 *
2920 * Related: see {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
2921 */
2922
2923static VALUE
2924rb_ary_reverse_each(VALUE ary)
2925{
2926 rb_len_t len;
2927
2928 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
2929 len = RARRAY_LEN(ary);
2930 while (len--) {
2931 rb_len_t nlen;
2933 nlen = RARRAY_LEN(ary);
2934 if (nlen < len) {
2935 len = nlen;
2936 }
2937 }
2938 return ary;
2939}
2940
2941/*
2942 * call-seq:
2943 * length -> integer
2944 * size -> integer
2945 *
2946 * Returns the count of elements in +self+:
2947 *
2948 * [0, 1, 2].length # => 3
2949 * [].length # => 0
2950 *
2951 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
2952 */
2953
2954static VALUE
2955rb_ary_length(VALUE ary)
2956{
2958 return LEN2NUM(len);
2959}
2960
2961/*
2962 * call-seq:
2963 * empty? -> true or false
2964 *
2965 * Returns +true+ if the count of elements in +self+ is zero,
2966 * +false+ otherwise.
2967 *
2968 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
2969 */
2970
2971static VALUE
2972rb_ary_empty_p(VALUE ary)
2973{
2974 return RBOOL(RARRAY_LEN(ary) == 0);
2975}
2976
2977VALUE
2979{
2981 VALUE dup = rb_ary_new2(len);
2982 ary_memcpy(dup, 0, len, RARRAY_CONST_PTR(ary));
2983 ARY_SET_LEN(dup, len);
2984
2985 ary_verify(ary);
2986 ary_verify(dup);
2987 return dup;
2988}
2989
2990VALUE
2992{
2993 return ary_make_partial(ary, rb_cArray, 0, RARRAY_LEN(ary));
2994}
2995
2996#if USE_ZJIT
2997bool
2998rb_zjit_array_new_can_fastpath(rb_len_t len, size_t *alloc_size_out, VALUE *flags_out)
2999{
3000 if (!ary_embeddable_p(len)) {
3001 return false;
3002 }
3003 rb_len_t embed_size = ary_embed_size(len);
3004
3005 *alloc_size_out = embed_size;
3006 *flags_out = T_ARRAY | RARRAY_EMBED_FLAG | ((VALUE)len << RARRAY_EMBED_LEN_SHIFT);
3007 return true;
3008}
3009
3010bool
3011rb_zjit_array_dup_can_fastpath(VALUE ary, size_t *alloc_size_out, VALUE *flags_out, rb_len_t *len_out)
3012{
3014 if (!rb_zjit_array_new_can_fastpath(len, alloc_size_out, flags_out)) {
3015 return false;
3016 }
3017 else {
3018 *len_out = len;
3019 return true;
3020 }
3021}
3022#endif
3023
3024extern VALUE rb_output_fs;
3025
3026static void ary_join_1(VALUE obj, VALUE ary, VALUE sep, rb_len_t i, VALUE result, int *first);
3027
3028static VALUE
3029recursive_join(VALUE obj, VALUE argp, int recur)
3030{
3031 VALUE *arg = (VALUE *)argp;
3032 VALUE ary = arg[0];
3033 VALUE sep = arg[1];
3034 VALUE result = arg[2];
3035 int *first = (int *)arg[3];
3036
3037 if (recur) {
3038 rb_raise(rb_eArgError, "recursive array join");
3039 }
3040 else {
3041 ary_join_1(obj, ary, sep, 0, result, first);
3042 }
3043 return Qnil;
3044}
3045
3046static rb_len_t
3047ary_join_0(VALUE ary, VALUE sep, rb_len_t max, VALUE result)
3048{
3049 rb_len_t i;
3050 VALUE val;
3051
3052 if (max > 0) rb_enc_copy(result, RARRAY_AREF(ary, 0));
3053 for (i=0; i<max; i++) {
3054 val = RARRAY_AREF(ary, i);
3055 if (!RB_TYPE_P(val, T_STRING)) break;
3056 if (i > 0 && !NIL_P(sep))
3057 rb_str_buf_append(result, sep);
3058 rb_str_buf_append(result, val);
3059 }
3060 return i;
3061}
3062
3063static void
3064ary_join_1_str(VALUE dst, VALUE src, int *first)
3065{
3066 rb_str_buf_append(dst, src);
3067 if (*first) {
3068 rb_enc_copy(dst, src);
3069 *first = FALSE;
3070 }
3071}
3072
3073static void
3074ary_join_1_ary(VALUE obj, VALUE ary, VALUE sep, VALUE result, VALUE val, int *first)
3075{
3076 if (val == ary) {
3077 rb_raise(rb_eArgError, "recursive array join");
3078 }
3079 else {
3080 VALUE args[4];
3081
3082 *first = FALSE;
3083 args[0] = val;
3084 args[1] = sep;
3085 args[2] = result;
3086 args[3] = (VALUE)first;
3087 rb_exec_recursive(recursive_join, obj, (VALUE)args);
3088 }
3089}
3090
3091static void
3092ary_join_1(VALUE obj, VALUE ary, VALUE sep, rb_len_t i, VALUE result, int *first)
3093{
3094 VALUE val, tmp;
3095
3096 for (; i<RARRAY_LEN(ary); i++) {
3097 if (i > 0 && !NIL_P(sep))
3098 rb_str_buf_append(result, sep);
3099
3100 val = RARRAY_AREF(ary, i);
3101 if (RB_TYPE_P(val, T_STRING)) {
3102 ary_join_1_str(result, val, first);
3103 }
3104 else if (RB_TYPE_P(val, T_ARRAY)) {
3105 ary_join_1_ary(val, ary, sep, result, val, first);
3106 }
3107 else if (!NIL_P(tmp = rb_check_string_type(val))) {
3108 ary_join_1_str(result, tmp, first);
3109 }
3110 else if (!NIL_P(tmp = rb_check_array_type(val))) {
3111 ary_join_1_ary(val, ary, sep, result, tmp, first);
3112 }
3113 else {
3114 ary_join_1_str(result, rb_obj_as_string(val), first);
3115 }
3116 }
3117}
3118
3119/* Fast path for Array#join: when every element is a String in one fast-path encoding
3120 * (UTF-8 / US-ASCII / ASCII-8BIT) and the separator is byte-compatible, the result can
3121 * be produced with a single memcpy pass instead of appending each element through
3122 * rb_str_buf_append. Returns the joined String, or Qundef when any of those invariants
3123 * does not hold -- the caller then uses the general path. No user code runs here, so
3124 * the array cannot be mutated underneath us. */
3125static VALUE
3126ary_join_fast(VALUE ary, VALUE sep)
3127{
3128 rb_len_t n = RARRAY_LEN(ary);
3129 if (n == 0) return Qundef;
3130
3131 VALUE first = RARRAY_AREF(ary, 0);
3132 if (!RB_TYPE_P(first, T_STRING)) return Qundef;
3133 int encidx = ENCODING_GET(first);
3134 if (!rb_str_encindex_fastpath(encidx)) return Qundef;
3135
3136 /* cr accumulates the result code range exactly as rb_str_buf_append would. */
3138 rb_len_t sep_len = 0;
3139 const char *sep_ptr = NULL;
3140 if (!NIL_P(sep)) {
3141 int sep_cr = rb_enc_str_coderange(sep);
3142 /* The separator must share the element encoding, or be 7-bit (encidx is
3143 ASCII-compatible, so a 7-bit separator concatenates without negotiation). */
3144 if (ENCODING_GET(sep) != encidx && sep_cr != ENC_CODERANGE_7BIT) return Qundef;
3145 sep_ptr = RSTRING_PTR(sep);
3146 sep_len = RSTRING_LEN(sep);
3147 if (n > 1) cr = ENC_CODERANGE_AND(cr, sep_cr);
3148 }
3149
3150 /* One pass: confirm the shared encoding, measure the length, merge code ranges. */
3151 rb_len_t len = 1 + sep_len * (n - 1);
3152 for (rb_len_t i = 0; i < n; i++) {
3153 VALUE s = RARRAY_AREF(ary, i);
3154 if (!RB_TYPE_P(s, T_STRING) || ENCODING_GET(s) != encidx) return Qundef;
3155 len += RSTRING_LEN(s);
3156 cr = ENC_CODERANGE_AND(cr, rb_enc_str_coderange(s));
3157 }
3158
3159 VALUE result = rb_str_buf_new(len);
3160 rb_enc_associate_index(result, encidx);
3161 char *const buf = RSTRING_PTR(result);
3162 char *p = buf;
3163 for (rb_len_t i = 0; i < n; i++) {
3164 VALUE s = RARRAY_AREF(ary, i);
3165 rb_len_t slen = RSTRING_LEN(s);
3166 if (i > 0 && sep_len) {
3167 memcpy(p, sep_ptr, sep_len);
3168 p += sep_len;
3169 }
3170 memcpy(p, RSTRING_PTR(s), slen);
3171 p += slen;
3172 }
3173
3174 ENC_CODERANGE_CLEAR(result); /* keep rb_str_set_len from rescanning the bytes */
3175 rb_str_set_len(result, p - buf);
3176 ENC_CODERANGE_SET(result, cr);
3177 return result;
3178}
3179
3180VALUE
3182{
3183 rb_len_t len = 1, i;
3184 VALUE val, tmp, result;
3185
3186 if (RARRAY_LEN(ary) == 0) return rb_usascii_str_new(0, 0);
3187
3188 if (!NIL_P(sep)) StringValue(sep);
3189
3190 result = ary_join_fast(ary, sep);
3191 if (!UNDEF_P(result)) return result;
3192
3193 if (!NIL_P(sep)) {
3194 len += RSTRING_LEN(sep) * (RARRAY_LEN(ary) - 1);
3195 }
3196 rb_len_t len_memo = RARRAY_LEN(ary);
3197 for (i=0; i < len_memo; i++) {
3198 val = RARRAY_AREF(ary, i);
3199 if (RB_UNLIKELY(!RB_TYPE_P(val, T_STRING))) {
3200 tmp = rb_check_string_type(val);
3201 if (NIL_P(tmp) || tmp != val) {
3202 int first;
3203 rb_len_t n = RARRAY_LEN(ary);
3204 if (i > n) i = n;
3205 result = rb_str_buf_new(len + (n-i)*10);
3206 rb_enc_associate(result, rb_usascii_encoding());
3207 i = ary_join_0(ary, sep, i, result);
3208 first = i == 0;
3209 ary_join_1(ary, ary, sep, i, result, &first);
3210 return result;
3211 }
3212 len += RSTRING_LEN(tmp);
3213 len_memo = RARRAY_LEN(ary);
3214 }
3215 else {
3216 len += RSTRING_LEN(val);
3217 }
3218 }
3219
3220 result = rb_str_new(0, len);
3221 rb_str_set_len(result, 0);
3222
3223 ary_join_0(ary, sep, RARRAY_LEN(ary), result);
3224
3225 return result;
3226}
3227
3228/*
3229 * call-seq:
3230 * join(separator = $,) -> new_string
3231 *
3232 * Returns the new string formed by joining the string-converted elements of +self+
3233 * with the given +separator+ (defaults to <tt>$,</tt>):
3234 *
3235 * $, # => nil
3236 * %w[].join # => ""
3237 * %w[foo].join # => "foo"
3238 * a = %w[foo bar baz] # => ["foo", "bar", "baz"]
3239 * a.join # => "foobarbaz"
3240 * a.join('|') # => "foo|bar|baz"
3241 * a.join(' :|: ') # => "foo :|: bar :|: baz"
3242 *
3243 * Flattens and joins nested arrays:
3244 *
3245 * [:foo, [:bar, [:baz, :bat]]].join # => "foobarbazbat"
3246 *
3247 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3248 */
3249static VALUE
3250rb_ary_join_m(int argc, VALUE *argv, VALUE ary)
3251{
3252 VALUE sep;
3253
3254 if (rb_check_arity(argc, 0, 1) == 0 || NIL_P(sep = argv[0])) {
3255 sep = rb_output_fs;
3256 if (!NIL_P(sep)) {
3257 rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "$, is set to non-nil value");
3258 }
3259 }
3260
3261 return rb_ary_join(ary, sep);
3262}
3263
3264static VALUE
3265inspect_ary(VALUE ary, VALUE dummy, int recur)
3266{
3267 rb_len_t i;
3268 VALUE s, str;
3269
3270 if (recur) return rb_usascii_str_new_cstr("[...]");
3271 str = rb_str_buf_new2("[");
3272 for (i=0; i<RARRAY_LEN(ary); i++) {
3273 s = rb_inspect(RARRAY_AREF(ary, i));
3274 if (i > 0) rb_str_buf_cat2(str, ", ");
3275 else rb_enc_copy(str, s);
3276 rb_str_buf_append(str, s);
3277 }
3278 rb_str_buf_cat2(str, "]");
3279 return str;
3280}
3281
3282/*
3283 * call-seq:
3284 * inspect -> new_string
3285 * to_s -> new_string
3286 *
3287 * Returns the new string formed by calling method <tt>#inspect</tt>
3288 * on each array element:
3289 *
3290 * a = [:foo, 'bar', 2]
3291 * a.inspect # => "[:foo, \"bar\", 2]"
3292 *
3293 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3294 */
3295
3296static VALUE
3297rb_ary_inspect(VALUE ary)
3298{
3299 if (RARRAY_LEN(ary) == 0) return rb_usascii_str_new2("[]");
3300 return rb_exec_recursive(inspect_ary, ary, 0);
3301}
3302
3303VALUE
3305{
3306 return rb_ary_inspect(ary);
3307}
3308
3309/*
3310 * call-seq:
3311 * to_a -> self or new_array
3312 *
3313 * When +self+ is an instance of \Array, returns +self+.
3314 *
3315 * Otherwise, returns a new array containing the elements of +self+:
3316 *
3317 * class MyArray < Array; end
3318 * my_a = MyArray.new(['foo', 'bar', 'two'])
3319 * a = my_a.to_a
3320 * a # => ["foo", "bar", "two"]
3321 * a.class # => Array # Not MyArray.
3322 *
3323 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3324 */
3325
3326static VALUE
3327rb_ary_to_a(VALUE ary)
3328{
3329 if (rb_obj_class(ary) != rb_cArray) {
3331 rb_ary_replace(dup, ary);
3332 return dup;
3333 }
3334 return ary;
3335}
3336
3337/*
3338 * call-seq:
3339 * to_h -> new_hash
3340 * to_h {|element| ... } -> new_hash
3341 *
3342 * Returns a new hash formed from +self+.
3343 *
3344 * With no block given, each element of +self+ must be a 2-element sub-array;
3345 * forms each sub-array into a key-value pair in the new hash:
3346 *
3347 * a = [['foo', 'zero'], ['bar', 'one'], ['baz', 'two']]
3348 * a.to_h # => {"foo" => "zero", "bar" => "one", "baz" => "two"}
3349 * [].to_h # => {}
3350 *
3351 * With a block given, the block must return a 2-element array;
3352 * calls the block with each element of +self+;
3353 * forms each returned array into a key-value pair in the returned hash:
3354 *
3355 * a = ['foo', :bar, 1, [2, 3], {baz: 4}]
3356 * a.to_h {|element| [element, element.class] }
3357 * # => {"foo" => String, bar: Symbol, 1 => Integer, [2, 3] => Array, {baz: 4} => Hash}
3358 *
3359 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3360 */
3361
3362static VALUE
3363rb_ary_to_h(VALUE ary)
3364{
3365 rb_len_t i;
3366 VALUE hash = rb_hash_new_capa(RARRAY_LEN(ary));
3367 int block_given = rb_block_given_p();
3368
3369 for (i=0; i<RARRAY_LEN(ary); i++) {
3370 const VALUE e = rb_ary_elt(ary, i);
3371 const VALUE elt = block_given ? rb_yield_force_blockarg(e) : e;
3372 const VALUE key_value_pair = rb_check_array_type(elt);
3373 if (NIL_P(key_value_pair)) {
3374 rb_raise(rb_eTypeError, "wrong element type %"PRIsVALUE" at %"PRIdLEN" (expected array)",
3375 rb_obj_class(elt), i);
3376 }
3377 if (RARRAY_LEN(key_value_pair) != 2) {
3378 rb_raise(rb_eArgError, "wrong array length at %"PRIdLEN" (expected 2, was %"PRIdLEN")",
3379 i, RARRAY_LEN(key_value_pair));
3380 }
3381 rb_hash_aset(hash, RARRAY_AREF(key_value_pair, 0), RARRAY_AREF(key_value_pair, 1));
3382 }
3383 return hash;
3384}
3385
3386/*
3387 * call-seq:
3388 * to_ary -> self
3389 *
3390 * Returns +self+.
3391 */
3392
3393static VALUE
3394rb_ary_to_ary_m(VALUE ary)
3395{
3396 return ary;
3397}
3398
3399static void
3400ary_reverse(VALUE *p1, VALUE *p2)
3401{
3402 while (p1 < p2) {
3403 VALUE tmp = *p1;
3404 *p1++ = *p2;
3405 *p2-- = tmp;
3406 }
3407}
3408
3409VALUE
3411{
3412 VALUE *p2;
3414
3416 if (len > 1) {
3417 RARRAY_PTR_USE(ary, p1, {
3418 p2 = p1 + len - 1; /* points last item */
3419 ary_reverse(p1, p2);
3420 }); /* WB: no new reference */
3421 }
3422 return ary;
3423}
3424
3425/*
3426 * call-seq:
3427 * reverse! -> self
3428 *
3429 * Reverses the order of the elements of +self+;
3430 * returns +self+:
3431 *
3432 * a = [0, 1, 2]
3433 * a.reverse! # => [2, 1, 0]
3434 * a # => [2, 1, 0]
3435 *
3436 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
3437 */
3438
3439static VALUE
3440rb_ary_reverse_bang(VALUE ary)
3441{
3442 return rb_ary_reverse(ary);
3443}
3444
3445/*
3446 * call-seq:
3447 * reverse -> new_array
3448 *
3449 * Returns a new array containing the elements of +self+ in reverse order:
3450 *
3451 * [0, 1, 2].reverse # => [2, 1, 0]
3452 *
3453 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
3454 */
3455
3456static VALUE
3457rb_ary_reverse_m(VALUE ary)
3458{
3460 VALUE dup = rb_ary_new2(len);
3461
3462 if (len > 0) {
3463 const VALUE *p1 = RARRAY_CONST_PTR(ary);
3464 VALUE *p2 = (VALUE *)RARRAY_CONST_PTR(dup) + len - 1;
3465 do *p2-- = *p1++; while (--len > 0);
3466 rb_gc_writebarrier_remember(dup);
3467 }
3468 ARY_SET_LEN(dup, RARRAY_LEN(ary));
3469 return dup;
3470}
3471
3472static inline rb_len_t
3473rotate_count(rb_len_t cnt, rb_len_t len)
3474{
3475 return (cnt < 0) ? (len - (~cnt % len) - 1) : (cnt % len);
3476}
3477
3478static void
3479ary_rotate_ptr(VALUE *ptr, rb_len_t len, rb_len_t cnt)
3480{
3481 if (cnt == 1) {
3482 VALUE tmp = *ptr;
3483 memmove(ptr, ptr + 1, sizeof(VALUE)*(len - 1));
3484 *(ptr + len - 1) = tmp;
3485 }
3486 else if (cnt == len - 1) {
3487 VALUE tmp = *(ptr + len - 1);
3488 memmove(ptr + 1, ptr, sizeof(VALUE)*(len - 1));
3489 *ptr = tmp;
3490 }
3491 else {
3492 --len;
3493 if (cnt < len) ary_reverse(ptr + cnt, ptr + len);
3494 if (--cnt > 0) ary_reverse(ptr, ptr + cnt);
3495 if (len > 0) ary_reverse(ptr, ptr + len);
3496 }
3497}
3498
3499VALUE
3501{
3503
3504 if (cnt != 0) {
3506 if (len > 1 && (cnt = rotate_count(cnt, len)) > 0) {
3507 RARRAY_PTR_USE(ary, ptr, ary_rotate_ptr(ptr, len, cnt));
3508 return ary;
3509 }
3510 }
3511 return Qnil;
3512}
3513
3514/*
3515 * call-seq:
3516 * rotate!(count = 1) -> self
3517 *
3518 * Rotates +self+ in place by moving elements from one end to the other; returns +self+.
3519 *
3520 * With non-negative numeric +count+,
3521 * rotates +count+ elements from the beginning to the end:
3522 *
3523 * [0, 1, 2, 3].rotate!(2) # => [2, 3, 0, 1]
3524 [0, 1, 2, 3].rotate!(2.1) # => [2, 3, 0, 1]
3525 *
3526 * If +count+ is large, uses <tt>count % array.size</tt> as the count:
3527 *
3528 * [0, 1, 2, 3].rotate!(21) # => [1, 2, 3, 0]
3529 *
3530 * If +count+ is zero, rotates no elements:
3531 *
3532 * [0, 1, 2, 3].rotate!(0) # => [0, 1, 2, 3]
3533 *
3534 * With a negative numeric +count+, rotates in the opposite direction,
3535 * from end to beginning:
3536 *
3537 * [0, 1, 2, 3].rotate!(-1) # => [3, 0, 1, 2]
3538 *
3539 * If +count+ is small (far from zero), uses <tt>count % array.size</tt> as the count:
3540 *
3541 * [0, 1, 2, 3].rotate!(-21) # => [3, 0, 1, 2]
3542 *
3543 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
3544 */
3545
3546static VALUE
3547rb_ary_rotate_bang(int argc, VALUE *argv, VALUE ary)
3548{
3549 rb_len_t n = (rb_check_arity(argc, 0, 1) ? NUM2LEN(argv[0]) : 1);
3550 rb_ary_rotate(ary, n);
3551 return ary;
3552}
3553
3554/*
3555 * call-seq:
3556 * rotate(count = 1) -> new_array
3557 *
3558 * Returns a new array formed from +self+ with elements
3559 * rotated from one end to the other.
3560 *
3561 * With non-negative numeric +count+,
3562 * rotates elements from the beginning to the end:
3563 *
3564 * [0, 1, 2, 3].rotate(2) # => [2, 3, 0, 1]
3565 * [0, 1, 2, 3].rotate(2.1) # => [2, 3, 0, 1]
3566 *
3567 * If +count+ is large, uses <tt>count % array.size</tt> as the count:
3568 *
3569 * [0, 1, 2, 3].rotate(22) # => [2, 3, 0, 1]
3570 *
3571 * With a +count+ of zero, rotates no elements:
3572 *
3573 * [0, 1, 2, 3].rotate(0) # => [0, 1, 2, 3]
3574 *
3575 * With negative numeric +count+, rotates in the opposite direction,
3576 * from the end to the beginning:
3577 *
3578 * [0, 1, 2, 3].rotate(-1) # => [3, 0, 1, 2]
3579 *
3580 * If +count+ is small (far from zero), uses <tt>count % array.size</tt> as the count:
3581 *
3582 * [0, 1, 2, 3].rotate(-21) # => [3, 0, 1, 2]
3583 *
3584 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3585 */
3586
3587static VALUE
3588rb_ary_rotate_m(int argc, VALUE *argv, VALUE ary)
3589{
3590 VALUE rotated;
3591 const VALUE *ptr;
3592 rb_len_t len;
3593 rb_len_t cnt = (rb_check_arity(argc, 0, 1) ? NUM2LEN(argv[0]) : 1);
3594
3595 len = RARRAY_LEN(ary);
3596 rotated = rb_ary_new2(len);
3597 if (len > 0) {
3598 cnt = rotate_count(cnt, len);
3600 len -= cnt;
3601 ary_memcpy(rotated, 0, len, ptr + cnt);
3602 ary_memcpy(rotated, len, cnt, ptr);
3603 }
3604 ARY_SET_LEN(rotated, RARRAY_LEN(ary));
3605 return rotated;
3606}
3607
3608struct ary_sort_data {
3609 VALUE ary;
3610 VALUE receiver;
3611};
3612
3613static VALUE
3614sort_reentered(VALUE ary)
3615{
3616 if (RBASIC(ary)->klass) {
3617 rb_raise(rb_eRuntimeError, "sort reentered");
3618 }
3619 return Qnil;
3620}
3621
3622static void
3623sort_returned(struct ary_sort_data *data)
3624{
3625 if (rb_obj_frozen_p(data->receiver)) {
3626 rb_raise(rb_eFrozenError, "array frozen during sort");
3627 }
3628 sort_reentered(data->ary);
3629}
3630
3631static int
3632sort_1(const void *ap, const void *bp, void *dummy)
3633{
3634 struct ary_sort_data *data = dummy;
3635 VALUE retval = sort_reentered(data->ary);
3636 VALUE a = *(const VALUE *)ap, b = *(const VALUE *)bp;
3637 VALUE args[2];
3638 int n;
3639
3640 args[0] = a;
3641 args[1] = b;
3642 retval = rb_yield_values2(2, args);
3643 n = rb_cmpint(retval, a, b);
3644 sort_returned(data);
3645 return n;
3646}
3647
3648static int
3649sort_2(const void *ap, const void *bp, void *dummy)
3650{
3651 struct ary_sort_data *data = dummy;
3652 VALUE retval = sort_reentered(data->ary);
3653 VALUE a = *(const VALUE *)ap, b = *(const VALUE *)bp;
3654 int n;
3655
3656 if (FIXNUM_P(a) && FIXNUM_P(b) && CMP_OPTIMIZABLE(INTEGER)) {
3657 if ((long)a > (long)b) return 1;
3658 if ((long)a < (long)b) return -1;
3659 return 0;
3660 }
3661 if (STRING_P(a) && STRING_P(b) && CMP_OPTIMIZABLE(STRING)) {
3662 return rb_str_cmp(a, b);
3663 }
3664 if (RB_FLOAT_TYPE_P(a) && CMP_OPTIMIZABLE(FLOAT)) {
3665 return rb_float_cmp(a, b);
3666 }
3667
3668 retval = rb_funcallv(a, id_cmp, 1, &b);
3669 n = rb_cmpint(retval, a, b);
3670 sort_returned(data);
3671
3672 return n;
3673}
3674
3675/*
3676 * call-seq:
3677 * sort! -> self
3678 * sort! {|a, b| ... } -> self
3679 *
3680 * Like Array#sort, but returns +self+ with its elements sorted in place.
3681 *
3682 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
3683 */
3684
3685VALUE
3687{
3688 rb_ary_modify(ary);
3689 RUBY_ASSERT(!ARY_SHARED_P(ary));
3690 if (RARRAY_LEN(ary) > 1) {
3691 VALUE tmp = ary_make_substitution(ary); /* only ary refers tmp */
3692 struct ary_sort_data data;
3693 rb_len_t len = RARRAY_LEN(ary);
3694 RBASIC_CLEAR_CLASS(tmp);
3695 data.ary = tmp;
3696 data.receiver = ary;
3697 RARRAY_PTR_USE(tmp, ptr, {
3698 ruby_qsort(ptr, len, sizeof(VALUE),
3699 rb_block_given_p()?sort_1:sort_2, &data);
3700 }); /* WB: no new reference */
3701 rb_ary_modify(ary);
3702 if (ARY_EMBED_P(tmp)) {
3703 if (ARY_SHARED_P(ary)) { /* ary might be destructively operated in the given block */
3704 rb_ary_unshare(ary);
3705 FL_SET_EMBED(ary);
3706 }
3707 if (ARY_EMBED_LEN(tmp) > ARY_CAPA(ary)) {
3708 ary_resize_capa(ary, ARY_EMBED_LEN(tmp));
3709 }
3710 ary_memcpy(ary, 0, ARY_EMBED_LEN(tmp), ARY_EMBED_PTR(tmp));
3711 ARY_SET_LEN(ary, ARY_EMBED_LEN(tmp));
3712 }
3713 else {
3714 if (!ARY_EMBED_P(ary) && ARY_HEAP_PTR(ary) == ARY_HEAP_PTR(tmp)) {
3715 FL_UNSET_SHARED(ary);
3716 ARY_SET_CAPA(ary, RARRAY_LEN(tmp));
3717 }
3718 else {
3719 RUBY_ASSERT(!ARY_SHARED_P(tmp));
3720 if (ARY_EMBED_P(ary)) {
3721 FL_UNSET_EMBED(ary);
3722 }
3723 else if (ARY_SHARED_P(ary)) {
3724 /* ary might be destructively operated in the given block */
3725 rb_ary_unshare(ary);
3726 }
3727 else {
3728 ary_heap_free(ary);
3729 }
3730 ARY_SET_PTR(ary, ARY_HEAP_PTR(tmp));
3731 ARY_SET_HEAP_LEN(ary, len);
3732 ARY_SET_CAPA(ary, ARY_HEAP_LEN(tmp));
3733 }
3734 /* tmp was lost ownership for the ptr */
3735 FL_SET_EMBED(tmp);
3736 ARY_SET_EMBED_LEN(tmp, 0);
3737 OBJ_FREEZE(tmp);
3738 }
3739 /* tmp will be GC'ed. */
3740 RBASIC_SET_CLASS_RAW(tmp, rb_cArray); /* rb_cArray must be marked */
3741 }
3742 ary_verify(ary);
3743 return ary;
3744}
3745
3746/*
3747 * call-seq:
3748 * sort -> new_array
3749 * sort {|a, b| ... } -> new_array
3750 *
3751 * Returns a new array containing the elements of +self+, sorted.
3752 *
3753 * With no block given, compares elements using operator <tt>#<=></tt>
3754 * (see Object#<=>):
3755 *
3756 * [0, 2, 3, 1].sort # => [0, 1, 2, 3]
3757 *
3758 * With a block given, calls the block with each combination of pairs of elements from +self+;
3759 * for each pair +a+ and +b+, the block should return a numeric:
3760 *
3761 * - Negative when +b+ is to follow +a+.
3762 * - Zero when +a+ and +b+ are equivalent.
3763 * - Positive when +a+ is to follow +b+.
3764 *
3765 * Example:
3766 *
3767 * a = [3, 2, 0, 1]
3768 * a.sort {|a, b| a <=> b } # => [0, 1, 2, 3]
3769 * a.sort {|a, b| b <=> a } # => [3, 2, 1, 0]
3770 *
3771 * When the block returns zero, the order for +a+ and +b+ is indeterminate,
3772 * and may be unstable.
3773 *
3774 * See an example in Numeric#nonzero? for the idiom to sort more
3775 * complex structure.
3776 *
3777 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3778 */
3779
3780VALUE
3781rb_ary_sort(VALUE ary)
3782{
3783 ary = rb_ary_dup(ary);
3784 rb_ary_sort_bang(ary);
3785 return ary;
3786}
3787
3788static VALUE rb_ary_bsearch_index(VALUE ary);
3789
3790/*
3791 * call-seq:
3792 * bsearch {|element| ... } -> found_element or nil
3793 * bsearch -> new_enumerator
3794 *
3795 * Returns the element from +self+ found by a binary search,
3796 * or +nil+ if the search found no suitable element.
3797 *
3798 * See {Binary Searching}[rdoc-ref:language/bsearch.rdoc].
3799 *
3800 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3801 */
3802
3803static VALUE
3804rb_ary_bsearch(VALUE ary)
3805{
3806 VALUE index_result = rb_ary_bsearch_index(ary);
3807
3808 if (RB_INTEGER_TYPE_P(index_result)) {
3809 return rb_ary_entry(ary, NUM2LEN(index_result));
3810 }
3811 return index_result;
3812}
3813
3814/*
3815 * call-seq:
3816 * bsearch_index {|element| ... } -> integer or nil
3817 * bsearch_index -> new_enumerator
3818 *
3819 * Returns the integer index of the element from +self+ found by a binary search,
3820 * or +nil+ if the search found no suitable element.
3821 *
3822 * See {Binary Searching}[rdoc-ref:language/bsearch.rdoc].
3823 *
3824 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3825 */
3826
3827static VALUE
3828rb_ary_bsearch_index(VALUE ary)
3829{
3830 rb_len_t low = 0, high = RARRAY_LEN(ary), mid;
3831 int smaller = 0, satisfied = 0;
3832 VALUE v, val;
3833
3834 RETURN_ENUMERATOR(ary, 0, 0);
3835 while (low < high) {
3836 mid = low + ((high - low) / 2);
3837 val = rb_ary_entry(ary, mid);
3838 v = rb_yield(val);
3839 if (FIXNUM_P(v)) {
3840 if (v == INT2FIX(0)) return LEN2NUM(mid);
3841 smaller = (SIGNED_VALUE)v < 0; /* Fixnum preserves its sign-bit */
3842 }
3843 else if (v == Qtrue) {
3844 satisfied = 1;
3845 smaller = 1;
3846 }
3847 else if (!RTEST(v)) {
3848 smaller = 0;
3849 }
3850 else if (rb_obj_is_kind_of(v, rb_cNumeric)) {
3851 const VALUE zero = INT2FIX(0);
3852 switch (rb_cmpint(rb_funcallv(v, id_cmp, 1, &zero), v, zero)) {
3853 case 0: return LEN2NUM(mid);
3854 case 1: smaller = 0; break;
3855 case -1: smaller = 1;
3856 }
3857 }
3858 else {
3859 rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE
3860 " (must be numeric, true, false or nil)",
3861 rb_obj_class(v));
3862 }
3863 if (smaller) {
3864 high = mid;
3865 }
3866 else {
3867 low = mid + 1;
3868 }
3869 }
3870 if (!satisfied) return Qnil;
3871 return LEN2NUM(low);
3872}
3873
3874
3875static VALUE
3876sort_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, dummy))
3877{
3878 return rb_yield(i);
3879}
3880
3881/*
3882 * call-seq:
3883 * sort_by! {|element| ... } -> self
3884 * sort_by! -> new_enumerator
3885 *
3886 * With a block given, sorts the elements of +self+ in place;
3887 * returns self.
3888 *
3889 * Calls the block with each successive element;
3890 * sorts elements based on the values returned from the block:
3891 *
3892 * a = ['aaaa', 'bbb', 'cc', 'd']
3893 * a.sort_by! {|element| element.size }
3894 * a # => ["d", "cc", "bbb", "aaaa"]
3895 *
3896 * For duplicate values returned by the block, the ordering is indeterminate, and may be unstable.
3897 *
3898 * With no block given, returns a new Enumerator.
3899 *
3900 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
3901 */
3902
3903static VALUE
3904rb_ary_sort_by_bang(VALUE ary)
3905{
3906 VALUE sorted;
3907
3908 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3909 rb_ary_modify(ary);
3910 if (RARRAY_LEN(ary) > 1) {
3911 sorted = rb_block_call(ary, rb_intern("sort_by"), 0, 0, sort_by_i, 0);
3912 rb_ary_replace(ary, sorted);
3913 }
3914 return ary;
3915}
3916
3917
3918/*
3919 * call-seq:
3920 * collect {|element| ... } -> new_array
3921 * collect -> new_enumerator
3922 * map {|element| ... } -> new_array
3923 * map -> new_enumerator
3924 *
3925 * With a block given, calls the block with each element of +self+;
3926 * returns a new array whose elements are the return values from the block:
3927 *
3928 * a = [:foo, 'bar', 2]
3929 * a1 = a.map {|element| element.class }
3930 * a1 # => [Symbol, String, Integer]
3931 *
3932 * With no block given, returns a new Enumerator.
3933 *
3934 * Related: #collect!;
3935 * see also {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3936 */
3937
3938static VALUE
3939rb_ary_collect(VALUE ary)
3940{
3941 rb_len_t i;
3942 VALUE collect;
3943
3944 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3945 collect = rb_ary_new2(RARRAY_LEN(ary));
3946 for (i = 0; i < RARRAY_LEN(ary); i++) {
3947 rb_ary_push(collect, rb_yield(RARRAY_AREF(ary, i)));
3948 }
3949 return collect;
3950}
3951
3952
3953/*
3954 * call-seq:
3955 * collect! {|element| ... } -> self
3956 * collect! -> new_enumerator
3957 * map! {|element| ... } -> self
3958 * map! -> new_enumerator
3959 *
3960 * With a block given, calls the block with each element of +self+
3961 * and replaces the element with the block's return value;
3962 * returns +self+:
3963 *
3964 * a = [:foo, 'bar', 2]
3965 * a.map! { |element| element.class } # => [Symbol, String, Integer]
3966 *
3967 * With no block given, returns a new Enumerator.
3968 *
3969 * Related: #collect;
3970 * see also {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3971 */
3972
3973static VALUE
3974rb_ary_collect_bang(VALUE ary)
3975{
3976 rb_len_t i;
3977
3978 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3979 rb_ary_modify(ary);
3980 for (i = 0; i < RARRAY_LEN(ary); i++) {
3981 rb_ary_store(ary, i, rb_yield(RARRAY_AREF(ary, i)));
3982 }
3983 return ary;
3984}
3985
3986VALUE
3987rb_get_values_at(VALUE obj, rb_len_t olen, int argc, const VALUE *argv, VALUE (*func) (VALUE, rb_len_t))
3988{
3989 VALUE result = rb_ary_new2(argc);
3990 rb_len_t beg, len, i, j;
3991
3992 for (i=0; i<argc; i++) {
3993 if (FIXNUM_P(argv[i])) {
3994 rb_ary_push(result, (*func)(obj, FIX2LONG(argv[i])));
3995 continue;
3996 }
3997 /* check if idx is Range */
3998 if (rb_range_beg_len(argv[i], &beg, &len, olen, 1)) {
3999 rb_len_t end = olen < beg+len ? olen : beg+len;
4000 for (j = beg; j < end; j++) {
4001 rb_ary_push(result, (*func)(obj, j));
4002 }
4003 if (beg + len > j)
4004 rb_ary_resize(result, RARRAY_LEN(result) + (beg + len) - j);
4005 continue;
4006 }
4007 rb_ary_push(result, (*func)(obj, NUM2LEN(argv[i])));
4008 }
4009 return result;
4010}
4011
4012static VALUE
4013append_values_at_single(VALUE result, VALUE ary, rb_len_t olen, VALUE idx)
4014{
4015 rb_len_t beg, len;
4016 if (FIXNUM_P(idx)) {
4017 beg = FIX2LONG(idx);
4018 }
4019 /* check if idx is Range */
4020 else if (rb_range_beg_len(idx, &beg, &len, olen, 1)) {
4021 if (len > 0) {
4022 // rb_range_beg_len may run arbitrary code that modifies ary, so we
4023 // need to re-calculate olen
4024 const rb_len_t olen = RARRAY_LEN(ary);
4025 const VALUE *const src = RARRAY_CONST_PTR(ary);
4026 const rb_len_t end = beg + len;
4027 const rb_len_t prevlen = RARRAY_LEN(result);
4028 if (beg < olen) {
4029 rb_ary_cat(result, src + beg, end > olen ? olen-beg : len);
4030 }
4031 if (end > olen) {
4032 rb_ary_store(result, prevlen + len - 1, Qnil);
4033 }
4034 }
4035 return result;
4036 }
4037 else {
4038 beg = NUM2LEN(idx);
4039 }
4040 return rb_ary_push(result, rb_ary_entry(ary, beg));
4041}
4042
4043/*
4044 * call-seq:
4045 * values_at(*specifiers) -> new_array
4046 *
4047 * Returns elements from +self+ in a new array; does not modify +self+.
4048 *
4049 * The objects included in the returned array are the elements of +self+
4050 * selected by the given +specifiers+,
4051 * each of which must be a numeric index or a Range.
4052 *
4053 * In brief:
4054 *
4055 * a = ['a', 'b', 'c', 'd']
4056 *
4057 * # Index specifiers.
4058 * a.values_at(2, 0, 2, 0) # => ["c", "a", "c", "a"] # May repeat.
4059 * a.values_at(-4, -3, -2, -1) # => ["a", "b", "c", "d"] # Counts backwards if negative.
4060 * a.values_at(-50, 50) # => [nil, nil] # Outside of self.
4061 *
4062 * # Range specifiers.
4063 * a.values_at(1..3) # => ["b", "c", "d"] # From range.begin to range.end.
4064 * a.values_at(1...3) # => ["b", "c"] # End excluded.
4065 * a.values_at(3..1) # => [] # No such elements.
4066 *
4067 * a.values_at(-3..3) # => ["b", "c", "d"] # Negative range.begin counts backwards.
4068 * a.values_at(-50..3) # Raises RangeError.
4069 *
4070 * a.values_at(1..-2) # => ["b", "c"] # Negative range.end counts backwards.
4071 * a.values_at(1..-50) # => [] # No such elements.
4072 *
4073 * # Mixture of specifiers.
4074 * a.values_at(2..3, 3, 0..1, 0) # => ["c", "d", "d", "a", "b", "a"]
4075 *
4076 * With no +specifiers+ given, returns a new empty array:
4077 *
4078 * a = ['a', 'b', 'c', 'd']
4079 * a.values_at # => []
4080 *
4081 * For each numeric specifier +index+, includes an element:
4082 *
4083 * - For each non-negative numeric specifier +index+ that is in-range (less than <tt>self.size</tt>),
4084 * includes the element at offset +index+:
4085 *
4086 * a.values_at(0, 2) # => ["a", "c"]
4087 * a.values_at(0.1, 2.9) # => ["a", "c"]
4088 *
4089 * - For each negative numeric +index+ that is in-range (greater than or equal to <tt>- self.size</tt>),
4090 * counts backwards from the end of +self+:
4091 *
4092 * a.values_at(-1, -4) # => ["d", "a"]
4093 *
4094 * The given indexes may be in any order, and may repeat:
4095 *
4096 * a.values_at(2, 0, 1, 0, 2) # => ["c", "a", "b", "a", "c"]
4097 *
4098 * For each +index+ that is out-of-range, includes +nil+:
4099 *
4100 * a.values_at(4, -5) # => [nil, nil]
4101 *
4102 * For each Range specifier +range+, includes elements
4103 * according to <tt>range.begin</tt> and <tt>range.end</tt>:
4104 *
4105 * - If both <tt>range.begin</tt> and <tt>range.end</tt>
4106 * are non-negative and in-range (less than <tt>self.size</tt>),
4107 * includes elements from index <tt>range.begin</tt>
4108 * through <tt>range.end - 1</tt> (if <tt>range.exclude_end?</tt>),
4109 * or through <tt>range.end</tt> (otherwise):
4110 *
4111 * a.values_at(1..2) # => ["b", "c"]
4112 * a.values_at(1...2) # => ["b"]
4113 *
4114 * - If <tt>range.begin</tt> is negative and in-range (greater than or equal to <tt>- self.size</tt>),
4115 * counts backwards from the end of +self+:
4116 *
4117 * a.values_at(-2..3) # => ["c", "d"]
4118 *
4119 * - If <tt>range.begin</tt> is negative and out-of-range, raises an exception:
4120 *
4121 * a.values_at(-5..3) # Raises RangeError.
4122 *
4123 * - If <tt>range.end</tt> is positive and out-of-range,
4124 * extends the returned array with +nil+ elements:
4125 *
4126 * a.values_at(1..5) # => ["b", "c", "d", nil, nil]
4127 *
4128 * - If <tt>range.end</tt> is negative and in-range,
4129 * counts backwards from the end of +self+:
4130 *
4131 * a.values_at(1..-2) # => ["b", "c"]
4132 *
4133 * - If <tt>range.end</tt> is negative and out-of-range,
4134 * returns an empty array:
4135 *
4136 * a.values_at(1..-5) # => []
4137 *
4138 * The given ranges may be in any order and may repeat:
4139 *
4140 * a.values_at(2..3, 0..1, 2..3) # => ["c", "d", "a", "b", "c", "d"]
4141 *
4142 * The given specifiers may be any mixture of indexes and ranges:
4143 *
4144 * a.values_at(3, 1..2, 0, 2..3) # => ["d", "b", "c", "a", "c", "d"]
4145 *
4146 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
4147 */
4148
4149static VALUE
4150rb_ary_values_at(int argc, VALUE *argv, VALUE ary)
4151{
4152 rb_len_t i, olen = RARRAY_LEN(ary);
4153 VALUE result = rb_ary_new_capa(argc);
4154 for (i = 0; i < argc; ++i) {
4155 append_values_at_single(result, ary, olen, argv[i]);
4156 }
4157 RB_GC_GUARD(ary);
4158 return result;
4159}
4160
4161
4162/*
4163 * call-seq:
4164 * select {|element| ... } -> new_array
4165 * select -> new_enumerator
4166 * filter {|element| ... } -> new_array
4167 * filter -> new_enumerator
4168 *
4169 * With a block given, calls the block with each element of +self+;
4170 * returns a new array containing those elements of +self+
4171 * for which the block returns a truthy value:
4172 *
4173 * a = [:foo, 'bar', 2, :bam]
4174 * a.select {|element| element.to_s.start_with?('b') }
4175 * # => ["bar", :bam]
4176 *
4177 * With no block given, returns a new Enumerator.
4178 *
4179 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
4180 */
4181
4182static VALUE
4183rb_ary_select(VALUE ary)
4184{
4185 VALUE result;
4186 rb_len_t i;
4187
4188 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
4189 result = rb_ary_new2(RARRAY_LEN(ary));
4190 for (i = 0; i < RARRAY_LEN(ary); i++) {
4191 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) {
4192 rb_ary_push(result, rb_ary_elt(ary, i));
4193 }
4194 }
4195 return result;
4196}
4197
4198struct select_bang_arg {
4199 VALUE ary;
4200 rb_len_t len[2];
4201};
4202
4203static VALUE
4204select_bang_i(VALUE a)
4205{
4206 volatile struct select_bang_arg *arg = (void *)a;
4207 VALUE ary = arg->ary;
4208 rb_len_t i1, i2;
4209
4210 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); arg->len[0] = ++i1) {
4211 VALUE v = RARRAY_AREF(ary, i1);
4212 if (!RTEST(rb_yield(v))) continue;
4213 if (i1 != i2) {
4214 rb_ary_store(ary, i2, v);
4215 }
4216 arg->len[1] = ++i2;
4217 }
4218 return (i1 == i2) ? Qnil : ary;
4219}
4220
4221static VALUE
4222select_bang_ensure(VALUE a)
4223{
4224 volatile struct select_bang_arg *arg = (void *)a;
4225 VALUE ary = arg->ary;
4226 rb_len_t len = RARRAY_LEN(ary);
4227 rb_len_t i1 = arg->len[0], i2 = arg->len[1];
4228
4229 if (i2 < len && i2 < i1) {
4230 rb_len_t tail = 0;
4231 rb_ary_modify(ary);
4232 if (i1 < len) {
4233 tail = len - i1;
4234 RARRAY_PTR_USE(ary, ptr, {
4235 MEMMOVE(ptr + i2, ptr + i1, VALUE, tail);
4236 });
4237 }
4238 ARY_SET_LEN(ary, i2 + tail);
4239 }
4240 return ary;
4241}
4242
4243/*
4244 * call-seq:
4245 * select! {|element| ... } -> self or nil
4246 * select! -> new_enumerator
4247 * filter! {|element| ... } -> self or nil
4248 * filter! -> new_enumerator
4249 *
4250 * With a block given, calls the block with each element of +self+;
4251 * removes from +self+ those elements for which the block returns +false+ or +nil+.
4252 *
4253 * Returns +self+ if any elements were removed:
4254 *
4255 * a = [:foo, 'bar', 2, :bam]
4256 * a.select! {|element| element.to_s.start_with?('b') } # => ["bar", :bam]
4257 *
4258 * Returns +nil+ if no elements were removed.
4259 *
4260 * With no block given, returns a new Enumerator.
4261 *
4262 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4263 */
4264
4265static VALUE
4266rb_ary_select_bang(VALUE ary)
4267{
4268 struct select_bang_arg args;
4269
4270 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
4271 rb_ary_modify(ary);
4272
4273 args.ary = ary;
4274 args.len[0] = args.len[1] = 0;
4275 return rb_ensure(select_bang_i, (VALUE)&args, select_bang_ensure, (VALUE)&args);
4276}
4277
4278/*
4279 * call-seq:
4280 * keep_if {|element| ... } -> self
4281 * keep_if -> new_enumerator
4282 *
4283 * With a block given, calls the block with each element of +self+;
4284 * removes the element from +self+ if the block does not return a truthy value:
4285 *
4286 * a = [:foo, 'bar', 2, :bam]
4287 * a.keep_if {|element| element.to_s.start_with?('b') } # => ["bar", :bam]
4288 *
4289 * With no block given, returns a new Enumerator.
4290 *
4291 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4292 */
4293
4294static VALUE
4295rb_ary_keep_if(VALUE ary)
4296{
4297 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
4298 rb_ary_select_bang(ary);
4299 return ary;
4300}
4301
4302static void
4303ary_resize_smaller(VALUE ary, rb_len_t len)
4304{
4305 rb_ary_modify(ary);
4306 if (RARRAY_LEN(ary) > len) {
4307 ARY_SET_LEN(ary, len);
4308 if (len * 2 < ARY_CAPA(ary) &&
4309 ARY_CAPA(ary) > ARY_DEFAULT_SIZE) {
4310 ary_resize_capa(ary, len * 2);
4311 }
4312 }
4313}
4314
4315/*
4316 * call-seq:
4317 * delete(object) -> last_removed_object
4318 * delete(object) {|element| ... } -> last_removed_object or block_return
4319 *
4320 * Removes zero or more elements from +self+.
4321 *
4322 * With no block given,
4323 * removes from +self+ each element +ele+ such that <tt>ele == object</tt>;
4324 * returns the last removed element:
4325 *
4326 * a = [0, 1, 2, 2.0]
4327 * a.delete(2) # => 2.0
4328 * a # => [0, 1]
4329 *
4330 * Returns +nil+ if no elements removed:
4331 *
4332 * a.delete(2) # => nil
4333 *
4334 * With a block given,
4335 * removes from +self+ each element +ele+ such that <tt>ele == object</tt>.
4336 *
4337 * If any such elements are found, ignores the block
4338 * and returns the last removed element:
4339 *
4340 * a = [0, 1, 2, 2.0]
4341 * a.delete(2) {|element| fail 'Cannot happen' } # => 2.0
4342 * a # => [0, 1]
4343 *
4344 * If no such element is found, returns the block's return value:
4345 *
4346 * a.delete(2) {|element| "Element #{element} not found." }
4347 * # => "Element 2 not found."
4348 *
4349 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4350 */
4351
4352VALUE
4353rb_ary_delete(VALUE ary, VALUE item)
4354{
4355 VALUE v = item;
4356 rb_len_t i1, i2;
4357
4358 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
4359 VALUE e = RARRAY_AREF(ary, i1);
4360
4361 if (rb_equal(e, item)) {
4362 v = e;
4363 continue;
4364 }
4365 if (i1 != i2) {
4366 rb_ary_store(ary, i2, e);
4367 }
4368 i2++;
4369 }
4370 if (RARRAY_LEN(ary) == i2) {
4371 if (rb_block_given_p()) {
4372 return rb_yield(item);
4373 }
4374 return Qnil;
4375 }
4376
4377 ary_resize_smaller(ary, i2);
4378
4379 ary_verify(ary);
4380 return v;
4381}
4382
4383void
4384rb_ary_delete_same(VALUE ary, VALUE item)
4385{
4386 rb_len_t i1, i2;
4387
4388 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
4389 VALUE e = RARRAY_AREF(ary, i1);
4390
4391 if (e == item) {
4392 continue;
4393 }
4394 if (i1 != i2) {
4395 rb_ary_store(ary, i2, e);
4396 }
4397 i2++;
4398 }
4399 if (RARRAY_LEN(ary) == i2) {
4400 return;
4401 }
4402
4403 ary_resize_smaller(ary, i2);
4404}
4405
4406VALUE
4408{
4409 rb_len_t len = RARRAY_LEN(ary);
4410 VALUE del;
4411
4412 if (pos >= len) return Qnil;
4413 if (pos < 0) {
4414 pos += len;
4415 if (pos < 0) return Qnil;
4416 }
4417
4418 rb_ary_modify(ary);
4419 del = RARRAY_AREF(ary, pos);
4420 RARRAY_PTR_USE(ary, ptr, {
4421 MEMMOVE(ptr+pos, ptr+pos+1, VALUE, len-pos-1);
4422 });
4423 ARY_INCREASE_LEN(ary, -1);
4424 ary_verify(ary);
4425 return del;
4426}
4427
4428/*
4429 * call-seq:
4430 * delete_at(index) -> removed_object or nil
4431 *
4432 * Removes the element of +self+ at the given +index+, which must be an
4433 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
4434 *
4435 * When +index+ is non-negative, deletes the element at offset +index+:
4436 *
4437 * a = [:foo, 'bar', 2]
4438 * a.delete_at(1) # => "bar"
4439 * a # => [:foo, 2]
4440 *
4441 * When +index+ is negative, counts backward from the end of the array:
4442 *
4443 * a = [:foo, 'bar', 2]
4444 * a.delete_at(-2) # => "bar"
4445 * a # => [:foo, 2]
4446 *
4447 * When +index+ is out of range, returns +nil+.
4448 *
4449 * a = [:foo, 'bar', 2]
4450 * a.delete_at(3) # => nil
4451 * a.delete_at(-4) # => nil
4452 *
4453 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4454 */
4455
4456static VALUE
4457rb_ary_delete_at_m(VALUE ary, VALUE pos)
4458{
4459 return rb_ary_delete_at(ary, NUM2LEN(pos));
4460}
4461
4462static VALUE
4463ary_slice_bang_by_rb_ary_splice(VALUE ary, rb_len_t pos, rb_len_t len)
4464{
4465 const rb_len_t orig_len = RARRAY_LEN(ary);
4466
4467 if (len < 0) {
4468 return Qnil;
4469 }
4470 else if (pos < -orig_len) {
4471 return Qnil;
4472 }
4473 else if (pos < 0) {
4474 pos += orig_len;
4475 }
4476 else if (orig_len < pos) {
4477 return Qnil;
4478 }
4479 if (orig_len < pos + len) {
4480 len = orig_len - pos;
4481 }
4482 if (len == 0) {
4483 return rb_ary_new2(0);
4484 }
4485 else {
4486 VALUE arg2 = rb_ary_new4(len, RARRAY_CONST_PTR(ary)+pos);
4487 ary_splice(ary, pos, len, 0, 0, FALSE);
4488 return arg2;
4489 }
4490}
4491
4492/*
4493 * call-seq:
4494 * slice!(index) -> object or nil
4495 * slice!(start, length) -> new_array or nil
4496 * slice!(range) -> new_array or nil
4497 *
4498 * Removes and returns elements from +self+.
4499 *
4500 * With numeric argument +index+ given,
4501 * removes and returns the element at offset +index+:
4502 *
4503 * a = ['a', 'b', 'c', 'd']
4504 * a.slice!(2) # => "c"
4505 * a # => ["a", "b", "d"]
4506 * a.slice!(2.1) # => "d"
4507 * a # => ["a", "b"]
4508 *
4509 * If +index+ is negative, counts backwards from the end of +self+:
4510 *
4511 * a = ['a', 'b', 'c', 'd']
4512 * a.slice!(-2) # => "c"
4513 * a # => ["a", "b", "d"]
4514 *
4515 * If +index+ is out of range, returns +nil+.
4516 *
4517 * With numeric arguments +start+ and +length+ given,
4518 * removes +length+ elements from +self+ beginning at zero-based offset +start+;
4519 * returns the removed objects in a new array:
4520 *
4521 * a = ['a', 'b', 'c', 'd']
4522 * a.slice!(1, 2) # => ["b", "c"]
4523 * a # => ["a", "d"]
4524 * a.slice!(0.1, 1.1) # => ["a"]
4525 * a # => ["d"]
4526 *
4527 * If +start+ is negative, counts backwards from the end of +self+:
4528 *
4529 * a = ['a', 'b', 'c', 'd']
4530 * a.slice!(-2, 1) # => ["c"]
4531 * a # => ["a", "b", "d"]
4532 *
4533 * If +start+ is out-of-range, returns +nil+:
4534 *
4535 * a = ['a', 'b', 'c', 'd']
4536 * a.slice!(5, 1) # => nil
4537 * a.slice!(-5, 1) # => nil
4538 *
4539 * If <tt>start + length</tt> exceeds the array size,
4540 * removes and returns all elements from offset +start+ to the end:
4541 *
4542 * a = ['a', 'b', 'c', 'd']
4543 * a.slice!(2, 50) # => ["c", "d"]
4544 * a # => ["a", "b"]
4545 *
4546 * If <tt>start == a.size</tt> and +length+ is non-negative,
4547 * returns a new empty array.
4548 *
4549 * If +length+ is negative, returns +nil+.
4550 *
4551 * With Range argument +range+ given,
4552 * treats <tt>range.min</tt> as +start+ (as above)
4553 * and <tt>range.size</tt> as +length+ (as above):
4554 *
4555 * a = ['a', 'b', 'c', 'd']
4556 * a.slice!(1..2) # => ["b", "c"]
4557 * a # => ["a", "d"]
4558 *
4559 * If <tt>range.start == a.size</tt>, returns a new empty array:
4560 *
4561 * a = ['a', 'b', 'c', 'd']
4562 * a.slice!(4..5) # => []
4563 *
4564 * If <tt>range.start</tt> is larger than the array size, returns +nil+:
4565 *
4566 * a = ['a', 'b', 'c', 'd']
4567 a.slice!(5..6) # => nil
4568 *
4569 * If <tt>range.start</tt> is negative,
4570 * calculates the start index by counting backwards from the end of +self+:
4571 *
4572 * a = ['a', 'b', 'c', 'd']
4573 * a.slice!(-2..2) # => ["c"]
4574 *
4575 * If <tt>range.end</tt> is negative,
4576 * calculates the end index by counting backwards from the end of +self+:
4577 *
4578 * a = ['a', 'b', 'c', 'd']
4579 * a.slice!(0..-2) # => ["a", "b", "c"]
4580 *
4581 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4582 */
4583
4584static VALUE
4585rb_ary_slice_bang(int argc, VALUE *argv, VALUE ary)
4586{
4587 VALUE arg1;
4588 rb_len_t pos, len;
4589
4590 rb_ary_modify_check(ary);
4591 rb_check_arity(argc, 1, 2);
4592 arg1 = argv[0];
4593
4594 if (argc == 2) {
4595 pos = NUM2LEN(argv[0]);
4596 len = NUM2LEN(argv[1]);
4597 return ary_slice_bang_by_rb_ary_splice(ary, pos, len);
4598 }
4599
4600 if (!FIXNUM_P(arg1)) {
4601 switch (rb_range_beg_len(arg1, &pos, &len, RARRAY_LEN(ary), 0)) {
4602 case Qtrue:
4603 /* valid range */
4604 return ary_slice_bang_by_rb_ary_splice(ary, pos, len);
4605 case Qnil:
4606 /* invalid range */
4607 return Qnil;
4608 default:
4609 /* not a range */
4610 break;
4611 }
4612 }
4613
4614 return rb_ary_delete_at(ary, NUM2LEN(arg1));
4615}
4616
4617static VALUE
4618ary_reject(VALUE orig, VALUE result)
4619{
4620 rb_len_t i;
4621
4622 for (i = 0; i < RARRAY_LEN(orig); i++) {
4623 VALUE v = RARRAY_AREF(orig, i);
4624
4625 if (!RTEST(rb_yield(v))) {
4626 rb_ary_push(result, v);
4627 }
4628 }
4629 return result;
4630}
4631
4632static VALUE
4633reject_bang_i(VALUE a)
4634{
4635 volatile struct select_bang_arg *arg = (void *)a;
4636 VALUE ary = arg->ary;
4637 rb_len_t i1, i2;
4638
4639 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); arg->len[0] = ++i1) {
4640 VALUE v = RARRAY_AREF(ary, i1);
4641 if (RTEST(rb_yield(v))) continue;
4642 if (i1 != i2) {
4643 rb_ary_store(ary, i2, v);
4644 }
4645 arg->len[1] = ++i2;
4646 }
4647 return (i1 == i2) ? Qnil : ary;
4648}
4649
4650static VALUE
4651ary_reject_bang(VALUE ary)
4652{
4653 struct select_bang_arg args;
4654 rb_ary_modify_check(ary);
4655 args.ary = ary;
4656 args.len[0] = args.len[1] = 0;
4657 return rb_ensure(reject_bang_i, (VALUE)&args, select_bang_ensure, (VALUE)&args);
4658}
4659
4660/*
4661 * call-seq:
4662 * reject! {|element| ... } -> self or nil
4663 * reject! -> new_enumerator
4664 *
4665 * With a block given, calls the block with each element of +self+;
4666 * removes each element for which the block returns a truthy value.
4667 *
4668 * Returns +self+ if any elements removed:
4669 *
4670 * a = [:foo, 'bar', 2, 'bat']
4671 * a.reject! {|element| element.to_s.start_with?('b') } # => [:foo, 2]
4672 *
4673 * Returns +nil+ if no elements removed.
4674 *
4675 * With no block given, returns a new Enumerator.
4676 *
4677 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4678 */
4679
4680static VALUE
4681rb_ary_reject_bang(VALUE ary)
4682{
4683 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
4684 rb_ary_modify(ary);
4685 return ary_reject_bang(ary);
4686}
4687
4688/*
4689 * call-seq:
4690 * reject {|element| ... } -> new_array
4691 * reject -> new_enumerator
4692 *
4693 * With a block given, returns a new array whose elements are all those from +self+
4694 * for which the block returns +false+ or +nil+:
4695 *
4696 * a = [:foo, 'bar', 2, 'bat']
4697 * a1 = a.reject {|element| element.to_s.start_with?('b') }
4698 * a1 # => [:foo, 2]
4699 *
4700 * With no block given, returns a new Enumerator.
4701 *
4702 * Related: {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
4703 */
4704
4705static VALUE
4706rb_ary_reject(VALUE ary)
4707{
4708 VALUE rejected_ary;
4709
4710 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
4711 rejected_ary = rb_ary_new();
4712 ary_reject(ary, rejected_ary);
4713 return rejected_ary;
4714}
4715
4716/*
4717 * call-seq:
4718 * delete_if {|element| ... } -> self
4719 * delete_if -> new_numerator
4720 *
4721 * With a block given, calls the block with each element of +self+;
4722 * removes the element if the block returns a truthy value;
4723 * returns +self+:
4724 *
4725 * a = [:foo, 'bar', 2, 'bat']
4726 * a.delete_if {|element| element.to_s.start_with?('b') } # => [:foo, 2]
4727 *
4728 * With no block given, returns a new Enumerator.
4729 *
4730 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4731 */
4732
4733static VALUE
4734rb_ary_delete_if(VALUE ary)
4735{
4736 ary_verify(ary);
4737 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
4738 ary_reject_bang(ary);
4739 return ary;
4740}
4741
4742static VALUE
4743take_i(RB_BLOCK_CALL_FUNC_ARGLIST(val, cbarg))
4744{
4745 VALUE *args = (VALUE *)cbarg;
4746 if (argc > 1) val = rb_ary_new4(argc, argv);
4747 rb_ary_push(args[0], val);
4748 if (--args[1] == 0) rb_iter_break();
4749 return Qnil;
4750}
4751
4752static VALUE
4753take_items(VALUE obj, rb_len_t n)
4754{
4755 VALUE result = rb_check_array_type(obj);
4756 VALUE args[2];
4757
4758 if (n == 0) return result;
4759 if (!NIL_P(result)) return rb_ary_subseq(result, 0, n);
4760 result = rb_ary_new2(n);
4761 args[0] = result; args[1] = (VALUE)n;
4762 if (UNDEF_P(rb_check_block_call(obj, idEach, 0, 0, take_i, (VALUE)args)))
4763 rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (must respond to :each)",
4764 rb_obj_class(obj));
4765 return result;
4766}
4767
4768
4769/*
4770 * call-seq:
4771 * zip(*other_arrays) -> new_array
4772 * zip(*other_arrays) {|sub_array| ... } -> nil
4773 *
4774 * With no block given, combines +self+ with the collection of +other_arrays+;
4775 * returns a new array of sub-arrays:
4776 *
4777 * [0, 1].zip(['zero', 'one'], [:zero, :one])
4778 * # => [[0, "zero", :zero], [1, "one", :one]]
4779 *
4780 * Returned:
4781 *
4782 * - The outer array is of size <tt>self.size</tt>.
4783 * - Each sub-array is of size <tt>other_arrays.size + 1</tt>.
4784 * - The _nth_ sub-array contains (in order):
4785 *
4786 * - The _nth_ element of +self+.
4787 * - The _nth_ element of each of the other arrays, as available.
4788 *
4789 * Example:
4790 *
4791 * a = [0, 1]
4792 * zipped = a.zip(['zero', 'one'], [:zero, :one])
4793 * # => [[0, "zero", :zero], [1, "one", :one]]
4794 * zipped.size # => 2 # Same size as a.
4795 * zipped.first.size # => 3 # Size of other arrays plus 1.
4796 *
4797 * When the other arrays are all the same size as +self+,
4798 * the returned sub-arrays are a rearrangement containing exactly elements of all the arrays
4799 * (including +self+), with no omissions or additions:
4800 *
4801 * a = [:a0, :a1, :a2, :a3]
4802 * b = [:b0, :b1, :b2, :b3]
4803 * c = [:c0, :c1, :c2, :c3]
4804 * d = a.zip(b, c)
4805 * pp d
4806 * # =>
4807 * [[:a0, :b0, :c0],
4808 * [:a1, :b1, :c1],
4809 * [:a2, :b2, :c2],
4810 * [:a3, :b3, :c3]]
4811 *
4812 * When one of the other arrays is smaller than +self+,
4813 * pads the corresponding sub-array with +nil+ elements:
4814 *
4815 * a = [:a0, :a1, :a2, :a3]
4816 * b = [:b0, :b1, :b2]
4817 * c = [:c0, :c1]
4818 * d = a.zip(b, c)
4819 * pp d
4820 * # =>
4821 * [[:a0, :b0, :c0],
4822 * [:a1, :b1, :c1],
4823 * [:a2, :b2, nil],
4824 * [:a3, nil, nil]]
4825 *
4826 * When one of the other arrays is larger than +self+,
4827 * _ignores_ its trailing elements:
4828 *
4829 * a = [:a0, :a1, :a2, :a3]
4830 * b = [:b0, :b1, :b2, :b3, :b4]
4831 * c = [:c0, :c1, :c2, :c3, :c4, :c5]
4832 * d = a.zip(b, c)
4833 * pp d
4834 * # =>
4835 * [[:a0, :b0, :c0],
4836 * [:a1, :b1, :c1],
4837 * [:a2, :b2, :c2],
4838 * [:a3, :b3, :c3]]
4839 *
4840 * With a block given, calls the block with each of the other arrays;
4841 * returns +nil+:
4842 *
4843 * d = []
4844 * a = [:a0, :a1, :a2, :a3]
4845 * b = [:b0, :b1, :b2, :b3]
4846 * c = [:c0, :c1, :c2, :c3]
4847 * a.zip(b, c) {|sub_array| d.push(sub_array.reverse) } # => nil
4848 * pp d
4849 * # =>
4850 * [[:c0, :b0, :a0],
4851 * [:c1, :b1, :a1],
4852 * [:c2, :b2, :a2],
4853 * [:c3, :b3, :a3]]
4854 *
4855 * For an *object* in *other_arrays* that is not actually an array,
4856 * forms the "other array" as <tt>object.to_ary</tt>, if defined,
4857 * or as <tt>object.each.to_a</tt> otherwise.
4858 *
4859 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
4860 */
4861
4862static VALUE
4863rb_ary_zip(int argc, VALUE *argv, VALUE ary)
4864{
4865 int i, j;
4866 rb_len_t len = RARRAY_LEN(ary);
4867 VALUE result = Qnil;
4868
4869 for (i=0; i<argc; i++) {
4870 argv[i] = take_items(argv[i], len);
4871 }
4872
4873 if (rb_block_given_p()) {
4874 int arity = rb_block_arity();
4875
4876 if (arity > 1) {
4877 VALUE work, *tmp;
4878
4879 tmp = ALLOCV_N(VALUE, work, argc+1);
4880
4881 for (i=0; i<RARRAY_LEN(ary); i++) {
4882 tmp[0] = RARRAY_AREF(ary, i);
4883 for (j=0; j<argc; j++) {
4884 tmp[j+1] = rb_ary_elt(argv[j], i);
4885 }
4886 rb_yield_values2(argc+1, tmp);
4887 }
4888
4889 if (work) ALLOCV_END(work);
4890 }
4891 else {
4892 for (i=0; i<RARRAY_LEN(ary); i++) {
4893 VALUE tmp = rb_ary_new2(argc+1);
4894
4895 rb_ary_push(tmp, RARRAY_AREF(ary, i));
4896 for (j=0; j<argc; j++) {
4897 rb_ary_push(tmp, rb_ary_elt(argv[j], i));
4898 }
4899 rb_yield(tmp);
4900 }
4901 }
4902 }
4903 else {
4904 result = rb_ary_new_capa(len);
4905
4906 for (i=0; i<RARRAY_LEN(ary); i++) {
4907 VALUE tmp = rb_ary_new_capa(argc+1);
4908
4909 rb_ary_push(tmp, RARRAY_AREF(ary, i));
4910 for (j=0; j<argc; j++) {
4911 rb_ary_push(tmp, rb_ary_elt(argv[j], i));
4912 }
4913 rb_ary_push(result, tmp);
4914 }
4915 }
4916
4917 return result;
4918}
4919
4920/*
4921 * call-seq:
4922 * transpose -> new_array
4923 *
4924 * Returns a new array that is +self+
4925 * as a {transposed matrix}[https://en.wikipedia.org/wiki/Transpose]:
4926 *
4927 * a = [[:a0, :a1], [:b0, :b1], [:c0, :c1]]
4928 * a.transpose # => [[:a0, :b0, :c0], [:a1, :b1, :c1]]
4929 *
4930 * The elements of +self+ must all be the same size.
4931 *
4932 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
4933 */
4934
4935static VALUE
4936rb_ary_transpose(VALUE ary)
4937{
4938 rb_len_t elen = -1, alen, i, j;
4939 VALUE tmp, result = 0;
4940
4941 alen = RARRAY_LEN(ary);
4942 if (alen == 0) return rb_ary_dup(ary);
4943 for (i=0; i<alen; i++) {
4944 tmp = to_ary(rb_ary_elt(ary, i));
4945 if (elen < 0) { /* first element */
4946 elen = RARRAY_LEN(tmp);
4947 result = rb_ary_new2(elen);
4948 for (j=0; j<elen; j++) {
4949 rb_ary_store(result, j, rb_ary_new2(alen));
4950 }
4951 }
4952 else if (elen != RARRAY_LEN(tmp)) {
4953 rb_raise(rb_eIndexError, "element size differs (%"PRIdLEN" should be %"PRIdLEN")",
4954 RARRAY_LEN(tmp), elen);
4955 }
4956 for (j=0; j<elen; j++) {
4957 rb_ary_store(rb_ary_elt(result, j), i, rb_ary_elt(tmp, j));
4958 }
4959 }
4960 return result;
4961}
4962
4963/*
4964 * call-seq:
4965 * initialize_copy(other_array) -> self
4966 * replace(other_array) -> self
4967 *
4968 * Replaces the elements of +self+ with the elements of +other_array+, which must be an
4969 * {array-convertible object}[rdoc-ref:implicit_conversion.rdoc@Array-Convertible+Objects];
4970 * returns +self+:
4971 *
4972 * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
4973 * a.replace(['d', 'e']) # => ["d", "e"]
4974 *
4975 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
4976 */
4977
4978VALUE
4979rb_ary_replace(VALUE copy, VALUE orig)
4980{
4981 rb_ary_modify_check(copy);
4982 orig = to_ary(orig);
4983 if (copy == orig) return copy;
4984
4985 rb_ary_reset(copy);
4986
4987 /* orig has enough space to embed the contents of orig. */
4988 if (RARRAY_LEN(orig) <= ary_embed_capa(copy)) {
4989 RUBY_ASSERT(ARY_EMBED_P(copy));
4990 ary_memcpy(copy, 0, RARRAY_LEN(orig), RARRAY_CONST_PTR(orig));
4991 ARY_SET_EMBED_LEN(copy, RARRAY_LEN(orig));
4992 }
4993 /* orig is embedded but copy does not have enough space to embed the
4994 * contents of orig. */
4995 else if (ARY_EMBED_P(orig)) {
4996 rb_len_t len = ARY_EMBED_LEN(orig);
4997 VALUE *ptr = ary_heap_alloc_buffer(len);
4998
4999 FL_UNSET_EMBED(copy);
5000 ARY_SET_PTR(copy, ptr);
5001 ARY_SET_LEN(copy, len);
5002 ARY_SET_CAPA(copy, len);
5003
5004 // No allocation and exception expected that could leave `copy` in a
5005 // bad state from the edits above.
5006 ary_memcpy(copy, 0, len, RARRAY_CONST_PTR(orig));
5007 }
5008 /* Otherwise, orig is on heap and copy does not have enough space to embed
5009 * the contents of orig. */
5010 else {
5011 VALUE shared_root = ary_make_shared(orig);
5012 FL_UNSET_EMBED(copy);
5013 ARY_SET_PTR(copy, ARY_HEAP_PTR(orig));
5014 ARY_SET_LEN(copy, ARY_HEAP_LEN(orig));
5015 rb_ary_set_shared(copy, shared_root);
5016
5017 RUBY_ASSERT(RB_OBJ_SHAREABLE_P(copy) ? RB_OBJ_SHAREABLE_P(shared_root) : 1);
5018 }
5019 ary_verify(copy);
5020 return copy;
5021}
5022
5023/*
5024 * call-seq:
5025 * clear -> self
5026 *
5027 * Removes all elements from +self+; returns +self+:
5028 *
5029 * a = [:foo, 'bar', 2]
5030 * a.clear # => []
5031 *
5032 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
5033 */
5034
5035VALUE
5037{
5038 rb_ary_modify_check(ary);
5039 if (ARY_SHARED_P(ary)) {
5040 rb_ary_unshare(ary);
5041 FL_SET_EMBED(ary);
5042 ARY_SET_EMBED_LEN(ary, 0);
5043 }
5044 else {
5045 ARY_SET_LEN(ary, 0);
5046 if (ARY_DEFAULT_SIZE * 2 < ARY_CAPA(ary)) {
5047 ary_resize_capa(ary, ARY_DEFAULT_SIZE * 2);
5048 }
5049 }
5050 ary_verify(ary);
5051 return ary;
5052}
5053
5054/*
5055 * call-seq:
5056 * fill(object, start = nil, count = nil) -> self
5057 * fill(object, range) -> self
5058 * fill(start = nil, count = nil) {|element| ... } -> self
5059 * fill(range) {|element| ... } -> self
5060 *
5061 * Replaces selected elements in +self+;
5062 * may add elements to +self+;
5063 * always returns +self+ (never a new array).
5064 *
5065 * In brief:
5066 *
5067 * # Non-negative start.
5068 * ['a', 'b', 'c', 'd'].fill('-', 1, 2) # => ["a", "-", "-", "d"]
5069 * ['a', 'b', 'c', 'd'].fill(1, 2) {|e| e.to_s } # => ["a", "1", "2", "d"]
5070 *
5071 * # Extends with specified values if necessary.
5072 * ['a', 'b', 'c', 'd'].fill('-', 3, 2) # => ["a", "b", "c", "-", "-"]
5073 * ['a', 'b', 'c', 'd'].fill(3, 2) {|e| e.to_s } # => ["a", "b", "c", "3", "4"]
5074 *
5075 * # Fills with nils if necessary.
5076 * ['a', 'b', 'c', 'd'].fill('-', 6, 2) # => ["a", "b", "c", "d", nil, nil, "-", "-"]
5077 * ['a', 'b', 'c', 'd'].fill(6, 2) {|e| e.to_s } # => ["a", "b", "c", "d", nil, nil, "6", "7"]
5078 *
5079 * # For negative start, counts backwards from the end.
5080 * ['a', 'b', 'c', 'd'].fill('-', -3, 3) # => ["a", "-", "-", "-"]
5081 * ['a', 'b', 'c', 'd'].fill(-3, 3) {|e| e.to_s } # => ["a", "1", "2", "3"]
5082 *
5083 * # Range.
5084 * ['a', 'b', 'c', 'd'].fill('-', 1..2) # => ["a", "-", "-", "d"]
5085 * ['a', 'b', 'c', 'd'].fill(1..2) {|e| e.to_s } # => ["a", "1", "2", "d"]
5086 *
5087 * When arguments +start+ and +count+ are given,
5088 * they select the elements of +self+ to be replaced;
5089 * each must be an
5090 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]
5091 * (or +nil+):
5092 *
5093 * - +start+ specifies the zero-based offset of the first element to be replaced;
5094 * +nil+ means zero.
5095 * - +count+ is the number of consecutive elements to be replaced;
5096 * +nil+ means "all the rest."
5097 *
5098 * With argument +object+ given,
5099 * that one object is used for all replacements:
5100 *
5101 * o = Object.new # => #<Object:0x0000014e7bff7600>
5102 * a = ['a', 'b', 'c', 'd'] # => ["a", "b", "c", "d"]
5103 * a.fill(o, 1, 2)
5104 * # => ["a", #<Object:0x0000014e7bff7600>, #<Object:0x0000014e7bff7600>, "d"]
5105 *
5106 * With a block given, the block is called once for each element to be replaced;
5107 * the value passed to the block is the _index_ of the element to be replaced
5108 * (not the element itself);
5109 * the block's return value replaces the element:
5110 *
5111 * a = ['a', 'b', 'c', 'd'] # => ["a", "b", "c", "d"]
5112 * a.fill(1, 2) {|element| element.to_s } # => ["a", "1", "2", "d"]
5113 *
5114 * For arguments +start+ and +count+:
5115 *
5116 * - If +start+ is non-negative,
5117 * replaces +count+ elements beginning at offset +start+:
5118 *
5119 * ['a', 'b', 'c', 'd'].fill('-', 0, 2) # => ["-", "-", "c", "d"]
5120 * ['a', 'b', 'c', 'd'].fill('-', 1, 2) # => ["a", "-", "-", "d"]
5121 * ['a', 'b', 'c', 'd'].fill('-', 2, 2) # => ["a", "b", "-", "-"]
5122 *
5123 * ['a', 'b', 'c', 'd'].fill(0, 2) {|e| e.to_s } # => ["0", "1", "c", "d"]
5124 * ['a', 'b', 'c', 'd'].fill(1, 2) {|e| e.to_s } # => ["a", "1", "2", "d"]
5125 * ['a', 'b', 'c', 'd'].fill(2, 2) {|e| e.to_s } # => ["a", "b", "2", "3"]
5126 *
5127 * Extends +self+ if necessary:
5128 *
5129 * ['a', 'b', 'c', 'd'].fill('-', 3, 2) # => ["a", "b", "c", "-", "-"]
5130 * ['a', 'b', 'c', 'd'].fill('-', 4, 2) # => ["a", "b", "c", "d", "-", "-"]
5131 *
5132 * ['a', 'b', 'c', 'd'].fill(3, 2) {|e| e.to_s } # => ["a", "b", "c", "3", "4"]
5133 * ['a', 'b', 'c', 'd'].fill(4, 2) {|e| e.to_s } # => ["a", "b", "c", "d", "4", "5"]
5134 *
5135 * Fills with +nil+ if necessary:
5136 *
5137 * ['a', 'b', 'c', 'd'].fill('-', 5, 2) # => ["a", "b", "c", "d", nil, "-", "-"]
5138 * ['a', 'b', 'c', 'd'].fill('-', 6, 2) # => ["a", "b", "c", "d", nil, nil, "-", "-"]
5139 *
5140 * ['a', 'b', 'c', 'd'].fill(5, 2) {|e| e.to_s } # => ["a", "b", "c", "d", nil, "5", "6"]
5141 * ['a', 'b', 'c', 'd'].fill(6, 2) {|e| e.to_s } # => ["a", "b", "c", "d", nil, nil, "6", "7"]
5142 *
5143 * Does nothing if +count+ is non-positive:
5144 *
5145 * ['a', 'b', 'c', 'd'].fill('-', 2, 0) # => ["a", "b", "c", "d"]
5146 * ['a', 'b', 'c', 'd'].fill('-', 2, -100) # => ["a", "b", "c", "d"]
5147 * ['a', 'b', 'c', 'd'].fill('-', 6, -100) # => ["a", "b", "c", "d"]
5148 *
5149 * ['a', 'b', 'c', 'd'].fill(2, 0) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
5150 * ['a', 'b', 'c', 'd'].fill(2, -100) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
5151 * ['a', 'b', 'c', 'd'].fill(6, -100) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
5152 *
5153 * - If +start+ is negative, counts backwards from the end of +self+:
5154 *
5155 * ['a', 'b', 'c', 'd'].fill('-', -4, 3) # => ["-", "-", "-", "d"]
5156 * ['a', 'b', 'c', 'd'].fill('-', -3, 3) # => ["a", "-", "-", "-"]
5157 *
5158 * ['a', 'b', 'c', 'd'].fill(-4, 3) {|e| e.to_s } # => ["0", "1", "2", "d"]
5159 * ['a', 'b', 'c', 'd'].fill(-3, 3) {|e| e.to_s } # => ["a", "1", "2", "3"]
5160 *
5161 * Extends +self+ if necessary:
5162 *
5163 * ['a', 'b', 'c', 'd'].fill('-', -2, 3) # => ["a", "b", "-", "-", "-"]
5164 * ['a', 'b', 'c', 'd'].fill('-', -1, 3) # => ["a", "b", "c", "-", "-", "-"]
5165 *
5166 * ['a', 'b', 'c', 'd'].fill(-2, 3) {|e| e.to_s } # => ["a", "b", "2", "3", "4"]
5167 * ['a', 'b', 'c', 'd'].fill(-1, 3) {|e| e.to_s } # => ["a", "b", "c", "3", "4", "5"]
5168 *
5169 * Starts at the beginning of +self+ if +start+ is negative and out-of-range:
5170 *
5171 * ['a', 'b', 'c', 'd'].fill('-', -5, 2) # => ["-", "-", "c", "d"]
5172 * ['a', 'b', 'c', 'd'].fill('-', -6, 2) # => ["-", "-", "c", "d"]
5173 *
5174 * ['a', 'b', 'c', 'd'].fill(-5, 2) {|e| e.to_s } # => ["0", "1", "c", "d"]
5175 * ['a', 'b', 'c', 'd'].fill(-6, 2) {|e| e.to_s } # => ["0", "1", "c", "d"]
5176 *
5177 * Does nothing if +count+ is non-positive:
5178 *
5179 * ['a', 'b', 'c', 'd'].fill('-', -2, 0) # => ["a", "b", "c", "d"]
5180 * ['a', 'b', 'c', 'd'].fill('-', -2, -1) # => ["a", "b", "c", "d"]
5181 *
5182 * ['a', 'b', 'c', 'd'].fill(-2, 0) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
5183 * ['a', 'b', 'c', 'd'].fill(-2, -1) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
5184 *
5185 * When argument +range+ is given,
5186 * it must be a Range object whose members are numeric;
5187 * its +begin+ and +end+ values determine the elements of +self+
5188 * to be replaced:
5189 *
5190 * - If both +begin+ and +end+ are positive, they specify the first and last elements
5191 * to be replaced:
5192 *
5193 * ['a', 'b', 'c', 'd'].fill('-', 1..2) # => ["a", "-", "-", "d"]
5194 * ['a', 'b', 'c', 'd'].fill(1..2) {|e| e.to_s } # => ["a", "1", "2", "d"]
5195 *
5196 * If +end+ is smaller than +begin+, replaces no elements:
5197 *
5198 * ['a', 'b', 'c', 'd'].fill('-', 2..1) # => ["a", "b", "c", "d"]
5199 * ['a', 'b', 'c', 'd'].fill(2..1) {|e| e.to_s } # => ["a", "b", "c", "d"]
5200 *
5201 * - If either is negative (or both are negative), counts backwards from the end of +self+:
5202 *
5203 * ['a', 'b', 'c', 'd'].fill('-', -3..2) # => ["a", "-", "-", "d"]
5204 * ['a', 'b', 'c', 'd'].fill('-', 1..-2) # => ["a", "-", "-", "d"]
5205 * ['a', 'b', 'c', 'd'].fill('-', -3..-2) # => ["a", "-", "-", "d"]
5206 *
5207 * ['a', 'b', 'c', 'd'].fill(-3..2) {|e| e.to_s } # => ["a", "1", "2", "d"]
5208 * ['a', 'b', 'c', 'd'].fill(1..-2) {|e| e.to_s } # => ["a", "1", "2", "d"]
5209 * ['a', 'b', 'c', 'd'].fill(-3..-2) {|e| e.to_s } # => ["a", "1", "2", "d"]
5210 *
5211 * - If the +end+ value is excluded (see Range#exclude_end?), omits the last replacement:
5212 *
5213 * ['a', 'b', 'c', 'd'].fill('-', 1...2) # => ["a", "-", "c", "d"]
5214 * ['a', 'b', 'c', 'd'].fill('-', 1...-2) # => ["a", "-", "c", "d"]
5215 *
5216 * ['a', 'b', 'c', 'd'].fill(1...2) {|e| e.to_s } # => ["a", "1", "c", "d"]
5217 * ['a', 'b', 'c', 'd'].fill(1...-2) {|e| e.to_s } # => ["a", "1", "c", "d"]
5218 *
5219 * - If the range is endless (see {Endless Ranges}[rdoc-ref:Range@Endless+Ranges]),
5220 * replaces elements to the end of +self+:
5221 *
5222 * ['a', 'b', 'c', 'd'].fill('-', 1..) # => ["a", "-", "-", "-"]
5223 * ['a', 'b', 'c', 'd'].fill(1..) {|e| e.to_s } # => ["a", "1", "2", "3"]
5224 *
5225 * - If the range is beginless (see {Beginless Ranges}[rdoc-ref:Range@Beginless+Ranges]),
5226 * replaces elements from the beginning of +self+:
5227 *
5228 * ['a', 'b', 'c', 'd'].fill('-', ..2) # => ["-", "-", "-", "d"]
5229 * ['a', 'b', 'c', 'd'].fill(..2) {|e| e.to_s } # => ["0", "1", "2", "d"]
5230 *
5231 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
5232 */
5233
5234static VALUE
5235rb_ary_fill(int argc, VALUE *argv, VALUE ary)
5236{
5237 VALUE item = Qundef, arg1, arg2;
5238 rb_len_t beg = 0, end = 0, len = 0;
5239
5240 if (rb_block_given_p()) {
5241 rb_scan_args(argc, argv, "02", &arg1, &arg2);
5242 argc += 1; /* hackish */
5243 }
5244 else {
5245 rb_scan_args(argc, argv, "12", &item, &arg1, &arg2);
5246 }
5247 switch (argc) {
5248 case 1:
5249 beg = 0;
5250 len = RARRAY_LEN(ary);
5251 break;
5252 case 2:
5253 if (rb_range_beg_len(arg1, &beg, &len, RARRAY_LEN(ary), 1)) {
5254 break;
5255 }
5256 /* fall through */
5257 case 3:
5258 beg = NIL_P(arg1) ? 0 : NUM2LEN(arg1);
5259 if (beg < 0) {
5260 beg = RARRAY_LEN(ary) + beg;
5261 if (beg < 0) beg = 0;
5262 }
5263 len = NIL_P(arg2) ? RARRAY_LEN(ary) - beg : NUM2LEN(arg2);
5264 break;
5265 }
5266 rb_ary_modify(ary);
5267 if (len < 0) {
5268 return ary;
5269 }
5270 if (beg >= ARY_MAX_SIZE || len > ARY_MAX_SIZE - beg) {
5271 rb_raise(rb_eArgError, "argument too big");
5272 }
5273 end = beg + len;
5274 if (RARRAY_LEN(ary) < end) {
5275 if (end >= ARY_CAPA(ary)) {
5276 ary_resize_capa(ary, end);
5277 }
5278 ary_mem_clear(ary, RARRAY_LEN(ary), end - RARRAY_LEN(ary));
5279 ARY_SET_LEN(ary, end);
5280 }
5281
5282 if (UNDEF_P(item)) {
5283 VALUE v;
5284 rb_len_t i;
5285
5286 for (i=beg; i<end; i++) {
5287 v = rb_yield(LEN2NUM(i));
5288 if (i>=RARRAY_LEN(ary)) break;
5289 ARY_SET(ary, i, v);
5290 }
5291 }
5292 else {
5293 ary_memfill(ary, beg, len, item);
5294 }
5295 return ary;
5296}
5297
5298/*
5299 * call-seq:
5300 * self + other_array -> new_array
5301 *
5302 * Returns a new array containing all elements of +self+
5303 * followed by all elements of +other_array+:
5304 *
5305 * a = [0, 1] + [2, 3]
5306 * a # => [0, 1, 2, 3]
5307 *
5308 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5309 */
5310
5311VALUE
5313{
5314 VALUE z;
5315 rb_len_t len, xlen, ylen;
5316
5317 y = to_ary(y);
5318 xlen = RARRAY_LEN(x);
5319 ylen = RARRAY_LEN(y);
5320 len = xlen + ylen;
5321 z = rb_ary_new2(len);
5322
5323 ary_memcpy(z, 0, xlen, RARRAY_CONST_PTR(x));
5324 ary_memcpy(z, xlen, ylen, RARRAY_CONST_PTR(y));
5325 ARY_SET_LEN(z, len);
5326 return z;
5327}
5328
5329static VALUE
5330ary_append(VALUE x, VALUE y)
5331{
5332 if (RARRAY_LEN(y) > 0) {
5333 rb_ary_splice(x, RARRAY_LEN(x), 0, y);
5334 }
5335 return x;
5336}
5337
5338/*
5339 * call-seq:
5340 * concat(*other_arrays) -> self
5341 *
5342 * Adds to +self+ all elements from each array in +other_arrays+; returns +self+:
5343 *
5344 * a = [0, 1]
5345 * a.concat(['two', 'three'], [:four, :five], a)
5346 * # => [0, 1, "two", "three", :four, :five, 0, 1]
5347 *
5348 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
5349 */
5350
5351static VALUE
5352rb_ary_concat_multi(int argc, VALUE *argv, VALUE ary)
5353{
5354 rb_ary_modify_check(ary);
5355
5356 if (argc == 1) {
5357 rb_ary_concat(ary, argv[0]);
5358 }
5359 else if (argc > 1) {
5360 int i;
5361 VALUE args = rb_ary_hidden_new(argc);
5362 for (i = 0; i < argc; i++) {
5363 rb_ary_concat(args, argv[i]);
5364 }
5365 ary_append(ary, args);
5366 }
5367
5368 ary_verify(ary);
5369 return ary;
5370}
5371
5372VALUE
5374{
5375 return ary_append(x, to_ary(y));
5376}
5377
5378/*
5379 * call-seq:
5380 * self * n -> new_array
5381 * self * string_separator -> new_string
5382 *
5383 * When non-negative integer argument +n+ is given,
5384 * returns a new array built by concatenating +n+ copies of +self+:
5385 *
5386 * a = ['x', 'y']
5387 * a * 3 # => ["x", "y", "x", "y", "x", "y"]
5388 *
5389 * When string argument +string_separator+ is given,
5390 * equivalent to <tt>self.join(string_separator)</tt>:
5391 *
5392 * [0, [0, 1], {foo: 0}] * ', ' # => "0, 0, 1, {foo: 0}"
5393 *
5394 */
5395
5396static VALUE
5397rb_ary_times(VALUE ary, VALUE times)
5398{
5399 VALUE ary2, tmp;
5400 const VALUE *ptr;
5401 rb_len_t t, len;
5402
5403 tmp = rb_check_string_type(times);
5404 if (!NIL_P(tmp)) {
5405 return rb_ary_join(ary, tmp);
5406 }
5407
5408 len = NUM2LEN(times);
5409 if (len == 0) {
5410 ary2 = ary_new(rb_cArray, 0);
5411 goto out;
5412 }
5413 if (len < 0) {
5414 rb_raise(rb_eArgError, "negative argument");
5415 }
5416 if (ARY_MAX_SIZE/len < RARRAY_LEN(ary)) {
5417 rb_raise(rb_eArgError, "argument too big");
5418 }
5419 len *= RARRAY_LEN(ary);
5420
5421 ary2 = ary_new(rb_cArray, len);
5422 ARY_SET_LEN(ary2, len);
5423
5424 ptr = RARRAY_CONST_PTR(ary);
5425 t = RARRAY_LEN(ary);
5426 if (0 < t) {
5427 ary_memcpy(ary2, 0, t, ptr);
5428 while (t <= len/2) {
5429 ary_memcpy(ary2, t, t, RARRAY_CONST_PTR(ary2));
5430 t *= 2;
5431 }
5432 if (t < len) {
5433 ary_memcpy(ary2, t, len-t, RARRAY_CONST_PTR(ary2));
5434 }
5435 }
5436 out:
5437 return ary2;
5438}
5439
5440/*
5441 * call-seq:
5442 * assoc(object) -> found_array or nil
5443 *
5444 * Returns the first element +ele+ in +self+ such that +ele+ is an array
5445 * and <tt>ele[0] == object</tt>:
5446 *
5447 * a = [{foo: 0}, [2, 4], [4, 5, 6], [4, 5]]
5448 * a.assoc(4) # => [4, 5, 6]
5449 *
5450 * Returns +nil+ if no such element is found.
5451 *
5452 * Related: Array#rassoc;
5453 * see also {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
5454 */
5455
5456VALUE
5457rb_ary_assoc(VALUE ary, VALUE key)
5458{
5459 rb_len_t i;
5460 VALUE v;
5461
5462 for (i = 0; i < RARRAY_LEN(ary); ++i) {
5463 v = rb_check_array_type(RARRAY_AREF(ary, i));
5464 if (!NIL_P(v) && RARRAY_LEN(v) > 0 &&
5465 rb_equal(RARRAY_AREF(v, 0), key))
5466 return v;
5467 }
5468 return Qnil;
5469}
5470
5471/*
5472 * call-seq:
5473 * rassoc(object) -> found_array or nil
5474 *
5475 * Returns the first element +ele+ in +self+ such that +ele+ is an array
5476 * and <tt>ele[1] == object</tt>:
5477 *
5478 * a = [{foo: 0}, [2, 4], [4, 5, 6], [4, 5]]
5479 * a.rassoc(4) # => [2, 4]
5480 * a.rassoc(5) # => [4, 5, 6]
5481 *
5482 * Returns +nil+ if no such element is found.
5483 *
5484 * Related: Array#assoc;
5485 * see also {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
5486 */
5487
5488VALUE
5489rb_ary_rassoc(VALUE ary, VALUE value)
5490{
5491 rb_len_t i;
5492 VALUE v;
5493
5494 for (i = 0; i < RARRAY_LEN(ary); ++i) {
5495 v = rb_check_array_type(RARRAY_AREF(ary, i));
5496 if (RB_TYPE_P(v, T_ARRAY) &&
5497 RARRAY_LEN(v) > 1 &&
5498 rb_equal(RARRAY_AREF(v, 1), value))
5499 return v;
5500 }
5501 return Qnil;
5502}
5503
5504static VALUE
5505recursive_equal(VALUE ary1, VALUE ary2, int recur)
5506{
5507 rb_len_t i, len1;
5508 const VALUE *p1, *p2;
5509
5510 if (recur) return Qtrue; /* Subtle! */
5511
5512 /* rb_equal() can evacuate ptrs */
5513 p1 = RARRAY_CONST_PTR(ary1);
5514 p2 = RARRAY_CONST_PTR(ary2);
5515 len1 = RARRAY_LEN(ary1);
5516
5517 for (i = 0; i < len1; i++) {
5518 if (*p1 != *p2) {
5519 if (rb_equal(*p1, *p2)) {
5520 len1 = RARRAY_LEN(ary1);
5521 if (len1 != RARRAY_LEN(ary2))
5522 return Qfalse;
5523 if (len1 < i)
5524 return Qtrue;
5525 p1 = RARRAY_CONST_PTR(ary1) + i;
5526 p2 = RARRAY_CONST_PTR(ary2) + i;
5527 }
5528 else {
5529 return Qfalse;
5530 }
5531 }
5532 p1++;
5533 p2++;
5534 }
5535 return Qtrue;
5536}
5537
5538/*
5539 * call-seq:
5540 * self == other_array -> true or false
5541 *
5542 * Returns whether both:
5543 *
5544 * - +self+ and +other_array+ are the same size.
5545 * - Their corresponding elements are the same;
5546 * that is, for each index +i+ in <tt>(0...self.size)</tt>,
5547 * <tt>self[i] == other_array[i]</tt>.
5548 *
5549 * Examples:
5550 *
5551 * [:foo, 'bar', 2] == [:foo, 'bar', 2] # => true
5552 * [:foo, 'bar', 2] == [:foo, 'bar', 2.0] # => true
5553 * [:foo, 'bar', 2] == [:foo, 'bar'] # => false # Different sizes.
5554 * [:foo, 'bar', 2] == [:foo, 'bar', 3] # => false # Different elements.
5555 *
5556 * This method is different from method Array#eql?,
5557 * which compares elements using <tt>Object#eql?</tt>.
5558 *
5559 * Related: see {Methods for Comparing}[rdoc-ref:Array@Methods+for+Comparing].
5560 */
5561
5562static VALUE
5563rb_ary_equal(VALUE ary1, VALUE ary2)
5564{
5565 if (ary1 == ary2) return Qtrue;
5566 if (!RB_TYPE_P(ary2, T_ARRAY)) {
5567 if (!rb_respond_to(ary2, idTo_ary)) {
5568 return Qfalse;
5569 }
5570 return rb_equal(ary2, ary1);
5571 }
5572 if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return Qfalse;
5573 if (RARRAY_CONST_PTR(ary1) == RARRAY_CONST_PTR(ary2)) return Qtrue;
5574 return rb_exec_recursive_paired(recursive_equal, ary1, ary2, ary2);
5575}
5576
5577static VALUE
5578recursive_eql(VALUE ary1, VALUE ary2, int recur)
5579{
5580 rb_len_t i, len1;
5581 const VALUE *p1, *p2;
5582
5583 if (recur) return Qtrue; /* Subtle! */
5584
5585 /* rb_eql() can resize either array and evacuate ptrs */
5586 p1 = RARRAY_CONST_PTR(ary1);
5587 p2 = RARRAY_CONST_PTR(ary2);
5588 len1 = RARRAY_LEN(ary1);
5589
5590 for (i = 0; i < len1; i++) {
5591 if (p1[i] != p2[i]) {
5592 if (!rb_eql(p1[i], p2[i])) return Qfalse;
5593 len1 = RARRAY_LEN(ary1);
5594 if (len1 != RARRAY_LEN(ary2)) return Qfalse;
5595 p1 = RARRAY_CONST_PTR(ary1);
5596 p2 = RARRAY_CONST_PTR(ary2);
5597 }
5598 }
5599 return Qtrue;
5600}
5601
5602/*
5603 * call-seq:
5604 * eql?(other_array) -> true or false
5605 *
5606 * Returns +true+ if +self+ and +other_array+ are the same size,
5607 * and if, for each index +i+ in +self+, <tt>self[i].eql?(other_array[i])</tt>:
5608 *
5609 * a0 = [:foo, 'bar', 2]
5610 * a1 = [:foo, 'bar', 2]
5611 * a1.eql?(a0) # => true
5612 *
5613 * Otherwise, returns +false+.
5614 *
5615 * This method is different from method Array#==,
5616 * which compares using method <tt>Object#==</tt>.
5617 *
5618 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
5619 */
5620
5621static VALUE
5622rb_ary_eql(VALUE ary1, VALUE ary2)
5623{
5624 if (ary1 == ary2) return Qtrue;
5625 if (!RB_TYPE_P(ary2, T_ARRAY)) return Qfalse;
5626 if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return Qfalse;
5627 if (RARRAY_CONST_PTR(ary1) == RARRAY_CONST_PTR(ary2)) return Qtrue;
5628 return rb_exec_recursive_paired(recursive_eql, ary1, ary2, ary2);
5629}
5630
5631static VALUE
5632ary_hash_values(rb_len_t len, const VALUE *elements, const VALUE ary)
5633{
5634 rb_len_t i;
5635 st_index_t h;
5636 VALUE n;
5637
5638 h = rb_hash_start(len);
5639 h = rb_hash_uint(h, (st_index_t)rb_ary_hash_values);
5640 for (i=0; i<len; i++) {
5641 n = rb_hash(elements[i]);
5642 h = rb_hash_uint(h, NUM2LONG(n));
5643 if (ary) {
5644 len = RARRAY_LEN(ary);
5645 elements = RARRAY_CONST_PTR(ary);
5646 }
5647 }
5648 h = rb_hash_end(h);
5649 return ST2FIX(h);
5650}
5651
5652VALUE
5653rb_ary_hash_values(rb_len_t len, const VALUE *elements)
5654{
5655 return ary_hash_values(len, elements, 0);
5656}
5657
5658/*
5659 * call-seq:
5660 * hash -> integer
5661 *
5662 * Returns the integer hash value for +self+.
5663 *
5664 * Two arrays with the same content will have the same hash value
5665 * (and will compare using eql?):
5666 *
5667 * ['a', 'b'].hash == ['a', 'b'].hash # => true
5668 * ['a', 'b'].hash == ['a', 'c'].hash # => false
5669 * ['a', 'b'].hash == ['a'].hash # => false
5670 *
5671 */
5672
5673static VALUE
5674rb_ary_hash(VALUE ary)
5675{
5677 return ary_hash_values(RARRAY_LEN(ary), RARRAY_CONST_PTR(ary), ary);
5678}
5679
5680/*
5681 * call-seq:
5682 * include?(object) -> true or false
5683 *
5684 * Returns whether for some element +element+ in +self+,
5685 * <tt>object == element</tt>:
5686 *
5687 * [0, 1, 2].include?(2) # => true
5688 * [0, 1, 2].include?(2.0) # => true
5689 * [0, 1, 2].include?(2.1) # => false
5690 *
5691 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
5692 */
5693
5694VALUE
5695rb_ary_includes(VALUE ary, VALUE item)
5696{
5697 rb_len_t i;
5698 VALUE e;
5699
5700 for (i=0; i<RARRAY_LEN(ary); i++) {
5701 e = RARRAY_AREF(ary, i);
5702 if (rb_equal(e, item)) {
5703 return Qtrue;
5704 }
5705 }
5706 return Qfalse;
5707}
5708
5709static VALUE
5710rb_ary_includes_by_eql(VALUE ary, VALUE item)
5711{
5712 rb_len_t i;
5713 VALUE e;
5714
5715 for (i=0; i<RARRAY_LEN(ary); i++) {
5716 e = RARRAY_AREF(ary, i);
5717 if (rb_eql(item, e)) {
5718 return Qtrue;
5719 }
5720 }
5721 return Qfalse;
5722}
5723
5724static VALUE
5725recursive_cmp(VALUE ary1, VALUE ary2, int recur)
5726{
5727 rb_len_t i, len;
5728
5729 if (recur) return Qundef; /* Subtle! */
5730 len = RARRAY_LEN(ary1);
5731 if (len > RARRAY_LEN(ary2)) {
5732 len = RARRAY_LEN(ary2);
5733 }
5734 for (i=0; i<len; i++) {
5735 VALUE e1 = rb_ary_elt(ary1, i), e2 = rb_ary_elt(ary2, i);
5736 VALUE v = rb_funcallv(e1, id_cmp, 1, &e2);
5737 if (v != INT2FIX(0)) {
5738 return v;
5739 }
5740 }
5741 return Qundef;
5742}
5743
5744/*
5745 * call-seq:
5746 * self <=> other_array -> -1, 0, or 1
5747 *
5748 * Returns -1, 0, or 1 as +self+ is determined
5749 * to be less than, equal to, or greater than +other_array+.
5750 *
5751 * Iterates over each index +i+ in <tt>(0...self.size)</tt>:
5752 *
5753 * - Computes <tt>result[i]</tt> as <tt>self[i] <=> other_array[i]</tt>.
5754 * - Immediately returns 1 if <tt>result[i]</tt> is 1:
5755 *
5756 * [0, 1, 2] <=> [0, 0, 2] # => 1
5757 *
5758 * - Immediately returns -1 if <tt>result[i]</tt> is -1:
5759 *
5760 * [0, 1, 2] <=> [0, 2, 2] # => -1
5761 *
5762 * - Continues if <tt>result[i]</tt> is 0.
5763 *
5764 * When every +result+ is 0,
5765 * returns <tt>self.size <=> other_array.size</tt>
5766 * (see Integer#<=>):
5767 *
5768 * [0, 1, 2] <=> [0, 1] # => 1
5769 * [0, 1, 2] <=> [0, 1, 2] # => 0
5770 * [0, 1, 2] <=> [0, 1, 2, 3] # => -1
5771 *
5772 * Note that when +other_array+ is larger than +self+,
5773 * its trailing elements do not affect the result:
5774 *
5775 * [0, 1, 2] <=> [0, 1, 2, -3] # => -1
5776 * [0, 1, 2] <=> [0, 1, 2, 0] # => -1
5777 * [0, 1, 2] <=> [0, 1, 2, 3] # => -1
5778 *
5779 * Related: see {Methods for Comparing}[rdoc-ref:Array@Methods+for+Comparing].
5780 */
5781
5782VALUE
5783rb_ary_cmp(VALUE ary1, VALUE ary2)
5784{
5785 rb_len_t len;
5786 VALUE v;
5787
5788 ary2 = rb_check_array_type(ary2);
5789 if (NIL_P(ary2)) return Qnil;
5790 if (ary1 == ary2) return INT2FIX(0);
5791 v = rb_exec_recursive_paired(recursive_cmp, ary1, ary2, ary2);
5792 if (!UNDEF_P(v)) return v;
5793 len = RARRAY_LEN(ary1) - RARRAY_LEN(ary2);
5794 if (len == 0) return INT2FIX(0);
5795 if (len > 0) return INT2FIX(1);
5796 return INT2FIX(-1);
5797}
5798
5799static void
5800rb_ary_union_set(VALUE set, VALUE ary)
5801{
5802 for (rb_len_t i = 0; i < RARRAY_LEN(ary); i++) {
5803 rb_set_add_no_check(set, RARRAY_AREF(ary, i));
5804 }
5805}
5806
5807static VALUE
5808ary_to_set(VALUE ary)
5809{
5811 rb_ary_union_set(set, ary);
5812 return set;
5813}
5814
5815/*
5816 * call-seq:
5817 * self - other_array -> new_array
5818 *
5819 * Returns a new array containing only those elements of +self+
5820 * that are not found in +other_array+;
5821 * the order from +self+ is preserved:
5822 *
5823 * [0, 1, 1, 2, 1, 1, 3, 1, 1] - [1] # => [0, 2, 3]
5824 * [0, 1, 1, 2, 1, 1, 3, 1, 1] - [3, 2, 0, :foo] # => [1, 1, 1, 1, 1, 1]
5825 * [0, 1, 2] - [:foo] # => [0, 1, 2]
5826 *
5827 * Element are compared using method <tt>#eql?</tt>
5828 * (as defined in each element of +self+).
5829 *
5830 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5831 */
5832
5833VALUE
5834rb_ary_diff(VALUE ary1, VALUE ary2)
5835{
5836 ary2 = to_ary(ary2);
5837 if (RARRAY_LEN(ary2) == 0) { return ary_make_shared_copy(ary1); }
5838 VALUE ary3 = rb_ary_new();
5839
5840 if (RARRAY_LEN(ary1) <= SMALL_ARRAY_LEN || RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
5841 for (rb_len_t i = 0; i < RARRAY_LEN(ary1); i++) {
5842 VALUE elt = rb_ary_elt(ary1, i);
5843 if (rb_ary_includes_by_eql(ary2, elt)) continue;
5844 rb_ary_push(ary3, elt);
5845 }
5846 return ary3;
5847 }
5848
5849 VALUE set = ary_to_set(ary2);
5850 for (rb_len_t i = 0; i < RARRAY_LEN(ary1); i++) {
5851 if (rb_set_lookup(set, RARRAY_AREF(ary1, i))) continue;
5852 rb_ary_push(ary3, rb_ary_elt(ary1, i));
5853 }
5854
5855 return ary3;
5856}
5857
5858/*
5859 * call-seq:
5860 * difference(*other_arrays = []) -> new_array
5861 *
5862 * Returns a new array containing only those elements from +self+
5863 * that are not found in any of the given +other_arrays+;
5864 * items are compared using <tt>eql?</tt>; order from +self+ is preserved:
5865 *
5866 * [0, 1, 1, 2, 1, 1, 3, 1, 1].difference([1]) # => [0, 2, 3]
5867 * [0, 1, 2, 3].difference([3, 0], [1, 3]) # => [2]
5868 * [0, 1, 2].difference([4]) # => [0, 1, 2]
5869 * [0, 1, 2].difference # => [0, 1, 2]
5870 *
5871 * Returns a copy of +self+ if no arguments are given.
5872 *
5873 * Related: Array#-;
5874 * see also {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5875 */
5876
5877static VALUE
5878rb_ary_difference_multi(int argc, VALUE *argv, VALUE ary)
5879{
5880 volatile VALUE t0;
5881 bool *is_set = ALLOCV_N(bool, t0, argc);
5882 VALUE ary_diff = rb_ary_new();
5883 rb_len_t length = RARRAY_LEN(ary);
5884
5885 for (rb_len_t i = 0; i < argc; i++) {
5886 argv[i] = to_ary(argv[i]);
5887 is_set[i] = (length > SMALL_ARRAY_LEN && RARRAY_LEN(argv[i]) > SMALL_ARRAY_LEN);
5888 if (is_set[i]) {
5889 argv[i] = ary_to_set(argv[i]);
5890 }
5891 }
5892
5893 for (rb_len_t i = 0; i < RARRAY_LEN(ary); i++) {
5894 int j;
5895 VALUE elt = rb_ary_elt(ary, i);
5896 for (j = 0; j < argc; j++) {
5897 if (is_set[j]) {
5898 if (rb_set_lookup(argv[j], elt))
5899 break;
5900 }
5901 else {
5902 if (rb_ary_includes_by_eql(argv[j], elt)) break;
5903 }
5904 }
5905 if (j == argc) rb_ary_push(ary_diff, elt);
5906 }
5907
5908 ALLOCV_END(t0);
5909
5910 return ary_diff;
5911}
5912
5913
5914/*
5915 * call-seq:
5916 * self & other_array -> new_array
5917 *
5918 * Returns a new array containing the _intersection_ of +self+ and +other_array+;
5919 * that is, containing those elements found in both +self+ and +other_array+:
5920 *
5921 * [0, 1, 2, 3] & [1, 2] # => [1, 2]
5922 *
5923 * Omits duplicates:
5924 *
5925 * [0, 1, 1, 0] & [0, 1] # => [0, 1]
5926 *
5927 * Preserves order from +self+:
5928 *
5929 * [0, 1, 2] & [3, 2, 1, 0] # => [0, 1, 2]
5930 *
5931 * Identifies common elements using method <tt>#eql?</tt>
5932 * (as defined in each element of +self+).
5933 *
5934 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5935 */
5936
5937
5938static VALUE
5939rb_ary_and(VALUE ary1, VALUE ary2)
5940{
5941 ary2 = to_ary(ary2);
5942 VALUE ary3 = rb_ary_new();
5943 if (RARRAY_LEN(ary1) == 0 || RARRAY_LEN(ary2) == 0) return ary3;
5944
5945 if (RARRAY_LEN(ary1) <= SMALL_ARRAY_LEN && RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
5946 for (rb_len_t i = 0; i < RARRAY_LEN(ary1); i++) {
5947 VALUE v = RARRAY_AREF(ary1, i);
5948 if (!rb_ary_includes_by_eql(ary2, v)) continue;
5949 if (rb_ary_includes_by_eql(ary3, v)) continue;
5950 rb_ary_push(ary3, v);
5951 }
5952 return ary3;
5953 }
5954
5955 VALUE set = ary_to_set(ary2);
5956
5957 for (rb_len_t i = 0; i < RARRAY_LEN(ary1); i++) {
5958 VALUE v = RARRAY_AREF(ary1, i);
5959 if (rb_set_delete_no_check(set, v)) {
5960 rb_ary_push(ary3, v);
5961 }
5962 }
5963
5964 return ary3;
5965}
5966
5967/*
5968 * call-seq:
5969 * intersection(*other_arrays) -> new_array
5970 *
5971 * Returns a new array containing each element in +self+ that is +#eql?+
5972 * to at least one element in each of the given +other_arrays+;
5973 * duplicates are omitted:
5974 *
5975 * [0, 0, 1, 1, 2, 3].intersection([0, 1, 2], [0, 1, 3]) # => [0, 1]
5976 *
5977 * Each element must correctly implement method <tt>#hash</tt>.
5978 *
5979 * Order from +self+ is preserved:
5980 *
5981 * [0, 1, 2].intersection([2, 1, 0]) # => [0, 1, 2]
5982 *
5983 * Returns a copy of +self+ if no arguments are given.
5984 *
5985 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5986 */
5987
5988static VALUE
5989rb_ary_intersection_multi(int argc, VALUE *argv, VALUE ary)
5990{
5991 VALUE result = rb_ary_dup(ary);
5992 int i;
5993
5994 for (i = 0; i < argc; i++) {
5995 result = rb_ary_and(result, argv[i]);
5996 }
5997
5998 return result;
5999}
6000
6001static void
6002rb_ary_union(VALUE ary_union, VALUE ary)
6003{
6004 rb_len_t i;
6005 for (i = 0; i < RARRAY_LEN(ary); i++) {
6006 VALUE elt = rb_ary_elt(ary, i);
6007 if (rb_ary_includes_by_eql(ary_union, elt)) continue;
6008 rb_ary_push(ary_union, elt);
6009 }
6010}
6011
6012/*
6013 * call-seq:
6014 * self | other_array -> new_array
6015 *
6016 * Returns the union of +self+ and +other_array+;
6017 * duplicates are removed; order is preserved;
6018 * items are compared using <tt>eql?</tt> and <tt>hash</tt>:
6019 *
6020 * [0, 1] | [2, 3] # => [0, 1, 2, 3]
6021 * [0, 1, 1] | [2, 2, 3] # => [0, 1, 2, 3]
6022 * [0, 1, 2] | [3, 2, 1, 0] # => [0, 1, 2, 3]
6023 *
6024 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
6025 */
6026
6027static VALUE
6028rb_ary_or(VALUE ary1, VALUE ary2)
6029{
6030 ary2 = to_ary(ary2);
6031 if (RARRAY_LEN(ary1) + RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
6032 VALUE ary3 = rb_ary_new();
6033 rb_ary_union(ary3, ary1);
6034 rb_ary_union(ary3, ary2);
6035 return ary3;
6036 }
6037
6039 rb_ary_union_set(set, ary1);
6040 rb_ary_union_set(set, ary2);
6041
6042 return rb_set_to_a(set);
6043}
6044
6045/*
6046 * call-seq:
6047 * union(*other_arrays) -> new_array
6048 *
6049 * Returns a new array that is the union of the elements of +self+
6050 * and all given arrays +other_arrays+;
6051 * items are compared using <tt>eql?</tt> and <tt>hash</tt>:
6052 *
6053 * [0, 1, 2, 3].union([4, 5], [6, 7]) # => [0, 1, 2, 3, 4, 5, 6, 7]
6054 *
6055 * Removes duplicates (preserving the first found):
6056 *
6057 * [0, 1, 1].union([2, 1], [3, 1]) # => [0, 1, 2, 3]
6058 *
6059 * Preserves order (preserving the position of the first found):
6060 *
6061 * [3, 2, 1, 0].union([5, 3], [4, 2]) # => [3, 2, 1, 0, 5, 4]
6062 *
6063 * With no arguments given, returns a copy of +self+.
6064 *
6065 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
6066 */
6067
6068static VALUE
6069rb_ary_union_multi(int argc, VALUE *argv, VALUE ary)
6070{
6071 rb_len_t sum = RARRAY_LEN(ary);
6072 for (int i = 0; i < argc; i++) {
6073 argv[i] = to_ary(argv[i]);
6074 sum += RARRAY_LEN(argv[i]);
6075 }
6076
6077 if (sum <= SMALL_ARRAY_LEN) {
6078 VALUE ary_union = rb_ary_new();
6079
6080 rb_ary_union(ary_union, ary);
6081 for (int i = 0; i < argc; i++) rb_ary_union(ary_union, argv[i]);
6082
6083 return ary_union;
6084 }
6085
6086 VALUE set = rb_obj_hide(rb_set_new_capa(sum));
6087 rb_ary_union_set(set, ary);
6088 for (int i = 0; i < argc; i++) rb_ary_union_set(set, argv[i]);
6089
6090 return rb_set_to_a(set);
6091}
6092
6093/*
6094 * call-seq:
6095 * intersect?(other_array) -> true or false
6096 *
6097 * Returns whether +other_array+ has at least one element that is +#eql?+ to some element of +self+:
6098 *
6099 * [1, 2, 3].intersect?([3, 4, 5]) # => true
6100 * [1, 2, 3].intersect?([4, 5, 6]) # => false
6101 *
6102 * Each element must correctly implement method <tt>#hash</tt>.
6103 *
6104 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
6105 */
6106
6107static VALUE
6108rb_ary_intersect_p(VALUE ary1, VALUE ary2)
6109{
6110 ary2 = to_ary(ary2);
6111 if (RARRAY_LEN(ary1) == 0 || RARRAY_LEN(ary2) == 0) return Qfalse;
6112
6113 if (RARRAY_LEN(ary1) <= SMALL_ARRAY_LEN && RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
6114 for (rb_len_t i = 0; i < RARRAY_LEN(ary1); i++) {
6115 VALUE v = RARRAY_AREF(ary1, i);
6116 if (rb_ary_includes_by_eql(ary2, v)) return Qtrue;
6117 }
6118 return Qfalse;
6119 }
6120
6121 VALUE shorter = ary1;
6122 VALUE longer = ary2;
6123 if (RARRAY_LEN(ary1) > RARRAY_LEN(ary2)) {
6124 longer = ary1;
6125 shorter = ary2;
6126 }
6127
6128 VALUE set = ary_to_set(shorter);
6129 VALUE result = Qfalse;
6130
6131 for (rb_len_t i = 0; i < RARRAY_LEN(longer); i++) {
6132 VALUE v = RARRAY_AREF(longer, i);
6133 if (rb_set_lookup(set, v)) {
6134 result = Qtrue;
6135 break;
6136 }
6137 }
6138
6139 return result;
6140}
6141
6142static VALUE
6143ary_max_generic(VALUE ary, rb_len_t i, VALUE vmax)
6144{
6145 RUBY_ASSERT(i > 0 && i < RARRAY_LEN(ary));
6146
6147 VALUE v;
6148 for (; i < RARRAY_LEN(ary); ++i) {
6149 v = RARRAY_AREF(ary, i);
6150
6151 if (rb_cmpint(rb_funcallv(vmax, id_cmp, 1, &v), vmax, v) < 0) {
6152 vmax = v;
6153 }
6154 }
6155
6156 return vmax;
6157}
6158
6159static VALUE
6160ary_max_opt_fixnum(VALUE ary, rb_len_t i, VALUE vmax)
6161{
6162 const rb_len_t n = RARRAY_LEN(ary);
6163 RUBY_ASSERT(i > 0 && i < n);
6164 RUBY_ASSERT(FIXNUM_P(vmax));
6165
6166 VALUE v;
6167 for (; i < n; ++i) {
6168 v = RARRAY_AREF(ary, i);
6169
6170 if (FIXNUM_P(v)) {
6171 if ((long)vmax < (long)v) {
6172 vmax = v;
6173 }
6174 }
6175 else {
6176 return ary_max_generic(ary, i, vmax);
6177 }
6178 }
6179
6180 return vmax;
6181}
6182
6183static VALUE
6184ary_max_opt_float(VALUE ary, rb_len_t i, VALUE vmax)
6185{
6186 const rb_len_t n = RARRAY_LEN(ary);
6187 RUBY_ASSERT(i > 0 && i < n);
6189
6190 VALUE v;
6191 for (; i < n; ++i) {
6192 v = RARRAY_AREF(ary, i);
6193
6194 if (RB_FLOAT_TYPE_P(v)) {
6195 if (rb_float_cmp(vmax, v) < 0) {
6196 vmax = v;
6197 }
6198 }
6199 else {
6200 return ary_max_generic(ary, i, vmax);
6201 }
6202 }
6203
6204 return vmax;
6205}
6206
6207static VALUE
6208ary_max_opt_string(VALUE ary, rb_len_t i, VALUE vmax)
6209{
6210 const rb_len_t n = RARRAY_LEN(ary);
6211 RUBY_ASSERT(i > 0 && i < n);
6212 RUBY_ASSERT(STRING_P(vmax));
6213
6214 VALUE v;
6215 for (; i < n; ++i) {
6216 v = RARRAY_AREF(ary, i);
6217
6218 if (STRING_P(v)) {
6219 if (rb_str_cmp(vmax, v) < 0) {
6220 vmax = v;
6221 }
6222 }
6223 else {
6224 return ary_max_generic(ary, i, vmax);
6225 }
6226 }
6227
6228 return vmax;
6229}
6230
6231/*
6232 * call-seq:
6233 * max -> element
6234 * max(count) -> new_array
6235 * max {|a, b| ... } -> element
6236 * max(count) {|a, b| ... } -> new_array
6237 *
6238 * Returns one of the following:
6239 *
6240 * - The maximum-valued element from +self+.
6241 * - A new array of maximum-valued elements from +self+.
6242 *
6243 * Does not modify +self+.
6244 *
6245 * With no block given, each element in +self+ must respond to method <tt>#<=></tt>
6246 * with a numeric.
6247 *
6248 * With no argument and no block, returns the element in +self+
6249 * having the maximum value per method <tt>#<=></tt>:
6250 *
6251 * [1, 0, 3, 2].max # => 3
6252 *
6253 * With non-negative numeric argument +count+ and no block,
6254 * returns a new array with at most +count+ elements,
6255 * in descending order, per method <tt>#<=></tt>:
6256 *
6257 * [1, 0, 3, 2].max(3) # => [3, 2, 1]
6258 * [1, 0, 3, 2].max(3.0) # => [3, 2, 1]
6259 * [1, 0, 3, 2].max(9) # => [3, 2, 1, 0]
6260 * [1, 0, 3, 2].max(0) # => []
6261 *
6262 * With a block given, the block must return a numeric.
6263 *
6264 * With a block and no argument, calls the block <tt>self.size - 1</tt> times to compare elements;
6265 * returns the element having the maximum value per the block:
6266 *
6267 * ['0', '', '000', '00'].max {|a, b| a.size <=> b.size }
6268 * # => "000"
6269 *
6270 * With non-negative numeric argument +count+ and a block,
6271 * returns a new array with at most +count+ elements,
6272 * in descending order, per the block:
6273 *
6274 * ['0', '', '000', '00'].max(2) {|a, b| a.size <=> b.size }
6275 * # => ["000", "00"]
6276 *
6277 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
6278 */
6279static VALUE
6280rb_ary_max(int argc, VALUE *argv, VALUE ary)
6281{
6282 VALUE result = Qundef, v;
6283 VALUE num;
6284 rb_len_t i;
6285
6286 if (rb_check_arity(argc, 0, 1) && !NIL_P(num = argv[0]))
6287 return rb_nmin_run(ary, num, 0, 1, 1);
6288
6289 const rb_len_t n = RARRAY_LEN(ary);
6290 if (rb_block_given_p()) {
6291 for (i = 0; i < RARRAY_LEN(ary); i++) {
6292 v = RARRAY_AREF(ary, i);
6293 if (UNDEF_P(result) || rb_cmpint(rb_yield_values(2, v, result), v, result) > 0) {
6294 result = v;
6295 }
6296 }
6297 }
6298 else if (n > 0) {
6299 result = RARRAY_AREF(ary, 0);
6300 if (n > 1) {
6301 if (FIXNUM_P(result) && CMP_OPTIMIZABLE(INTEGER)) {
6302 return ary_max_opt_fixnum(ary, 1, result);
6303 }
6304 else if (STRING_P(result) && CMP_OPTIMIZABLE(STRING)) {
6305 return ary_max_opt_string(ary, 1, result);
6306 }
6307 else if (RB_FLOAT_TYPE_P(result) && CMP_OPTIMIZABLE(FLOAT)) {
6308 return ary_max_opt_float(ary, 1, result);
6309 }
6310 else {
6311 return ary_max_generic(ary, 1, result);
6312 }
6313 }
6314 }
6315 if (UNDEF_P(result)) return Qnil;
6316 return result;
6317}
6318
6319static VALUE
6320ary_min_generic(VALUE ary, rb_len_t i, VALUE vmin)
6321{
6322 RUBY_ASSERT(i > 0 && i < RARRAY_LEN(ary));
6323
6324 VALUE v;
6325 for (; i < RARRAY_LEN(ary); ++i) {
6326 v = RARRAY_AREF(ary, i);
6327
6328 if (rb_cmpint(rb_funcallv(vmin, id_cmp, 1, &v), vmin, v) > 0) {
6329 vmin = v;
6330 }
6331 }
6332
6333 return vmin;
6334}
6335
6336static VALUE
6337ary_min_opt_fixnum(VALUE ary, rb_len_t i, VALUE vmin)
6338{
6339 const rb_len_t n = RARRAY_LEN(ary);
6340 RUBY_ASSERT(i > 0 && i < n);
6341 RUBY_ASSERT(FIXNUM_P(vmin));
6342
6343 VALUE a;
6344 for (; i < n; ++i) {
6345 a = RARRAY_AREF(ary, i);
6346
6347 if (FIXNUM_P(a)) {
6348 if ((long)vmin > (long)a) {
6349 vmin = a;
6350 }
6351 }
6352 else {
6353 return ary_min_generic(ary, i, vmin);
6354 }
6355 }
6356
6357 return vmin;
6358}
6359
6360static VALUE
6361ary_min_opt_float(VALUE ary, rb_len_t i, VALUE vmin)
6362{
6363 const rb_len_t n = RARRAY_LEN(ary);
6364 RUBY_ASSERT(i > 0 && i < n);
6366
6367 VALUE a;
6368 for (; i < n; ++i) {
6369 a = RARRAY_AREF(ary, i);
6370
6371 if (RB_FLOAT_TYPE_P(a)) {
6372 if (rb_float_cmp(vmin, a) > 0) {
6373 vmin = a;
6374 }
6375 }
6376 else {
6377 return ary_min_generic(ary, i, vmin);
6378 }
6379 }
6380
6381 return vmin;
6382}
6383
6384static VALUE
6385ary_min_opt_string(VALUE ary, rb_len_t i, VALUE vmin)
6386{
6387 const rb_len_t n = RARRAY_LEN(ary);
6388 RUBY_ASSERT(i > 0 && i < n);
6389 RUBY_ASSERT(STRING_P(vmin));
6390
6391 VALUE a;
6392 for (; i < n; ++i) {
6393 a = RARRAY_AREF(ary, i);
6394
6395 if (STRING_P(a)) {
6396 if (rb_str_cmp(vmin, a) > 0) {
6397 vmin = a;
6398 }
6399 }
6400 else {
6401 return ary_min_generic(ary, i, vmin);
6402 }
6403 }
6404
6405 return vmin;
6406}
6407
6408/*
6409 * call-seq:
6410 * min -> element
6411 * min(count) -> new_array
6412 * min {|a, b| ... } -> element
6413 * min(count) {|a, b| ... } -> new_array
6414 *
6415 * Returns one of the following:
6416 *
6417 * - The minimum-valued element from +self+.
6418 * - A new array of minimum-valued elements from +self+.
6419 *
6420 * Does not modify +self+.
6421 *
6422 * With no block given, each element in +self+ must respond to method <tt>#<=></tt>
6423 * with a numeric.
6424 *
6425 * With no argument and no block, returns the element in +self+
6426 * having the minimum value per method <tt>#<=></tt>:
6427 *
6428 * [1, 0, 3, 2].min # => 0
6429 *
6430 * With non-negative numeric argument +count+ and no block,
6431 * returns a new array with at most +count+ elements,
6432 * in ascending order, per method <tt>#<=></tt>:
6433 *
6434 * [1, 0, 3, 2].min(3) # => [0, 1, 2]
6435 * [1, 0, 3, 2].min(3.0) # => [0, 1, 2]
6436 * [1, 0, 3, 2].min(9) # => [0, 1, 2, 3]
6437 * [1, 0, 3, 2].min(0) # => []
6438 *
6439 * With a block given, the block must return a numeric.
6440 *
6441 * With a block and no argument, calls the block <tt>self.size - 1</tt> times to compare elements;
6442 * returns the element having the minimum value per the block:
6443 *
6444 * ['0', '', '000', '00'].min {|a, b| a.size <=> b.size }
6445 * # => ""
6446 *
6447 * With non-negative numeric argument +count+ and a block,
6448 * returns a new array with at most +count+ elements,
6449 * in ascending order, per the block:
6450 *
6451 * ['0', '', '000', '00'].min(2) {|a, b| a.size <=> b.size }
6452 * # => ["", "0"]
6453 *
6454 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
6455 */
6456static VALUE
6457rb_ary_min(int argc, VALUE *argv, VALUE ary)
6458{
6459 VALUE result = Qundef, v;
6460 VALUE num;
6461 rb_len_t i;
6462
6463 if (rb_check_arity(argc, 0, 1) && !NIL_P(num = argv[0]))
6464 return rb_nmin_run(ary, num, 0, 0, 1);
6465
6466 const rb_len_t n = RARRAY_LEN(ary);
6467 if (rb_block_given_p()) {
6468 for (i = 0; i < RARRAY_LEN(ary); i++) {
6469 v = RARRAY_AREF(ary, i);
6470 if (UNDEF_P(result) || rb_cmpint(rb_yield_values(2, v, result), v, result) < 0) {
6471 result = v;
6472 }
6473 }
6474 }
6475 else if (n > 0) {
6476 result = RARRAY_AREF(ary, 0);
6477 if (n > 1) {
6478 if (FIXNUM_P(result) && CMP_OPTIMIZABLE(INTEGER)) {
6479 return ary_min_opt_fixnum(ary, 1, result);
6480 }
6481 else if (STRING_P(result) && CMP_OPTIMIZABLE(STRING)) {
6482 return ary_min_opt_string(ary, 1, result);
6483 }
6484 else if (RB_FLOAT_TYPE_P(result) && CMP_OPTIMIZABLE(FLOAT)) {
6485 return ary_min_opt_float(ary, 1, result);
6486 }
6487 else {
6488 return ary_min_generic(ary, 1, result);
6489 }
6490 }
6491 }
6492 if (UNDEF_P(result)) return Qnil;
6493 return result;
6494}
6495
6496/*
6497 * call-seq:
6498 * minmax -> array
6499 * minmax {|a, b| ... } -> array
6500 *
6501 * Returns a 2-element array containing the minimum-valued and maximum-valued
6502 * elements from +self+;
6503 * does not modify +self+.
6504 *
6505 * With no block given, the minimum and maximum values are determined using method <tt>#<=></tt>:
6506 *
6507 * [1, 0, 3, 2].minmax # => [0, 3]
6508 *
6509 * With a block given, the block must return a numeric;
6510 * the block is called <tt>self.size - 1</tt> times to compare elements;
6511 * returns the elements having the minimum and maximum values per the block:
6512 *
6513 * ['0', '', '000', '00'].minmax {|a, b| a.size <=> b.size }
6514 * # => ["", "000"]
6515 *
6516 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
6517 */
6518static VALUE
6519rb_ary_minmax(VALUE ary)
6520{
6521 if (rb_block_given_p()) {
6522 return rb_call_super(0, NULL);
6523 }
6524 return rb_assoc_new(rb_ary_min(0, 0, ary), rb_ary_max(0, 0, ary));
6525}
6526
6527static int
6528push_value_i(VALUE elt, VALUE ary)
6529{
6530 rb_ary_push(ary, elt);
6531 return ST_CONTINUE;
6532}
6533
6534/*
6535 * call-seq:
6536 * uniq! -> self or nil
6537 * uniq! {|element| ... } -> self or nil
6538 *
6539 * Removes duplicate elements from +self+, the first occurrence always being retained;
6540 * returns +self+ if any elements removed, +nil+ otherwise.
6541 *
6542 * With no block given, identifies and removes elements using method <tt>eql?</tt>
6543 * and <tt>hash</tt> to compare elements:
6544 *
6545 * a = [0, 0, 1, 1, 2, 2]
6546 * a.uniq! # => [0, 1, 2]
6547 * a.uniq! # => nil
6548 *
6549 * With a block given, calls the block for each element;
6550 * identifies and omits "duplicate" elements using method <tt>eql?</tt>
6551 * and <tt>hash</tt> to compare <i>block return values</i>;
6552 * that is, an element is a duplicate if its block return value
6553 * is the same as that of a previous element:
6554 *
6555 * a = ['a', 'aa', 'aaa', 'b', 'bb', 'bbb']
6556 * a.uniq! {|element| element.size } # => ["a", "aa", "aaa"]
6557 * a.uniq! {|element| element.size } # => nil
6558 *
6559 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
6560 */
6561static VALUE
6562rb_ary_uniq_bang(VALUE ary)
6563{
6564 rb_ary_modify_check(ary);
6565 if (RARRAY_LEN(ary) <= 1)
6566 return Qnil;
6567
6568 if (rb_block_given_p()) {
6570 VALUE uniq = rb_ary_new_capa(RARRAY_LEN(ary));
6571 for (rb_len_t i = 0; i < RARRAY_LEN(ary); i++) {
6572 VALUE elt = rb_ary_elt(ary, i);
6573 if (rb_set_add_no_check(set, rb_yield(elt)))
6574 rb_ary_push(uniq, elt);
6575 }
6576 if (RARRAY_LEN(ary) == RARRAY_LEN(uniq))
6577 return Qnil;
6578 rb_ary_replace(ary, uniq);
6579 return ary;
6580 }
6581
6582 VALUE set = ary_to_set(ary);
6583 rb_len_t size = (rb_len_t)rb_set_size(set);
6584 if (RARRAY_LEN(ary) == size) {
6585 return Qnil;
6586 }
6587 rb_ary_modify_check(ary);
6588 ARY_SET_LEN(ary, 0);
6589 if (ARY_SHARED_P(ary)) {
6590 rb_ary_unshare(ary);
6591 FL_SET_EMBED(ary);
6592 }
6593 ary_resize_capa(ary, size);
6594 rb_set_foreach(set, push_value_i, ary);
6595
6596 return ary;
6597}
6598
6599/*
6600 * call-seq:
6601 * uniq -> new_array
6602 * uniq {|element| ... } -> new_array
6603 *
6604 * Returns a new array containing those elements from +self+ that are not duplicates,
6605 * the first occurrence always being retained.
6606 *
6607 * With no block given, identifies and omits duplicate elements using method <tt>eql?</tt>
6608 * and <tt>hash</tt> to compare elements:
6609 *
6610 * a = [0, 0, 1, 1, 2, 2]
6611 * a.uniq # => [0, 1, 2]
6612 *
6613 * With a block given, calls the block for each element;
6614 * identifies and omits "duplicate" elements using method <tt>eql?</tt>
6615 * and <tt>hash</tt> to compare <i>block return values</i>;
6616 * that is, an element is a duplicate if its block return value
6617 * is the same as that of a previous element:
6618 *
6619 * a = ['a', 'aa', 'aaa', 'b', 'bb', 'bbb']
6620 * a.uniq {|element| element.size } # => ["a", "aa", "aaa"]
6621 *
6622 * Related: {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
6623 */
6624
6625static VALUE
6626rb_ary_uniq(VALUE ary)
6627{
6628 if (RARRAY_LEN(ary) <= 1) {
6629 return rb_ary_dup(ary);
6630 }
6631
6633
6634 if (rb_block_given_p()) {
6635 VALUE uniq = rb_ary_new_capa(RARRAY_LEN(ary));
6636 for (rb_len_t i = 0; i < RARRAY_LEN(ary); i++) {
6637 VALUE elt = rb_ary_elt(ary, i);
6638 if (rb_set_add_no_check(set, rb_yield(elt)))
6639 rb_ary_push(uniq, elt);
6640 }
6641 return uniq;
6642 }
6643 else {
6644 rb_ary_union_set(set, ary);
6645 return rb_set_to_a(set);
6646 }
6647}
6648
6649/*
6650 * call-seq:
6651 * compact! -> self or nil
6652 *
6653 * Removes all +nil+ elements from +self+;
6654 * Returns +self+ if any elements are removed, +nil+ otherwise:
6655 *
6656 * a = [nil, 0, nil, false, nil, '', nil, [], nil, {}]
6657 * a.compact! # => [0, false, "", [], {}]
6658 * a # => [0, false, "", [], {}]
6659 * a.compact! # => nil
6660 *
6661 * Related: Array#compact;
6662 * see also {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
6663 */
6664
6665VALUE
6666rb_ary_compact_bang(VALUE ary)
6667{
6668 VALUE *p, *t, *end;
6669 rb_len_t n;
6670
6671 rb_ary_modify(ary);
6672 p = t = (VALUE *)RARRAY_CONST_PTR(ary); /* WB: no new reference */
6673 end = p + RARRAY_LEN(ary);
6674
6675 while (t < end) {
6676 if (NIL_P(*t)) t++;
6677 else *p++ = *t++;
6678 }
6679 n = p - RARRAY_CONST_PTR(ary);
6680 if (RARRAY_LEN(ary) == n) {
6681 return Qnil;
6682 }
6683 ary_resize_smaller(ary, n);
6684
6685 return ary;
6686}
6687
6688/*
6689 * call-seq:
6690 * compact -> new_array
6691 *
6692 * Returns a new array containing only the non-+nil+ elements from +self+;
6693 * element order is preserved:
6694 *
6695 * a = [nil, 0, nil, false, nil, '', nil, [], nil, {}]
6696 * a.compact # => [0, false, "", [], {}]
6697 *
6698 * Related: Array#compact!;
6699 * see also {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
6700 */
6701
6702static VALUE
6703rb_ary_compact(VALUE ary)
6704{
6705 ary = rb_ary_dup(ary);
6706 rb_ary_compact_bang(ary);
6707 return ary;
6708}
6709
6710/*
6711 * call-seq:
6712 * count -> integer
6713 * count(object) -> integer
6714 * count {|element| ... } -> integer
6715 *
6716 * Returns a count of specified elements.
6717 *
6718 * With no argument and no block, returns the count of all elements:
6719 *
6720 * [0, :one, 'two', 3, 3.0].count # => 5
6721 *
6722 * With argument +object+ given, returns the count of elements <tt>==</tt> to +object+:
6723 *
6724 * [0, :one, 'two', 3, 3.0].count(3) # => 2
6725 *
6726 * With no argument and a block given, calls the block with each element;
6727 * returns the count of elements for which the block returns a truthy value:
6728 *
6729 * [0, 1, 2, 3].count {|element| element > 1 } # => 2
6730 *
6731 * With argument +object+ and a block given, issues a warning, ignores the block,
6732 * and returns the count of elements <tt>==</tt> to +object+.
6733 *
6734 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
6735 */
6736
6737static VALUE
6738rb_ary_count(int argc, VALUE *argv, VALUE ary)
6739{
6740 rb_len_t i, n = 0;
6741
6742 if (rb_check_arity(argc, 0, 1) == 0) {
6743 VALUE v;
6744
6745 if (!rb_block_given_p())
6746 return LEN2NUM(RARRAY_LEN(ary));
6747
6748 for (i = 0; i < RARRAY_LEN(ary); i++) {
6749 v = RARRAY_AREF(ary, i);
6750 if (RTEST(rb_yield(v))) n++;
6751 }
6752 }
6753 else {
6754 VALUE obj = argv[0];
6755
6756 if (rb_block_given_p()) {
6757 rb_warn("given block not used");
6758 }
6759 for (i = 0; i < RARRAY_LEN(ary); i++) {
6760 if (rb_equal(RARRAY_AREF(ary, i), obj)) n++;
6761 }
6762 }
6763
6764 return LEN2NUM(n);
6765}
6766
6767static VALUE
6768flatten(VALUE ary, int level)
6769{
6770 rb_len_t i;
6771 VALUE stack, result, tmp = Qnil, elt;
6772 VALUE memo = Qfalse;
6773
6774 for (i = 0; i < RARRAY_LEN(ary); i++) {
6775 elt = RARRAY_AREF(ary, i);
6776 tmp = rb_check_array_type(elt);
6777 if (!NIL_P(tmp)) {
6778 break;
6779 }
6780 }
6781 if (NIL_P(tmp)) {
6782 return ary;
6783 }
6784 if (i > RARRAY_LEN(ary)) {
6785 /* ary was shrunk while converting an element with #to_ary, so
6786 the scanned elements may no longer exist in ary */
6787 i = RARRAY_LEN(ary);
6788 }
6789
6790 result = ary_new(0, RARRAY_LEN(ary));
6791 ary_memcpy(result, 0, i, RARRAY_CONST_PTR(ary));
6792 ARY_SET_LEN(result, i);
6793
6794 stack = ary_new(0, ARY_DEFAULT_SIZE);
6795 rb_ary_push(stack, ary);
6796 rb_ary_push(stack, LEN2NUM(i + 1));
6797
6798 if (level < 0) {
6799 memo = rb_obj_hide(rb_ident_set_new());
6800 rb_set_add(memo, ary);
6801 rb_set_add(memo, tmp);
6802 }
6803
6804 ary = tmp;
6805 i = 0;
6806
6807 while (1) {
6808 while (i < RARRAY_LEN(ary)) {
6809 elt = RARRAY_AREF(ary, i++);
6810 if (level >= 0 && RARRAY_LEN(stack) / 2 >= level) {
6811 rb_ary_push(result, elt);
6812 continue;
6813 }
6814 tmp = rb_check_array_type(elt);
6815 if (RBASIC(result)->klass) {
6816 if (RTEST(memo)) {
6817 rb_set_clear(memo);
6818 }
6819 rb_raise(rb_eRuntimeError, "flatten reentered");
6820 }
6821 if (NIL_P(tmp)) {
6822 rb_ary_push(result, elt);
6823 }
6824 else {
6825 if (memo) {
6826 if (rb_set_lookup(memo, tmp)) {
6827 rb_set_clear(memo);
6828 rb_raise(rb_eArgError, "tried to flatten recursive array");
6829 }
6830 rb_set_add(memo, tmp);
6831 }
6832 rb_ary_push(stack, ary);
6833 rb_ary_push(stack, LEN2NUM(i));
6834 ary = tmp;
6835 i = 0;
6836 }
6837 }
6838 if (RARRAY_LEN(stack) == 0) {
6839 break;
6840 }
6841 if (memo) {
6842 rb_set_delete(memo, ary);
6843 }
6844 tmp = rb_ary_pop(stack);
6845 i = NUM2LEN(tmp);
6846 ary = rb_ary_pop(stack);
6847 }
6848
6849 if (memo) {
6850 rb_set_clear(memo);
6851 }
6852
6853 RBASIC_SET_CLASS(result, rb_cArray);
6854 return result;
6855}
6856
6857static inline VALUE
6858single_nested_array(VALUE ary)
6859{
6860 // Fast path for the common variadic argument pattern:
6861 // def foo(*args)
6862 // args.flatten!
6863 // ...
6864 if (RARRAY_LEN(ary) == 1) {
6865 VALUE first = RARRAY_AREF(ary, 0);
6866 if (RB_TYPE_P(first, T_ARRAY) && CLASS_OF(first) == rb_cArray) {
6867 return first;
6868 }
6869 }
6870 return 0;
6871}
6872
6873/*
6874 * call-seq:
6875 * flatten!(depth = nil) -> self or nil
6876 *
6877 * Returns +self+ as a recursively flattening of +self+ to +depth+ levels of recursion;
6878 * +depth+ must be an
6879 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects],
6880 * or +nil+.
6881 * At each level of recursion:
6882 *
6883 * - Each element that is an array is "flattened"
6884 * (that is, replaced by its individual array elements).
6885 * - Each element that is not an array is unchanged
6886 * (even if the element is an object that has instance method +flatten+).
6887 *
6888 * Returns +nil+ if no elements were flattened.
6889 *
6890 * With non-negative integer argument +depth+, flattens recursively through +depth+ levels:
6891 *
6892 * a = [ 0, [ 1, [2, 3], 4 ], 5, {foo: 0}, Set.new([6, 7]) ]
6893 * a # => [0, [1, [2, 3], 4], 5, {foo: 0}, Set[6, 7]]
6894 * a.dup.flatten!(1) # => [0, 1, [2, 3], 4, 5, {foo: 0}, Set[6, 7]]
6895 * a.dup.flatten!(1.1) # => [0, 1, [2, 3], 4, 5, {foo: 0}, Set[6, 7]]
6896 * a.dup.flatten!(2) # => [0, 1, 2, 3, 4, 5, {foo: 0}, Set[6, 7]]
6897 * a.dup.flatten!(3) # => [0, 1, 2, 3, 4, 5, {foo: 0}, Set[6, 7]]
6898 *
6899 * With +nil+ or negative argument +depth+, flattens all levels:
6900 *
6901 * a.dup.flatten! # => [0, 1, 2, 3, 4, 5, {foo: 0}, Set[6, 7]]
6902 * a.dup.flatten!(-1) # => [0, 1, 2, 3, 4, 5, {foo: 0}, Set[6, 7]]
6903 *
6904 * Related: Array#flatten;
6905 * see also {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
6906 */
6907
6908static VALUE
6909rb_ary_flatten_bang(int argc, VALUE *argv, VALUE ary)
6910{
6911 int mod = 0, level = -1;
6912 VALUE result, lv;
6913
6914 lv = (rb_check_arity(argc, 0, 1) ? argv[0] : Qnil);
6915 rb_ary_modify_check(ary);
6916 if (!NIL_P(lv)) level = NUM2INT(lv);
6917 if (level == 0) return Qnil;
6918
6919 VALUE child = single_nested_array(ary);
6920 if (child) {
6921 if (level == 1) {
6922 result = child;
6923 }
6924 else {
6925 if (level > 1) level--;
6926 result = flatten(child, level);
6927 }
6928 }
6929 else {
6930 result = flatten(ary, level);
6931 if (result == ary) {
6932 return Qnil;
6933 }
6934 }
6935
6936 if (result != child && !(mod = ARY_EMBED_P(result))) rb_ary_freeze(result);
6937 rb_ary_replace(ary, result);
6938 if (mod) ARY_SET_EMBED_LEN(result, 0);
6939
6940 return ary;
6941}
6942
6943/*
6944 * call-seq:
6945 * flatten(depth = nil) -> new_array
6946 *
6947 * Returns a new array that is a recursive flattening of +self+
6948 * to +depth+ levels of recursion;
6949 * +depth+ must be an
6950 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]
6951 * or +nil+.
6952 * At each level of recursion:
6953 *
6954 * - Each element that is an array is "flattened"
6955 * (that is, replaced by its individual array elements).
6956 * - Each element that is not an array is unchanged
6957 * (even if the element is an object that has instance method +flatten+).
6958 *
6959 * With non-negative integer argument +depth+, flattens recursively through +depth+ levels:
6960 *
6961 * a = [ 0, [ 1, [2, 3], 4 ], 5, {foo: 0}, Set.new([6, 7]) ]
6962 * a # => [0, [1, [2, 3], 4], 5, {foo: 0}, Set[6, 7]]
6963 * a.flatten(0) # => [0, [1, [2, 3], 4], 5, {foo: 0}, Set[6, 7]]
6964 * a.flatten(1 ) # => [0, 1, [2, 3], 4, 5, {foo: 0}, Set[6, 7]]
6965 * a.flatten(1.1) # => [0, 1, [2, 3], 4, 5, {foo: 0}, Set[6, 7]]
6966 * a.flatten(2) # => [0, 1, 2, 3, 4, 5, {foo: 0}, Set[6, 7]]
6967 * a.flatten(3) # => [0, 1, 2, 3, 4, 5, {foo: 0}, Set[6, 7]]
6968 *
6969 * With +nil+ or negative +depth+, flattens all levels.
6970 *
6971 * a.flatten # => [0, 1, 2, 3, 4, 5, {foo: 0}, Set[6, 7]]
6972 * a.flatten(-1) # => [0, 1, 2, 3, 4, 5, {foo: 0}, Set[6, 7]]
6973 *
6974 * Related: Array#flatten!;
6975 * see also {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
6976 */
6977
6978static VALUE
6979rb_ary_flatten(int argc, VALUE *argv, VALUE ary)
6980{
6981 int level = -1;
6982 VALUE result;
6983
6984 if (rb_check_arity(argc, 0, 1) && !NIL_P(argv[0])) {
6985 level = NUM2INT(argv[0]);
6986 if (level == 0) return ary_make_shared_copy(ary);
6987 }
6988
6989 VALUE child = single_nested_array(ary);
6990 if (child) {
6991 if (level == 1) {
6992 result = child;
6993 }
6994 else {
6995 level--;
6996 result = flatten(child, level);
6997 }
6998 }
6999 else {
7000 result = flatten(ary, level);
7001 }
7002
7003 if (result == ary || result == child) {
7004 return ary_make_shared_copy(result);
7005 }
7006
7007 return result;
7008}
7009
7010#if SIZEOF_RB_LEN_T > SIZEOF_LONG
7011/* rb_random_ulong_limited takes an unsigned long, narrower than an Array length here. */
7012static rb_len_t
7013rand_upto(VALUE randgen, rb_len_t max)
7014{
7015 if ((rb_ulen_t)max - 1 <= ULONG_MAX) {
7016 return (rb_len_t)rb_random_ulong_limited(randgen, (unsigned long)(max - 1));
7017 }
7018
7019 VALUE lim = LEN2NUM(max);
7020 VALUE v = rb_to_int(rb_funcallv_public(randgen, rb_intern("rand"), 1, &lim));
7021 if (rb_num_negative_p(v)) {
7022 rb_raise(rb_eRangeError, "random number too small %"PRIsVALUE, v);
7023 }
7024 if (RTEST(rb_int_ge(v, lim))) {
7025 rb_raise(rb_eRangeError, "random number too big %"PRIsVALUE, v);
7026 }
7027 return NUM2LEN(v);
7028}
7029#define RAND_UPTO(max) rand_upto(randgen, (max))
7030#else
7031#define RAND_UPTO(max) (rb_len_t)rb_random_ulong_limited((randgen), (max)-1)
7032#endif
7033
7034static VALUE
7035rb_ary_shuffle_bang(rb_execution_context_t *ec, VALUE ary, VALUE randgen)
7036{
7037 rb_len_t i, len;
7038
7039 rb_ary_modify(ary);
7040 i = len = RARRAY_LEN(ary);
7041 RARRAY_PTR_USE(ary, ptr, {
7042 while (i > 1) {
7043 rb_len_t j = RAND_UPTO(i);
7044 VALUE tmp;
7045 if (len != RARRAY_LEN(ary) || ptr != RARRAY_CONST_PTR(ary)) {
7046 rb_raise(rb_eRuntimeError, "modified during shuffle");
7047 }
7048 tmp = ptr[--i];
7049 ptr[i] = ptr[j];
7050 ptr[j] = tmp;
7051 }
7052 }); /* WB: no new reference */
7053 return ary;
7054}
7055
7056static VALUE
7057rb_ary_shuffle(rb_execution_context_t *ec, VALUE ary, VALUE randgen)
7058{
7059 ary = rb_ary_dup(ary);
7060 rb_ary_shuffle_bang(ec, ary, randgen);
7061 return ary;
7062}
7063
7064static const rb_data_type_t ary_sample_memo_type = {
7065 .wrap_struct_name = "ary_sample_memo",
7066 .function = {
7067 .dfree = (RUBY_DATA_FUNC)st_free_table,
7068 },
7069 .flags = RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_THREAD_SAFE_FREE
7070};
7071
7072static VALUE
7073ary_sample1(rb_execution_context_t *ec, VALUE ary, const VALUE randgen)
7074{
7075 rb_len_t len = RARRAY_LEN(ary);
7076 rb_len_t i = (len < 2) ? 0 : RAND_UPTO(len);
7077 return rb_ary_elt(ary, i);
7078}
7079
7080static VALUE
7081ary_sample0(rb_execution_context_t *ec, VALUE ary)
7082{
7083 return ary_sample1(ec, ary, rb_cRandom);
7084}
7085
7086static VALUE
7087ary_sample(rb_execution_context_t *ec, VALUE ary, VALUE randgen, VALUE nv)
7088{
7089 VALUE result;
7090 rb_len_t n, len, i, j, k, idx[10];
7091 rb_len_t memo_threshold;
7092
7093 n = NUM2LEN(nv);
7094 if (n < 0) rb_raise(rb_eArgError, "negative sample number");
7095 len = RARRAY_LEN(ary);
7096 if (n > len) n = len;
7097 if (n <= numberof(idx)) {
7098 rb_len_t rnds[numberof(idx)], sorted[numberof(idx)];
7099
7100 for (i = 0; i < n; ++i) {
7101 rnds[i] = RAND_UPTO(len - i);
7102 }
7103 k = len;
7104 len = RARRAY_LEN(ary);
7105 if (len < k /* && n <= numberof(idx) */) {
7106 for (i = 0; i < n; ++i) {
7107 if (rnds[i] >= len - i) return rb_ary_new_capa(0);
7108 }
7109 }
7110 if (n > len) n = len;
7111 switch (n) {
7112 case 0:
7113 return rb_ary_new_capa(0);
7114 case 1:
7115 i = rnds[0];
7116 return rb_ary_new_from_args(1, RARRAY_AREF(ary, i));
7117 case 2:
7118 i = rnds[0];
7119 j = rnds[1];
7120 if (j >= i) j++;
7121 return rb_ary_new_from_args(2, RARRAY_AREF(ary, i), RARRAY_AREF(ary, j));
7122 case 3:
7123 i = rnds[0];
7124 j = rnds[1];
7125 k = rnds[2];
7126 {
7127 rb_len_t l = j, g = i;
7128 if (j >= i) l = i, g = ++j;
7129 if (k >= l && (++k >= g)) ++k;
7130 }
7131 return rb_ary_new_from_args(3, RARRAY_AREF(ary, i), RARRAY_AREF(ary, j), RARRAY_AREF(ary, k));
7132 }
7133 sorted[0] = idx[0] = rnds[0];
7134 for (i=1; i<n; i++) {
7135 k = rnds[i];
7136 for (j = 0; j < i; ++j) {
7137 if (k < sorted[j]) break;
7138 ++k;
7139 }
7140 memmove(&sorted[j+1], &sorted[j], sizeof(sorted[0])*(i-j));
7141 sorted[j] = idx[i] = k;
7142 }
7143 result = rb_ary_new_capa(n);
7144 RARRAY_PTR_USE(result, ptr_result, {
7145 for (i=0; i<n; i++) {
7146 ptr_result[i] = RARRAY_AREF(ary, idx[i]);
7147 }
7148 });
7149 ARY_SET_LEN(result, n);
7150 return result;
7151 }
7152
7153 memo_threshold =
7154 len < 2560 ? len / 128 :
7155 len < 5120 ? len / 64 :
7156 len < 10240 ? len / 32 :
7157 len / 16;
7158 if (n <= memo_threshold / 2) {
7159 rb_len_t max_idx = 0;
7160 VALUE vmemo = TypedData_Wrap_Struct(0, &ary_sample_memo_type, 0);
7161 st_table *memo = st_init_numtable_with_size(n);
7162 RTYPEDDATA_DATA(vmemo) = memo;
7163 result = rb_ary_new_capa(n);
7164 RARRAY_PTR_USE(result, ptr_result, {
7165 for (i=0; i<n; i++) {
7166 rb_len_t r = RAND_UPTO(len-i) + i;
7167 ptr_result[i] = r;
7168 if (r > max_idx) max_idx = r;
7169 }
7170 len = RARRAY_LEN(ary);
7171 if (len <= max_idx) n = 0;
7172 else if (n > len) n = len;
7173 RARRAY_PTR_USE(ary, ptr_ary, {
7174 for (i=0; i<n; i++) {
7175 rb_len_t j2 = j = ptr_result[i];
7176 rb_len_t i2 = i;
7177 st_data_t value;
7178 if (st_lookup(memo, (st_data_t)i, &value)) i2 = (rb_len_t)value;
7179 if (st_lookup(memo, (st_data_t)j, &value)) j2 = (rb_len_t)value;
7180 st_insert(memo, (st_data_t)j, (st_data_t)i2);
7181 ptr_result[i] = ptr_ary[j2];
7182 }
7183 });
7184 });
7185 RTYPEDDATA_DATA(vmemo) = 0;
7186 st_free_table(memo);
7187 RB_GC_GUARD(vmemo);
7188 }
7189 else {
7190 result = rb_ary_dup(ary);
7191 RBASIC_CLEAR_CLASS(result);
7192 RB_GC_GUARD(ary);
7193 RARRAY_PTR_USE(result, ptr_result, {
7194 for (i=0; i<n; i++) {
7195 j = RAND_UPTO(len-i) + i;
7196 nv = ptr_result[j];
7197 ptr_result[j] = ptr_result[i];
7198 ptr_result[i] = nv;
7199 }
7200 });
7201 RBASIC_SET_CLASS_RAW(result, rb_cArray);
7202 }
7203 ARY_SET_LEN(result, n);
7204
7205 return result;
7206}
7207
7208static VALUE
7209ary_sized_alloc(rb_execution_context_t *ec, VALUE self)
7210{
7211 return rb_ary_new2(RARRAY_LEN(self));
7212}
7213
7214static VALUE
7215rb_ary_cycle_size(VALUE self, VALUE args, VALUE eobj)
7216{
7217 rb_len_t mul;
7218 VALUE n = Qnil;
7219 if (args && (RARRAY_LEN(args) > 0)) {
7220 n = RARRAY_AREF(args, 0);
7221 }
7222 if (RARRAY_LEN(self) == 0) return INT2FIX(0);
7223 if (NIL_P(n)) return DBL2NUM(HUGE_VAL);
7224 mul = NUM2LEN(n);
7225 if (mul <= 0) return INT2FIX(0);
7226 n = LEN2NUM(mul);
7227 return rb_int_mul(rb_ary_length(self), n);
7228}
7229
7230/*
7231 * call-seq:
7232 * cycle(count = nil) {|element| ... } -> nil
7233 * cycle(count = nil) -> new_enumerator
7234 *
7235 * With a block given, may call the block, depending on the value of argument +count+;
7236 * +count+ must be an
7237 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects],
7238 * or +nil+.
7239 *
7240 * When +count+ is positive,
7241 * calls the block with each element, then does so repeatedly,
7242 * until it has done so +count+ times; returns +nil+:
7243 *
7244 * output = []
7245 * [0, 1].cycle(2) {|element| output.push(element) } # => nil
7246 * output # => [0, 1, 0, 1]
7247 *
7248 * When +count+ is zero or negative, does not call the block:
7249 *
7250 * [0, 1].cycle(0) {|element| fail 'Cannot happen' } # => nil
7251 * [0, 1].cycle(-1) {|element| fail 'Cannot happen' } # => nil
7252 *
7253 * When +count+ is +nil+, cycles forever:
7254 *
7255 * # Prints 0 and 1 forever.
7256 * [0, 1].cycle {|element| puts element }
7257 * [0, 1].cycle(nil) {|element| puts element }
7258 *
7259 * With no block given, returns a new Enumerator.
7260 *
7261 * Related: see {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
7262 */
7263static VALUE
7264rb_ary_cycle(int argc, VALUE *argv, VALUE ary)
7265{
7266 rb_len_t n, i;
7267
7268 rb_check_arity(argc, 0, 1);
7269
7270 RETURN_SIZED_ENUMERATOR(ary, argc, argv, rb_ary_cycle_size);
7271 if (argc == 0 || NIL_P(argv[0])) {
7272 n = -1;
7273 }
7274 else {
7275 n = NUM2LEN(argv[0]);
7276 if (n <= 0) return Qnil;
7277 }
7278
7279 while (RARRAY_LEN(ary) > 0 && (n < 0 || 0 < n--)) {
7280 for (i=0; i<RARRAY_LEN(ary); i++) {
7281 rb_yield(RARRAY_AREF(ary, i));
7282 }
7283 }
7284 return Qnil;
7285}
7286
7287/*
7288 * Build a ruby array of the corresponding values and yield it to the
7289 * associated block.
7290 * Return the class of +values+ for reentry check.
7291 */
7292static int
7293yield_indexed_values(const VALUE values, const rb_len_t r, const rb_len_t *const p)
7294{
7295 const VALUE result = rb_ary_new2(r);
7296 rb_len_t i;
7297
7298 for (i = 0; i < r; i++) ARY_SET(result, i, RARRAY_AREF(values, p[i]));
7299 ARY_SET_LEN(result, r);
7300 rb_yield(result);
7301 return !RBASIC(values)->klass;
7302}
7303
7304/*
7305 * Compute permutations of +r+ elements of the set <code>[0..n-1]</code>.
7306 *
7307 * When we have a complete permutation of array indices, copy the values
7308 * at those indices into a new array and yield that array.
7309 *
7310 * n: the size of the set
7311 * r: the number of elements in each permutation
7312 * p: the array (of size r) that we're filling in
7313 * used: an array of booleans: whether a given index is already used
7314 * values: the Ruby array that holds the actual values to permute
7315 */
7316static void
7317permute0(const rb_len_t n, const rb_len_t r, rb_len_t *const p, char *const used, const VALUE values)
7318{
7319 rb_len_t i = 0, index = 0;
7320
7321 for (;;) {
7322 const char *const unused = memchr(&used[i], 0, n-i);
7323 if (!unused) {
7324 if (!index) break;
7325 i = p[--index]; /* pop index */
7326 used[i++] = 0; /* index unused */
7327 }
7328 else {
7329 i = unused - used;
7330 p[index] = i;
7331 used[i] = 1; /* mark index used */
7332 ++index;
7333 if (index < r-1) { /* if not done yet */
7334 p[index] = i = 0;
7335 continue;
7336 }
7337 for (i = 0; i < n; ++i) {
7338 if (used[i]) continue;
7339 p[index] = i;
7340 if (!yield_indexed_values(values, r, p)) {
7341 rb_raise(rb_eRuntimeError, "permute reentered");
7342 }
7343 }
7344 i = p[--index]; /* pop index */
7345 used[i] = 0; /* index unused */
7346 p[index] = ++i;
7347 }
7348 }
7349}
7350
7351/*
7352 * Returns the product of from, from-1, ..., from - how_many + 1.
7353 * https://en.wikipedia.org/wiki/Pochhammer_symbol
7354 */
7355static VALUE
7356descending_factorial(rb_len_t from, rb_len_t how_many)
7357{
7358 VALUE cnt;
7359 if (how_many > 0) {
7360 cnt = LEN2NUM(from);
7361 while (--how_many > 0) {
7362 rb_len_t v = --from;
7363 cnt = rb_int_mul(cnt, LEN2NUM(v));
7364 }
7365 }
7366 else {
7367 cnt = LONG2FIX(how_many == 0);
7368 }
7369 return cnt;
7370}
7371
7372static VALUE
7373binomial_coefficient(rb_len_t comb, rb_len_t size)
7374{
7375 VALUE r;
7376 rb_len_t i;
7377 if (comb > size-comb) {
7378 comb = size-comb;
7379 }
7380 if (comb < 0) {
7381 return LONG2FIX(0);
7382 }
7383 else if (comb == 0) {
7384 return LONG2FIX(1);
7385 }
7386 r = LEN2NUM(size);
7387 for (i = 1; i < comb; ++i) {
7388 r = rb_int_mul(r, LEN2NUM(size - i));
7389 r = rb_int_idiv(r, LEN2NUM(i + 1));
7390 }
7391 return r;
7392}
7393
7394static VALUE
7395rb_ary_permutation_size(VALUE ary, VALUE args, VALUE eobj)
7396{
7397 rb_len_t n = RARRAY_LEN(ary);
7398 rb_len_t k = (args && (RARRAY_LEN(args) > 0)) ? NUM2LEN(RARRAY_AREF(args, 0)) : n;
7399
7400 return descending_factorial(n, k);
7401}
7402
7403/*
7404 * call-seq:
7405 * permutation(count = self.size) {|permutation| ... } -> self
7406 * permutation(count = self.size) -> new_enumerator
7407 *
7408 * Iterates over permutations of the elements of +self+;
7409 * the order of permutations is indeterminate.
7410 *
7411 * With a block and an in-range positive integer argument +count+ (<tt>0 < count <= self.size</tt>) given,
7412 * calls the block with each permutation of +self+ of size +count+;
7413 * returns +self+:
7414 *
7415 * a = [0, 1, 2]
7416 * perms = []
7417 * a.permutation(1) {|perm| perms.push(perm) }
7418 * perms # => [[0], [1], [2]]
7419 *
7420 * perms = []
7421 * a.permutation(2) {|perm| perms.push(perm) }
7422 * perms # => [[0, 1], [0, 2], [1, 0], [1, 2], [2, 0], [2, 1]]
7423 *
7424 * perms = []
7425 * a.permutation(3) {|perm| perms.push(perm) }
7426 * perms # => [[0, 1, 2], [0, 2, 1], [1, 0, 2], [1, 2, 0], [2, 0, 1], [2, 1, 0]]
7427 *
7428 * When +count+ is zero, calls the block once with a new empty array:
7429 *
7430 * perms = []
7431 * a.permutation(0) {|perm| perms.push(perm) }
7432 * perms # => [[]]
7433 *
7434 * When +count+ is out of range (negative or larger than <tt>self.size</tt>),
7435 * does not call the block:
7436 *
7437 * a.permutation(-1) {|permutation| fail 'Cannot happen' }
7438 * a.permutation(4) {|permutation| fail 'Cannot happen' }
7439 *
7440 * With no block given, returns a new Enumerator.
7441 *
7442 * Related: {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
7443 */
7444
7445static VALUE
7446rb_ary_permutation(int argc, VALUE *argv, VALUE ary)
7447{
7448 rb_len_t r, i;
7449
7450 RETURN_SIZED_ENUMERATOR(ary, argc, argv, rb_ary_permutation_size); /* Return enumerator if no block */
7451 if (rb_check_arity(argc, 0, 1) && !NIL_P(argv[0])) {
7452 r = NUM2LEN(argv[0]); /* Permutation size from argument */
7453 }
7454 else {
7455 r = RARRAY_LEN(ary);
7456 }
7457
7458 rb_len_t n = RARRAY_LEN(ary);
7459
7460 if (r < 0 || n < r) {
7461 /* no permutations: yield nothing */
7462 }
7463 else if (r == 0) { /* exactly one permutation: the zero-length array */
7465 }
7466 else if (r == 1) { /* this is a special, easy case */
7467 for (i = 0; i < RARRAY_LEN(ary); i++) {
7468 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
7469 }
7470 }
7471 else { /* this is the general case */
7472 volatile VALUE t0;
7473 rb_len_t *p = ALLOCV_N(rb_len_t, t0, r+roomof(n, sizeof(rb_len_t)));
7474 char *used = (char*)(p + r);
7475 VALUE ary0 = ary_make_hidden_shared_copy(ary); /* private defensive copy of ary */
7476
7477 MEMZERO(used, char, n); /* initialize array */
7478
7479 permute0(n, r, p, used, ary0); /* compute and yield permutations */
7480 ALLOCV_END(t0);
7481 RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
7482 }
7483 return ary;
7484}
7485
7486static void
7487combinate0(const rb_len_t len, const rb_len_t n, rb_len_t *const stack, const VALUE values)
7488{
7489 rb_len_t lev = 0;
7490
7491 MEMZERO(stack+1, rb_len_t, n);
7492 stack[0] = -1;
7493 for (;;) {
7494 for (lev++; lev < n; lev++) {
7495 stack[lev+1] = stack[lev]+1;
7496 }
7497 if (!yield_indexed_values(values, n, stack+1)) {
7498 rb_raise(rb_eRuntimeError, "combination reentered");
7499 }
7500 do {
7501 if (lev == 0) return;
7502 stack[lev--]++;
7503 } while (stack[lev+1]+n == len+lev+1);
7504 }
7505}
7506
7507static VALUE
7508rb_ary_combination_size(VALUE ary, VALUE args, VALUE eobj)
7509{
7510 rb_len_t n = RARRAY_LEN(ary);
7511 rb_len_t k = NUM2LEN(RARRAY_AREF(args, 0));
7512
7513 return binomial_coefficient(k, n);
7514}
7515
7516/*
7517 * call-seq:
7518 * combination(count) {|element| ... } -> self
7519 * combination(count) -> new_enumerator
7520 *
7521 * When a block and a positive
7522 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]
7523 * argument +count+ (<tt>0 < count <= self.size</tt>)
7524 * are given, calls the block with each combination of +self+ of size +count+;
7525 * returns +self+:
7526 *
7527 * a = %w[a b c] # => ["a", "b", "c"]
7528 * a.combination(2) {|combination| p combination } # => ["a", "b", "c"]
7529 *
7530 * Output:
7531 *
7532 * ["a", "b"]
7533 * ["a", "c"]
7534 * ["b", "c"]
7535 *
7536 * The order of the yielded combinations is not guaranteed.
7537 *
7538 * When +count+ is zero, calls the block once with a new empty array:
7539 *
7540 * a.combination(0) {|combination| p combination }
7541 * [].combination(0) {|combination| p combination }
7542 *
7543 * Output:
7544 *
7545 * []
7546 * []
7547 *
7548 * When +count+ is negative or larger than +self.size+ and +self+ is non-empty,
7549 * does not call the block:
7550 *
7551 * a.combination(-1) {|combination| fail 'Cannot happen' } # => ["a", "b", "c"]
7552 * a.combination(4) {|combination| fail 'Cannot happen' } # => ["a", "b", "c"]
7553 *
7554 * With no block given, returns a new Enumerator.
7555 *
7556 * Related: Array#permutation;
7557 * see also {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
7558 */
7559
7560static VALUE
7561rb_ary_combination(VALUE ary, VALUE num)
7562{
7563 rb_len_t i, n, len;
7564
7565 n = NUM2LEN(num);
7566 RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_combination_size);
7567 len = RARRAY_LEN(ary);
7568 if (n < 0 || len < n) {
7569 /* yield nothing */
7570 }
7571 else if (n == 0) {
7573 }
7574 else if (n == 1) {
7575 for (i = 0; i < RARRAY_LEN(ary); i++) {
7576 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
7577 }
7578 }
7579 else {
7580 VALUE ary0 = ary_make_hidden_shared_copy(ary); /* private defensive copy of ary */
7581 volatile VALUE t0;
7582 rb_len_t *stack = ALLOCV_N(rb_len_t, t0, n+1);
7583
7584 combinate0(len, n, stack, ary0);
7585 ALLOCV_END(t0);
7586 RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
7587 }
7588 return ary;
7589}
7590
7591/*
7592 * Compute repeated permutations of +r+ elements of the set
7593 * <code>[0..n-1]</code>.
7594 *
7595 * When we have a complete repeated permutation of array indices, copy the
7596 * values at those indices into a new array and yield that array.
7597 *
7598 * n: the size of the set
7599 * r: the number of elements in each permutation
7600 * p: the array (of size r) that we're filling in
7601 * values: the Ruby array that holds the actual values to permute
7602 */
7603static void
7604rpermute0(const rb_len_t n, const rb_len_t r, rb_len_t *const p, const VALUE values)
7605{
7606 rb_len_t i = 0, index = 0;
7607
7608 p[index] = i;
7609 for (;;) {
7610 if (++index < r-1) {
7611 p[index] = i = 0;
7612 continue;
7613 }
7614 for (i = 0; i < n; ++i) {
7615 p[index] = i;
7616 if (!yield_indexed_values(values, r, p)) {
7617 rb_raise(rb_eRuntimeError, "repeated permute reentered");
7618 }
7619 }
7620 do {
7621 if (index <= 0) return;
7622 } while ((i = ++p[--index]) >= n);
7623 }
7624}
7625
7626static VALUE
7627rb_ary_repeated_permutation_size(VALUE ary, VALUE args, VALUE eobj)
7628{
7629 rb_len_t n = RARRAY_LEN(ary);
7630 rb_len_t k = NUM2LEN(RARRAY_AREF(args, 0));
7631
7632 if (k < 0) {
7633 return LONG2FIX(0);
7634 }
7635 if (n <= 0) {
7636 return LONG2FIX(!k);
7637 }
7638 return rb_int_pow(LEN2NUM(n), LEN2NUM(k));
7639}
7640
7641/*
7642 * call-seq:
7643 * repeated_permutation(size) {|permutation| ... } -> self
7644 * repeated_permutation(size) -> new_enumerator
7645 *
7646 * With a block given, calls the block with each repeated permutation of length +size+
7647 * of the elements of +self+;
7648 * each permutation is an array;
7649 * returns +self+. The order of the permutations is indeterminate.
7650 *
7651 * If a positive integer argument +size+ is given,
7652 * calls the block with each +size+-tuple repeated permutation of the elements of +self+.
7653 * The number of permutations is <tt>self.size**size</tt>.
7654 *
7655 * Examples:
7656 *
7657 * - +size+ is 1:
7658 *
7659 * p = []
7660 * [0, 1, 2].repeated_permutation(1) {|permutation| p.push(permutation) }
7661 * p # => [[0], [1], [2]]
7662 *
7663 * - +size+ is 2:
7664 *
7665 * p = []
7666 * [0, 1, 2].repeated_permutation(2) {|permutation| p.push(permutation) }
7667 * p # => [[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2], [2, 0], [2, 1], [2, 2]]
7668 *
7669 * If +size+ is zero, calls the block once with an empty array.
7670 *
7671 * If +size+ is negative, does not call the block:
7672 *
7673 * [0, 1, 2].repeated_permutation(-1) {|permutation| fail 'Cannot happen' }
7674 *
7675 * With no block given, returns a new Enumerator.
7676 *
7677 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
7678 */
7679static VALUE
7680rb_ary_repeated_permutation(VALUE ary, VALUE num)
7681{
7682 RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_repeated_permutation_size); /* Return Enumerator if no block */
7683 rb_len_t r = NUM2LEN(num); /* Permutation size from argument */
7684 rb_len_t n = RARRAY_LEN(ary);
7685
7686 if (r < 0) {
7687 /* no permutations: yield nothing */
7688 }
7689 else if (r == 0) { /* exactly one permutation: the zero-length array */
7691 }
7692 else if (r == 1) { /* this is a special, easy case */
7693 for (rb_len_t i = 0; i < RARRAY_LEN(ary); i++) {
7694 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
7695 }
7696 }
7697 else { /* this is the general case */
7698 volatile VALUE t0;
7699 rb_len_t *p = ALLOCV_N(rb_len_t, t0, r);
7700 VALUE ary0 = ary_make_hidden_shared_copy(ary); /* private defensive copy of ary */
7701
7702 rpermute0(n, r, p, ary0); /* compute and yield repeated permutations */
7703 ALLOCV_END(t0);
7704 RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
7705 }
7706 return ary;
7707}
7708
7709static void
7710rcombinate0(const rb_len_t n, const rb_len_t r, rb_len_t *const p, const rb_len_t rest, const VALUE values)
7711{
7712 rb_len_t i = 0, index = 0;
7713
7714 p[index] = i;
7715 for (;;) {
7716 if (++index < r-1) {
7717 p[index] = i;
7718 continue;
7719 }
7720 for (; i < n; ++i) {
7721 p[index] = i;
7722 if (!yield_indexed_values(values, r, p)) {
7723 rb_raise(rb_eRuntimeError, "repeated combination reentered");
7724 }
7725 }
7726 do {
7727 if (index <= 0) return;
7728 } while ((i = ++p[--index]) >= n);
7729 }
7730}
7731
7732static VALUE
7733rb_ary_repeated_combination_size(VALUE ary, VALUE args, VALUE eobj)
7734{
7735 rb_len_t n = RARRAY_LEN(ary);
7736 rb_len_t k = NUM2LEN(RARRAY_AREF(args, 0));
7737 if (k == 0) {
7738 return LONG2FIX(1);
7739 }
7740 return binomial_coefficient(k, n + k - 1);
7741}
7742
7743/*
7744 * call-seq:
7745 * repeated_combination(size) {|combination| ... } -> self
7746 * repeated_combination(size) -> new_enumerator
7747 *
7748 * With a block given, calls the block with each repeated combination of length +size+
7749 * of the elements of +self+;
7750 * each combination is an array;
7751 * returns +self+. The order of the combinations is indeterminate.
7752 *
7753 * If a positive integer argument +size+ is given,
7754 * calls the block with each +size+-tuple repeated combination of the elements of +self+.
7755 * The number of combinations is <tt>(size+1)(size+2)/2</tt>.
7756 *
7757 * Examples:
7758 *
7759 * - +size+ is 1:
7760 *
7761 * c = []
7762 * [0, 1, 2].repeated_combination(1) {|combination| c.push(combination) }
7763 * c # => [[0], [1], [2]]
7764 *
7765 * - +size+ is 2:
7766 *
7767 * c = []
7768 * [0, 1, 2].repeated_combination(2) {|combination| c.push(combination) }
7769 * c # => [[0, 0], [0, 1], [0, 2], [1, 1], [1, 2], [2, 2]]
7770 *
7771 * If +size+ is zero, calls the block once with an empty array.
7772 *
7773 * If +size+ is negative, does not call the block:
7774 *
7775 * [0, 1, 2].repeated_combination(-1) {|combination| fail 'Cannot happen' }
7776 *
7777 * With no block given, returns a new Enumerator.
7778 *
7779 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
7780 */
7781
7782static VALUE
7783rb_ary_repeated_combination(VALUE ary, VALUE num)
7784{
7785 rb_len_t n, i, len;
7786
7787 n = NUM2LEN(num); /* Combination size from argument */
7788 RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_repeated_combination_size); /* Return enumerator if no block */
7789 len = RARRAY_LEN(ary);
7790 if (n < 0) {
7791 /* yield nothing */
7792 }
7793 else if (n == 0) {
7795 }
7796 else if (n == 1) {
7797 for (i = 0; i < RARRAY_LEN(ary); i++) {
7798 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
7799 }
7800 }
7801 else if (len == 0) {
7802 /* yield nothing */
7803 }
7804 else {
7805 volatile VALUE t0;
7806 rb_len_t *p = ALLOCV_N(rb_len_t, t0, n);
7807 VALUE ary0 = ary_make_hidden_shared_copy(ary); /* private defensive copy of ary */
7808
7809 rcombinate0(len, n, p, n, ary0); /* compute and yield repeated combinations */
7810 ALLOCV_END(t0);
7811 RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
7812 }
7813 return ary;
7814}
7815
7816/*
7817 * call-seq:
7818 * product(*other_arrays) -> new_array
7819 * product(*other_arrays) {|combination| ... } -> self
7820 *
7821 * Computes all combinations of elements from all the arrays,
7822 * including both +self+ and +other_arrays+:
7823 *
7824 * - The number of combinations is the product of the sizes of all the arrays,
7825 * including both +self+ and +other_arrays+.
7826 * - The order of the returned combinations is indeterminate.
7827 *
7828 * With no block given, returns the combinations as an array of arrays:
7829 *
7830 * p = [0, 1].product([2, 3])
7831 * # => [[0, 2], [0, 3], [1, 2], [1, 3]]
7832 * p.size # => 4
7833 * p = [0, 1].product([2, 3], [4, 5])
7834 * # => [[0, 2, 4], [0, 2, 5], [0, 3, 4], [0, 3, 5], [1, 2, 4], [1, 2, 5], [1, 3, 4], [1, 3,...
7835 * p.size # => 8
7836 *
7837 * If +self+ or any argument is empty, returns an empty array:
7838 *
7839 * [].product([2, 3], [4, 5]) # => []
7840 * [0, 1].product([2, 3], []) # => []
7841 *
7842 * If no argument is given, returns an array of 1-element arrays,
7843 * each containing an element of +self+:
7844 *
7845 * [0, 1, 2].product # => [[0], [1], [2]]
7846 *
7847 * With a block given, calls the block with each combination; returns +self+:
7848 *
7849 * p = []
7850 * [0, 1].product([2, 3]) {|combination| p.push(combination) }
7851 * p # => [[0, 2], [0, 3], [1, 2], [1, 3]]
7852 *
7853 * If +self+ or any argument is empty, does not call the block:
7854 *
7855 * [].product([2, 3], [4, 5]) {|combination| fail 'Cannot happen' }
7856 * # => []
7857 * [0, 1].product([2, 3], []) {|combination| fail 'Cannot happen' }
7858 * # => [0, 1]
7859 *
7860 * If no argument is given, calls the block with each element of +self+ as a 1-element array:
7861 *
7862 * p = []
7863 * [0, 1].product {|combination| p.push(combination) }
7864 * p # => [[0], [1]]
7865 *
7866 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
7867 */
7868
7869static VALUE
7870rb_ary_product(int argc, VALUE *argv, VALUE ary)
7871{
7872 int n = argc+1; /* How many arrays we're operating on */
7873 volatile VALUE t0 = rb_ary_hidden_new(n);
7874 volatile VALUE t1 = Qundef;
7875 VALUE *arrays = RARRAY_PTR(t0); /* The arrays we're computing the product of */
7876 rb_len_t *counters = ALLOCV_N(rb_len_t, t1, n); /* The current position in each one */
7877 VALUE result = Qnil; /* The array we'll be returning, when no block given */
7878 rb_len_t i,j;
7879 rb_len_t resultlen = 1;
7880
7881 /* initialize the arrays of arrays */
7882 ARY_SET_LEN(t0, n);
7883 arrays[0] = ary;
7884 for (i = 1; i < n; i++) arrays[i] = Qnil;
7885 for (i = 1; i < n; i++) arrays[i] = to_ary(argv[i-1]);
7886
7887 /* initialize the counters for the arrays */
7888 for (i = 0; i < n; i++) counters[i] = 0;
7889
7890 /* Otherwise, allocate and fill in an array of results */
7891 if (rb_block_given_p()) {
7892 /* Make defensive copies of arrays; exit if any is empty */
7893 for (i = 0; i < n; i++) {
7894 if (RARRAY_LEN(arrays[i]) == 0) goto done;
7895 arrays[i] = ary_make_shared_copy(arrays[i]);
7896 }
7897 }
7898 else {
7899 /* Compute the length of the result array; return [] if any is empty */
7900 for (i = 0; i < n; i++) {
7901 rb_len_t k = RARRAY_LEN(arrays[i]);
7902 if (k == 0) {
7903 result = rb_ary_new2(0);
7904 goto done;
7905 }
7906 if (MUL_OVERFLOW_SIGNED_INTEGER_P(resultlen, k, RB_LEN_MIN, RB_LEN_MAX))
7907 rb_raise(rb_eRangeError, "too big to product");
7908 resultlen *= k;
7909 }
7910 result = rb_ary_new2(resultlen);
7911 }
7912 for (;;) {
7913 int m;
7914 /* fill in one subarray */
7915 VALUE subarray = rb_ary_new2(n);
7916 for (j = 0; j < n; j++) {
7917 rb_ary_push(subarray, rb_ary_entry(arrays[j], counters[j]));
7918 }
7919
7920 /* put it on the result array */
7921 if (NIL_P(result)) {
7922 FL_SET(t0, RARRAY_SHARED_ROOT_FLAG);
7923 rb_yield(subarray);
7924 if (!FL_TEST(t0, RARRAY_SHARED_ROOT_FLAG)) {
7925 rb_raise(rb_eRuntimeError, "product reentered");
7926 }
7927 else {
7928 FL_UNSET(t0, RARRAY_SHARED_ROOT_FLAG);
7929 }
7930 }
7931 else {
7932 rb_ary_push(result, subarray);
7933 }
7934
7935 /*
7936 * Increment the last counter. If it overflows, reset to 0
7937 * and increment the one before it.
7938 */
7939 m = n-1;
7940 counters[m]++;
7941 while (counters[m] == RARRAY_LEN(arrays[m])) {
7942 counters[m] = 0;
7943 /* If the first counter overflows, we are done */
7944 if (--m < 0) goto done;
7945 counters[m]++;
7946 }
7947 }
7948
7949done:
7950 ALLOCV_END(t1);
7951
7952 return NIL_P(result) ? ary : result;
7953}
7954
7955/*
7956 * call-seq:
7957 * take(count) -> new_array
7958 *
7959 * Returns a new array containing the first +count+ element of +self+
7960 * (as available);
7961 * +count+ must be a non-negative numeric;
7962 * does not modify +self+:
7963 *
7964 * a = ['a', 'b', 'c', 'd']
7965 * a.take(2) # => ["a", "b"]
7966 * a.take(2.1) # => ["a", "b"]
7967 * a.take(50) # => ["a", "b", "c", "d"]
7968 * a.take(0) # => []
7969 *
7970 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
7971 */
7972
7973static VALUE
7974rb_ary_take(VALUE obj, VALUE n)
7975{
7976 rb_len_t len = NUM2LEN(n);
7977 if (len < 0) {
7978 rb_raise(rb_eArgError, "attempt to take negative size");
7979 }
7980 return rb_ary_subseq(obj, 0, len);
7981}
7982
7983/*
7984 * call-seq:
7985 * take_while {|element| ... } -> new_array
7986 * take_while -> new_enumerator
7987 *
7988 * With a block given, calls the block with each successive element of +self+;
7989 * stops iterating if the block returns +false+ or +nil+;
7990 * returns a new array containing those elements for which the block returned a truthy value:
7991 *
7992 * a = [0, 1, 2, 3, 4, 5]
7993 * a.take_while {|element| element < 3 } # => [0, 1, 2]
7994 * a.take_while {|element| true } # => [0, 1, 2, 3, 4, 5]
7995 * a.take_while {|element| false } # => []
7996 *
7997 * With no block given, returns a new Enumerator.
7998 *
7999 * Does not modify +self+.
8000 *
8001 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
8002 */
8003
8004static VALUE
8005rb_ary_take_while(VALUE ary)
8006{
8007 rb_len_t i;
8008
8009 RETURN_ENUMERATOR(ary, 0, 0);
8010 for (i = 0; i < RARRAY_LEN(ary); i++) {
8011 if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) break;
8012 }
8013 return rb_ary_take(ary, LEN2NUM(i));
8014}
8015
8016/*
8017 * call-seq:
8018 * drop(count) -> new_array
8019 *
8020 * Returns a new array containing all but the first +count+ element of +self+,
8021 * where +count+ is a non-negative integer;
8022 * does not modify +self+.
8023 *
8024 * Examples:
8025 *
8026 * a = [0, 1, 2, 3, 4, 5]
8027 * a.drop(0) # => [0, 1, 2, 3, 4, 5]
8028 * a.drop(1) # => [1, 2, 3, 4, 5]
8029 * a.drop(2) # => [2, 3, 4, 5]
8030 * a.drop(9) # => []
8031 *
8032 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
8033 */
8034
8035static VALUE
8036rb_ary_drop(VALUE ary, VALUE n)
8037{
8038 VALUE result;
8039 rb_len_t pos = NUM2LEN(n);
8040 if (pos < 0) {
8041 rb_raise(rb_eArgError, "attempt to drop negative size");
8042 }
8043
8044 result = rb_ary_subseq(ary, pos, RARRAY_LEN(ary));
8045 if (NIL_P(result)) result = rb_ary_new();
8046 return result;
8047}
8048
8049/*
8050 * call-seq:
8051 * drop_while {|element| ... } -> new_array
8052 * drop_while -> new_enumerator
8053 *
8054 * With a block given, calls the block with each successive element of +self+;
8055 * stops if the block returns +false+ or +nil+;
8056 * returns a new array _omitting_ those elements for which the block returned a truthy value;
8057 * does not modify +self+:
8058 *
8059 * a = [0, 1, 2, 3, 4, 5]
8060 * a.drop_while {|element| element < 3 } # => [3, 4, 5]
8061 *
8062 * With no block given, returns a new Enumerator.
8063 *
8064 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
8065 */
8066
8067static VALUE
8068rb_ary_drop_while(VALUE ary)
8069{
8070 rb_len_t i;
8071
8072 RETURN_ENUMERATOR(ary, 0, 0);
8073 for (i = 0; i < RARRAY_LEN(ary); i++) {
8074 if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) break;
8075 }
8076 return rb_ary_drop(ary, LEN2NUM(i));
8077}
8078
8079/*
8080 * call-seq:
8081 * any? -> true or false
8082 * any?(object) -> true or false
8083 * any? {|element| ... } -> true or false
8084 *
8085 * Returns whether for any element of +self+, a given criterion is satisfied.
8086 *
8087 * With no block and no argument, returns whether any element of +self+ is truthy:
8088 *
8089 * [nil, false, []].any? # => true # Array object is truthy.
8090 * [nil, false, {}].any? # => true # Hash object is truthy.
8091 * [nil, false, ''].any? # => true # String object is truthy.
8092 * [nil, false].any? # => false # Nil and false are not truthy.
8093 *
8094 * With argument +object+ given,
8095 * returns whether <tt>object === ele</tt> for any element +ele+ in +self+:
8096 *
8097 * [nil, false, 0].any?(0) # => true
8098 * [nil, false, 1].any?(0) # => false
8099 * [nil, false, 'food'].any?(/foo/) # => true
8100 * [nil, false, 'food'].any?(/bar/) # => false
8101 *
8102 * With a block given,
8103 * calls the block with each element in +self+;
8104 * returns whether the block returns any truthy value:
8105 *
8106 * [0, 1, 2].any? {|ele| ele < 1 } # => true
8107 * [0, 1, 2].any? {|ele| ele < 0 } # => false
8108 *
8109 * With both a block and argument +object+ given,
8110 * ignores the block and uses +object+ as above.
8111 *
8112 * <b>Special case</b>: returns +false+ if +self+ is empty
8113 * (regardless of any given argument or block).
8114 *
8115 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
8116 */
8117
8118static VALUE
8119rb_ary_any_p(int argc, VALUE *argv, VALUE ary)
8120{
8121 rb_len_t i, len = RARRAY_LEN(ary);
8122
8123 rb_check_arity(argc, 0, 1);
8124 if (!len) return Qfalse;
8125 if (argc) {
8126 if (rb_block_given_p()) {
8127 rb_warn("given block not used");
8128 }
8129 for (i = 0; i < RARRAY_LEN(ary); ++i) {
8130 if (RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) return Qtrue;
8131 }
8132 }
8133 else if (!rb_block_given_p()) {
8134 for (i = 0; i < len; ++i) {
8135 if (RTEST(RARRAY_AREF(ary, i))) return Qtrue;
8136 }
8137 }
8138 else {
8139 for (i = 0; i < RARRAY_LEN(ary); ++i) {
8140 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) return Qtrue;
8141 }
8142 }
8143 return Qfalse;
8144}
8145
8146/*
8147 * call-seq:
8148 * all? -> true or false
8149 * all?(object) -> true or false
8150 * all? {|element| ... } -> true or false
8151 *
8152 * Returns whether for every element of +self+,
8153 * a given criterion is satisfied.
8154 *
8155 * With no block and no argument,
8156 * returns whether every element of +self+ is truthy:
8157 *
8158 * [[], {}, '', 0, 0.0, Object.new].all? # => true # All truthy objects.
8159 * [[], {}, '', 0, 0.0, nil].all? # => false # nil is not truthy.
8160 * [[], {}, '', 0, 0.0, false].all? # => false # false is not truthy.
8161 *
8162 * With argument +object+ given, returns whether <tt>object === ele</tt>
8163 * for every element +ele+ in +self+:
8164 *
8165 * [0, 0, 0].all?(0) # => true
8166 * [0, 1, 2].all?(1) # => false
8167 * ['food', 'fool', 'foot'].all?(/foo/) # => true
8168 * ['food', 'drink'].all?(/foo/) # => false
8169 *
8170 * With a block given, calls the block with each element in +self+;
8171 * returns whether the block returns only truthy values:
8172 *
8173 * [0, 1, 2].all? { |ele| ele < 3 } # => true
8174 * [0, 1, 2].all? { |ele| ele < 2 } # => false
8175 *
8176 * With both a block and argument +object+ given,
8177 * ignores the block and uses +object+ as above.
8178 *
8179 * <b>Special case</b>: returns +true+ if +self+ is empty
8180 * (regardless of any given argument or block).
8181 *
8182 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
8183 */
8184
8185static VALUE
8186rb_ary_all_p(int argc, VALUE *argv, VALUE ary)
8187{
8188 rb_len_t i, len = RARRAY_LEN(ary);
8189
8190 rb_check_arity(argc, 0, 1);
8191 if (!len) return Qtrue;
8192 if (argc) {
8193 if (rb_block_given_p()) {
8194 rb_warn("given block not used");
8195 }
8196 for (i = 0; i < RARRAY_LEN(ary); ++i) {
8197 if (!RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) return Qfalse;
8198 }
8199 }
8200 else if (!rb_block_given_p()) {
8201 for (i = 0; i < len; ++i) {
8202 if (!RTEST(RARRAY_AREF(ary, i))) return Qfalse;
8203 }
8204 }
8205 else {
8206 for (i = 0; i < RARRAY_LEN(ary); ++i) {
8207 if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) return Qfalse;
8208 }
8209 }
8210 return Qtrue;
8211}
8212
8213/*
8214 * call-seq:
8215 * none? -> true or false
8216 * none?(object) -> true or false
8217 * none? {|element| ... } -> true or false
8218 *
8219 * Returns +true+ if no element of +self+ meets a given criterion, +false+ otherwise.
8220 *
8221 * With no block given and no argument, returns +true+ if +self+ has no truthy elements,
8222 * +false+ otherwise:
8223 *
8224 * [nil, false].none? # => true
8225 * [nil, 0, false].none? # => false
8226 * [].none? # => true
8227 *
8228 * With argument +object+ given, returns +false+ if for any element +element+,
8229 * <tt>object === element</tt>; +true+ otherwise:
8230 *
8231 * ['food', 'drink'].none?(/bar/) # => true
8232 * ['food', 'drink'].none?(/foo/) # => false
8233 * [].none?(/foo/) # => true
8234 * [0, 1, 2].none?(3) # => true
8235 * [0, 1, 2].none?(1) # => false
8236 *
8237 * With a block given, calls the block with each element in +self+;
8238 * returns +true+ if the block returns no truthy value, +false+ otherwise:
8239 *
8240 * [0, 1, 2].none? {|element| element > 3 } # => true
8241 * [0, 1, 2].none? {|element| element > 1 } # => false
8242 *
8243 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
8244 */
8245
8246static VALUE
8247rb_ary_none_p(int argc, VALUE *argv, VALUE ary)
8248{
8249 rb_len_t i, len = RARRAY_LEN(ary);
8250
8251 rb_check_arity(argc, 0, 1);
8252 if (!len) return Qtrue;
8253 if (argc) {
8254 if (rb_block_given_p()) {
8255 rb_warn("given block not used");
8256 }
8257 for (i = 0; i < RARRAY_LEN(ary); ++i) {
8258 if (RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) return Qfalse;
8259 }
8260 }
8261 else if (!rb_block_given_p()) {
8262 for (i = 0; i < len; ++i) {
8263 if (RTEST(RARRAY_AREF(ary, i))) return Qfalse;
8264 }
8265 }
8266 else {
8267 for (i = 0; i < RARRAY_LEN(ary); ++i) {
8268 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) return Qfalse;
8269 }
8270 }
8271 return Qtrue;
8272}
8273
8274/*
8275 * call-seq:
8276 * one? -> true or false
8277 * one? {|element| ... } -> true or false
8278 * one?(object) -> true or false
8279 *
8280 * Returns +true+ if exactly one element of +self+ meets a given criterion.
8281 *
8282 * With no block given and no argument, returns +true+ if +self+ has exactly one truthy element,
8283 * +false+ otherwise:
8284 *
8285 * [nil, 0].one? # => true
8286 * [0, 0].one? # => false
8287 * [nil, nil].one? # => false
8288 * [].one? # => false
8289 *
8290 * With a block given, calls the block with each element in +self+;
8291 * returns +true+ if the block a truthy value for exactly one element, +false+ otherwise:
8292 *
8293 * [0, 1, 2].one? {|element| element > 0 } # => false
8294 * [0, 1, 2].one? {|element| element > 1 } # => true
8295 * [0, 1, 2].one? {|element| element > 2 } # => false
8296 *
8297 * With argument +object+ given, returns +true+ if for exactly one element +element+, <tt>object === element</tt>;
8298 * +false+ otherwise:
8299 *
8300 * [0, 1, 2].one?(0) # => true
8301 * [0, 0, 1].one?(0) # => false
8302 * [1, 1, 2].one?(0) # => false
8303 * ['food', 'drink'].one?(/bar/) # => false
8304 * ['food', 'drink'].one?(/foo/) # => true
8305 * [].one?(/foo/) # => false
8306 *
8307 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
8308 */
8309
8310static VALUE
8311rb_ary_one_p(int argc, VALUE *argv, VALUE ary)
8312{
8313 rb_len_t i, len = RARRAY_LEN(ary);
8314 VALUE result = Qfalse;
8315
8316 rb_check_arity(argc, 0, 1);
8317 if (!len) return Qfalse;
8318 if (argc) {
8319 if (rb_block_given_p()) {
8320 rb_warn("given block not used");
8321 }
8322 for (i = 0; i < RARRAY_LEN(ary); ++i) {
8323 if (RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) {
8324 if (result) return Qfalse;
8325 result = Qtrue;
8326 }
8327 }
8328 }
8329 else if (!rb_block_given_p()) {
8330 for (i = 0; i < len; ++i) {
8331 if (RTEST(RARRAY_AREF(ary, i))) {
8332 if (result) return Qfalse;
8333 result = Qtrue;
8334 }
8335 }
8336 }
8337 else {
8338 for (i = 0; i < RARRAY_LEN(ary); ++i) {
8339 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) {
8340 if (result) return Qfalse;
8341 result = Qtrue;
8342 }
8343 }
8344 }
8345 return result;
8346}
8347
8348/*
8349 * call-seq:
8350 * dig(index, *identifiers) -> object
8351 *
8352 * Finds and returns the object in nested object
8353 * specified by +index+ and +identifiers+;
8354 * the nested objects may be instances of various classes.
8355 * See {Dig Methods}[rdoc-ref:dig_methods.rdoc].
8356 *
8357 * Examples:
8358 *
8359 * a = [:foo, [:bar, :baz, [:bat, :bam]]]
8360 * a.dig(1) # => [:bar, :baz, [:bat, :bam]]
8361 * a.dig(1, 2) # => [:bat, :bam]
8362 * a.dig(1, 2, 0) # => :bat
8363 * a.dig(1, 2, 3) # => nil
8364 *
8365 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
8366 */
8367
8368static VALUE
8369rb_ary_dig(int argc, VALUE *argv, VALUE self)
8370{
8372 self = rb_ary_at(self, *argv);
8373 if (!--argc) return self;
8374 ++argv;
8375 return rb_obj_dig(argc, argv, self, Qnil);
8376}
8377
8378static inline VALUE
8379finish_exact_sum(long n, VALUE r, VALUE v, int z)
8380{
8381 if (n != 0)
8382 v = rb_fix_plus(LONG2FIX(n), v);
8383 if (!UNDEF_P(r)) {
8384 v = rb_rational_plus(r, v);
8385 }
8386 else if (!n && z) {
8387 v = rb_fix_plus(LONG2FIX(0), v);
8388 }
8389 return v;
8390}
8391
8392/*
8393 * call-seq:
8394 * sum(init = 0) -> object
8395 * sum(init = 0) {|element| ... } -> object
8396 *
8397 * With no block given, returns the sum of +init+ and all elements of +self+;
8398 * for array +array+ and value +init+, equivalent to:
8399 *
8400 * sum = init
8401 * array.each {|element| sum += element }
8402 * sum
8403 *
8404 * For example, <tt>[e0, e1, e2].sum</tt> returns <tt>init + e0 + e1 + e2</tt>.
8405 *
8406 * Examples:
8407 *
8408 * [0, 1, 2, 3].sum # => 6
8409 * [0, 1, 2, 3].sum(100) # => 106
8410 * ['abc', 'def', 'ghi'].sum('jkl') # => "jklabcdefghi"
8411 * [[:foo, :bar], ['foo', 'bar']].sum([2, 3])
8412 * # => [2, 3, :foo, :bar, "foo", "bar"]
8413 *
8414 * The +init+ value and elements need not be numeric, but must all be <tt>+</tt>-compatible:
8415 *
8416 * # Raises TypeError: Array can't be coerced into Integer.
8417 * [[:foo, :bar], ['foo', 'bar']].sum(2)
8418 *
8419 * With a block given, calls the block with each element of +self+;
8420 * the block's return value (instead of the element itself) is used as the addend:
8421 *
8422 * ['zero', 1, :two].sum('Coerced and concatenated: ') {|element| element.to_s }
8423 * # => "Coerced and concatenated: zero1two"
8424 *
8425 * Notes:
8426 *
8427 * - Array#join and Array#flatten may be faster than Array#sum
8428 * for an array of strings or an array of arrays.
8429 * - Array#sum method may not respect method redefinition of "+" methods such as Integer#+.
8430 *
8431 */
8432
8433static VALUE
8434rb_ary_sum(int argc, VALUE *argv, VALUE ary)
8435{
8436 VALUE e, v, r;
8437 rb_len_t i;
8438 long n;
8439 int block_given;
8440
8441 v = (rb_check_arity(argc, 0, 1) ? argv[0] : LONG2FIX(0));
8442
8443 block_given = rb_block_given_p();
8444
8445 if (RARRAY_LEN(ary) == 0)
8446 return v;
8447
8448 n = 0;
8449 r = Qundef;
8450
8451 bool init_is_float = RB_FLOAT_TYPE_P(v);
8452 if (init_is_float) {
8453 v = LONG2FIX(0);
8454 }
8455 else if (!RB_INTEGER_TYPE_P(v) && !RB_TYPE_P(v, T_RATIONAL)) {
8456 i = 0;
8457 goto init_is_a_value;
8458 }
8459
8460 for (i = 0; i < RARRAY_LEN(ary); i++) {
8461 e = RARRAY_AREF(ary, i);
8462 if (block_given)
8463 e = rb_yield(e);
8464 if (FIXNUM_P(e)) {
8465 n += FIX2LONG(e); /* should not overflow long type */
8466 if (!FIXABLE(n)) {
8467 v = rb_big_plus(LONG2NUM(n), v);
8468 n = 0;
8469 }
8470 }
8471 else if (RB_BIGNUM_TYPE_P(e))
8472 v = rb_big_plus(e, v);
8473 else if (RB_TYPE_P(e, T_RATIONAL)) {
8474 if (UNDEF_P(r))
8475 r = e;
8476 else
8477 r = rb_rational_plus(r, e);
8478 }
8479 else
8480 goto not_exact;
8481 }
8482 v = finish_exact_sum(n, r, v, argc!=0);
8483 if (init_is_float) v = rb_float_plus(argv[0], v);
8484 return v;
8485
8486 not_exact:
8487 v = finish_exact_sum(n, r, v, i!=0);
8488
8489 if (init_is_float && !RB_FLOAT_TYPE_P(e)) {
8490 v = rb_float_plus(argv[0], v);
8491 goto has_some_value;
8492 }
8493
8494 if (init_is_float || RB_FLOAT_TYPE_P(e)) {
8495 /*
8496 * Kahan-Babuska balancing compensated summation algorithm
8497 * See https://link.springer.com/article/10.1007/s00607-005-0139-x
8498 */
8499 double f, c;
8500 double x, t;
8501
8502 f = NUM2DBL(v);
8503 c = 0.0;
8504 if (init_is_float) {
8505 x = RFLOAT_VALUE(argv[0]);
8506 t = f + x;
8507 f = t;
8508 }
8509 goto has_float_value;
8510 for (; i < RARRAY_LEN(ary); i++) {
8511 e = RARRAY_AREF(ary, i);
8512 if (block_given)
8513 e = rb_yield(e);
8514 if (RB_FLOAT_TYPE_P(e))
8515 has_float_value:
8516 x = RFLOAT_VALUE(e);
8517 else if (FIXNUM_P(e))
8518 x = FIX2LONG(e);
8519 else if (RB_BIGNUM_TYPE_P(e))
8520 x = rb_big2dbl(e);
8521 else if (RB_TYPE_P(e, T_RATIONAL))
8522 x = rb_num2dbl(e);
8523 else
8524 goto not_float;
8525
8526 if (isnan(f)) continue;
8527 if (isnan(x)) {
8528 f = x;
8529 continue;
8530 }
8531 if (isinf(x)) {
8532 if (isinf(f) && signbit(x) != signbit(f))
8533 f = NAN;
8534 else
8535 f = x;
8536 continue;
8537 }
8538 if (isinf(f)) continue;
8539
8540 t = f + x;
8541 if (fabs(f) >= fabs(x))
8542 c += ((f - t) + x);
8543 else
8544 c += ((x - t) + f);
8545 f = t;
8546 }
8547 f += c;
8548 return DBL2NUM(f);
8549
8550 not_float:
8551 v = DBL2NUM(f);
8552 }
8553
8554 goto has_some_value;
8555 init_is_a_value:
8556 for (; i < RARRAY_LEN(ary); i++) {
8557 e = RARRAY_AREF(ary, i);
8558 if (block_given)
8559 e = rb_yield(e);
8560 has_some_value:
8561 v = rb_funcall(v, idPLUS, 1, e);
8562 }
8563 return v;
8564}
8565
8566/* :nodoc: */
8567static VALUE
8568rb_ary_deconstruct(VALUE ary)
8569{
8570 return ary;
8571}
8572
8573/*
8574 * An \Array object is an ordered, integer-indexed collection of objects,
8575 * called _elements_;
8576 * the object represents
8577 * an {array data structure}[https://en.wikipedia.org/wiki/Array_(data_structure)].
8578 *
8579 * An element may be any object (even another array);
8580 * elements may be any mixture of objects of different types.
8581 *
8582 * Important data structures that use arrays include:
8583 *
8584 * - {Coordinate vector}[https://en.wikipedia.org/wiki/Coordinate_vector].
8585 * - {Matrix}[https://en.wikipedia.org/wiki/Matrix_(mathematics)].
8586 * - {Heap}[https://en.wikipedia.org/wiki/Heap_(data_structure)].
8587 * - {Hash table}[https://en.wikipedia.org/wiki/Hash_table].
8588 * - {Deque (double-ended queue)}[https://en.wikipedia.org/wiki/Double-ended_queue].
8589 * - {Queue}[https://en.wikipedia.org/wiki/Queue_(abstract_data_type)].
8590 * - {Stack}[https://en.wikipedia.org/wiki/Stack_(abstract_data_type)].
8591 *
8592 * There are also array-like data structures:
8593 *
8594 * - {Associative array}[https://en.wikipedia.org/wiki/Associative_array] (see Hash).
8595 * - {Directory}[https://en.wikipedia.org/wiki/Directory_(computing)] (see Dir).
8596 * - {Environment}[https://en.wikipedia.org/wiki/Environment_variable] (see ENV).
8597 * - {Set}[https://en.wikipedia.org/wiki/Set_(abstract_data_type)] (see Set).
8598 * - {String}[https://en.wikipedia.org/wiki/String_(computer_science)] (see String).
8599 *
8600 * == \Array Indexes
8601 *
8602 * \Array indexing starts at 0, as in C or Java.
8603 *
8604 * A non-negative index is an offset from the first element:
8605 *
8606 * - Index 0 indicates the first element.
8607 * - Index 1 indicates the second element.
8608 * - ...
8609 *
8610 * A negative index is an offset, backwards, from the end of the array:
8611 *
8612 * - Index -1 indicates the last element.
8613 * - Index -2 indicates the next-to-last element.
8614 * - ...
8615 *
8616 *
8617 * === In-Range and Out-of-Range Indexes
8618 *
8619 * A non-negative index is <i>in range</i> if and only if it is smaller than
8620 * the size of the array. For a 3-element array:
8621 *
8622 * - Indexes 0 through 2 are in range.
8623 * - Index 3 is out of range.
8624 *
8625 * A negative index is <i>in range</i> if and only if its absolute value is
8626 * not larger than the size of the array. For a 3-element array:
8627 *
8628 * - Indexes -1 through -3 are in range.
8629 * - Index -4 is out of range.
8630 *
8631 * === Effective Index
8632 *
8633 * Although the effective index into an array is always an integer,
8634 * some methods (both within class \Array and elsewhere)
8635 * accept one or more non-integer arguments that are
8636 * {integer-convertible objects}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
8637 *
8638 * == Creating Arrays
8639 *
8640 * You can create an \Array object explicitly with:
8641 *
8642 * - An {array literal}[rdoc-ref:syntax/literals.rdoc@Array+Literals]:
8643 *
8644 * [1, 'one', :one, [2, 'two', :two]]
8645 *
8646 * - A {%w or %W string-array Literal}[rdoc-ref:syntax/literals.rdoc@w-and-w-String-Array-Literals]:
8647 *
8648 * %w[foo bar baz] # => ["foo", "bar", "baz"]
8649 * %w[1 % *] # => ["1", "%", "*"]
8650 *
8651 * - A {%i or %I symbol-array Literal}[rdoc-ref:syntax/literals.rdoc@i+and-I-Symbol-Array+Literals]:
8652 *
8653 * %i[foo bar baz] # => [:foo, :bar, :baz]
8654 * %i[1 % *] # => [:"1", :%, :*]
8655 *
8656 * - Method Kernel#Array:
8657 *
8658 * Array(["a", "b"]) # => ["a", "b"]
8659 * Array(1..5) # => [1, 2, 3, 4, 5]
8660 * Array(key: :value) # => [[:key, :value]]
8661 * Array(nil) # => []
8662 * Array(1) # => [1]
8663 * Array({:a => "a", :b => "b"}) # => [[:a, "a"], [:b, "b"]]
8664 *
8665 * - Method Array.new:
8666 *
8667 * Array.new # => []
8668 * Array.new(3) # => [nil, nil, nil]
8669 * Array.new(4) {Hash.new} # => [{}, {}, {}, {}]
8670 * Array.new(3, true) # => [true, true, true]
8671 *
8672 * Note that the last example above populates the array
8673 * with references to the same object.
8674 * This is recommended only in cases where that object is a natively immutable object
8675 * such as a symbol, a numeric, +nil+, +true+, or +false+.
8676 *
8677 * Another way to create an array with various objects, using a block;
8678 * this usage is safe for mutable objects such as hashes, strings or
8679 * other arrays:
8680 *
8681 * Array.new(4) {|i| i.to_s } # => ["0", "1", "2", "3"]
8682 *
8683 * Here is a way to create a multi-dimensional array:
8684 *
8685 * Array.new(3) {Array.new(3)}
8686 * # => [[nil, nil, nil], [nil, nil, nil], [nil, nil, nil]]
8687 *
8688 * A number of Ruby methods, both in the core and in the standard library,
8689 * provide instance method +to_a+, which converts an object to an array.
8690 *
8691 * - ARGF#to_a
8692 * - Array#to_a
8693 * - Enumerable#to_a
8694 * - Hash#to_a
8695 * - MatchData#to_a
8696 * - NilClass#to_a
8697 * - OptionParser#to_a
8698 * - Range#to_a
8699 * - Set#to_a
8700 * - Struct#to_a
8701 * - Time#to_a
8702 * - Benchmark::Tms#to_a
8703 * - CSV::Table#to_a
8704 * - Enumerator::Lazy#to_a
8705 * - Gem::List#to_a
8706 * - Gem::NameTuple#to_a
8707 * - Gem::Platform#to_a
8708 * - Gem::RequestSet::Lockfile::Tokenizer#to_a
8709 * - Gem::SourceList#to_a
8710 * - OpenSSL::X509::Extension#to_a
8711 * - OpenSSL::X509::Name#to_a
8712 * - Racc::ISet#to_a
8713 * - Rinda::RingFinger#to_a
8714 * - Ripper::Lexer::Elem#to_a
8715 * - RubyVM::InstructionSequence#to_a
8716 * - YAML::DBM#to_a
8717 *
8718 * == Example Usage
8719 *
8720 * In addition to the methods it mixes in through the Enumerable module,
8721 * class \Array has proprietary methods for accessing, searching and otherwise
8722 * manipulating arrays.
8723 *
8724 * Some of the more common ones are illustrated below.
8725 *
8726 * == Accessing Elements
8727 *
8728 * Elements in an array can be retrieved using the Array#[] method. It can
8729 * take a single integer argument (a numeric index), a pair of arguments
8730 * (start and length) or a range. Negative indices start counting from the end,
8731 * with -1 being the last element.
8732 *
8733 * arr = [1, 2, 3, 4, 5, 6]
8734 * arr[2] #=> 3
8735 * arr[100] #=> nil
8736 * arr[-3] #=> 4
8737 * arr[2, 3] #=> [3, 4, 5]
8738 * arr[1..4] #=> [2, 3, 4, 5]
8739 * arr[1..-3] #=> [2, 3, 4]
8740 *
8741 * Another way to access a particular array element is by using the #at method
8742 *
8743 * arr.at(0) #=> 1
8744 *
8745 * The #slice method works in an identical manner to Array#[].
8746 *
8747 * To raise an error for indices outside of the array bounds or else to
8748 * provide a default value when that happens, you can use #fetch.
8749 *
8750 * arr = ['a', 'b', 'c', 'd', 'e', 'f']
8751 * arr.fetch(100) #=> IndexError: index 100 outside of array bounds: -6...6
8752 * arr.fetch(100, "oops") #=> "oops"
8753 *
8754 * The special methods #first and #last will return the first and last
8755 * elements of an array, respectively.
8756 *
8757 * arr.first #=> 1
8758 * arr.last #=> 6
8759 *
8760 * To return the first +n+ elements of an array, use #take
8761 *
8762 * arr.take(3) #=> [1, 2, 3]
8763 *
8764 * #drop does the opposite of #take, by returning the elements after +n+
8765 * elements have been dropped:
8766 *
8767 * arr.drop(3) #=> [4, 5, 6]
8768 *
8769 * == Obtaining Information about an \Array
8770 *
8771 * An array keeps track of its own length at all times. To query an array
8772 * about the number of elements it contains, use #length, #count or #size.
8773 *
8774 * browsers = ['Chrome', 'Firefox', 'Safari', 'Opera', 'IE']
8775 * browsers.length #=> 5
8776 * browsers.count #=> 5
8777 *
8778 * To check whether an array contains any elements at all
8779 *
8780 * browsers.empty? #=> false
8781 *
8782 * To check whether a particular item is included in the array
8783 *
8784 * browsers.include?('Konqueror') #=> false
8785 *
8786 * == Adding Items to an \Array
8787 *
8788 * Items can be added to the end of an array by using either #push or #<<
8789 *
8790 * arr = [1, 2, 3, 4]
8791 * arr.push(5) #=> [1, 2, 3, 4, 5]
8792 * arr << 6 #=> [1, 2, 3, 4, 5, 6]
8793 *
8794 * #unshift will add a new item to the beginning of an array.
8795 *
8796 * arr.unshift(0) #=> [0, 1, 2, 3, 4, 5, 6]
8797 *
8798 * With #insert you can add a new element to an array at any position.
8799 *
8800 * arr.insert(3, 'apple') #=> [0, 1, 2, 'apple', 3, 4, 5, 6]
8801 *
8802 * Using the #insert method, you can also insert multiple values at once:
8803 *
8804 * arr.insert(3, 'orange', 'pear', 'grapefruit')
8805 * #=> [0, 1, 2, "orange", "pear", "grapefruit", "apple", 3, 4, 5, 6]
8806 *
8807 * == Removing Items from an \Array
8808 *
8809 * The method #pop removes the last element in an array and returns it:
8810 *
8811 * arr = [1, 2, 3, 4, 5, 6]
8812 * arr.pop #=> 6
8813 * arr #=> [1, 2, 3, 4, 5]
8814 *
8815 * To retrieve and at the same time remove the first item, use #shift:
8816 *
8817 * arr.shift #=> 1
8818 * arr #=> [2, 3, 4, 5]
8819 *
8820 * To delete an element at a particular index:
8821 *
8822 * arr.delete_at(2) #=> 4
8823 * arr #=> [2, 3, 5]
8824 *
8825 * To delete a particular element anywhere in an array, use #delete:
8826 *
8827 * arr = [1, 2, 2, 3]
8828 * arr.delete(2) #=> 2
8829 * arr #=> [1,3]
8830 *
8831 * A useful method if you need to remove +nil+ values from an array is
8832 * #compact:
8833 *
8834 * arr = ['foo', 0, nil, 'bar', 7, 'baz', nil]
8835 * arr.compact #=> ['foo', 0, 'bar', 7, 'baz']
8836 * arr #=> ['foo', 0, nil, 'bar', 7, 'baz', nil]
8837 * arr.compact! #=> ['foo', 0, 'bar', 7, 'baz']
8838 * arr #=> ['foo', 0, 'bar', 7, 'baz']
8839 *
8840 * Another common need is to remove duplicate elements from an array.
8841 *
8842 * It has the non-destructive #uniq, and destructive method #uniq!
8843 *
8844 * arr = [2, 5, 6, 556, 6, 6, 8, 9, 0, 123, 556]
8845 * arr.uniq #=> [2, 5, 6, 556, 8, 9, 0, 123]
8846 *
8847 * == Iterating over an \Array
8848 *
8849 * Like all classes that include the Enumerable module, class \Array has an each
8850 * method, which defines what elements should be iterated over and how. In
8851 * case of Array#each, all elements in +self+ are yielded to
8852 * the supplied block in sequence.
8853 *
8854 * Note that this operation leaves the array unchanged.
8855 *
8856 * arr = [1, 2, 3, 4, 5]
8857 * arr.each {|a| print a -= 10, " "}
8858 * # prints: -9 -8 -7 -6 -5
8859 * #=> [1, 2, 3, 4, 5]
8860 *
8861 * Another sometimes useful iterator is #reverse_each which will iterate over
8862 * the elements in the array in reverse order.
8863 *
8864 * words = %w[first second third fourth fifth sixth]
8865 * str = ""
8866 * words.reverse_each {|word| str += "#{word} "}
8867 * p str #=> "sixth fifth fourth third second first "
8868 *
8869 * The #map method can be used to create a new array based on the original
8870 * array, but with the values modified by the supplied block:
8871 *
8872 * arr.map {|a| 2*a} #=> [2, 4, 6, 8, 10]
8873 * arr #=> [1, 2, 3, 4, 5]
8874 * arr.map! {|a| a**2} #=> [1, 4, 9, 16, 25]
8875 * arr #=> [1, 4, 9, 16, 25]
8876 *
8877 *
8878 * == Selecting Items from an \Array
8879 *
8880 * Elements can be selected from an array according to criteria defined in a
8881 * block. The selection can happen in a destructive or a non-destructive
8882 * manner. While the destructive operations will modify the array they were
8883 * called on, the non-destructive methods usually return a new array with the
8884 * selected elements, but leave the original array unchanged.
8885 *
8886 * === Non-destructive Selection
8887 *
8888 * arr = [1, 2, 3, 4, 5, 6]
8889 * arr.select {|a| a > 3} #=> [4, 5, 6]
8890 * arr.reject {|a| a < 3} #=> [3, 4, 5, 6]
8891 * arr.drop_while {|a| a < 4} #=> [4, 5, 6]
8892 * arr #=> [1, 2, 3, 4, 5, 6]
8893 *
8894 * === Destructive Selection
8895 *
8896 * #select! and #reject! are the corresponding destructive methods to #select
8897 * and #reject
8898 *
8899 * Similar to #select vs. #reject, #delete_if and #keep_if have the exact
8900 * opposite result when supplied with the same block:
8901 *
8902 * arr.delete_if {|a| a < 4} #=> [4, 5, 6]
8903 * arr #=> [4, 5, 6]
8904 *
8905 * arr = [1, 2, 3, 4, 5, 6]
8906 * arr.keep_if {|a| a < 4} #=> [1, 2, 3]
8907 * arr #=> [1, 2, 3]
8908 *
8909 * == What's Here
8910 *
8911 * First, what's elsewhere. Class \Array:
8912 *
8913 * - Inherits from {class Object}[rdoc-ref:Object@Whats-Here].
8914 * - Includes {module Enumerable}[rdoc-ref:Enumerable@Whats-Here],
8915 * which provides dozens of additional methods.
8916 *
8917 * Here, class \Array provides methods that are useful for:
8918 *
8919 * - {Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array]
8920 * - {Querying}[rdoc-ref:Array@Methods+for+Querying]
8921 * - {Comparing}[rdoc-ref:Array@Methods+for+Comparing]
8922 * - {Fetching}[rdoc-ref:Array@Methods+for+Fetching]
8923 * - {Assigning}[rdoc-ref:Array@Methods+for+Assigning]
8924 * - {Deleting}[rdoc-ref:Array@Methods+for+Deleting]
8925 * - {Combining}[rdoc-ref:Array@Methods+for+Combining]
8926 * - {Iterating}[rdoc-ref:Array@Methods+for+Iterating]
8927 * - {Converting}[rdoc-ref:Array@Methods+for+Converting]
8928 * - {And more....}[rdoc-ref:Array@Other+Methods]
8929 *
8930 * === Methods for Creating an \Array
8931 *
8932 * - ::[]: Returns a new array populated with given objects.
8933 * - ::new: Returns a new array.
8934 * - ::try_convert: Returns a new array created from a given object.
8935 *
8936 * See also {Creating Arrays}[rdoc-ref:Array@Creating+Arrays].
8937 *
8938 * === Methods for Querying
8939 *
8940 * - #all?: Returns whether all elements meet a given criterion.
8941 * - #any?: Returns whether any element meets a given criterion.
8942 * - #count: Returns the count of elements that meet a given criterion.
8943 * - #empty?: Returns whether there are no elements.
8944 * - #find_index (aliased as #index): Returns the index of the first element that meets a given criterion.
8945 * - #hash: Returns the integer hash code.
8946 * - #include?: Returns whether any element <tt>==</tt> a given object.
8947 * - #length (aliased as #size): Returns the count of elements.
8948 * - #none?: Returns whether no element <tt>==</tt> a given object.
8949 * - #one?: Returns whether exactly one element <tt>==</tt> a given object.
8950 * - #rindex: Returns the index of the last element that meets a given criterion.
8951 *
8952 * === Methods for Comparing
8953 *
8954 * - #<=>: Returns -1, 0, or 1, as +self+ is less than, equal to, or greater than a given object.
8955 * - #==: Returns whether each element in +self+ is <tt>==</tt> to the corresponding element in a given object.
8956 * - #eql?: Returns whether each element in +self+ is <tt>eql?</tt> to the corresponding element in a given object.
8957
8958 * === Methods for Fetching
8959 *
8960 * These methods do not modify +self+.
8961 *
8962 * - #[] (aliased as #slice): Returns consecutive elements as determined by a given argument.
8963 * - #assoc: Returns the first element that is an array whose first element <tt>==</tt> a given object.
8964 * - #at: Returns the element at a given offset.
8965 * - #bsearch: Returns an element selected via a binary search as determined by a given block.
8966 * - #bsearch_index: Returns the index of an element selected via a binary search as determined by a given block.
8967 * - #compact: Returns an array containing all non-+nil+ elements.
8968 * - #dig: Returns the object in nested objects that is specified by a given index and additional arguments.
8969 * - #drop: Returns trailing elements as determined by a given index.
8970 * - #drop_while: Returns trailing elements as determined by a given block.
8971 * - #fetch: Returns the element at a given offset.
8972 * - #fetch_values: Returns elements at given offsets.
8973 * - #first: Returns one or more leading elements.
8974 * - #last: Returns one or more trailing elements.
8975 * - #max: Returns one or more maximum-valued elements, as determined by <tt>#<=></tt> or a given block.
8976 * - #min: Returns one or more minimum-valued elements, as determined by <tt>#<=></tt> or a given block.
8977 * - #minmax: Returns the minimum-valued and maximum-valued elements, as determined by <tt>#<=></tt> or a given block.
8978 * - #rassoc: Returns the first element that is an array whose second element <tt>==</tt> a given object.
8979 * - #reject: Returns an array containing elements not rejected by a given block.
8980 * - #reverse: Returns all elements in reverse order.
8981 * - #rotate: Returns all elements with some rotated from one end to the other.
8982 * - #sample: Returns one or more random elements.
8983 * - #select (aliased as #filter): Returns an array containing elements selected by a given block.
8984 * - #shuffle: Returns elements in a random order.
8985 * - #sort: Returns all elements in an order determined by <tt>#<=></tt> or a given block.
8986 * - #take: Returns leading elements as determined by a given index.
8987 * - #take_while: Returns leading elements as determined by a given block.
8988 * - #uniq: Returns an array containing non-duplicate elements.
8989 * - #values_at: Returns the elements at given offsets.
8990 *
8991 * === Methods for Assigning
8992 *
8993 * These methods add, replace, or reorder elements in +self+.
8994 *
8995 * - #<<: Appends an element.
8996 * - #[]=: Assigns specified elements with a given object.
8997 * - #concat: Appends all elements from given arrays.
8998 * - #fill: Replaces specified elements with specified objects.
8999 * - #flatten!: Replaces each nested array in +self+ with the elements from that array.
9000 * - #initialize_copy (aliased as #replace): Replaces the content of +self+ with the content of a given array.
9001 * - #insert: Inserts given objects at a given offset; does not replace elements.
9002 * - #push (aliased as #append): Appends elements.
9003 * - #reverse!: Replaces +self+ with its elements reversed.
9004 * - #rotate!: Replaces +self+ with its elements rotated.
9005 * - #shuffle!: Replaces +self+ with its elements in random order.
9006 * - #sort!: Replaces +self+ with its elements sorted, as determined by <tt>#<=></tt> or a given block.
9007 * - #sort_by!: Replaces +self+ with its elements sorted, as determined by a given block.
9008 * - #unshift (aliased as #prepend): Prepends leading elements.
9009 *
9010 * === Methods for Deleting
9011 *
9012 * Each of these methods removes elements from +self+:
9013 *
9014 * - #clear: Removes all elements.
9015 * - #compact!: Removes all +nil+ elements.
9016 * - #delete: Removes elements equal to a given object.
9017 * - #delete_at: Removes the element at a given offset.
9018 * - #delete_if: Removes elements specified by a given block.
9019 * - #keep_if: Removes elements not specified by a given block.
9020 * - #pop: Removes and returns the last element.
9021 * - #reject!: Removes elements specified by a given block.
9022 * - #select! (aliased as #filter!): Removes elements not specified by a given block.
9023 * - #shift: Removes and returns the first element.
9024 * - #slice!: Removes and returns a sequence of elements.
9025 * - #uniq!: Removes duplicates.
9026 *
9027 * === Methods for Combining
9028 *
9029 * - #&: Returns an array containing elements found both in +self+ and a given array.
9030 * - #+: Returns an array containing all elements of +self+ followed by all elements of a given array.
9031 * - #-: Returns an array containing all elements of +self+ that are not found in a given array.
9032 * - #|: Returns an array containing all element of +self+ and all elements of a given array, duplicates removed.
9033 * - #difference: Returns an array containing all elements of +self+ that are not found in any of the given arrays..
9034 * - #intersection: Returns an array containing elements found both in +self+ and in each given array.
9035 * - #product: Returns or yields all combinations of elements from +self+ and given arrays.
9036 * - #reverse: Returns an array containing all elements of +self+ in reverse order.
9037 * - #union: Returns an array containing all elements of +self+ and all elements of given arrays, duplicates removed.
9038 *
9039 * === Methods for Iterating
9040 *
9041 * - #combination: Calls a given block with combinations of elements of +self+; a combination does not use the same element more than once.
9042 * - #cycle: Calls a given block with each element, then does so again, for a specified number of times, or forever.
9043 * - #each: Passes each element to a given block.
9044 * - #each_index: Passes each element index to a given block.
9045 * - #permutation: Calls a given block with permutations of elements of +self+; a permutation does not use the same element more than once.
9046 * - #repeated_combination: Calls a given block with combinations of elements of +self+; a combination may use the same element more than once.
9047 * - #repeated_permutation: Calls a given block with permutations of elements of +self+; a permutation may use the same element more than once.
9048 * - #reverse_each: Passes each element, in reverse order, to a given block.
9049 *
9050 * === Methods for Converting
9051 *
9052 * - #collect (aliased as #map): Returns an array containing the block return-value for each element.
9053 * - #collect! (aliased as #map!): Replaces each element with a block return-value.
9054 * - #flatten: Returns an array that is a recursive flattening of +self+.
9055 * - #inspect (aliased as #to_s): Returns a new String containing the elements.
9056 * - #join: Returns a new String containing the elements joined by the field separator.
9057 * - #to_a: Returns +self+ or a new array containing all elements.
9058 * - #to_ary: Returns +self+.
9059 * - #to_h: Returns a new hash formed from the elements.
9060 * - #transpose: Transposes +self+, which must be an array of arrays.
9061 * - #zip: Returns a new array of arrays containing +self+ and given arrays.
9062 *
9063 * === Other Methods
9064 *
9065 * - #*: Returns one of the following:
9066 *
9067 * - With integer argument +n+, a new array that is the concatenation
9068 * of +n+ copies of +self+.
9069 * - With string argument +field_separator+, a new string that is equivalent to
9070 * <tt>join(field_separator)</tt>.
9071 *
9072 * - #pack: Packs the elements into a binary sequence.
9073 * - #sum: Returns a sum of elements according to either <tt>+</tt> or a given block.
9074 */
9075
9076void
9077Init_Array(void)
9078{
9079 fake_ary_flags = init_fake_ary_flags();
9080
9081 rb_cArray = rb_define_class("Array", rb_cObject);
9083
9084 rb_define_alloc_func(rb_cArray, empty_ary_alloc);
9085 rb_define_singleton_method(rb_cArray, "new", rb_ary_s_new, -1);
9086 rb_define_singleton_method(rb_cArray, "[]", rb_ary_s_create, -1);
9087 rb_define_singleton_method(rb_cArray, "try_convert", rb_ary_s_try_convert, 1);
9088 rb_define_method(rb_cArray, "initialize", rb_ary_initialize, -1);
9089 rb_define_method(rb_cArray, "initialize_copy", rb_ary_replace, 1);
9090
9091 rb_define_method(rb_cArray, "inspect", rb_ary_inspect, 0);
9092 rb_define_alias(rb_cArray, "to_s", "inspect");
9093 rb_define_method(rb_cArray, "to_a", rb_ary_to_a, 0);
9094 rb_define_method(rb_cArray, "to_h", rb_ary_to_h, 0);
9095 rb_define_method(rb_cArray, "to_ary", rb_ary_to_ary_m, 0);
9096
9097 rb_define_method(rb_cArray, "==", rb_ary_equal, 1);
9098 rb_define_method(rb_cArray, "eql?", rb_ary_eql, 1);
9099 rb_define_method(rb_cArray, "hash", rb_ary_hash, 0);
9100
9102 rb_define_method(rb_cArray, "[]=", rb_ary_aset, -1);
9103 rb_define_method(rb_cArray, "at", rb_ary_at, 1);
9104 rb_define_method(rb_cArray, "fetch", rb_ary_fetch, -1);
9105 rb_define_method(rb_cArray, "concat", rb_ary_concat_multi, -1);
9106 rb_define_method(rb_cArray, "union", rb_ary_union_multi, -1);
9107 rb_define_method(rb_cArray, "difference", rb_ary_difference_multi, -1);
9108 rb_define_method(rb_cArray, "intersection", rb_ary_intersection_multi, -1);
9109 rb_define_method(rb_cArray, "intersect?", rb_ary_intersect_p, 1);
9111 rb_define_method(rb_cArray, "push", rb_ary_push_m, -1);
9112 rb_define_alias(rb_cArray, "append", "push");
9113 rb_define_method(rb_cArray, "pop", rb_ary_pop_m, -1);
9114 rb_define_method(rb_cArray, "shift", rb_ary_shift_m, -1);
9115 rb_define_method(rb_cArray, "unshift", rb_ary_unshift_m, -1);
9116 rb_define_alias(rb_cArray, "prepend", "unshift");
9117 rb_define_method(rb_cArray, "insert", rb_ary_insert, -1);
9119 rb_define_method(rb_cArray, "each_index", rb_ary_each_index, 0);
9120 rb_define_method(rb_cArray, "reverse_each", rb_ary_reverse_each, 0);
9121 rb_define_method(rb_cArray, "length", rb_ary_length, 0);
9122 rb_define_method(rb_cArray, "size", rb_ary_length, 0);
9123 rb_define_method(rb_cArray, "empty?", rb_ary_empty_p, 0);
9124 rb_define_method(rb_cArray, "find", rb_ary_find, -1);
9125 rb_define_method(rb_cArray, "detect", rb_ary_find, -1);
9126 rb_define_method(rb_cArray, "rfind", rb_ary_rfind, -1);
9127 rb_define_method(rb_cArray, "find_index", rb_ary_index, -1);
9128 rb_define_method(rb_cArray, "index", rb_ary_index, -1);
9129 rb_define_method(rb_cArray, "rindex", rb_ary_rindex, -1);
9130 rb_define_method(rb_cArray, "join", rb_ary_join_m, -1);
9131 rb_define_method(rb_cArray, "reverse", rb_ary_reverse_m, 0);
9132 rb_define_method(rb_cArray, "reverse!", rb_ary_reverse_bang, 0);
9133 rb_define_method(rb_cArray, "rotate", rb_ary_rotate_m, -1);
9134 rb_define_method(rb_cArray, "rotate!", rb_ary_rotate_bang, -1);
9137 rb_define_method(rb_cArray, "sort_by!", rb_ary_sort_by_bang, 0);
9138 rb_define_method(rb_cArray, "collect", rb_ary_collect, 0);
9139 rb_define_method(rb_cArray, "collect!", rb_ary_collect_bang, 0);
9140 rb_define_method(rb_cArray, "map", rb_ary_collect, 0);
9141 rb_define_method(rb_cArray, "map!", rb_ary_collect_bang, 0);
9142 rb_define_method(rb_cArray, "select", rb_ary_select, 0);
9143 rb_define_method(rb_cArray, "select!", rb_ary_select_bang, 0);
9144 rb_define_method(rb_cArray, "filter", rb_ary_select, 0);
9145 rb_define_method(rb_cArray, "filter!", rb_ary_select_bang, 0);
9146 rb_define_method(rb_cArray, "keep_if", rb_ary_keep_if, 0);
9147 rb_define_method(rb_cArray, "values_at", rb_ary_values_at, -1);
9149 rb_define_method(rb_cArray, "delete_at", rb_ary_delete_at_m, 1);
9150 rb_define_method(rb_cArray, "delete_if", rb_ary_delete_if, 0);
9151 rb_define_method(rb_cArray, "reject", rb_ary_reject, 0);
9152 rb_define_method(rb_cArray, "reject!", rb_ary_reject_bang, 0);
9153 rb_define_method(rb_cArray, "zip", rb_ary_zip, -1);
9154 rb_define_method(rb_cArray, "transpose", rb_ary_transpose, 0);
9157 rb_define_method(rb_cArray, "fill", rb_ary_fill, -1);
9160
9161 rb_define_method(rb_cArray, "slice", rb_ary_aref, -1);
9162 rb_define_method(rb_cArray, "slice!", rb_ary_slice_bang, -1);
9163
9166
9168 rb_define_method(rb_cArray, "*", rb_ary_times, 1);
9169
9170 rb_define_method(rb_cArray, "-", rb_ary_diff, 1);
9171 rb_define_method(rb_cArray, "&", rb_ary_and, 1);
9172 rb_define_method(rb_cArray, "|", rb_ary_or, 1);
9173
9174 rb_define_method(rb_cArray, "max", rb_ary_max, -1);
9175 rb_define_method(rb_cArray, "min", rb_ary_min, -1);
9176 rb_define_method(rb_cArray, "minmax", rb_ary_minmax, 0);
9177
9178 rb_define_method(rb_cArray, "uniq", rb_ary_uniq, 0);
9179 rb_define_method(rb_cArray, "uniq!", rb_ary_uniq_bang, 0);
9180 rb_define_method(rb_cArray, "compact", rb_ary_compact, 0);
9181 rb_define_method(rb_cArray, "compact!", rb_ary_compact_bang, 0);
9182 rb_define_method(rb_cArray, "flatten", rb_ary_flatten, -1);
9183 rb_define_method(rb_cArray, "flatten!", rb_ary_flatten_bang, -1);
9184 rb_define_method(rb_cArray, "count", rb_ary_count, -1);
9185 rb_define_method(rb_cArray, "cycle", rb_ary_cycle, -1);
9186 rb_define_method(rb_cArray, "permutation", rb_ary_permutation, -1);
9187 rb_define_method(rb_cArray, "combination", rb_ary_combination, 1);
9188 rb_define_method(rb_cArray, "repeated_permutation", rb_ary_repeated_permutation, 1);
9189 rb_define_method(rb_cArray, "repeated_combination", rb_ary_repeated_combination, 1);
9190 rb_define_method(rb_cArray, "product", rb_ary_product, -1);
9191
9192 rb_define_method(rb_cArray, "take", rb_ary_take, 1);
9193 rb_define_method(rb_cArray, "take_while", rb_ary_take_while, 0);
9194 rb_define_method(rb_cArray, "drop", rb_ary_drop, 1);
9195 rb_define_method(rb_cArray, "drop_while", rb_ary_drop_while, 0);
9196 rb_define_method(rb_cArray, "bsearch", rb_ary_bsearch, 0);
9197 rb_define_method(rb_cArray, "bsearch_index", rb_ary_bsearch_index, 0);
9198 rb_define_method(rb_cArray, "any?", rb_ary_any_p, -1);
9199 rb_define_method(rb_cArray, "all?", rb_ary_all_p, -1);
9200 rb_define_method(rb_cArray, "none?", rb_ary_none_p, -1);
9201 rb_define_method(rb_cArray, "one?", rb_ary_one_p, -1);
9202 rb_define_method(rb_cArray, "dig", rb_ary_dig, -1);
9203 rb_define_method(rb_cArray, "sum", rb_ary_sum, -1);
9205
9206 rb_define_method(rb_cArray, "deconstruct", rb_ary_deconstruct, 0);
9207
9208 rb_cArray_empty_frozen = RB_OBJ_SET_SHAREABLE(rb_ary_freeze(rb_ary_new()));
9209 rb_vm_register_global_object(rb_cArray_empty_frozen);
9210}
9211
9212#include "array.rbinc"
#define RUBY_ASSERT_ALWAYS(expr,...)
A variant of RUBY_ASSERT that does not interface with RUBY_DEBUG.
Definition assert.h:199
#define RBIMPL_ASSERT_OR_ASSUME(...)
This is either RUBY_ASSERT or RBIMPL_ASSUME, depending on RUBY_DEBUG.
Definition assert.h:311
#define RUBY_ASSERT(...)
Asserts that the given expression is truthy if and only if RUBY_DEBUG is truthy.
Definition assert.h:219
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 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:399
#define NUM2DBL
Old name of rb_num2dbl.
Definition double.h:27
#define FL_SET
Old name of RB_FL_SET.
Definition fl_type.h: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:405
#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 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:406
void rb_category_warn(rb_warning_category_t category, const char *fmt,...)
Identical to rb_category_warning(), except it reports unless $VERBOSE is nil.
Definition error.c:474
void rb_iter_break(void)
Breaks from a block.
Definition vm.c:2416
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:2292
VALUE rb_obj_frozen_p(VALUE obj)
Same as RB_OBJ_FROZEN(), but returns Qtrue/Qfalse instead of #bool.
Definition object.c:1322
int rb_eql(VALUE lhs, VALUE rhs)
Checks for equality of the passed objects, in terms of Object#eql?.
Definition object.c:153
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:240
VALUE rb_inspect(VALUE obj)
Generates a human-readable textual representation of the given object.
Definition object.c:675
double rb_num2dbl(VALUE num)
Converts an instance of rb_cNumeric into C's double.
Definition object.c:3855
VALUE rb_equal(VALUE lhs, VALUE rhs)
This function is an optimised version of calling #==.
Definition object.c:140
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:912
VALUE rb_obj_freeze(VALUE obj)
Same as RB_OBJ_FREEZE(), but returns the given object.
Definition object.c:1315
VALUE rb_to_int(VALUE val)
Identical to rb_check_to_int(), except it raises in case of conversion mismatch.
Definition object.c:3347
#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
Encoding relates APIs.
VALUE rb_funcall(VALUE recv, ID mid, int n,...)
Calls a method.
Definition vm_eval.c:1148
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:1106
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:1199
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:1945
size_t rb_set_size(VALUE set)
Returns the number of elements in the set.
Definition set.c:2388
VALUE rb_set_clear(VALUE set)
Removes all entries from set.
Definition set.c:2376
bool rb_set_delete(VALUE set, VALUE element)
Removes the element from from set.
Definition set.c:2382
bool rb_set_add(VALUE set, VALUE element)
Adds element to set.
Definition set.c:2370
void rb_set_foreach(VALUE set, int(*func)(VALUE element, VALUE arg), VALUE arg)
Iterates over a set.
Definition set.c:2346
bool rb_set_lookup(VALUE set, VALUE element)
Whether the set contains the given element.
Definition set.c:2364
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:2358
#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:3525
#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:3904
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:4354
VALUE rb_str_buf_new(rb_len_t capa)
Allocates a "string buffer".
Definition string.c:1783
VALUE rb_check_string_type(VALUE obj)
Try converting an object to its stringised representation using its to_str method,...
Definition string.c:3072
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:1916
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:3715
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:1426
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:1448
VALUE rb_yield(VALUE val)
Yields the block.
Definition vm_eval.c:1403
#define RBIMPL_ATTR_MAYBE_UNUSED()
Wraps (or simulates) [[maybe_unused]]
#define MEMCPY(p1, p2, type, n)
Handy macro to call memcpy.
Definition memory.h:372
#define MEMZERO(p, type, n)
Handy macro to erase a region of memory.
Definition memory.h:360
#define RB_GC_GUARD(v)
Prevents premature destruction of local objects.
Definition memory.h:167
#define MEMMOVE(p1, p2, type, n)
Handy macro to call memmove.
Definition memory.h:384
VALUE rb_block_call(VALUE q, ID w, int e, const VALUE *r, type *t, VALUE y)
Call a method with a block.
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