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