Ruby: array.c Source File

Ruby 3.4.6p54 (2025-09-16 revision dbd83256b1cec76c69756ecb8758b9e1079833de)

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