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