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