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