1 /**********************************************************************
6 created at: Fri Aug 6 09:46:12 JST 1993
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
12 **********************************************************************/
14 #include "debug_counter.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"
28 #include "ruby/encoding.h"
30 #include "ruby/util.h"
38 #include "ruby_assert.h"
44 * 1: RARRAY_EMBED_FLAG
45 * The array is embedded (its contents follow the header, rather than
46 * being on a separately allocated buffer).
47 * 2: RARRAY_SHARED_FLAG (equal to ELTS_SHARED)
48 * The array is shared. The buffer this array points to is owned by
49 * another array (the shared root).
50 * 3-9: RARRAY_EMBED_LEN
51 * The length of the array when RARRAY_EMBED_FLAG is set.
52 * 12: RARRAY_SHARED_ROOT_FLAG
53 * The array is a shared root that does reference counting. The buffer
54 * this array points to is owned by this array but may be pointed to
56 * Note: Frozen arrays may be a shared root without this flag being
57 * set. Frozen arrays do not have reference counting because
58 * they cannot be modified. Not updating the reference count
59 * improves copy-on-write performance. Their reference count is
60 * assumed to be infinity.
61 * 14: RARRAY_PTR_IN_USE_FLAG
62 * The buffer of the array is in use. This is only used during
66 /* for OPTIMIZED_CMP: */
69 #define ARY_DEFAULT_SIZE 16
70 #define ARY_MAX_SIZE (LONG_MAX / (int)sizeof(VALUE))
71 #define SMALL_ARRAY_LEN 16
73 RBIMPL_ATTR_MAYBE_UNUSED()
75 should_be_T_ARRAY(VALUE ary
)
77 return RB_TYPE_P(ary
, T_ARRAY
);
80 #define ARY_HEAP_PTR(a) (RUBY_ASSERT(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.ptr)
81 #define ARY_HEAP_LEN(a) (RUBY_ASSERT(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.len)
82 #define ARY_HEAP_CAPA(a) (RUBY_ASSERT(!ARY_EMBED_P(a)), RUBY_ASSERT(!ARY_SHARED_ROOT_P(a)), \
83 RARRAY(a)->as.heap.aux.capa)
85 #define ARY_EMBED_PTR(a) (RUBY_ASSERT(ARY_EMBED_P(a)), RARRAY(a)->as.ary)
86 #define ARY_EMBED_LEN(a) \
87 (RUBY_ASSERT(ARY_EMBED_P(a)), \
88 (long)((RBASIC(a)->flags >> RARRAY_EMBED_LEN_SHIFT) & \
89 (RARRAY_EMBED_LEN_MASK >> RARRAY_EMBED_LEN_SHIFT)))
90 #define ARY_HEAP_SIZE(a) (RUBY_ASSERT(!ARY_EMBED_P(a)), RUBY_ASSERT(ARY_OWNS_HEAP_P(a)), ARY_CAPA(a) * sizeof(VALUE))
92 #define ARY_OWNS_HEAP_P(a) (RUBY_ASSERT(should_be_T_ARRAY((VALUE)(a))), \
93 !FL_TEST_RAW((a), RARRAY_SHARED_FLAG|RARRAY_EMBED_FLAG))
95 #define FL_SET_EMBED(a) do { \
96 RUBY_ASSERT(!ARY_SHARED_P(a)); \
97 FL_SET((a), RARRAY_EMBED_FLAG); \
101 #define FL_UNSET_EMBED(ary) FL_UNSET((ary), RARRAY_EMBED_FLAG|RARRAY_EMBED_LEN_MASK)
102 #define FL_SET_SHARED(ary) do { \
103 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
104 FL_SET((ary), RARRAY_SHARED_FLAG); \
106 #define FL_UNSET_SHARED(ary) FL_UNSET((ary), RARRAY_SHARED_FLAG)
108 #define ARY_SET_PTR(ary, p) do { \
109 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
110 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
111 RARRAY(ary)->as.heap.ptr = (p); \
113 #define ARY_SET_EMBED_LEN(ary, n) do { \
115 RUBY_ASSERT(ARY_EMBED_P(ary)); \
116 RBASIC(ary)->flags &= ~RARRAY_EMBED_LEN_MASK; \
117 RBASIC(ary)->flags |= (tmp_n) << RARRAY_EMBED_LEN_SHIFT; \
119 #define ARY_SET_HEAP_LEN(ary, n) do { \
120 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
121 RARRAY(ary)->as.heap.len = (n); \
123 #define ARY_SET_LEN(ary, n) do { \
124 if (ARY_EMBED_P(ary)) { \
125 ARY_SET_EMBED_LEN((ary), (n)); \
128 ARY_SET_HEAP_LEN((ary), (n)); \
130 RUBY_ASSERT(RARRAY_LEN(ary) == (n)); \
132 #define ARY_INCREASE_PTR(ary, n) do { \
133 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
134 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
135 RARRAY(ary)->as.heap.ptr += (n); \
137 #define ARY_INCREASE_LEN(ary, n) do { \
138 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
139 if (ARY_EMBED_P(ary)) { \
140 ARY_SET_EMBED_LEN((ary), RARRAY_LEN(ary)+(n)); \
143 RARRAY(ary)->as.heap.len += (n); \
147 #define ARY_CAPA(ary) (ARY_EMBED_P(ary) ? ary_embed_capa(ary) : \
148 ARY_SHARED_ROOT_P(ary) ? RARRAY_LEN(ary) : ARY_HEAP_CAPA(ary))
149 #define ARY_SET_CAPA(ary, n) do { \
150 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
151 RUBY_ASSERT(!ARY_SHARED_P(ary)); \
152 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
153 RARRAY(ary)->as.heap.aux.capa = (n); \
156 #define ARY_SHARED_ROOT_OCCUPIED(ary) (!OBJ_FROZEN(ary) && ARY_SHARED_ROOT_REFCNT(ary) == 1)
157 #define ARY_SET_SHARED_ROOT_REFCNT(ary, value) do { \
158 RUBY_ASSERT(ARY_SHARED_ROOT_P(ary)); \
159 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
160 RUBY_ASSERT((value) >= 0); \
161 RARRAY(ary)->as.heap.aux.capa = (value); \
163 #define FL_SET_SHARED_ROOT(ary) do { \
164 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
165 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
166 FL_SET((ary), RARRAY_SHARED_ROOT_FLAG); \
170 ARY_SET(VALUE a
, long i
, VALUE v
)
172 RUBY_ASSERT(!ARY_SHARED_P(a
));
173 RUBY_ASSERT(!OBJ_FROZEN(a
));
175 RARRAY_ASET(a
, i
, v
);
180 ary_embed_capa(VALUE ary
)
182 size_t size
= rb_gc_obj_slot_size(ary
) - offsetof(struct RArray
, as
.ary
);
183 RUBY_ASSERT(size
% sizeof(VALUE
) == 0);
184 return size
/ sizeof(VALUE
);
188 ary_embed_size(long capa
)
190 return offsetof(struct RArray
, as
.ary
) + (sizeof(VALUE
) * capa
);
194 ary_embeddable_p(long capa
)
196 return rb_gc_size_allocatable_p(ary_embed_size(capa
));
200 rb_ary_embeddable_p(VALUE ary
)
202 /* An array cannot be turned embeddable when the array is:
203 * - Shared root: other objects may point to the buffer of this array
204 * so we cannot make it embedded.
205 * - Frozen: this array may also be a shared root without the shared root
207 * - Shared: we don't want to re-embed an array that points to a shared
208 * root (to save memory).
210 return !(ARY_SHARED_ROOT_P(ary
) || OBJ_FROZEN(ary
) || ARY_SHARED_P(ary
));
214 rb_ary_size_as_embedded(VALUE ary
)
218 if (ARY_EMBED_P(ary
)) {
219 real_size
= ary_embed_size(ARY_EMBED_LEN(ary
));
221 else if (rb_ary_embeddable_p(ary
)) {
222 real_size
= ary_embed_size(ARY_HEAP_CAPA(ary
));
225 real_size
= sizeof(struct RArray
);
232 #define ary_verify(ary) ary_verify_(ary, __FILE__, __LINE__)
235 ary_verify_(VALUE ary
, const char *file
, int line
)
237 RUBY_ASSERT(RB_TYPE_P(ary
, T_ARRAY
));
239 if (ARY_SHARED_P(ary
)) {
240 VALUE root
= ARY_SHARED_ROOT(ary
);
241 const VALUE
*ptr
= ARY_HEAP_PTR(ary
);
242 const VALUE
*root_ptr
= RARRAY_CONST_PTR(root
);
243 long len
= ARY_HEAP_LEN(ary
), root_len
= RARRAY_LEN(root
);
244 RUBY_ASSERT(ARY_SHARED_ROOT_P(root
) || OBJ_FROZEN(root
));
245 RUBY_ASSERT(root_ptr
<= ptr
&& ptr
+ len
<= root_ptr
+ root_len
);
248 else if (ARY_EMBED_P(ary
)) {
249 RUBY_ASSERT(!ARY_SHARED_P(ary
));
250 RUBY_ASSERT(RARRAY_LEN(ary
) <= ary_embed_capa(ary
));
253 const VALUE
*ptr
= RARRAY_CONST_PTR(ary
);
254 long i
, len
= RARRAY_LEN(ary
);
256 if (len
> 1) len
= 1; /* check only HEAD */
257 for (i
=0; i
<len
; i
++) {
258 v
= ptr
[i
]; /* access check */
267 rb_ary_verify(VALUE ary
)
272 #define ary_verify(ary) ((void)0)
276 rb_ary_ptr_use_start(VALUE ary
)
279 FL_SET_RAW(ary
, RARRAY_PTR_IN_USE_FLAG
);
281 return (VALUE
*)RARRAY_CONST_PTR(ary
);
285 rb_ary_ptr_use_end(VALUE ary
)
288 FL_UNSET_RAW(ary
, RARRAY_PTR_IN_USE_FLAG
);
293 rb_mem_clear(VALUE
*mem
, long size
)
301 ary_mem_clear(VALUE ary
, long beg
, long size
)
303 RARRAY_PTR_USE(ary
, ptr
, {
304 rb_mem_clear(ptr
+ beg
, size
);
309 memfill(register VALUE
*mem
, register long size
, register VALUE val
)
317 ary_memfill(VALUE ary
, long beg
, long size
, VALUE val
)
319 RARRAY_PTR_USE(ary
, ptr
, {
320 memfill(ptr
+ beg
, size
, val
);
321 RB_OBJ_WRITTEN(ary
, Qundef
, val
);
326 ary_memcpy0(VALUE ary
, long beg
, long argc
, const VALUE
*argv
, VALUE buff_owner_ary
)
328 RUBY_ASSERT(!ARY_SHARED_P(buff_owner_ary
));
330 if (argc
> (int)(128/sizeof(VALUE
)) /* is magic number (cache line size) */) {
331 rb_gc_writebarrier_remember(buff_owner_ary
);
332 RARRAY_PTR_USE(ary
, ptr
, {
333 MEMCPY(ptr
+beg
, argv
, VALUE
, argc
);
338 RARRAY_PTR_USE(ary
, ptr
, {
339 for (i
=0; i
<argc
; i
++) {
340 RB_OBJ_WRITE(buff_owner_ary
, &ptr
[i
+beg
], argv
[i
]);
347 ary_memcpy(VALUE ary
, long beg
, long argc
, const VALUE
*argv
)
349 ary_memcpy0(ary
, beg
, argc
, argv
, ary
);
353 ary_heap_alloc_buffer(size_t capa
)
355 return ALLOC_N(VALUE
, capa
);
359 ary_heap_free_ptr(VALUE ary
, const VALUE
*ptr
, long size
)
361 ruby_sized_xfree((void *)ptr
, size
);
365 ary_heap_free(VALUE ary
)
367 ary_heap_free_ptr(ary
, ARY_HEAP_PTR(ary
), ARY_HEAP_SIZE(ary
));
371 ary_heap_realloc(VALUE ary
, size_t new_capa
)
373 SIZED_REALLOC_N(RARRAY(ary
)->as
.heap
.ptr
, VALUE
, new_capa
, ARY_HEAP_CAPA(ary
));
380 rb_ary_make_embedded(VALUE ary
)
382 RUBY_ASSERT(rb_ary_embeddable_p(ary
));
383 if (!ARY_EMBED_P(ary
)) {
384 const VALUE
*buf
= ARY_HEAP_PTR(ary
);
385 long len
= ARY_HEAP_LEN(ary
);
388 ARY_SET_EMBED_LEN(ary
, len
);
390 MEMCPY((void *)ARY_EMBED_PTR(ary
), (void *)buf
, VALUE
, len
);
392 ary_heap_free_ptr(ary
, buf
, len
* sizeof(VALUE
));
397 ary_resize_capa(VALUE ary
, long capacity
)
399 RUBY_ASSERT(RARRAY_LEN(ary
) <= capacity
);
400 RUBY_ASSERT(!OBJ_FROZEN(ary
));
401 RUBY_ASSERT(!ARY_SHARED_P(ary
));
403 if (capacity
> ary_embed_capa(ary
)) {
404 size_t new_capa
= capacity
;
405 if (ARY_EMBED_P(ary
)) {
406 long len
= ARY_EMBED_LEN(ary
);
407 VALUE
*ptr
= ary_heap_alloc_buffer(capacity
);
409 MEMCPY(ptr
, ARY_EMBED_PTR(ary
), VALUE
, len
);
411 ARY_SET_PTR(ary
, ptr
);
412 ARY_SET_HEAP_LEN(ary
, len
);
415 new_capa
= ary_heap_realloc(ary
, capacity
);
417 ARY_SET_CAPA(ary
, new_capa
);
420 if (!ARY_EMBED_P(ary
)) {
421 long len
= ARY_HEAP_LEN(ary
);
422 long old_capa
= ARY_HEAP_CAPA(ary
);
423 const VALUE
*ptr
= ARY_HEAP_PTR(ary
);
425 if (len
> capacity
) len
= capacity
;
426 MEMCPY((VALUE
*)RARRAY(ary
)->as
.ary
, ptr
, VALUE
, len
);
427 ary_heap_free_ptr(ary
, ptr
, old_capa
);
430 ARY_SET_LEN(ary
, len
);
438 ary_shrink_capa(VALUE ary
)
440 long capacity
= ARY_HEAP_LEN(ary
);
441 long old_capa
= ARY_HEAP_CAPA(ary
);
442 RUBY_ASSERT(!ARY_SHARED_P(ary
));
443 RUBY_ASSERT(old_capa
>= capacity
);
444 if (old_capa
> capacity
) ary_heap_realloc(ary
, capacity
);
450 ary_double_capa(VALUE ary
, long min
)
452 long new_capa
= ARY_CAPA(ary
) / 2;
454 if (new_capa
< ARY_DEFAULT_SIZE
) {
455 new_capa
= ARY_DEFAULT_SIZE
;
457 if (new_capa
>= ARY_MAX_SIZE
- min
) {
458 new_capa
= (ARY_MAX_SIZE
- min
) / 2;
461 ary_resize_capa(ary
, new_capa
);
467 rb_ary_decrement_share(VALUE shared_root
)
469 if (!OBJ_FROZEN(shared_root
)) {
470 long num
= ARY_SHARED_ROOT_REFCNT(shared_root
);
471 ARY_SET_SHARED_ROOT_REFCNT(shared_root
, num
- 1);
476 rb_ary_unshare(VALUE ary
)
478 VALUE shared_root
= ARY_SHARED_ROOT(ary
);
479 rb_ary_decrement_share(shared_root
);
480 FL_UNSET_SHARED(ary
);
484 rb_ary_reset(VALUE ary
)
486 if (ARY_OWNS_HEAP_P(ary
)) {
489 else if (ARY_SHARED_P(ary
)) {
494 ARY_SET_EMBED_LEN(ary
, 0);
498 rb_ary_increment_share(VALUE shared_root
)
500 if (!OBJ_FROZEN(shared_root
)) {
501 long num
= ARY_SHARED_ROOT_REFCNT(shared_root
);
502 RUBY_ASSERT(num
>= 0);
503 ARY_SET_SHARED_ROOT_REFCNT(shared_root
, num
+ 1);
509 rb_ary_set_shared(VALUE ary
, VALUE shared_root
)
511 RUBY_ASSERT(!ARY_EMBED_P(ary
));
512 RUBY_ASSERT(!OBJ_FROZEN(ary
));
513 RUBY_ASSERT(ARY_SHARED_ROOT_P(shared_root
) || OBJ_FROZEN(shared_root
));
515 rb_ary_increment_share(shared_root
);
517 RB_OBJ_WRITE(ary
, &RARRAY(ary
)->as
.heap
.aux
.shared_root
, shared_root
);
519 RB_DEBUG_COUNTER_INC(obj_ary_shared_create
);
523 rb_ary_modify_check(VALUE ary
)
525 rb_check_frozen(ary
);
530 rb_ary_cancel_sharing(VALUE ary
)
532 if (ARY_SHARED_P(ary
)) {
533 long shared_len
, len
= RARRAY_LEN(ary
);
534 VALUE shared_root
= ARY_SHARED_ROOT(ary
);
536 ary_verify(shared_root
);
538 if (len
<= ary_embed_capa(ary
)) {
539 const VALUE
*ptr
= ARY_HEAP_PTR(ary
);
540 FL_UNSET_SHARED(ary
);
542 MEMCPY((VALUE
*)ARY_EMBED_PTR(ary
), ptr
, VALUE
, len
);
543 rb_ary_decrement_share(shared_root
);
544 ARY_SET_EMBED_LEN(ary
, len
);
546 else if (ARY_SHARED_ROOT_OCCUPIED(shared_root
) && len
> ((shared_len
= RARRAY_LEN(shared_root
))>>1)) {
547 long shift
= RARRAY_CONST_PTR(ary
) - RARRAY_CONST_PTR(shared_root
);
548 FL_UNSET_SHARED(ary
);
549 ARY_SET_PTR(ary
, RARRAY_CONST_PTR(shared_root
));
550 ARY_SET_CAPA(ary
, shared_len
);
551 RARRAY_PTR_USE(ary
, ptr
, {
552 MEMMOVE(ptr
, ptr
+shift
, VALUE
, len
);
554 FL_SET_EMBED(shared_root
);
555 rb_ary_decrement_share(shared_root
);
558 VALUE
*ptr
= ary_heap_alloc_buffer(len
);
559 MEMCPY(ptr
, ARY_HEAP_PTR(ary
), VALUE
, len
);
561 ARY_SET_CAPA(ary
, len
);
562 ARY_SET_PTR(ary
, ptr
);
565 rb_gc_writebarrier_remember(ary
);
571 rb_ary_modify(VALUE ary
)
573 rb_ary_modify_check(ary
);
574 rb_ary_cancel_sharing(ary
);
578 ary_ensure_room_for_push(VALUE ary
, long add_len
)
580 long old_len
= RARRAY_LEN(ary
);
581 long new_len
= old_len
+ add_len
;
584 if (old_len
> ARY_MAX_SIZE
- add_len
) {
585 rb_raise(rb_eIndexError
, "index %ld too big", new_len
);
587 if (ARY_SHARED_P(ary
)) {
588 if (new_len
> ary_embed_capa(ary
)) {
589 VALUE shared_root
= ARY_SHARED_ROOT(ary
);
590 if (ARY_SHARED_ROOT_OCCUPIED(shared_root
)) {
591 if (ARY_HEAP_PTR(ary
) - RARRAY_CONST_PTR(shared_root
) + new_len
<= RARRAY_LEN(shared_root
)) {
592 rb_ary_modify_check(ary
);
595 ary_verify(shared_root
);
599 /* if array is shared, then it is likely it participate in push/shift pattern */
601 capa
= ARY_CAPA(ary
);
602 if (new_len
> capa
- (capa
>> 6)) {
603 ary_double_capa(ary
, new_len
);
614 rb_ary_modify_check(ary
);
616 capa
= ARY_CAPA(ary
);
617 if (new_len
> capa
) {
618 ary_double_capa(ary
, new_len
);
627 * array.freeze -> self
629 * Freezes +self+; returns +self+:
632 * a.frozen? # => false
634 * a.frozen? # => true
636 * An attempt to modify a frozen +Array+ raises FrozenError.
640 rb_ary_freeze(VALUE ary
)
642 return rb_obj_freeze(ary
);
645 /* This can be used to take a snapshot of an array (with
646 e.g. rb_ary_replace) and check later whether the array has been
647 modified from the snapshot. The snapshot is cheap, though if
648 something does modify the array it will pay the cost of copying
649 it. If Array#pop or Array#shift has been called, the array will
650 be still shared with the snapshot, but the array length will
653 rb_ary_shared_with_p(VALUE ary1
, VALUE ary2
)
655 if (!ARY_EMBED_P(ary1
) && ARY_SHARED_P(ary1
) &&
656 !ARY_EMBED_P(ary2
) && ARY_SHARED_P(ary2
) &&
657 ARY_SHARED_ROOT(ary1
) == ARY_SHARED_ROOT(ary2
) &&
658 ARY_HEAP_LEN(ary1
) == ARY_HEAP_LEN(ary2
)) {
665 ary_alloc_embed(VALUE klass
, long capa
)
667 size_t size
= ary_embed_size(capa
);
668 RUBY_ASSERT(rb_gc_size_allocatable_p(size
));
669 NEWOBJ_OF(ary
, struct RArray
, klass
,
670 T_ARRAY
| RARRAY_EMBED_FLAG
| (RGENGC_WB_PROTECTED_ARRAY
? FL_WB_PROTECTED
: 0),
673 * FL_SET_EMBED((VALUE)ary);
674 * ARY_SET_EMBED_LEN((VALUE)ary, 0);
680 ary_alloc_heap(VALUE klass
)
682 NEWOBJ_OF(ary
, struct RArray
, klass
,
683 T_ARRAY
| (RGENGC_WB_PROTECTED_ARRAY
? FL_WB_PROTECTED
: 0),
684 sizeof(struct RArray
), 0);
689 empty_ary_alloc(VALUE klass
)
691 RUBY_DTRACE_CREATE_HOOK(ARRAY
, 0);
692 return ary_alloc_embed(klass
, 0);
696 ary_new(VALUE klass
, long capa
)
701 rb_raise(rb_eArgError
, "negative array size (or size too big)");
703 if (capa
> ARY_MAX_SIZE
) {
704 rb_raise(rb_eArgError
, "array size too big");
707 RUBY_DTRACE_CREATE_HOOK(ARRAY
, capa
);
709 if (ary_embeddable_p(capa
)) {
710 ary
= ary_alloc_embed(klass
, capa
);
713 ary
= ary_alloc_heap(klass
);
714 ARY_SET_CAPA(ary
, capa
);
715 RUBY_ASSERT(!ARY_EMBED_P(ary
));
717 ARY_SET_PTR(ary
, ary_heap_alloc_buffer(capa
));
718 ARY_SET_HEAP_LEN(ary
, 0);
725 rb_ary_new_capa(long capa
)
727 return ary_new(rb_cArray
, capa
);
733 return rb_ary_new_capa(0);
737 (rb_ary_new_from_args
)(long n
, ...)
743 ary
= rb_ary_new2(n
);
746 for (i
=0; i
<n
; i
++) {
747 ARY_SET(ary
, i
, va_arg(ar
, VALUE
));
756 rb_ary_tmp_new_from_values(VALUE klass
, long n
, const VALUE
*elts
)
760 ary
= ary_new(klass
, n
);
762 ary_memcpy(ary
, 0, n
, elts
);
770 rb_ary_new_from_values(long n
, const VALUE
*elts
)
772 return rb_ary_tmp_new_from_values(rb_cArray
, n
, elts
);
776 ec_ary_alloc_embed(rb_execution_context_t
*ec
, VALUE klass
, long capa
)
778 size_t size
= ary_embed_size(capa
);
779 RUBY_ASSERT(rb_gc_size_allocatable_p(size
));
780 NEWOBJ_OF(ary
, struct RArray
, klass
,
781 T_ARRAY
| RARRAY_EMBED_FLAG
| (RGENGC_WB_PROTECTED_ARRAY
? FL_WB_PROTECTED
: 0),
784 * FL_SET_EMBED((VALUE)ary);
785 * ARY_SET_EMBED_LEN((VALUE)ary, 0);
791 ec_ary_alloc_heap(rb_execution_context_t
*ec
, VALUE klass
)
793 NEWOBJ_OF(ary
, struct RArray
, klass
,
794 T_ARRAY
| (RGENGC_WB_PROTECTED_ARRAY
? FL_WB_PROTECTED
: 0),
795 sizeof(struct RArray
), ec
);
800 ec_ary_new(rb_execution_context_t
*ec
, VALUE klass
, long capa
)
805 rb_raise(rb_eArgError
, "negative array size (or size too big)");
807 if (capa
> ARY_MAX_SIZE
) {
808 rb_raise(rb_eArgError
, "array size too big");
811 RUBY_DTRACE_CREATE_HOOK(ARRAY
, capa
);
813 if (ary_embeddable_p(capa
)) {
814 ary
= ec_ary_alloc_embed(ec
, klass
, capa
);
817 ary
= ec_ary_alloc_heap(ec
, klass
);
818 ARY_SET_CAPA(ary
, capa
);
819 RUBY_ASSERT(!ARY_EMBED_P(ary
));
821 ARY_SET_PTR(ary
, ary_heap_alloc_buffer(capa
));
822 ARY_SET_HEAP_LEN(ary
, 0);
829 rb_ec_ary_new_from_values(rb_execution_context_t
*ec
, long n
, const VALUE
*elts
)
833 ary
= ec_ary_new(ec
, rb_cArray
, n
);
835 ary_memcpy(ary
, 0, n
, elts
);
843 rb_ary_hidden_new(long capa
)
845 VALUE ary
= ary_new(0, capa
);
850 rb_ary_hidden_new_fill(long capa
)
852 VALUE ary
= rb_ary_hidden_new(capa
);
853 ary_memfill(ary
, 0, capa
, Qnil
);
854 ARY_SET_LEN(ary
, capa
);
859 rb_ary_free(VALUE ary
)
861 if (ARY_OWNS_HEAP_P(ary
)) {
862 if (USE_DEBUG_COUNTER
&&
863 !ARY_SHARED_ROOT_P(ary
) &&
864 ARY_HEAP_CAPA(ary
) > RARRAY_LEN(ary
)) {
865 RB_DEBUG_COUNTER_INC(obj_ary_extracapa
);
868 RB_DEBUG_COUNTER_INC(obj_ary_ptr
);
872 RB_DEBUG_COUNTER_INC(obj_ary_embed
);
875 if (ARY_SHARED_P(ary
)) {
876 RB_DEBUG_COUNTER_INC(obj_ary_shared
);
878 if (ARY_SHARED_ROOT_P(ary
) && ARY_SHARED_ROOT_OCCUPIED(ary
)) {
879 RB_DEBUG_COUNTER_INC(obj_ary_shared_root_occupied
);
884 rb_ary_memsize(VALUE ary
)
886 if (ARY_OWNS_HEAP_P(ary
)) {
887 return ARY_CAPA(ary
) * sizeof(VALUE
);
895 ary_make_shared(VALUE ary
)
899 if (ARY_SHARED_P(ary
)) {
900 return ARY_SHARED_ROOT(ary
);
902 else if (ARY_SHARED_ROOT_P(ary
)) {
905 else if (OBJ_FROZEN(ary
)) {
906 if (!ARY_EMBED_P(ary
)) {
907 ary_shrink_capa(ary
);
912 long capa
= ARY_CAPA(ary
);
913 long len
= RARRAY_LEN(ary
);
915 /* Shared roots cannot be embedded because the reference count
916 * (refcnt) is stored in as.heap.aux.capa. */
917 VALUE shared
= ary_alloc_heap(0);
918 FL_SET_SHARED_ROOT(shared
);
920 if (ARY_EMBED_P(ary
)) {
921 VALUE
*ptr
= ary_heap_alloc_buffer(capa
);
922 ARY_SET_PTR(shared
, ptr
);
923 ary_memcpy(shared
, 0, len
, RARRAY_CONST_PTR(ary
));
926 ARY_SET_HEAP_LEN(ary
, len
);
927 ARY_SET_PTR(ary
, ptr
);
930 ARY_SET_PTR(shared
, RARRAY_CONST_PTR(ary
));
933 ARY_SET_LEN(shared
, capa
);
934 ary_mem_clear(shared
, len
, capa
- len
);
935 rb_ary_set_shared(ary
, shared
);
945 ary_make_substitution(VALUE ary
)
947 long len
= RARRAY_LEN(ary
);
949 if (ary_embeddable_p(len
)) {
950 VALUE subst
= rb_ary_new_capa(len
);
951 RUBY_ASSERT(ARY_EMBED_P(subst
));
953 ary_memcpy(subst
, 0, len
, RARRAY_CONST_PTR(ary
));
954 ARY_SET_EMBED_LEN(subst
, len
);
958 return rb_ary_increment_share(ary_make_shared(ary
));
963 rb_assoc_new(VALUE car
, VALUE cdr
)
965 return rb_ary_new3(2, car
, cdr
);
969 rb_to_array_type(VALUE ary
)
971 return rb_convert_type_with_id(ary
, T_ARRAY
, "Array", idTo_ary
);
973 #define to_ary rb_to_array_type
976 rb_check_array_type(VALUE ary
)
978 return rb_check_convert_type_with_id(ary
, T_ARRAY
, "Array", idTo_ary
);
982 rb_check_to_array(VALUE ary
)
984 return rb_check_convert_type_with_id(ary
, T_ARRAY
, "Array", idTo_a
);
988 rb_to_array(VALUE ary
)
990 return rb_convert_type_with_id(ary
, T_ARRAY
, "Array", idTo_a
);
995 * Array.try_convert(object) -> object, new_array, or nil
997 * If +object+ is an +Array+ object, returns +object+.
999 * Otherwise if +object+ responds to <tt>:to_ary</tt>,
1000 * calls <tt>object.to_ary</tt> and returns the result.
1002 * Returns +nil+ if +object+ does not respond to <tt>:to_ary</tt>
1004 * Raises an exception unless <tt>object.to_ary</tt> returns an +Array+ object.
1008 rb_ary_s_try_convert(VALUE dummy
, VALUE ary
)
1010 return rb_check_array_type(ary
);
1015 rb_ary_s_new(int argc
, VALUE
*argv
, VALUE klass
)
1019 if (klass
== rb_cArray
) {
1021 if (argc
> 0 && FIXNUM_P(argv
[0])) {
1022 size
= FIX2LONG(argv
[0]);
1023 if (size
< 0) size
= 0;
1026 ary
= ary_new(klass
, size
);
1028 rb_obj_call_init_kw(ary
, argc
, argv
, RB_PASS_CALLED_KEYWORDS
);
1031 ary
= rb_class_new_instance_pass_kw(argc
, argv
, klass
);
1039 * Array.new -> new_empty_array
1040 * Array.new(array) -> new_array
1041 * Array.new(size) -> new_array
1042 * Array.new(size, default_value) -> new_array
1043 * Array.new(size) {|index| ... } -> new_array
1045 * Returns a new +Array+.
1047 * With no block and no arguments, returns a new empty +Array+ object.
1049 * With no block and a single +Array+ argument +array+,
1050 * returns a new +Array+ formed from +array+:
1052 * a = Array.new([:foo, 'bar', 2])
1053 * a.class # => Array
1054 * a # => [:foo, "bar", 2]
1056 * With no block and a single Integer argument +size+,
1057 * returns a new +Array+ of the given size
1058 * whose elements are all +nil+:
1061 * a # => [nil, nil, nil]
1063 * With no block and arguments +size+ and +default_value+,
1064 * returns an +Array+ of the given size;
1065 * each element is that same +default_value+:
1067 * a = Array.new(3, 'x')
1068 * a # => ['x', 'x', 'x']
1070 * With a block and argument +size+,
1071 * returns an +Array+ of the given size;
1072 * the block is called with each successive integer +index+;
1073 * the element for that +index+ is the return value from the block:
1075 * a = Array.new(3) {|index| "Element #{index}" }
1076 * a # => ["Element 0", "Element 1", "Element 2"]
1078 * Raises ArgumentError if +size+ is negative.
1080 * With a block and no argument,
1081 * or a single argument +0+,
1082 * ignores the block and returns a new empty +Array+.
1086 rb_ary_initialize(int argc
, VALUE
*argv
, VALUE ary
)
1094 RUBY_ASSERT(ARY_EMBED_P(ary
));
1095 RUBY_ASSERT(ARY_EMBED_LEN(ary
) == 0);
1096 if (rb_block_given_p()) {
1097 rb_warning("given block not used");
1101 rb_scan_args(argc
, argv
, "02", &size
, &val
);
1102 if (argc
== 1 && !FIXNUM_P(size
)) {
1103 val
= rb_check_array_type(size
);
1105 rb_ary_replace(ary
, val
);
1110 len
= NUM2LONG(size
);
1111 /* NUM2LONG() may call size.to_int, ary can be frozen, modified, etc */
1113 rb_raise(rb_eArgError
, "negative array size");
1115 if (len
> ARY_MAX_SIZE
) {
1116 rb_raise(rb_eArgError
, "array size too big");
1118 /* recheck after argument conversion */
1120 ary_resize_capa(ary
, len
);
1121 if (rb_block_given_p()) {
1125 rb_warn("block supersedes default value argument");
1127 for (i
=0; i
<len
; i
++) {
1128 rb_ary_store(ary
, i
, rb_yield(LONG2NUM(i
)));
1129 ARY_SET_LEN(ary
, i
+ 1);
1133 ary_memfill(ary
, 0, len
, val
);
1134 ARY_SET_LEN(ary
, len
);
1140 * Returns a new array populated with the given objects.
1142 * Array.[]( 1, 'a', /^A/) # => [1, "a", /^A/]
1143 * Array[ 1, 'a', /^A/ ] # => [1, "a", /^A/]
1144 * [ 1, 'a', /^A/ ] # => [1, "a", /^A/]
1148 rb_ary_s_create(int argc
, VALUE
*argv
, VALUE klass
)
1150 VALUE ary
= ary_new(klass
, argc
);
1151 if (argc
> 0 && argv
) {
1152 ary_memcpy(ary
, 0, argc
, argv
);
1153 ARY_SET_LEN(ary
, argc
);
1160 rb_ary_store(VALUE ary
, long idx
, VALUE val
)
1162 long len
= RARRAY_LEN(ary
);
1167 rb_raise(rb_eIndexError
, "index %ld too small for array; minimum: %ld",
1171 else if (idx
>= ARY_MAX_SIZE
) {
1172 rb_raise(rb_eIndexError
, "index %ld too big", idx
);
1176 if (idx
>= ARY_CAPA(ary
)) {
1177 ary_double_capa(ary
, idx
);
1180 ary_mem_clear(ary
, len
, idx
- len
+ 1);
1184 ARY_SET_LEN(ary
, idx
+ 1);
1186 ARY_SET(ary
, idx
, val
);
1190 ary_make_partial(VALUE ary
, VALUE klass
, long offset
, long len
)
1192 RUBY_ASSERT(offset
>= 0);
1193 RUBY_ASSERT(len
>= 0);
1194 RUBY_ASSERT(offset
+len
<= RARRAY_LEN(ary
));
1196 VALUE result
= ary_alloc_heap(klass
);
1197 size_t embed_capa
= ary_embed_capa(result
);
1198 if ((size_t)len
<= embed_capa
) {
1199 FL_SET_EMBED(result
);
1200 ary_memcpy(result
, 0, len
, RARRAY_CONST_PTR(ary
) + offset
);
1201 ARY_SET_EMBED_LEN(result
, len
);
1204 VALUE shared
= ary_make_shared(ary
);
1206 /* The ary_make_shared call may allocate, which can trigger a GC
1207 * compaction. This can cause the array to be embedded because it has
1209 FL_UNSET_EMBED(result
);
1211 ARY_SET_PTR(result
, RARRAY_CONST_PTR(ary
));
1212 ARY_SET_LEN(result
, RARRAY_LEN(ary
));
1213 rb_ary_set_shared(result
, shared
);
1215 ARY_INCREASE_PTR(result
, offset
);
1216 ARY_SET_LEN(result
, len
);
1226 ary_make_partial_step(VALUE ary
, VALUE klass
, long offset
, long len
, long step
)
1228 RUBY_ASSERT(offset
>= 0);
1229 RUBY_ASSERT(len
>= 0);
1230 RUBY_ASSERT(offset
+len
<= RARRAY_LEN(ary
));
1231 RUBY_ASSERT(step
!= 0);
1233 const long orig_len
= len
;
1235 if (step
> 0 && step
>= len
) {
1236 VALUE result
= ary_new(klass
, 1);
1237 VALUE
*ptr
= (VALUE
*)ARY_EMBED_PTR(result
);
1238 const VALUE
*values
= RARRAY_CONST_PTR(ary
);
1240 RB_OBJ_WRITE(result
, ptr
, values
[offset
]);
1241 ARY_SET_EMBED_LEN(result
, 1);
1244 else if (step
< 0 && step
< -len
) {
1248 long ustep
= (step
< 0) ? -step
: step
;
1249 len
= roomof(len
, ustep
);
1252 long j
= offset
+ ((step
> 0) ? 0 : (orig_len
- 1));
1254 VALUE result
= ary_new(klass
, len
);
1255 if (ARY_EMBED_P(result
)) {
1256 VALUE
*ptr
= (VALUE
*)ARY_EMBED_PTR(result
);
1257 const VALUE
*values
= RARRAY_CONST_PTR(ary
);
1259 for (i
= 0; i
< len
; ++i
) {
1260 RB_OBJ_WRITE(result
, ptr
+i
, values
[j
]);
1263 ARY_SET_EMBED_LEN(result
, len
);
1266 const VALUE
*values
= RARRAY_CONST_PTR(ary
);
1268 RARRAY_PTR_USE(result
, ptr
, {
1269 for (i
= 0; i
< len
; ++i
) {
1270 RB_OBJ_WRITE(result
, ptr
+i
, values
[j
]);
1274 ARY_SET_LEN(result
, len
);
1281 ary_make_shared_copy(VALUE ary
)
1283 return ary_make_partial(ary
, rb_cArray
, 0, RARRAY_LEN(ary
));
1286 enum ary_take_pos_flags
1293 ary_take_first_or_last_n(VALUE ary
, long n
, enum ary_take_pos_flags last
)
1295 long len
= RARRAY_LEN(ary
);
1302 rb_raise(rb_eArgError
, "negative array size");
1307 return ary_make_partial(ary
, rb_cArray
, offset
, n
);
1311 ary_take_first_or_last(int argc
, const VALUE
*argv
, VALUE ary
, enum ary_take_pos_flags last
)
1313 argc
= rb_check_arity(argc
, 0, 1);
1314 /* the case optional argument is omitted should be handled in
1315 * callers of this function. if another arity case is added,
1316 * this arity check needs to rewrite. */
1317 RUBY_ASSERT_ALWAYS(argc
== 1);
1318 return ary_take_first_or_last_n(ary
, NUM2LONG(argv
[0]), last
);
1323 * array << object -> self
1325 * Appends +object+ to +self+; returns +self+:
1327 * a = [:foo, 'bar', 2]
1328 * a << :baz # => [:foo, "bar", 2, :baz]
1330 * Appends +object+ as one element, even if it is another +Array+:
1332 * a = [:foo, 'bar', 2]
1334 * a1 # => [:foo, "bar", 2, [3, 4]]
1339 rb_ary_push(VALUE ary
, VALUE item
)
1341 long idx
= RARRAY_LEN((ary_verify(ary
), ary
));
1342 VALUE target_ary
= ary_ensure_room_for_push(ary
, 1);
1343 RARRAY_PTR_USE(ary
, ptr
, {
1344 RB_OBJ_WRITE(target_ary
, &ptr
[idx
], item
);
1346 ARY_SET_LEN(ary
, idx
+ 1);
1352 rb_ary_cat(VALUE ary
, const VALUE
*argv
, long len
)
1354 long oldlen
= RARRAY_LEN(ary
);
1355 VALUE target_ary
= ary_ensure_room_for_push(ary
, len
);
1356 ary_memcpy0(ary
, oldlen
, len
, argv
, target_ary
);
1357 ARY_SET_LEN(ary
, oldlen
+ len
);
1363 * array.push(*objects) -> self
1365 * Appends trailing elements.
1367 * Appends each argument in +objects+ to +self+; returns +self+:
1369 * a = [:foo, 'bar', 2]
1370 * a.push(:baz, :bat) # => [:foo, "bar", 2, :baz, :bat]
1372 * Appends each argument as one element, even if it is another +Array+:
1374 * a = [:foo, 'bar', 2]
1375 * a1 = a.push([:baz, :bat], [:bam, :bad])
1376 * a1 # => [:foo, "bar", 2, [:baz, :bat], [:bam, :bad]]
1378 * Related: #pop, #shift, #unshift.
1382 rb_ary_push_m(int argc
, VALUE
*argv
, VALUE ary
)
1384 return rb_ary_cat(ary
, argv
, argc
);
1388 rb_ary_pop(VALUE ary
)
1391 rb_ary_modify_check(ary
);
1392 n
= RARRAY_LEN(ary
);
1393 if (n
== 0) return Qnil
;
1394 if (ARY_OWNS_HEAP_P(ary
) &&
1395 n
* 3 < ARY_CAPA(ary
) &&
1396 ARY_CAPA(ary
) > ARY_DEFAULT_SIZE
)
1398 ary_resize_capa(ary
, n
* 2);
1401 ARY_SET_LEN(ary
, n
);
1403 return RARRAY_AREF(ary
, n
);
1408 * array.pop -> object or nil
1409 * array.pop(n) -> new_array
1411 * Removes and returns trailing elements.
1413 * When no argument is given and +self+ is not empty,
1414 * removes and returns the last element:
1416 * a = [:foo, 'bar', 2]
1418 * a # => [:foo, "bar"]
1420 * Returns +nil+ if the array is empty.
1422 * When a non-negative Integer argument +n+ is given and is in range,
1424 * removes and returns the last +n+ elements in a new +Array+:
1425 * a = [:foo, 'bar', 2]
1426 * a.pop(2) # => ["bar", 2]
1428 * If +n+ is positive and out of range,
1429 * removes and returns all elements:
1431 * a = [:foo, 'bar', 2]
1432 * a.pop(50) # => [:foo, "bar", 2]
1434 * Related: #push, #shift, #unshift.
1438 rb_ary_pop_m(int argc
, VALUE
*argv
, VALUE ary
)
1443 return rb_ary_pop(ary
);
1446 rb_ary_modify_check(ary
);
1447 result
= ary_take_first_or_last(argc
, argv
, ary
, ARY_TAKE_LAST
);
1448 ARY_INCREASE_LEN(ary
, -RARRAY_LEN(result
));
1454 rb_ary_shift(VALUE ary
)
1457 long len
= RARRAY_LEN(ary
);
1460 rb_ary_modify_check(ary
);
1464 top
= RARRAY_AREF(ary
, 0);
1466 rb_ary_behead(ary
, 1);
1473 * array.shift -> object or nil
1474 * array.shift(n) -> new_array
1476 * Removes and returns leading elements.
1478 * When no argument is given, removes and returns the first element:
1480 * a = [:foo, 'bar', 2]
1484 * Returns +nil+ if +self+ is empty.
1486 * When positive Integer argument +n+ is given, removes the first +n+ elements;
1487 * returns those elements in a new +Array+:
1489 * a = [:foo, 'bar', 2]
1490 * a.shift(2) # => [:foo, 'bar']
1493 * If +n+ is as large as or larger than <tt>self.length</tt>,
1494 * removes all elements; returns those elements in a new +Array+:
1496 * a = [:foo, 'bar', 2]
1497 * a.shift(3) # => [:foo, 'bar', 2]
1499 * If +n+ is zero, returns a new empty +Array+; +self+ is unmodified.
1501 * Related: #push, #pop, #unshift.
1505 rb_ary_shift_m(int argc
, VALUE
*argv
, VALUE ary
)
1511 return rb_ary_shift(ary
);
1514 rb_ary_modify_check(ary
);
1515 result
= ary_take_first_or_last(argc
, argv
, ary
, ARY_TAKE_FIRST
);
1516 n
= RARRAY_LEN(result
);
1517 rb_ary_behead(ary
,n
);
1523 rb_ary_behead(VALUE ary
, long n
)
1529 rb_ary_modify_check(ary
);
1531 if (!ARY_SHARED_P(ary
)) {
1532 if (ARY_EMBED_P(ary
) || RARRAY_LEN(ary
) < ARY_DEFAULT_SIZE
) {
1533 RARRAY_PTR_USE(ary
, ptr
, {
1534 MEMMOVE(ptr
, ptr
+ n
, VALUE
, RARRAY_LEN(ary
) - n
);
1535 }); /* WB: no new reference */
1536 ARY_INCREASE_LEN(ary
, -n
);
1541 ary_mem_clear(ary
, 0, n
);
1542 ary_make_shared(ary
);
1544 else if (ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary
))) {
1545 ary_mem_clear(ary
, 0, n
);
1548 ARY_INCREASE_PTR(ary
, n
);
1549 ARY_INCREASE_LEN(ary
, -n
);
1556 make_room_for_unshift(VALUE ary
, const VALUE
*head
, VALUE
*sharedp
, int argc
, long capa
, long len
)
1558 if (head
- sharedp
< argc
) {
1559 long room
= capa
- len
- argc
;
1562 MEMMOVE((VALUE
*)sharedp
+ argc
+ room
, head
, VALUE
, len
);
1563 head
= sharedp
+ argc
+ room
;
1565 ARY_SET_PTR(ary
, head
- argc
);
1566 RUBY_ASSERT(ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary
)));
1569 return ARY_SHARED_ROOT(ary
);
1573 ary_modify_for_unshift(VALUE ary
, int argc
)
1575 long len
= RARRAY_LEN(ary
);
1576 long new_len
= len
+ argc
;
1578 const VALUE
*head
, *sharedp
;
1581 capa
= ARY_CAPA(ary
);
1582 if (capa
- (capa
>> 6) <= new_len
) {
1583 ary_double_capa(ary
, new_len
);
1586 /* use shared array for big "queues" */
1587 if (new_len
> ARY_DEFAULT_SIZE
* 4 && !ARY_EMBED_P(ary
)) {
1590 /* make a room for unshifted items */
1591 capa
= ARY_CAPA(ary
);
1592 ary_make_shared(ary
);
1594 head
= sharedp
= RARRAY_CONST_PTR(ary
);
1595 return make_room_for_unshift(ary
, head
, (void *)sharedp
, argc
, capa
, len
);
1599 RARRAY_PTR_USE(ary
, ptr
, {
1600 MEMMOVE(ptr
+ argc
, ptr
, VALUE
, len
);
1609 ary_ensure_room_for_unshift(VALUE ary
, int argc
)
1611 long len
= RARRAY_LEN(ary
);
1612 long new_len
= len
+ argc
;
1614 if (len
> ARY_MAX_SIZE
- argc
) {
1615 rb_raise(rb_eIndexError
, "index %ld too big", new_len
);
1617 else if (! ARY_SHARED_P(ary
)) {
1618 return ary_modify_for_unshift(ary
, argc
);
1621 VALUE shared_root
= ARY_SHARED_ROOT(ary
);
1622 long capa
= RARRAY_LEN(shared_root
);
1624 if (! ARY_SHARED_ROOT_OCCUPIED(shared_root
)) {
1625 return ary_modify_for_unshift(ary
, argc
);
1627 else if (new_len
> capa
) {
1628 return ary_modify_for_unshift(ary
, argc
);
1631 const VALUE
* head
= RARRAY_CONST_PTR(ary
);
1632 void *sharedp
= (void *)RARRAY_CONST_PTR(shared_root
);
1634 rb_ary_modify_check(ary
);
1635 return make_room_for_unshift(ary
, head
, sharedp
, argc
, capa
, len
);
1642 * array.unshift(*objects) -> self
1644 * Prepends the given +objects+ to +self+:
1646 * a = [:foo, 'bar', 2]
1647 * a.unshift(:bam, :bat) # => [:bam, :bat, :foo, "bar", 2]
1649 * Related: #push, #pop, #shift.
1653 rb_ary_unshift_m(int argc
, VALUE
*argv
, VALUE ary
)
1655 long len
= RARRAY_LEN(ary
);
1659 rb_ary_modify_check(ary
);
1663 target_ary
= ary_ensure_room_for_unshift(ary
, argc
);
1664 ary_memcpy0(ary
, 0, argc
, argv
, target_ary
);
1665 ARY_SET_LEN(ary
, len
+ argc
);
1670 rb_ary_unshift(VALUE ary
, VALUE item
)
1672 return rb_ary_unshift_m(1, &item
, ary
);
1675 /* faster version - use this if you don't need to treat negative offset */
1677 rb_ary_elt(VALUE ary
, long offset
)
1679 long len
= RARRAY_LEN(ary
);
1680 if (len
== 0) return Qnil
;
1681 if (offset
< 0 || len
<= offset
) {
1684 return RARRAY_AREF(ary
, offset
);
1688 rb_ary_entry(VALUE ary
, long offset
)
1690 return rb_ary_entry_internal(ary
, offset
);
1694 rb_ary_subseq_step(VALUE ary
, long beg
, long len
, long step
)
1697 long alen
= RARRAY_LEN(ary
);
1699 if (beg
> alen
) return Qnil
;
1700 if (beg
< 0 || len
< 0) return Qnil
;
1702 if (alen
< len
|| alen
< beg
+ len
) {
1706 if (len
== 0) return ary_new(klass
, 0);
1708 rb_raise(rb_eArgError
, "slice step cannot be zero");
1710 return ary_make_partial(ary
, klass
, beg
, len
);
1712 return ary_make_partial_step(ary
, klass
, beg
, len
, step
);
1716 rb_ary_subseq(VALUE ary
, long beg
, long len
)
1718 return rb_ary_subseq_step(ary
, beg
, len
, 1);
1721 static VALUE
rb_ary_aref2(VALUE ary
, VALUE b
, VALUE e
);
1725 * array[index] -> object or nil
1726 * array[start, length] -> object or nil
1727 * array[range] -> object or nil
1728 * array[aseq] -> object or nil
1729 * array.slice(index) -> object or nil
1730 * array.slice(start, length) -> object or nil
1731 * array.slice(range) -> object or nil
1732 * array.slice(aseq) -> object or nil
1734 * Returns elements from +self+; does not modify +self+.
1738 * a = [:foo, 'bar', 2]
1741 * a[1, 2] # => ["bar", 2]
1742 * a[0..1] # => [:foo, "bar"]
1743 * a[0..-2] # => [:foo, "bar"]
1744 * a[-2..2] # => ["bar", 2]
1746 * When a single Integer argument +index+ is given, returns the element at offset +index+:
1748 * a = [:foo, 'bar', 2]
1751 * a # => [:foo, "bar", 2]
1753 * If +index+ is negative, counts relative to the end of +self+:
1755 * a = [:foo, 'bar', 2]
1759 * If +index+ is out of range, returns +nil+.
1761 * When two Integer arguments +start+ and +length+ are given,
1762 * returns a new +Array+ of size +length+ containing successive elements beginning at offset +start+:
1764 * a = [:foo, 'bar', 2]
1765 * a[0, 2] # => [:foo, "bar"]
1766 * a[1, 2] # => ["bar", 2]
1768 * If <tt>start + length</tt> is greater than <tt>self.length</tt>,
1769 * returns all elements from offset +start+ to the end:
1771 * a = [:foo, 'bar', 2]
1772 * a[0, 4] # => [:foo, "bar", 2]
1773 * a[1, 3] # => ["bar", 2]
1776 * If <tt>start == self.size</tt> and <tt>length >= 0</tt>,
1777 * returns a new empty +Array+.
1779 * If +length+ is negative, returns +nil+.
1781 * When a single Range argument +range+ is given,
1782 * treats <tt>range.min</tt> as +start+ above
1783 * and <tt>range.size</tt> as +length+ above:
1785 * a = [:foo, 'bar', 2]
1786 * a[0..1] # => [:foo, "bar"]
1787 * a[1..2] # => ["bar", 2]
1789 * Special case: If <tt>range.start == a.size</tt>, returns a new empty +Array+.
1791 * If <tt>range.end</tt> is negative, calculates the end index from the end:
1793 * a = [:foo, 'bar', 2]
1794 * a[0..-1] # => [:foo, "bar", 2]
1795 * a[0..-2] # => [:foo, "bar"]
1796 * a[0..-3] # => [:foo]
1798 * If <tt>range.start</tt> is negative, calculates the start index from the end:
1800 * a = [:foo, 'bar', 2]
1802 * a[-2..2] # => ["bar", 2]
1803 * a[-3..2] # => [:foo, "bar", 2]
1805 * If <tt>range.start</tt> is larger than the array size, returns +nil+.
1807 * a = [:foo, 'bar', 2]
1812 * When a single Enumerator::ArithmeticSequence argument +aseq+ is given,
1813 * returns an +Array+ of elements corresponding to the indexes produced by
1816 * a = ['--', 'data1', '--', 'data2', '--', 'data3']
1817 * a[(1..).step(2)] # => ["data1", "data2", "data3"]
1819 * Unlike slicing with range, if the start or the end of the arithmetic sequence
1820 * is larger than array size, throws RangeError.
1822 * a = ['--', 'data1', '--', 'data2', '--', 'data3']
1823 * a[(1..11).step(2)]
1824 * # RangeError (((1..11).step(2)) out of range)
1826 * # RangeError (((7..).step(2)) out of range)
1828 * If given a single argument, and its type is not one of the listed, tries to
1829 * convert it to Integer, and raises if it is impossible:
1831 * a = [:foo, 'bar', 2]
1832 * # Raises TypeError (no implicit conversion of Symbol into Integer):
1838 rb_ary_aref(int argc
, const VALUE
*argv
, VALUE ary
)
1840 rb_check_arity(argc
, 1, 2);
1842 return rb_ary_aref2(ary
, argv
[0], argv
[1]);
1844 return rb_ary_aref1(ary
, argv
[0]);
1848 rb_ary_aref2(VALUE ary
, VALUE b
, VALUE e
)
1850 long beg
= NUM2LONG(b
);
1851 long len
= NUM2LONG(e
);
1853 beg
+= RARRAY_LEN(ary
);
1855 return rb_ary_subseq(ary
, beg
, len
);
1859 rb_ary_aref1(VALUE ary
, VALUE arg
)
1861 long beg
, len
, step
;
1863 /* special case - speeding up */
1864 if (FIXNUM_P(arg
)) {
1865 return rb_ary_entry(ary
, FIX2LONG(arg
));
1867 /* check if idx is Range or ArithmeticSequence */
1868 switch (rb_arithmetic_sequence_beg_len_step(arg
, &beg
, &len
, &step
, RARRAY_LEN(ary
), 0)) {
1874 return rb_ary_subseq_step(ary
, beg
, len
, step
);
1877 return rb_ary_entry(ary
, NUM2LONG(arg
));
1882 * array.at(index) -> object
1884 * Returns the element at Integer offset +index+; does not modify +self+.
1885 * a = [:foo, 'bar', 2]
1892 rb_ary_at(VALUE ary
, VALUE pos
)
1894 return rb_ary_entry(ary
, NUM2LONG(pos
));
1899 rb_ary_first(int argc
, VALUE
*argv
, VALUE ary
)
1902 if (RARRAY_LEN(ary
) == 0) return Qnil
;
1903 return RARRAY_AREF(ary
, 0);
1906 return ary_take_first_or_last(argc
, argv
, ary
, ARY_TAKE_FIRST
);
1912 ary_first(VALUE self
)
1914 return (RARRAY_LEN(self
) == 0) ? Qnil
: RARRAY_AREF(self
, 0);
1918 ary_last(VALUE self
)
1920 long len
= RARRAY_LEN(self
);
1921 return (len
== 0) ? Qnil
: RARRAY_AREF(self
, len
-1);
1925 rb_ary_last(int argc
, const VALUE
*argv
, VALUE ary
) // used by parse.y
1928 return ary_last(ary
);
1931 return ary_take_first_or_last(argc
, argv
, ary
, ARY_TAKE_LAST
);
1937 * array.fetch(index) -> element
1938 * array.fetch(index, default_value) -> element
1939 * array.fetch(index) {|index| ... } -> element
1941 * Returns the element at offset +index+.
1943 * With the single Integer argument +index+,
1944 * returns the element at offset +index+:
1946 * a = [:foo, 'bar', 2]
1947 * a.fetch(1) # => "bar"
1949 * If +index+ is negative, counts from the end of the array:
1951 * a = [:foo, 'bar', 2]
1952 * a.fetch(-1) # => 2
1953 * a.fetch(-2) # => "bar"
1955 * With arguments +index+ and +default_value+,
1956 * returns the element at offset +index+ if index is in range,
1957 * otherwise returns +default_value+:
1959 * a = [:foo, 'bar', 2]
1960 * a.fetch(1, nil) # => "bar"
1962 * With argument +index+ and a block,
1963 * returns the element at offset +index+ if index is in range
1964 * (and the block is not called); otherwise calls the block with index and returns its return value:
1966 * a = [:foo, 'bar', 2]
1967 * a.fetch(1) {|index| raise 'Cannot happen' } # => "bar"
1968 * a.fetch(50) {|index| "Value for #{index}" } # => "Value for 50"
1973 rb_ary_fetch(int argc
, VALUE
*argv
, VALUE ary
)
1979 rb_scan_args(argc
, argv
, "11", &pos
, &ifnone
);
1980 block_given
= rb_block_given_p();
1981 if (block_given
&& argc
== 2) {
1982 rb_warn("block supersedes default value argument");
1984 idx
= NUM2LONG(pos
);
1987 idx
+= RARRAY_LEN(ary
);
1989 if (idx
< 0 || RARRAY_LEN(ary
) <= idx
) {
1990 if (block_given
) return rb_yield(pos
);
1992 rb_raise(rb_eIndexError
, "index %ld outside of array bounds: %ld...%ld",
1993 idx
- (idx
< 0 ? RARRAY_LEN(ary
) : 0), -RARRAY_LEN(ary
), RARRAY_LEN(ary
));
1997 return RARRAY_AREF(ary
, idx
);
2002 * array.index(object) -> integer or nil
2003 * array.index {|element| ... } -> integer or nil
2004 * array.index -> new_enumerator
2006 * Returns the index of a specified element.
2008 * When argument +object+ is given but no block,
2009 * returns the index of the first element +element+
2010 * for which <tt>object == element</tt>:
2012 * a = [:foo, 'bar', 2, 'bar']
2013 * a.index('bar') # => 1
2015 * Returns +nil+ if no such element found.
2017 * When both argument +object+ and a block are given,
2018 * calls the block with each successive element;
2019 * returns the index of the first element for which the block returns a truthy value:
2021 * a = [:foo, 'bar', 2, 'bar']
2022 * a.index {|element| element == 'bar' } # => 1
2024 * Returns +nil+ if the block never returns a truthy value.
2026 * When neither an argument nor a block is given, returns a new Enumerator:
2028 * a = [:foo, 'bar', 2]
2030 * e # => #<Enumerator: [:foo, "bar", 2]:index>
2031 * e.each {|element| element == 'bar' } # => 1
2037 rb_ary_index(int argc
, VALUE
*argv
, VALUE ary
)
2043 RETURN_ENUMERATOR(ary
, 0, 0);
2044 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
2045 if (RTEST(rb_yield(RARRAY_AREF(ary
, i
)))) {
2051 rb_check_arity(argc
, 0, 1);
2053 if (rb_block_given_p())
2054 rb_warn("given block not used");
2055 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
2056 VALUE e
= RARRAY_AREF(ary
, i
);
2057 if (rb_equal(e
, val
)) {
2066 * array.rindex(object) -> integer or nil
2067 * array.rindex {|element| ... } -> integer or nil
2068 * array.rindex -> new_enumerator
2070 * Returns the index of the last element for which <tt>object == element</tt>.
2072 * When argument +object+ is given but no block, returns the index of the last such element found:
2074 * a = [:foo, 'bar', 2, 'bar']
2075 * a.rindex('bar') # => 3
2077 * Returns +nil+ if no such object found.
2079 * When a block is given but no argument, calls the block with each successive element;
2080 * returns the index of the last element for which the block returns a truthy value:
2082 * a = [:foo, 'bar', 2, 'bar']
2083 * a.rindex {|element| element == 'bar' } # => 3
2085 * Returns +nil+ if the block never returns a truthy value.
2087 * When neither an argument nor a block is given, returns a new Enumerator:
2089 * a = [:foo, 'bar', 2, 'bar']
2091 * e # => #<Enumerator: [:foo, "bar", 2, "bar"]:rindex>
2092 * e.each {|element| element == 'bar' } # => 3
2098 rb_ary_rindex(int argc
, VALUE
*argv
, VALUE ary
)
2101 long i
= RARRAY_LEN(ary
), len
;
2104 RETURN_ENUMERATOR(ary
, 0, 0);
2106 if (RTEST(rb_yield(RARRAY_AREF(ary
, i
))))
2108 if (i
> (len
= RARRAY_LEN(ary
))) {
2114 rb_check_arity(argc
, 0, 1);
2116 if (rb_block_given_p())
2117 rb_warn("given block not used");
2119 VALUE e
= RARRAY_AREF(ary
, i
);
2120 if (rb_equal(e
, val
)) {
2123 if (i
> RARRAY_LEN(ary
)) {
2131 rb_ary_to_ary(VALUE obj
)
2133 VALUE tmp
= rb_check_array_type(obj
);
2135 if (!NIL_P(tmp
)) return tmp
;
2136 return rb_ary_new3(1, obj
);
2140 rb_ary_splice(VALUE ary
, long beg
, long len
, const VALUE
*rptr
, long rlen
)
2145 if (len
< 0) rb_raise(rb_eIndexError
, "negative length (%ld)", len
);
2146 olen
= RARRAY_LEN(ary
);
2150 rb_raise(rb_eIndexError
, "index %ld too small for array; minimum: %ld",
2154 if (olen
< len
|| olen
< beg
+ len
) {
2159 const VALUE
*optr
= RARRAY_CONST_PTR(ary
);
2160 rofs
= (rptr
>= optr
&& rptr
< optr
+ olen
) ? rptr
- optr
: -1;
2165 if (beg
> ARY_MAX_SIZE
- rlen
) {
2166 rb_raise(rb_eIndexError
, "index %ld too big", beg
);
2168 target_ary
= ary_ensure_room_for_push(ary
, rlen
-len
); /* len is 0 or negative */
2170 ary_mem_clear(ary
, olen
, beg
- olen
);
2172 if (rofs
!= -1) rptr
= RARRAY_CONST_PTR(ary
) + rofs
;
2173 ary_memcpy0(ary
, beg
, rlen
, rptr
, target_ary
);
2175 ARY_SET_LEN(ary
, len
);
2180 if (olen
- len
> ARY_MAX_SIZE
- rlen
) {
2181 rb_raise(rb_eIndexError
, "index %ld too big", olen
+ rlen
- len
);
2184 alen
= olen
+ rlen
- len
;
2185 if (alen
>= ARY_CAPA(ary
)) {
2186 ary_double_capa(ary
, alen
);
2190 RARRAY_PTR_USE(ary
, ptr
,
2191 MEMMOVE(ptr
+ beg
+ rlen
, ptr
+ beg
+ len
,
2192 VALUE
, olen
- (beg
+ len
)));
2193 ARY_SET_LEN(ary
, alen
);
2197 rb_gc_writebarrier_remember(ary
);
2200 /* In this case, we're copying from a region in this array, so
2201 * we don't need to fire the write barrier. */
2202 rptr
= RARRAY_CONST_PTR(ary
) + rofs
;
2205 /* do not use RARRAY_PTR() because it can causes GC.
2206 * ary can contain T_NONE object because it is not cleared.
2208 RARRAY_PTR_USE(ary
, ptr
,
2209 MEMMOVE(ptr
+ beg
, rptr
, VALUE
, rlen
));
2215 rb_ary_set_len(VALUE ary
, long len
)
2219 rb_ary_modify_check(ary
);
2220 if (ARY_SHARED_P(ary
)) {
2221 rb_raise(rb_eRuntimeError
, "can't set length of shared ");
2223 if (len
> (capa
= (long)ARY_CAPA(ary
))) {
2224 rb_bug("probable buffer overflow: %ld for %ld", len
, capa
);
2226 ARY_SET_LEN(ary
, len
);
2230 rb_ary_resize(VALUE ary
, long len
)
2235 olen
= RARRAY_LEN(ary
);
2236 if (len
== olen
) return ary
;
2237 if (len
> ARY_MAX_SIZE
) {
2238 rb_raise(rb_eIndexError
, "index %ld too big", len
);
2241 if (len
>= ARY_CAPA(ary
)) {
2242 ary_double_capa(ary
, len
);
2244 ary_mem_clear(ary
, olen
, len
- olen
);
2245 ARY_SET_LEN(ary
, len
);
2247 else if (ARY_EMBED_P(ary
)) {
2248 ARY_SET_EMBED_LEN(ary
, len
);
2250 else if (len
<= ary_embed_capa(ary
)) {
2251 const VALUE
*ptr
= ARY_HEAP_PTR(ary
);
2252 long ptr_capa
= ARY_HEAP_SIZE(ary
);
2253 bool is_malloc_ptr
= !ARY_SHARED_P(ary
);
2257 MEMCPY((VALUE
*)ARY_EMBED_PTR(ary
), ptr
, VALUE
, len
); /* WB: no new reference */
2258 ARY_SET_EMBED_LEN(ary
, len
);
2260 if (is_malloc_ptr
) ruby_sized_xfree((void *)ptr
, ptr_capa
);
2263 if (olen
> len
+ ARY_DEFAULT_SIZE
) {
2264 size_t new_capa
= ary_heap_realloc(ary
, len
);
2265 ARY_SET_CAPA(ary
, new_capa
);
2267 ARY_SET_HEAP_LEN(ary
, len
);
2274 ary_aset_by_rb_ary_store(VALUE ary
, long key
, VALUE val
)
2276 rb_ary_store(ary
, key
, val
);
2281 ary_aset_by_rb_ary_splice(VALUE ary
, long beg
, long len
, VALUE val
)
2283 VALUE rpl
= rb_ary_to_ary(val
);
2284 rb_ary_splice(ary
, beg
, len
, RARRAY_CONST_PTR(rpl
), RARRAY_LEN(rpl
));
2291 * array[index] = object -> object
2292 * array[start, length] = object -> object
2293 * array[range] = object -> object
2295 * Assigns elements in +self+; returns the given +object+.
2299 * a_orig = [:foo, 'bar', 2]
2300 * # With argument index.
2302 * a[0] = 'foo' # => "foo"
2303 * a # => ["foo", "bar", 2]
2305 * a[7] = 'foo' # => "foo"
2306 * a # => [:foo, "bar", 2, nil, nil, nil, nil, "foo"]
2307 * # With arguments start and length.
2309 * a[0, 2] = 'foo' # => "foo"
2312 * a[6, 50] = 'foo' # => "foo"
2313 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2314 * # With argument range.
2316 * a[0..1] = 'foo' # => "foo"
2319 * a[6..50] = 'foo' # => "foo"
2320 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2322 * When Integer argument +index+ is given, assigns +object+ to an element in +self+.
2324 * If +index+ is non-negative, assigns +object+ the element at offset +index+:
2326 * a = [:foo, 'bar', 2]
2327 * a[0] = 'foo' # => "foo"
2328 * a # => ["foo", "bar", 2]
2330 * If +index+ is greater than <tt>self.length</tt>, extends the array:
2332 * a = [:foo, 'bar', 2]
2333 * a[7] = 'foo' # => "foo"
2334 * a # => [:foo, "bar", 2, nil, nil, nil, nil, "foo"]
2336 * If +index+ is negative, counts backwards from the end of the array:
2338 * a = [:foo, 'bar', 2]
2339 * a[-1] = 'two' # => "two"
2340 * a # => [:foo, "bar", "two"]
2342 * When Integer arguments +start+ and +length+ are given and +object+ is not an +Array+,
2343 * removes <tt>length - 1</tt> elements beginning at offset +start+,
2344 * and assigns +object+ at offset +start+:
2346 * a = [:foo, 'bar', 2]
2347 * a[0, 2] = 'foo' # => "foo"
2350 * If +start+ is negative, counts backwards from the end of the array:
2352 * a = [:foo, 'bar', 2]
2353 * a[-2, 2] = 'foo' # => "foo"
2354 * a # => [:foo, "foo"]
2356 * If +start+ is non-negative and outside the array (<tt> >= self.size</tt>),
2357 * extends the array with +nil+, assigns +object+ at offset +start+,
2358 * and ignores +length+:
2360 * a = [:foo, 'bar', 2]
2361 * a[6, 50] = 'foo' # => "foo"
2362 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2364 * If +length+ is zero, shifts elements at and following offset +start+
2365 * and assigns +object+ at offset +start+:
2367 * a = [:foo, 'bar', 2]
2368 * a[1, 0] = 'foo' # => "foo"
2369 * a # => [:foo, "foo", "bar", 2]
2371 * If +length+ is too large for the existing array, does not extend the array:
2373 * a = [:foo, 'bar', 2]
2374 * a[1, 5] = 'foo' # => "foo"
2375 * a # => [:foo, "foo"]
2377 * When Range argument +range+ is given and +object+ is not an +Array+,
2378 * removes <tt>length - 1</tt> elements beginning at offset +start+,
2379 * and assigns +object+ at offset +start+:
2381 * a = [:foo, 'bar', 2]
2382 * a[0..1] = 'foo' # => "foo"
2385 * if <tt>range.begin</tt> is negative, counts backwards from the end of the array:
2387 * a = [:foo, 'bar', 2]
2388 * a[-2..2] = 'foo' # => "foo"
2389 * a # => [:foo, "foo"]
2391 * If the array length is less than <tt>range.begin</tt>,
2392 * extends the array with +nil+, assigns +object+ at offset <tt>range.begin</tt>,
2393 * and ignores +length+:
2395 * a = [:foo, 'bar', 2]
2396 * a[6..50] = 'foo' # => "foo"
2397 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2399 * If <tt>range.end</tt> is zero, shifts elements at and following offset +start+
2400 * and assigns +object+ at offset +start+:
2402 * a = [:foo, 'bar', 2]
2403 * a[1..0] = 'foo' # => "foo"
2404 * a # => [:foo, "foo", "bar", 2]
2406 * If <tt>range.end</tt> is negative, assigns +object+ at offset +start+,
2407 * retains <tt>range.end.abs -1</tt> elements past that, and removes those beyond:
2409 * a = [:foo, 'bar', 2]
2410 * a[1..-1] = 'foo' # => "foo"
2411 * a # => [:foo, "foo"]
2412 * a = [:foo, 'bar', 2]
2413 * a[1..-2] = 'foo' # => "foo"
2414 * a # => [:foo, "foo", 2]
2415 * a = [:foo, 'bar', 2]
2416 * a[1..-3] = 'foo' # => "foo"
2417 * a # => [:foo, "foo", "bar", 2]
2418 * a = [:foo, 'bar', 2]
2420 * If <tt>range.end</tt> is too large for the existing array,
2421 * replaces array elements, but does not extend the array with +nil+ values:
2423 * a = [:foo, 'bar', 2]
2424 * a[1..5] = 'foo' # => "foo"
2425 * a # => [:foo, "foo"]
2430 rb_ary_aset(int argc
, VALUE
*argv
, VALUE ary
)
2432 long offset
, beg
, len
;
2434 rb_check_arity(argc
, 2, 3);
2435 rb_ary_modify_check(ary
);
2437 beg
= NUM2LONG(argv
[0]);
2438 len
= NUM2LONG(argv
[1]);
2439 return ary_aset_by_rb_ary_splice(ary
, beg
, len
, argv
[2]);
2441 if (FIXNUM_P(argv
[0])) {
2442 offset
= FIX2LONG(argv
[0]);
2443 return ary_aset_by_rb_ary_store(ary
, offset
, argv
[1]);
2445 if (rb_range_beg_len(argv
[0], &beg
, &len
, RARRAY_LEN(ary
), 1)) {
2446 /* check if idx is Range */
2447 return ary_aset_by_rb_ary_splice(ary
, beg
, len
, argv
[1]);
2450 offset
= NUM2LONG(argv
[0]);
2451 return ary_aset_by_rb_ary_store(ary
, offset
, argv
[1]);
2456 * array.insert(index, *objects) -> self
2458 * Inserts given +objects+ before or after the element at Integer index +offset+;
2461 * When +index+ is non-negative, inserts all given +objects+
2462 * before the element at offset +index+:
2464 * a = [:foo, 'bar', 2]
2465 * a.insert(1, :bat, :bam) # => [:foo, :bat, :bam, "bar", 2]
2467 * Extends the array if +index+ is beyond the array (<tt>index >= self.size</tt>):
2469 * a = [:foo, 'bar', 2]
2470 * a.insert(5, :bat, :bam)
2471 * a # => [:foo, "bar", 2, nil, nil, :bat, :bam]
2473 * Does nothing if no objects given:
2475 * a = [:foo, 'bar', 2]
2479 * a # => [:foo, "bar", 2]
2481 * When +index+ is negative, inserts all given +objects+
2482 * _after_ the element at offset <tt>index+self.size</tt>:
2484 * a = [:foo, 'bar', 2]
2485 * a.insert(-2, :bat, :bam)
2486 * a # => [:foo, "bar", :bat, :bam, 2]
2491 rb_ary_insert(int argc
, VALUE
*argv
, VALUE ary
)
2495 rb_check_arity(argc
, 1, UNLIMITED_ARGUMENTS
);
2496 rb_ary_modify_check(ary
);
2497 pos
= NUM2LONG(argv
[0]);
2498 if (argc
== 1) return ary
;
2500 pos
= RARRAY_LEN(ary
);
2503 long minpos
= -RARRAY_LEN(ary
) - 1;
2505 rb_raise(rb_eIndexError
, "index %ld too small for array; minimum: %ld",
2510 rb_ary_splice(ary
, pos
, 0, argv
+ 1, argc
- 1);
2515 rb_ary_length(VALUE ary
);
2518 ary_enum_length(VALUE ary
, VALUE args
, VALUE eobj
)
2520 return rb_ary_length(ary
);
2523 // Primitive to avoid a race condition in Array#each.
2524 // Return `true` and write `value` and `index` if the element exists.
2526 ary_fetch_next(VALUE self
, VALUE
*index
, VALUE
*value
)
2528 long i
= NUM2LONG(*index
);
2529 if (i
>= RARRAY_LEN(self
)) {
2532 *value
= RARRAY_AREF(self
, i
);
2533 *index
= LONG2NUM(i
+ 1);
2538 rb_ary_each(VALUE ary
)
2542 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
2543 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
2544 rb_yield(RARRAY_AREF(ary
, i
));
2551 * array.each_index {|index| ... } -> self
2552 * array.each_index -> Enumerator
2554 * Iterates over array indexes.
2556 * When a block given, passes each successive array index to the block;
2559 * a = [:foo, 'bar', 2]
2560 * a.each_index {|index| puts "#{index} #{a[index]}" }
2568 * Allows the array to be modified during iteration:
2570 * a = [:foo, 'bar', 2]
2571 * a.each_index {|index| puts index; a.clear if index > 0 }
2578 * When no block given, returns a new Enumerator:
2580 * a = [:foo, 'bar', 2]
2582 * e # => #<Enumerator: [:foo, "bar", 2]:each_index>
2583 * a1 = e.each {|index| puts "#{index} #{a[index]}"}
2591 * Related: #each, #reverse_each.
2595 rb_ary_each_index(VALUE ary
)
2598 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
2600 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
2601 rb_yield(LONG2NUM(i
));
2608 * array.reverse_each {|element| ... } -> self
2609 * array.reverse_each -> Enumerator
2611 * Iterates backwards over array elements.
2613 * When a block given, passes, in reverse order, each element to the block;
2616 * a = [:foo, 'bar', 2]
2617 * a.reverse_each {|element| puts "#{element.class} #{element}" }
2625 * Allows the array to be modified during iteration:
2627 * a = [:foo, 'bar', 2]
2628 * a.reverse_each {|element| puts element; a.clear if element.to_s.start_with?('b') }
2635 * When no block given, returns a new Enumerator:
2637 * a = [:foo, 'bar', 2]
2638 * e = a.reverse_each
2639 * e # => #<Enumerator: [:foo, "bar", 2]:reverse_each>
2640 * a1 = e.each {|element| puts "#{element.class} #{element}" }
2648 * Related: #each, #each_index.
2652 rb_ary_reverse_each(VALUE ary
)
2656 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
2657 len
= RARRAY_LEN(ary
);
2660 rb_yield(RARRAY_AREF(ary
, len
));
2661 nlen
= RARRAY_LEN(ary
);
2671 * array.length -> an_integer
2673 * Returns the count of elements in +self+.
2677 rb_ary_length(VALUE ary
)
2679 long len
= RARRAY_LEN(ary
);
2680 return LONG2NUM(len
);
2685 * array.empty? -> true or false
2687 * Returns +true+ if the count of elements in +self+ is zero,
2688 * +false+ otherwise.
2692 rb_ary_empty_p(VALUE ary
)
2694 return RBOOL(RARRAY_LEN(ary
) == 0);
2698 rb_ary_dup(VALUE ary
)
2700 long len
= RARRAY_LEN(ary
);
2701 VALUE dup
= rb_ary_new2(len
);
2702 ary_memcpy(dup
, 0, len
, RARRAY_CONST_PTR(ary
));
2703 ARY_SET_LEN(dup
, len
);
2711 rb_ary_resurrect(VALUE ary
)
2713 return ary_make_partial(ary
, rb_cArray
, 0, RARRAY_LEN(ary
));
2716 extern VALUE rb_output_fs
;
2718 static void ary_join_1(VALUE obj
, VALUE ary
, VALUE sep
, long i
, VALUE result
, int *first
);
2721 recursive_join(VALUE obj
, VALUE argp
, int recur
)
2723 VALUE
*arg
= (VALUE
*)argp
;
2726 VALUE result
= arg
[2];
2727 int *first
= (int *)arg
[3];
2730 rb_raise(rb_eArgError
, "recursive array join");
2733 ary_join_1(obj
, ary
, sep
, 0, result
, first
);
2739 ary_join_0(VALUE ary
, VALUE sep
, long max
, VALUE result
)
2744 if (max
> 0) rb_enc_copy(result
, RARRAY_AREF(ary
, 0));
2745 for (i
=0; i
<max
; i
++) {
2746 val
= RARRAY_AREF(ary
, i
);
2747 if (!RB_TYPE_P(val
, T_STRING
)) break;
2748 if (i
> 0 && !NIL_P(sep
))
2749 rb_str_buf_append(result
, sep
);
2750 rb_str_buf_append(result
, val
);
2756 ary_join_1_str(VALUE dst
, VALUE src
, int *first
)
2758 rb_str_buf_append(dst
, src
);
2760 rb_enc_copy(dst
, src
);
2766 ary_join_1_ary(VALUE obj
, VALUE ary
, VALUE sep
, VALUE result
, VALUE val
, int *first
)
2769 rb_raise(rb_eArgError
, "recursive array join");
2778 args
[3] = (VALUE
)first
;
2779 rb_exec_recursive(recursive_join
, obj
, (VALUE
)args
);
2784 ary_join_1(VALUE obj
, VALUE ary
, VALUE sep
, long i
, VALUE result
, int *first
)
2788 for (; i
<RARRAY_LEN(ary
); i
++) {
2789 if (i
> 0 && !NIL_P(sep
))
2790 rb_str_buf_append(result
, sep
);
2792 val
= RARRAY_AREF(ary
, i
);
2793 if (RB_TYPE_P(val
, T_STRING
)) {
2794 ary_join_1_str(result
, val
, first
);
2796 else if (RB_TYPE_P(val
, T_ARRAY
)) {
2797 ary_join_1_ary(val
, ary
, sep
, result
, val
, first
);
2799 else if (!NIL_P(tmp
= rb_check_string_type(val
))) {
2800 ary_join_1_str(result
, tmp
, first
);
2802 else if (!NIL_P(tmp
= rb_check_array_type(val
))) {
2803 ary_join_1_ary(val
, ary
, sep
, result
, tmp
, first
);
2806 ary_join_1_str(result
, rb_obj_as_string(val
), first
);
2812 rb_ary_join(VALUE ary
, VALUE sep
)
2815 VALUE val
, tmp
, result
;
2817 if (RARRAY_LEN(ary
) == 0) return rb_usascii_str_new(0, 0);
2821 len
+= RSTRING_LEN(sep
) * (RARRAY_LEN(ary
) - 1);
2823 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
2824 val
= RARRAY_AREF(ary
, i
);
2825 tmp
= rb_check_string_type(val
);
2827 if (NIL_P(tmp
) || tmp
!= val
) {
2829 long n
= RARRAY_LEN(ary
);
2831 result
= rb_str_buf_new(len
+ (n
-i
)*10);
2832 rb_enc_associate(result
, rb_usascii_encoding());
2833 i
= ary_join_0(ary
, sep
, i
, result
);
2835 ary_join_1(ary
, ary
, sep
, i
, result
, &first
);
2839 len
+= RSTRING_LEN(tmp
);
2842 result
= rb_str_new(0, len
);
2843 rb_str_set_len(result
, 0);
2845 ary_join_0(ary
, sep
, RARRAY_LEN(ary
), result
);
2852 * array.join ->new_string
2853 * array.join(separator = $,) -> new_string
2855 * Returns the new String formed by joining the array elements after conversion.
2856 * For each element +element+:
2858 * - Uses <tt>element.to_s</tt> if +element+ is not a <tt>kind_of?(Array)</tt>.
2859 * - Uses recursive <tt>element.join(separator)</tt> if +element+ is a <tt>kind_of?(Array)</tt>.
2861 * With no argument, joins using the output field separator, <tt>$,</tt>:
2863 * a = [:foo, 'bar', 2]
2865 * a.join # => "foobar2"
2867 * With \string argument +separator+, joins using that separator:
2869 * a = [:foo, 'bar', 2]
2870 * a.join("\n") # => "foo\nbar\n2"
2872 * Joins recursively for nested Arrays:
2874 * a = [:foo, [:bar, [:baz, :bat]]]
2875 * a.join # => "foobarbazbat"
2879 rb_ary_join_m(int argc
, VALUE
*argv
, VALUE ary
)
2883 if (rb_check_arity(argc
, 0, 1) == 0 || NIL_P(sep
= argv
[0])) {
2886 rb_category_warn(RB_WARN_CATEGORY_DEPRECATED
, "$, is set to non-nil value");
2890 return rb_ary_join(ary
, sep
);
2894 inspect_ary(VALUE ary
, VALUE dummy
, int recur
)
2899 if (recur
) return rb_usascii_str_new_cstr("[...]");
2900 str
= rb_str_buf_new2("[");
2901 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
2902 s
= rb_inspect(RARRAY_AREF(ary
, i
));
2903 if (i
> 0) rb_str_buf_cat2(str
, ", ");
2904 else rb_enc_copy(str
, s
);
2905 rb_str_buf_append(str
, s
);
2907 rb_str_buf_cat2(str
, "]");
2913 * array.inspect -> new_string
2915 * Returns the new String formed by calling method <tt>#inspect</tt>
2916 * on each array element:
2918 * a = [:foo, 'bar', 2]
2919 * a.inspect # => "[:foo, \"bar\", 2]"
2924 rb_ary_inspect(VALUE ary
)
2926 if (RARRAY_LEN(ary
) == 0) return rb_usascii_str_new2("[]");
2927 return rb_exec_recursive(inspect_ary
, ary
, 0);
2931 rb_ary_to_s(VALUE ary
)
2933 return rb_ary_inspect(ary
);
2938 * to_a -> self or new_array
2940 * When +self+ is an instance of +Array+, returns +self+:
2942 * a = [:foo, 'bar', 2]
2943 * a.to_a # => [:foo, "bar", 2]
2945 * Otherwise, returns a new +Array+ containing the elements of +self+:
2947 * class MyArray < Array; end
2948 * a = MyArray.new(['foo', 'bar', 'two'])
2949 * a.instance_of?(Array) # => false
2950 * a.kind_of?(Array) # => true
2952 * a1 # => ["foo", "bar", "two"]
2953 * a1.class # => Array # Not MyArray
2958 rb_ary_to_a(VALUE ary
)
2960 if (rb_obj_class(ary
) != rb_cArray
) {
2961 VALUE dup
= rb_ary_new2(RARRAY_LEN(ary
));
2962 rb_ary_replace(dup
, ary
);
2970 * array.to_h -> new_hash
2971 * array.to_h {|item| ... } -> new_hash
2973 * Returns a new Hash formed from +self+.
2975 * When a block is given, calls the block with each array element;
2976 * the block must return a 2-element +Array+ whose two elements
2977 * form a key-value pair in the returned Hash:
2979 * a = ['foo', :bar, 1, [2, 3], {baz: 4}]
2980 * h = a.to_h {|item| [item, item] }
2981 * h # => {"foo"=>"foo", :bar=>:bar, 1=>1, [2, 3]=>[2, 3], {:baz=>4}=>{:baz=>4}}
2983 * When no block is given, +self+ must be an +Array+ of 2-element sub-arrays,
2984 * each sub-array is formed into a key-value pair in the new Hash:
2987 * a = [['foo', 'zero'], ['bar', 'one'], ['baz', 'two']]
2989 * h # => {"foo"=>"zero", "bar"=>"one", "baz"=>"two"}
2994 rb_ary_to_h(VALUE ary
)
2997 VALUE hash
= rb_hash_new_with_size(RARRAY_LEN(ary
));
2998 int block_given
= rb_block_given_p();
3000 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
3001 const VALUE e
= rb_ary_elt(ary
, i
);
3002 const VALUE elt
= block_given
? rb_yield_force_blockarg(e
) : e
;
3003 const VALUE key_value_pair
= rb_check_array_type(elt
);
3004 if (NIL_P(key_value_pair
)) {
3005 rb_raise(rb_eTypeError
, "wrong element type %"PRIsVALUE
" at %ld (expected array)",
3006 rb_obj_class(elt
), i
);
3008 if (RARRAY_LEN(key_value_pair
) != 2) {
3009 rb_raise(rb_eArgError
, "wrong array length at %ld (expected 2, was %ld)",
3010 i
, RARRAY_LEN(key_value_pair
));
3012 rb_hash_aset(hash
, RARRAY_AREF(key_value_pair
, 0), RARRAY_AREF(key_value_pair
, 1));
3019 * array.to_ary -> self
3025 rb_ary_to_ary_m(VALUE ary
)
3031 ary_reverse(VALUE
*p1
, VALUE
*p2
)
3041 rb_ary_reverse(VALUE ary
)
3044 long len
= RARRAY_LEN(ary
);
3048 RARRAY_PTR_USE(ary
, p1
, {
3049 p2
= p1
+ len
- 1; /* points last item */
3050 ary_reverse(p1
, p2
);
3051 }); /* WB: no new reference */
3058 * array.reverse! -> self
3060 * Reverses +self+ in place:
3062 * a = ['foo', 'bar', 'two']
3063 * a.reverse! # => ["two", "bar", "foo"]
3068 rb_ary_reverse_bang(VALUE ary
)
3070 return rb_ary_reverse(ary
);
3075 * array.reverse -> new_array
3077 * Returns a new +Array+ with the elements of +self+ in reverse order:
3079 * a = ['foo', 'bar', 'two']
3081 * a1 # => ["two", "bar", "foo"]
3086 rb_ary_reverse_m(VALUE ary
)
3088 long len
= RARRAY_LEN(ary
);
3089 VALUE dup
= rb_ary_new2(len
);
3092 const VALUE
*p1
= RARRAY_CONST_PTR(ary
);
3093 VALUE
*p2
= (VALUE
*)RARRAY_CONST_PTR(dup
) + len
- 1;
3094 do *p2
-- = *p1
++; while (--len
> 0);
3096 ARY_SET_LEN(dup
, RARRAY_LEN(ary
));
3101 rotate_count(long cnt
, long len
)
3103 return (cnt
< 0) ? (len
- (~cnt
% len
) - 1) : (cnt
% len
);
3107 ary_rotate_ptr(VALUE
*ptr
, long len
, long cnt
)
3111 memmove(ptr
, ptr
+ 1, sizeof(VALUE
)*(len
- 1));
3112 *(ptr
+ len
- 1) = tmp
;
3114 else if (cnt
== len
- 1) {
3115 VALUE tmp
= *(ptr
+ len
- 1);
3116 memmove(ptr
+ 1, ptr
, sizeof(VALUE
)*(len
- 1));
3121 if (cnt
< len
) ary_reverse(ptr
+ cnt
, ptr
+ len
);
3122 if (--cnt
> 0) ary_reverse(ptr
, ptr
+ cnt
);
3123 if (len
> 0) ary_reverse(ptr
, ptr
+ len
);
3128 rb_ary_rotate(VALUE ary
, long cnt
)
3133 long len
= RARRAY_LEN(ary
);
3134 if (len
> 1 && (cnt
= rotate_count(cnt
, len
)) > 0) {
3135 RARRAY_PTR_USE(ary
, ptr
, ary_rotate_ptr(ptr
, len
, cnt
));
3144 * array.rotate! -> self
3145 * array.rotate!(count) -> self
3147 * Rotates +self+ in place by moving elements from one end to the other; returns +self+.
3149 * When no argument given, rotates the first element to the last position:
3151 * a = [:foo, 'bar', 2, 'bar']
3152 * a.rotate! # => ["bar", 2, "bar", :foo]
3154 * When given a non-negative Integer +count+,
3155 * rotates +count+ elements from the beginning to the end:
3157 * a = [:foo, 'bar', 2]
3159 * a # => [2, :foo, "bar"]
3161 * If +count+ is large, uses <tt>count % array.size</tt> as the count:
3163 * a = [:foo, 'bar', 2]
3165 * a # => [2, :foo, "bar"]
3167 * If +count+ is zero, returns +self+ unmodified:
3169 * a = [:foo, 'bar', 2]
3171 * a # => [:foo, "bar", 2]
3173 * When given a negative Integer +count+, rotates in the opposite direction,
3174 * from end to beginning:
3176 * a = [:foo, 'bar', 2]
3178 * a # => ["bar", 2, :foo]
3180 * If +count+ is small (far from zero), uses <tt>count % array.size</tt> as the count:
3182 * a = [:foo, 'bar', 2]
3184 * a # => ["bar", 2, :foo]
3189 rb_ary_rotate_bang(int argc
, VALUE
*argv
, VALUE ary
)
3191 long n
= (rb_check_arity(argc
, 0, 1) ? NUM2LONG(argv
[0]) : 1);
3192 rb_ary_rotate(ary
, n
);
3198 * array.rotate -> new_array
3199 * array.rotate(count) -> new_array
3201 * Returns a new +Array+ formed from +self+ with elements
3202 * rotated from one end to the other.
3204 * When no argument given, returns a new +Array+ that is like +self+,
3205 * except that the first element has been rotated to the last position:
3207 * a = [:foo, 'bar', 2, 'bar']
3209 * a1 # => ["bar", 2, "bar", :foo]
3211 * When given a non-negative Integer +count+,
3212 * returns a new +Array+ with +count+ elements rotated from the beginning to the end:
3214 * a = [:foo, 'bar', 2]
3216 * a1 # => [2, :foo, "bar"]
3218 * If +count+ is large, uses <tt>count % array.size</tt> as the count:
3220 * a = [:foo, 'bar', 2]
3222 * a1 # => [2, :foo, "bar"]
3224 * If +count+ is zero, returns a copy of +self+, unmodified:
3226 * a = [:foo, 'bar', 2]
3228 * a1 # => [:foo, "bar", 2]
3230 * When given a negative Integer +count+, rotates in the opposite direction,
3231 * from end to beginning:
3233 * a = [:foo, 'bar', 2]
3235 * a1 # => ["bar", 2, :foo]
3237 * If +count+ is small (far from zero), uses <tt>count % array.size</tt> as the count:
3239 * a = [:foo, 'bar', 2]
3241 * a1 # => ["bar", 2, :foo]
3246 rb_ary_rotate_m(int argc
, VALUE
*argv
, VALUE ary
)
3251 long cnt
= (rb_check_arity(argc
, 0, 1) ? NUM2LONG(argv
[0]) : 1);
3253 len
= RARRAY_LEN(ary
);
3254 rotated
= rb_ary_new2(len
);
3256 cnt
= rotate_count(cnt
, len
);
3257 ptr
= RARRAY_CONST_PTR(ary
);
3259 ary_memcpy(rotated
, 0, len
, ptr
+ cnt
);
3260 ary_memcpy(rotated
, len
, cnt
, ptr
);
3262 ARY_SET_LEN(rotated
, RARRAY_LEN(ary
));
3266 struct ary_sort_data
{
3272 sort_reentered(VALUE ary
)
3274 if (RBASIC(ary
)->klass
) {
3275 rb_raise(rb_eRuntimeError
, "sort reentered");
3281 sort_returned(struct ary_sort_data
*data
)
3283 if (rb_obj_frozen_p(data
->receiver
)) {
3284 rb_raise(rb_eFrozenError
, "array frozen during sort");
3286 sort_reentered(data
->ary
);
3290 sort_1(const void *ap
, const void *bp
, void *dummy
)
3292 struct ary_sort_data
*data
= dummy
;
3293 VALUE retval
= sort_reentered(data
->ary
);
3294 VALUE a
= *(const VALUE
*)ap
, b
= *(const VALUE
*)bp
;
3300 retval
= rb_yield_values2(2, args
);
3301 n
= rb_cmpint(retval
, a
, b
);
3302 sort_returned(data
);
3307 sort_2(const void *ap
, const void *bp
, void *dummy
)
3309 struct ary_sort_data
*data
= dummy
;
3310 VALUE retval
= sort_reentered(data
->ary
);
3311 VALUE a
= *(const VALUE
*)ap
, b
= *(const VALUE
*)bp
;
3314 if (FIXNUM_P(a
) && FIXNUM_P(b
) && CMP_OPTIMIZABLE(INTEGER
)) {
3315 if ((long)a
> (long)b
) return 1;
3316 if ((long)a
< (long)b
) return -1;
3319 if (STRING_P(a
) && STRING_P(b
) && CMP_OPTIMIZABLE(STRING
)) {
3320 return rb_str_cmp(a
, b
);
3322 if (RB_FLOAT_TYPE_P(a
) && CMP_OPTIMIZABLE(FLOAT
)) {
3323 return rb_float_cmp(a
, b
);
3326 retval
= rb_funcallv(a
, id_cmp
, 1, &b
);
3327 n
= rb_cmpint(retval
, a
, b
);
3328 sort_returned(data
);
3335 * array.sort! -> self
3336 * array.sort! {|a, b| ... } -> self
3338 * Returns +self+ with its elements sorted in place.
3340 * With no block, compares elements using operator <tt><=></tt>
3343 * a = 'abcde'.split('').shuffle
3344 * a # => ["e", "b", "d", "a", "c"]
3346 * a # => ["a", "b", "c", "d", "e"]
3348 * With a block, calls the block with each element pair;
3349 * for each element pair +a+ and +b+, the block should return an integer:
3351 * - Negative when +b+ is to follow +a+.
3352 * - Zero when +a+ and +b+ are equivalent.
3353 * - Positive when +a+ is to follow +b+.
3357 * a = 'abcde'.split('').shuffle
3358 * a # => ["e", "b", "d", "a", "c"]
3359 * a.sort! {|a, b| a <=> b }
3360 * a # => ["a", "b", "c", "d", "e"]
3361 * a.sort! {|a, b| b <=> a }
3362 * a # => ["e", "d", "c", "b", "a"]
3364 * When the block returns zero, the order for +a+ and +b+ is indeterminate,
3365 * and may be unstable:
3367 * a = 'abcde'.split('').shuffle
3368 * a # => ["e", "b", "d", "a", "c"]
3369 * a.sort! {|a, b| 0 }
3370 * a # => ["d", "e", "c", "a", "b"]
3375 rb_ary_sort_bang(VALUE ary
)
3378 RUBY_ASSERT(!ARY_SHARED_P(ary
));
3379 if (RARRAY_LEN(ary
) > 1) {
3380 VALUE tmp
= ary_make_substitution(ary
); /* only ary refers tmp */
3381 struct ary_sort_data data
;
3382 long len
= RARRAY_LEN(ary
);
3383 RBASIC_CLEAR_CLASS(tmp
);
3385 data
.receiver
= ary
;
3386 RARRAY_PTR_USE(tmp
, ptr
, {
3387 ruby_qsort(ptr
, len
, sizeof(VALUE
),
3388 rb_block_given_p()?sort_1
:sort_2
, &data
);
3389 }); /* WB: no new reference */
3391 if (ARY_EMBED_P(tmp
)) {
3392 if (ARY_SHARED_P(ary
)) { /* ary might be destructively operated in the given block */
3393 rb_ary_unshare(ary
);
3396 if (ARY_EMBED_LEN(tmp
) > ARY_CAPA(ary
)) {
3397 ary_resize_capa(ary
, ARY_EMBED_LEN(tmp
));
3399 ary_memcpy(ary
, 0, ARY_EMBED_LEN(tmp
), ARY_EMBED_PTR(tmp
));
3400 ARY_SET_LEN(ary
, ARY_EMBED_LEN(tmp
));
3403 if (!ARY_EMBED_P(ary
) && ARY_HEAP_PTR(ary
) == ARY_HEAP_PTR(tmp
)) {
3404 FL_UNSET_SHARED(ary
);
3405 ARY_SET_CAPA(ary
, RARRAY_LEN(tmp
));
3408 RUBY_ASSERT(!ARY_SHARED_P(tmp
));
3409 if (ARY_EMBED_P(ary
)) {
3410 FL_UNSET_EMBED(ary
);
3412 else if (ARY_SHARED_P(ary
)) {
3413 /* ary might be destructively operated in the given block */
3414 rb_ary_unshare(ary
);
3419 ARY_SET_PTR(ary
, ARY_HEAP_PTR(tmp
));
3420 ARY_SET_HEAP_LEN(ary
, len
);
3421 ARY_SET_CAPA(ary
, ARY_HEAP_LEN(tmp
));
3423 /* tmp was lost ownership for the ptr */
3424 FL_UNSET(tmp
, FL_FREEZE
);
3426 ARY_SET_EMBED_LEN(tmp
, 0);
3427 FL_SET(tmp
, FL_FREEZE
);
3429 /* tmp will be GC'ed. */
3430 RBASIC_SET_CLASS_RAW(tmp
, rb_cArray
); /* rb_cArray must be marked */
3438 * array.sort -> new_array
3439 * array.sort {|a, b| ... } -> new_array
3441 * Returns a new +Array+ whose elements are those from +self+, sorted.
3443 * With no block, compares elements using operator <tt><=></tt>
3446 * a = 'abcde'.split('').shuffle
3447 * a # => ["e", "b", "d", "a", "c"]
3449 * a1 # => ["a", "b", "c", "d", "e"]
3451 * With a block, calls the block with each element pair;
3452 * for each element pair +a+ and +b+, the block should return an integer:
3454 * - Negative when +b+ is to follow +a+.
3455 * - Zero when +a+ and +b+ are equivalent.
3456 * - Positive when +a+ is to follow +b+.
3460 * a = 'abcde'.split('').shuffle
3461 * a # => ["e", "b", "d", "a", "c"]
3462 * a1 = a.sort {|a, b| a <=> b }
3463 * a1 # => ["a", "b", "c", "d", "e"]
3464 * a2 = a.sort {|a, b| b <=> a }
3465 * a2 # => ["e", "d", "c", "b", "a"]
3467 * When the block returns zero, the order for +a+ and +b+ is indeterminate,
3468 * and may be unstable:
3470 * a = 'abcde'.split('').shuffle
3471 * a # => ["e", "b", "d", "a", "c"]
3472 * a1 = a.sort {|a, b| 0 }
3473 * a1 # => ["c", "e", "b", "d", "a"]
3475 * Related: Enumerable#sort_by.
3479 rb_ary_sort(VALUE ary
)
3481 ary
= rb_ary_dup(ary
);
3482 rb_ary_sort_bang(ary
);
3486 static VALUE
rb_ary_bsearch_index(VALUE ary
);
3490 * array.bsearch {|element| ... } -> object
3491 * array.bsearch -> new_enumerator
3493 * Returns an element from +self+ selected by a binary search.
3495 * See {Binary Searching}[rdoc-ref:bsearch.rdoc].
3499 rb_ary_bsearch(VALUE ary
)
3501 VALUE index_result
= rb_ary_bsearch_index(ary
);
3503 if (FIXNUM_P(index_result
)) {
3504 return rb_ary_entry(ary
, FIX2LONG(index_result
));
3506 return index_result
;
3511 * array.bsearch_index {|element| ... } -> integer or nil
3512 * array.bsearch_index -> new_enumerator
3514 * Searches +self+ as described at method #bsearch,
3515 * but returns the _index_ of the found element instead of the element itself.
3519 rb_ary_bsearch_index(VALUE ary
)
3521 long low
= 0, high
= RARRAY_LEN(ary
), mid
;
3522 int smaller
= 0, satisfied
= 0;
3525 RETURN_ENUMERATOR(ary
, 0, 0);
3526 while (low
< high
) {
3527 mid
= low
+ ((high
- low
) / 2);
3528 val
= rb_ary_entry(ary
, mid
);
3531 if (v
== INT2FIX(0)) return INT2FIX(mid
);
3532 smaller
= (SIGNED_VALUE
)v
< 0; /* Fixnum preserves its sign-bit */
3534 else if (v
== Qtrue
) {
3538 else if (!RTEST(v
)) {
3541 else if (rb_obj_is_kind_of(v
, rb_cNumeric
)) {
3542 const VALUE zero
= INT2FIX(0);
3543 switch (rb_cmpint(rb_funcallv(v
, id_cmp
, 1, &zero
), v
, zero
)) {
3544 case 0: return INT2FIX(mid
);
3545 case 1: smaller
= 0; break;
3546 case -1: smaller
= 1;
3550 rb_raise(rb_eTypeError
, "wrong argument type %"PRIsVALUE
3551 " (must be numeric, true, false or nil)",
3561 if (!satisfied
) return Qnil
;
3562 return INT2FIX(low
);
3567 sort_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i
, dummy
))
3574 * array.sort_by! {|element| ... } -> self
3575 * array.sort_by! -> new_enumerator
3577 * Sorts the elements of +self+ in place,
3578 * using an ordering determined by the block; returns self.
3580 * Calls the block with each successive element;
3581 * sorts elements based on the values returned from the block.
3583 * For duplicates returned by the block, the ordering is indeterminate, and may be unstable.
3585 * This example sorts strings based on their sizes:
3587 * a = ['aaaa', 'bbb', 'cc', 'd']
3588 * a.sort_by! {|element| element.size }
3589 * a # => ["d", "cc", "bbb", "aaaa"]
3591 * Returns a new Enumerator if no block given:
3593 * a = ['aaaa', 'bbb', 'cc', 'd']
3594 * a.sort_by! # => #<Enumerator: ["aaaa", "bbb", "cc", "d"]:sort_by!>
3599 rb_ary_sort_by_bang(VALUE ary
)
3603 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
3605 sorted
= rb_block_call(ary
, rb_intern("sort_by"), 0, 0, sort_by_i
, 0);
3606 rb_ary_replace(ary
, sorted
);
3613 * array.map {|element| ... } -> new_array
3614 * array.map -> new_enumerator
3616 * Calls the block, if given, with each element of +self+;
3617 * returns a new +Array+ whose elements are the return values from the block:
3619 * a = [:foo, 'bar', 2]
3620 * a1 = a.map {|element| element.class }
3621 * a1 # => [Symbol, String, Integer]
3623 * Returns a new Enumerator if no block given:
3624 * a = [:foo, 'bar', 2]
3626 * a1 # => #<Enumerator: [:foo, "bar", 2]:map>
3631 rb_ary_collect(VALUE ary
)
3636 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
3637 collect
= rb_ary_new2(RARRAY_LEN(ary
));
3638 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
3639 rb_ary_push(collect
, rb_yield(RARRAY_AREF(ary
, i
)));
3647 * array.map! {|element| ... } -> self
3648 * array.map! -> new_enumerator
3650 * Calls the block, if given, with each element;
3651 * replaces the element with the block's return value:
3653 * a = [:foo, 'bar', 2]
3654 * a.map! { |element| element.class } # => [Symbol, String, Integer]
3656 * Returns a new Enumerator if no block given:
3658 * a = [:foo, 'bar', 2]
3660 * a1 # => #<Enumerator: [:foo, "bar", 2]:map!>
3665 rb_ary_collect_bang(VALUE ary
)
3669 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
3671 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
3672 rb_ary_store(ary
, i
, rb_yield(RARRAY_AREF(ary
, i
)));
3678 rb_get_values_at(VALUE obj
, long olen
, int argc
, const VALUE
*argv
, VALUE (*func
) (VALUE
, long))
3680 VALUE result
= rb_ary_new2(argc
);
3681 long beg
, len
, i
, j
;
3683 for (i
=0; i
<argc
; i
++) {
3684 if (FIXNUM_P(argv
[i
])) {
3685 rb_ary_push(result
, (*func
)(obj
, FIX2LONG(argv
[i
])));
3688 /* check if idx is Range */
3689 if (rb_range_beg_len(argv
[i
], &beg
, &len
, olen
, 1)) {
3690 long end
= olen
< beg
+len
? olen
: beg
+len
;
3691 for (j
= beg
; j
< end
; j
++) {
3692 rb_ary_push(result
, (*func
)(obj
, j
));
3695 rb_ary_resize(result
, RARRAY_LEN(result
) + (beg
+ len
) - j
);
3698 rb_ary_push(result
, (*func
)(obj
, NUM2LONG(argv
[i
])));
3704 append_values_at_single(VALUE result
, VALUE ary
, long olen
, VALUE idx
)
3707 if (FIXNUM_P(idx
)) {
3708 beg
= FIX2LONG(idx
);
3710 /* check if idx is Range */
3711 else if (rb_range_beg_len(idx
, &beg
, &len
, olen
, 1)) {
3713 const VALUE
*const src
= RARRAY_CONST_PTR(ary
);
3714 const long end
= beg
+ len
;
3715 const long prevlen
= RARRAY_LEN(result
);
3717 rb_ary_cat(result
, src
+ beg
, end
> olen
? olen
-beg
: len
);
3720 rb_ary_store(result
, prevlen
+ len
- 1, Qnil
);
3726 beg
= NUM2LONG(idx
);
3728 return rb_ary_push(result
, rb_ary_entry(ary
, beg
));
3733 * array.values_at(*indexes) -> new_array
3735 * Returns a new +Array+ whose elements are the elements
3736 * of +self+ at the given Integer or Range +indexes+.
3738 * For each positive +index+, returns the element at offset +index+:
3740 * a = [:foo, 'bar', 2]
3741 * a.values_at(0, 2) # => [:foo, 2]
3742 * a.values_at(0..1) # => [:foo, "bar"]
3744 * The given +indexes+ may be in any order, and may repeat:
3746 * a = [:foo, 'bar', 2]
3747 * a.values_at(2, 0, 1, 0, 2) # => [2, :foo, "bar", :foo, 2]
3748 * a.values_at(1, 0..2) # => ["bar", :foo, "bar", 2]
3750 * Assigns +nil+ for an +index+ that is too large:
3752 * a = [:foo, 'bar', 2]
3753 * a.values_at(0, 3, 1, 3) # => [:foo, nil, "bar", nil]
3755 * Returns a new empty +Array+ if no arguments given.
3757 * For each negative +index+, counts backward from the end of the array:
3759 * a = [:foo, 'bar', 2]
3760 * a.values_at(-1, -3) # => [2, :foo]
3762 * Assigns +nil+ for an +index+ that is too small:
3764 * a = [:foo, 'bar', 2]
3765 * a.values_at(0, -5, 1, -6, 2) # => [:foo, nil, "bar", nil, 2]
3767 * The given +indexes+ may have a mixture of signs:
3769 * a = [:foo, 'bar', 2]
3770 * a.values_at(0, -2, 1, -1) # => [:foo, "bar", "bar", 2]
3775 rb_ary_values_at(int argc
, VALUE
*argv
, VALUE ary
)
3777 long i
, olen
= RARRAY_LEN(ary
);
3778 VALUE result
= rb_ary_new_capa(argc
);
3779 for (i
= 0; i
< argc
; ++i
) {
3780 append_values_at_single(result
, ary
, olen
, argv
[i
]);
3789 * array.select {|element| ... } -> new_array
3790 * array.select -> new_enumerator
3792 * Calls the block, if given, with each element of +self+;
3793 * returns a new +Array+ containing those elements of +self+
3794 * for which the block returns a truthy value:
3796 * a = [:foo, 'bar', 2, :bam]
3797 * a1 = a.select {|element| element.to_s.start_with?('b') }
3798 * a1 # => ["bar", :bam]
3800 * Returns a new Enumerator if no block given:
3802 * a = [:foo, 'bar', 2, :bam]
3803 * a.select # => #<Enumerator: [:foo, "bar", 2, :bam]:select>
3808 rb_ary_select(VALUE ary
)
3813 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
3814 result
= rb_ary_new2(RARRAY_LEN(ary
));
3815 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
3816 if (RTEST(rb_yield(RARRAY_AREF(ary
, i
)))) {
3817 rb_ary_push(result
, rb_ary_elt(ary
, i
));
3823 struct select_bang_arg
{
3829 select_bang_i(VALUE a
)
3831 volatile struct select_bang_arg
*arg
= (void *)a
;
3832 VALUE ary
= arg
->ary
;
3835 for (i1
= i2
= 0; i1
< RARRAY_LEN(ary
); arg
->len
[0] = ++i1
) {
3836 VALUE v
= RARRAY_AREF(ary
, i1
);
3837 if (!RTEST(rb_yield(v
))) continue;
3839 rb_ary_store(ary
, i2
, v
);
3843 return (i1
== i2
) ? Qnil
: ary
;
3847 select_bang_ensure(VALUE a
)
3849 volatile struct select_bang_arg
*arg
= (void *)a
;
3850 VALUE ary
= arg
->ary
;
3851 long len
= RARRAY_LEN(ary
);
3852 long i1
= arg
->len
[0], i2
= arg
->len
[1];
3854 if (i2
< len
&& i2
< i1
) {
3859 RARRAY_PTR_USE(ary
, ptr
, {
3860 MEMMOVE(ptr
+ i2
, ptr
+ i1
, VALUE
, tail
);
3863 ARY_SET_LEN(ary
, i2
+ tail
);
3870 * array.select! {|element| ... } -> self or nil
3871 * array.select! -> new_enumerator
3873 * Calls the block, if given with each element of +self+;
3874 * removes from +self+ those elements for which the block returns +false+ or +nil+.
3876 * Returns +self+ if any elements were removed:
3878 * a = [:foo, 'bar', 2, :bam]
3879 * a.select! {|element| element.to_s.start_with?('b') } # => ["bar", :bam]
3881 * Returns +nil+ if no elements were removed.
3883 * Returns a new Enumerator if no block given:
3885 * a = [:foo, 'bar', 2, :bam]
3886 * a.select! # => #<Enumerator: [:foo, "bar", 2, :bam]:select!>
3891 rb_ary_select_bang(VALUE ary
)
3893 struct select_bang_arg args
;
3895 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
3899 args
.len
[0] = args
.len
[1] = 0;
3900 return rb_ensure(select_bang_i
, (VALUE
)&args
, select_bang_ensure
, (VALUE
)&args
);
3905 * array.keep_if {|element| ... } -> self
3906 * array.keep_if -> new_enumeration
3908 * Retains those elements for which the block returns a truthy value;
3909 * deletes all other elements; returns +self+:
3911 * a = [:foo, 'bar', 2, :bam]
3912 * a.keep_if {|element| element.to_s.start_with?('b') } # => ["bar", :bam]
3914 * Returns a new Enumerator if no block given:
3916 * a = [:foo, 'bar', 2, :bam]
3917 * a.keep_if # => #<Enumerator: [:foo, "bar", 2, :bam]:keep_if>
3922 rb_ary_keep_if(VALUE ary
)
3924 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
3925 rb_ary_select_bang(ary
);
3930 ary_resize_smaller(VALUE ary
, long len
)
3933 if (RARRAY_LEN(ary
) > len
) {
3934 ARY_SET_LEN(ary
, len
);
3935 if (len
* 2 < ARY_CAPA(ary
) &&
3936 ARY_CAPA(ary
) > ARY_DEFAULT_SIZE
) {
3937 ary_resize_capa(ary
, len
* 2);
3944 * array.delete(obj) -> deleted_object
3945 * array.delete(obj) {|nosuch| ... } -> deleted_object or block_return
3947 * Removes zero or more elements from +self+.
3949 * When no block is given,
3950 * removes from +self+ each element +ele+ such that <tt>ele == obj</tt>;
3951 * returns the last deleted element:
3953 * s1 = 'bar'; s2 = 'bar'
3954 * a = [:foo, s1, 2, s2]
3955 * a.delete('bar') # => "bar"
3958 * Returns +nil+ if no elements removed.
3960 * When a block is given,
3961 * removes from +self+ each element +ele+ such that <tt>ele == obj</tt>.
3963 * If any such elements are found, ignores the block
3964 * and returns the last deleted element:
3966 * s1 = 'bar'; s2 = 'bar'
3967 * a = [:foo, s1, 2, s2]
3968 * deleted_obj = a.delete('bar') {|obj| fail 'Cannot happen' }
3971 * If no such elements are found, returns the block's return value:
3973 * a = [:foo, 'bar', 2]
3974 * a.delete(:nosuch) {|obj| "#{obj} not found" } # => "nosuch not found"
3979 rb_ary_delete(VALUE ary
, VALUE item
)
3984 for (i1
= i2
= 0; i1
< RARRAY_LEN(ary
); i1
++) {
3985 VALUE e
= RARRAY_AREF(ary
, i1
);
3987 if (rb_equal(e
, item
)) {
3992 rb_ary_store(ary
, i2
, e
);
3996 if (RARRAY_LEN(ary
) == i2
) {
3997 if (rb_block_given_p()) {
3998 return rb_yield(item
);
4003 ary_resize_smaller(ary
, i2
);
4010 rb_ary_delete_same(VALUE ary
, VALUE item
)
4014 for (i1
= i2
= 0; i1
< RARRAY_LEN(ary
); i1
++) {
4015 VALUE e
= RARRAY_AREF(ary
, i1
);
4021 rb_ary_store(ary
, i2
, e
);
4025 if (RARRAY_LEN(ary
) == i2
) {
4029 ary_resize_smaller(ary
, i2
);
4033 rb_ary_delete_at(VALUE ary
, long pos
)
4035 long len
= RARRAY_LEN(ary
);
4038 if (pos
>= len
) return Qnil
;
4041 if (pos
< 0) return Qnil
;
4045 del
= RARRAY_AREF(ary
, pos
);
4046 RARRAY_PTR_USE(ary
, ptr
, {
4047 MEMMOVE(ptr
+pos
, ptr
+pos
+1, VALUE
, len
-pos
-1);
4049 ARY_INCREASE_LEN(ary
, -1);
4056 * array.delete_at(index) -> deleted_object or nil
4058 * Deletes an element from +self+, per the given Integer +index+.
4060 * When +index+ is non-negative, deletes the element at offset +index+:
4062 * a = [:foo, 'bar', 2]
4063 * a.delete_at(1) # => "bar"
4066 * If index is too large, returns +nil+.
4068 * When +index+ is negative, counts backward from the end of the array:
4070 * a = [:foo, 'bar', 2]
4071 * a.delete_at(-2) # => "bar"
4074 * If +index+ is too small (far from zero), returns nil.
4078 rb_ary_delete_at_m(VALUE ary
, VALUE pos
)
4080 return rb_ary_delete_at(ary
, NUM2LONG(pos
));
4084 ary_slice_bang_by_rb_ary_splice(VALUE ary
, long pos
, long len
)
4086 const long orig_len
= RARRAY_LEN(ary
);
4091 else if (pos
< -orig_len
) {
4097 else if (orig_len
< pos
) {
4100 if (orig_len
< pos
+ len
) {
4101 len
= orig_len
- pos
;
4104 return rb_ary_new2(0);
4107 VALUE arg2
= rb_ary_new4(len
, RARRAY_CONST_PTR(ary
)+pos
);
4108 rb_ary_splice(ary
, pos
, len
, 0, 0);
4115 * array.slice!(n) -> object or nil
4116 * array.slice!(start, length) -> new_array or nil
4117 * array.slice!(range) -> new_array or nil
4119 * Removes and returns elements from +self+.
4121 * When the only argument is an Integer +n+,
4122 * removes and returns the _nth_ element in +self+:
4124 * a = [:foo, 'bar', 2]
4125 * a.slice!(1) # => "bar"
4128 * If +n+ is negative, counts backwards from the end of +self+:
4130 * a = [:foo, 'bar', 2]
4131 * a.slice!(-1) # => 2
4132 * a # => [:foo, "bar"]
4134 * If +n+ is out of range, returns +nil+.
4136 * When the only arguments are Integers +start+ and +length+,
4137 * removes +length+ elements from +self+ beginning at offset +start+;
4138 * returns the deleted objects in a new +Array+:
4140 * a = [:foo, 'bar', 2]
4141 * a.slice!(0, 2) # => [:foo, "bar"]
4144 * If <tt>start + length</tt> exceeds the array size,
4145 * removes and returns all elements from offset +start+ to the end:
4147 * a = [:foo, 'bar', 2]
4148 * a.slice!(1, 50) # => ["bar", 2]
4151 * If <tt>start == a.size</tt> and +length+ is non-negative,
4152 * returns a new empty +Array+.
4154 * If +length+ is negative, returns +nil+.
4156 * When the only argument is a Range object +range+,
4157 * treats <tt>range.min</tt> as +start+ above and <tt>range.size</tt> as +length+ above:
4159 * a = [:foo, 'bar', 2]
4160 * a.slice!(1..2) # => ["bar", 2]
4163 * If <tt>range.start == a.size</tt>, returns a new empty +Array+.
4165 * If <tt>range.start</tt> is larger than the array size, returns +nil+.
4167 * If <tt>range.end</tt> is negative, counts backwards from the end of the array:
4169 * a = [:foo, 'bar', 2]
4170 * a.slice!(0..-2) # => [:foo, "bar"]
4173 * If <tt>range.start</tt> is negative,
4174 * calculates the start index backwards from the end of the array:
4176 * a = [:foo, 'bar', 2]
4177 * a.slice!(-2..2) # => ["bar", 2]
4183 rb_ary_slice_bang(int argc
, VALUE
*argv
, VALUE ary
)
4188 rb_ary_modify_check(ary
);
4189 rb_check_arity(argc
, 1, 2);
4193 pos
= NUM2LONG(argv
[0]);
4194 len
= NUM2LONG(argv
[1]);
4195 return ary_slice_bang_by_rb_ary_splice(ary
, pos
, len
);
4198 if (!FIXNUM_P(arg1
)) {
4199 switch (rb_range_beg_len(arg1
, &pos
, &len
, RARRAY_LEN(ary
), 0)) {
4202 return ary_slice_bang_by_rb_ary_splice(ary
, pos
, len
);
4212 return rb_ary_delete_at(ary
, NUM2LONG(arg1
));
4216 ary_reject(VALUE orig
, VALUE result
)
4220 for (i
= 0; i
< RARRAY_LEN(orig
); i
++) {
4221 VALUE v
= RARRAY_AREF(orig
, i
);
4223 if (!RTEST(rb_yield(v
))) {
4224 rb_ary_push(result
, v
);
4231 reject_bang_i(VALUE a
)
4233 volatile struct select_bang_arg
*arg
= (void *)a
;
4234 VALUE ary
= arg
->ary
;
4237 for (i1
= i2
= 0; i1
< RARRAY_LEN(ary
); arg
->len
[0] = ++i1
) {
4238 VALUE v
= RARRAY_AREF(ary
, i1
);
4239 if (RTEST(rb_yield(v
))) continue;
4241 rb_ary_store(ary
, i2
, v
);
4245 return (i1
== i2
) ? Qnil
: ary
;
4249 ary_reject_bang(VALUE ary
)
4251 struct select_bang_arg args
;
4252 rb_ary_modify_check(ary
);
4254 args
.len
[0] = args
.len
[1] = 0;
4255 return rb_ensure(reject_bang_i
, (VALUE
)&args
, select_bang_ensure
, (VALUE
)&args
);
4260 * array.reject! {|element| ... } -> self or nil
4261 * array.reject! -> new_enumerator
4263 * Removes each element for which the block returns a truthy value.
4265 * Returns +self+ if any elements removed:
4267 * a = [:foo, 'bar', 2, 'bat']
4268 * a.reject! {|element| element.to_s.start_with?('b') } # => [:foo, 2]
4270 * Returns +nil+ if no elements removed.
4272 * Returns a new Enumerator if no block given:
4274 * a = [:foo, 'bar', 2]
4275 * a.reject! # => #<Enumerator: [:foo, "bar", 2]:reject!>
4280 rb_ary_reject_bang(VALUE ary
)
4282 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
4284 return ary_reject_bang(ary
);
4289 * array.reject {|element| ... } -> new_array
4290 * array.reject -> new_enumerator
4292 * Returns a new +Array+ whose elements are all those from +self+
4293 * for which the block returns +false+ or +nil+:
4295 * a = [:foo, 'bar', 2, 'bat']
4296 * a1 = a.reject {|element| element.to_s.start_with?('b') }
4299 * Returns a new Enumerator if no block given:
4301 * a = [:foo, 'bar', 2]
4302 * a.reject # => #<Enumerator: [:foo, "bar", 2]:reject>
4307 rb_ary_reject(VALUE ary
)
4311 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
4312 rejected_ary
= rb_ary_new();
4313 ary_reject(ary
, rejected_ary
);
4314 return rejected_ary
;
4319 * array.delete_if {|element| ... } -> self
4320 * array.delete_if -> Enumerator
4322 * Removes each element in +self+ for which the block returns a truthy value;
4325 * a = [:foo, 'bar', 2, 'bat']
4326 * a.delete_if {|element| element.to_s.start_with?('b') } # => [:foo, 2]
4328 * Returns a new Enumerator if no block given:
4330 * a = [:foo, 'bar', 2]
4331 * a.delete_if # => #<Enumerator: [:foo, "bar", 2]:delete_if>
4336 rb_ary_delete_if(VALUE ary
)
4339 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
4340 ary_reject_bang(ary
);
4345 take_i(RB_BLOCK_CALL_FUNC_ARGLIST(val
, cbarg
))
4347 VALUE
*args
= (VALUE
*)cbarg
;
4348 if (argc
> 1) val
= rb_ary_new4(argc
, argv
);
4349 rb_ary_push(args
[0], val
);
4350 if (--args
[1] == 0) rb_iter_break();
4355 take_items(VALUE obj
, long n
)
4357 VALUE result
= rb_check_array_type(obj
);
4360 if (n
== 0) return result
;
4361 if (!NIL_P(result
)) return rb_ary_subseq(result
, 0, n
);
4362 result
= rb_ary_new2(n
);
4363 args
[0] = result
; args
[1] = (VALUE
)n
;
4364 if (UNDEF_P(rb_check_block_call(obj
, idEach
, 0, 0, take_i
, (VALUE
)args
)))
4365 rb_raise(rb_eTypeError
, "wrong argument type %"PRIsVALUE
" (must respond to :each)",
4373 * array.zip(*other_arrays) -> new_array
4374 * array.zip(*other_arrays) {|other_array| ... } -> nil
4376 * When no block given, returns a new +Array+ +new_array+ of size <tt>self.size</tt>
4377 * whose elements are Arrays.
4379 * Each nested array <tt>new_array[n]</tt> is of size <tt>other_arrays.size+1</tt>,
4382 * - The _nth_ element of +self+.
4383 * - The _nth_ element of each of the +other_arrays+.
4385 * If all +other_arrays+ and +self+ are the same size:
4387 * a = [:a0, :a1, :a2, :a3]
4388 * b = [:b0, :b1, :b2, :b3]
4389 * c = [:c0, :c1, :c2, :c3]
4391 * d # => [[:a0, :b0, :c0], [:a1, :b1, :c1], [:a2, :b2, :c2], [:a3, :b3, :c3]]
4393 * If any array in +other_arrays+ is smaller than +self+,
4394 * fills to <tt>self.size</tt> with +nil+:
4396 * a = [:a0, :a1, :a2, :a3]
4397 * b = [:b0, :b1, :b2]
4400 * d # => [[:a0, :b0, :c0], [:a1, :b1, :c1], [:a2, :b2, nil], [:a3, nil, nil]]
4402 * If any array in +other_arrays+ is larger than +self+,
4403 * its trailing elements are ignored:
4405 * a = [:a0, :a1, :a2, :a3]
4406 * b = [:b0, :b1, :b2, :b3, :b4]
4407 * c = [:c0, :c1, :c2, :c3, :c4, :c5]
4409 * d # => [[:a0, :b0, :c0], [:a1, :b1, :c1], [:a2, :b2, :c2], [:a3, :b3, :c3]]
4411 * If an argument is not an array, it extracts the values by calling #each:
4413 * a = [:a0, :a1, :a2, :a2]
4416 * c # => [[:a0, 1], [:a1, 2], [:a2, 3], [:a2, 4]]
4418 * When a block is given, calls the block with each of the sub-arrays (formed as above); returns +nil+:
4420 * a = [:a0, :a1, :a2, :a3]
4421 * b = [:b0, :b1, :b2, :b3]
4422 * c = [:c0, :c1, :c2, :c3]
4423 * a.zip(b, c) {|sub_array| p sub_array} # => nil
4435 rb_ary_zip(int argc
, VALUE
*argv
, VALUE ary
)
4438 long len
= RARRAY_LEN(ary
);
4439 VALUE result
= Qnil
;
4441 for (i
=0; i
<argc
; i
++) {
4442 argv
[i
] = take_items(argv
[i
], len
);
4445 if (rb_block_given_p()) {
4446 int arity
= rb_block_arity();
4451 tmp
= ALLOCV_N(VALUE
, work
, argc
+1);
4453 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
4454 tmp
[0] = RARRAY_AREF(ary
, i
);
4455 for (j
=0; j
<argc
; j
++) {
4456 tmp
[j
+1] = rb_ary_elt(argv
[j
], i
);
4458 rb_yield_values2(argc
+1, tmp
);
4461 if (work
) ALLOCV_END(work
);
4464 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
4465 VALUE tmp
= rb_ary_new2(argc
+1);
4467 rb_ary_push(tmp
, RARRAY_AREF(ary
, i
));
4468 for (j
=0; j
<argc
; j
++) {
4469 rb_ary_push(tmp
, rb_ary_elt(argv
[j
], i
));
4476 result
= rb_ary_new_capa(len
);
4478 for (i
=0; i
<len
; i
++) {
4479 VALUE tmp
= rb_ary_new_capa(argc
+1);
4481 rb_ary_push(tmp
, RARRAY_AREF(ary
, i
));
4482 for (j
=0; j
<argc
; j
++) {
4483 rb_ary_push(tmp
, rb_ary_elt(argv
[j
], i
));
4485 rb_ary_push(result
, tmp
);
4494 * array.transpose -> new_array
4496 * Transposes the rows and columns in an +Array+ of Arrays;
4497 * the nested Arrays must all be the same size:
4499 * a = [[:a0, :a1], [:b0, :b1], [:c0, :c1]]
4500 * a.transpose # => [[:a0, :b0, :c0], [:a1, :b1, :c1]]
4505 rb_ary_transpose(VALUE ary
)
4507 long elen
= -1, alen
, i
, j
;
4508 VALUE tmp
, result
= 0;
4510 alen
= RARRAY_LEN(ary
);
4511 if (alen
== 0) return rb_ary_dup(ary
);
4512 for (i
=0; i
<alen
; i
++) {
4513 tmp
= to_ary(rb_ary_elt(ary
, i
));
4514 if (elen
< 0) { /* first element */
4515 elen
= RARRAY_LEN(tmp
);
4516 result
= rb_ary_new2(elen
);
4517 for (j
=0; j
<elen
; j
++) {
4518 rb_ary_store(result
, j
, rb_ary_new2(alen
));
4521 else if (elen
!= RARRAY_LEN(tmp
)) {
4522 rb_raise(rb_eIndexError
, "element size differs (%ld should be %ld)",
4523 RARRAY_LEN(tmp
), elen
);
4525 for (j
=0; j
<elen
; j
++) {
4526 rb_ary_store(rb_ary_elt(result
, j
), i
, rb_ary_elt(tmp
, j
));
4534 * array.replace(other_array) -> self
4536 * Replaces the content of +self+ with the content of +other_array+; returns +self+:
4538 * a = [:foo, 'bar', 2]
4539 * a.replace(['foo', :bar, 3]) # => ["foo", :bar, 3]
4544 rb_ary_replace(VALUE copy
, VALUE orig
)
4546 rb_ary_modify_check(copy
);
4547 orig
= to_ary(orig
);
4548 if (copy
== orig
) return copy
;
4552 /* orig has enough space to embed the contents of orig. */
4553 if (RARRAY_LEN(orig
) <= ary_embed_capa(copy
)) {
4554 RUBY_ASSERT(ARY_EMBED_P(copy
));
4555 ary_memcpy(copy
, 0, RARRAY_LEN(orig
), RARRAY_CONST_PTR(orig
));
4556 ARY_SET_EMBED_LEN(copy
, RARRAY_LEN(orig
));
4558 /* orig is embedded but copy does not have enough space to embed the
4559 * contents of orig. */
4560 else if (ARY_EMBED_P(orig
)) {
4561 long len
= ARY_EMBED_LEN(orig
);
4562 VALUE
*ptr
= ary_heap_alloc_buffer(len
);
4564 FL_UNSET_EMBED(copy
);
4565 ARY_SET_PTR(copy
, ptr
);
4566 ARY_SET_LEN(copy
, len
);
4567 ARY_SET_CAPA(copy
, len
);
4569 // No allocation and exception expected that could leave `copy` in a
4570 // bad state from the edits above.
4571 ary_memcpy(copy
, 0, len
, RARRAY_CONST_PTR(orig
));
4573 /* Otherwise, orig is on heap and copy does not have enough space to embed
4574 * the contents of orig. */
4576 VALUE shared_root
= ary_make_shared(orig
);
4577 FL_UNSET_EMBED(copy
);
4578 ARY_SET_PTR(copy
, ARY_HEAP_PTR(orig
));
4579 ARY_SET_LEN(copy
, ARY_HEAP_LEN(orig
));
4580 rb_ary_set_shared(copy
, shared_root
);
4588 * array.clear -> self
4590 * Removes all elements from +self+:
4592 * a = [:foo, 'bar', 2]
4598 rb_ary_clear(VALUE ary
)
4600 rb_ary_modify_check(ary
);
4601 if (ARY_SHARED_P(ary
)) {
4602 if (!ARY_EMBED_P(ary
)) {
4603 rb_ary_unshare(ary
);
4605 ARY_SET_EMBED_LEN(ary
, 0);
4609 ARY_SET_LEN(ary
, 0);
4610 if (ARY_DEFAULT_SIZE
* 2 < ARY_CAPA(ary
)) {
4611 ary_resize_capa(ary
, ARY_DEFAULT_SIZE
* 2);
4620 * array.fill(obj) -> self
4621 * array.fill(obj, start) -> self
4622 * array.fill(obj, start, length) -> self
4623 * array.fill(obj, range) -> self
4624 * array.fill {|index| ... } -> self
4625 * array.fill(start) {|index| ... } -> self
4626 * array.fill(start, length) {|index| ... } -> self
4627 * array.fill(range) {|index| ... } -> self
4629 * Replaces specified elements in +self+ with specified objects; returns +self+.
4631 * With argument +obj+ and no block given, replaces all elements with that one object:
4633 * a = ['a', 'b', 'c', 'd']
4634 * a # => ["a", "b", "c", "d"]
4635 * a.fill(:X) # => [:X, :X, :X, :X]
4637 * With arguments +obj+ and Integer +start+, and no block given,
4638 * replaces elements based on the given start.
4640 * If +start+ is in range (<tt>0 <= start < array.size</tt>),
4641 * replaces all elements from offset +start+ through the end:
4643 * a = ['a', 'b', 'c', 'd']
4644 * a.fill(:X, 2) # => ["a", "b", :X, :X]
4646 * If +start+ is too large (<tt>start >= array.size</tt>), does nothing:
4648 * a = ['a', 'b', 'c', 'd']
4649 * a.fill(:X, 4) # => ["a", "b", "c", "d"]
4650 * a = ['a', 'b', 'c', 'd']
4651 * a.fill(:X, 5) # => ["a", "b", "c", "d"]
4653 * If +start+ is negative, counts from the end (starting index is <tt>start + array.size</tt>):
4655 * a = ['a', 'b', 'c', 'd']
4656 * a.fill(:X, -2) # => ["a", "b", :X, :X]
4658 * If +start+ is too small (less than and far from zero), replaces all elements:
4660 * a = ['a', 'b', 'c', 'd']
4661 * a.fill(:X, -6) # => [:X, :X, :X, :X]
4662 * a = ['a', 'b', 'c', 'd']
4663 * a.fill(:X, -50) # => [:X, :X, :X, :X]
4665 * With arguments +obj+, Integer +start+, and Integer +length+, and no block given,
4666 * replaces elements based on the given +start+ and +length+.
4668 * If +start+ is in range, replaces +length+ elements beginning at offset +start+:
4670 * a = ['a', 'b', 'c', 'd']
4671 * a.fill(:X, 1, 1) # => ["a", :X, "c", "d"]
4673 * If +start+ is negative, counts from the end:
4675 * a = ['a', 'b', 'c', 'd']
4676 * a.fill(:X, -2, 1) # => ["a", "b", :X, "d"]
4678 * If +start+ is large (<tt>start >= array.size</tt>), extends +self+ with +nil+:
4680 * a = ['a', 'b', 'c', 'd']
4681 * a.fill(:X, 5, 0) # => ["a", "b", "c", "d", nil]
4682 * a = ['a', 'b', 'c', 'd']
4683 * a.fill(:X, 5, 2) # => ["a", "b", "c", "d", nil, :X, :X]
4685 * If +length+ is zero or negative, replaces no elements:
4687 * a = ['a', 'b', 'c', 'd']
4688 * a.fill(:X, 1, 0) # => ["a", "b", "c", "d"]
4689 * a.fill(:X, 1, -1) # => ["a", "b", "c", "d"]
4691 * With arguments +obj+ and Range +range+, and no block given,
4692 * replaces elements based on the given range.
4694 * If the range is positive and ascending (<tt>0 < range.begin <= range.end</tt>),
4695 * replaces elements from <tt>range.begin</tt> to <tt>range.end</tt>:
4697 * a = ['a', 'b', 'c', 'd']
4698 * a.fill(:X, (1..1)) # => ["a", :X, "c", "d"]
4700 * If <tt>range.first</tt> is negative, replaces no elements:
4702 * a = ['a', 'b', 'c', 'd']
4703 * a.fill(:X, (-1..1)) # => ["a", "b", "c", "d"]
4705 * If <tt>range.last</tt> is negative, counts from the end:
4707 * a = ['a', 'b', 'c', 'd']
4708 * a.fill(:X, (0..-2)) # => [:X, :X, :X, "d"]
4709 * a = ['a', 'b', 'c', 'd']
4710 * a.fill(:X, (1..-2)) # => ["a", :X, :X, "d"]
4712 * If <tt>range.last</tt> and <tt>range.last</tt> are both negative,
4713 * both count from the end of the array:
4715 * a = ['a', 'b', 'c', 'd']
4716 * a.fill(:X, (-1..-1)) # => ["a", "b", "c", :X]
4717 * a = ['a', 'b', 'c', 'd']
4718 * a.fill(:X, (-2..-2)) # => ["a", "b", :X, "d"]
4720 * With no arguments and a block given, calls the block with each index;
4721 * replaces the corresponding element with the block's return value:
4723 * a = ['a', 'b', 'c', 'd']
4724 * a.fill { |index| "new_#{index}" } # => ["new_0", "new_1", "new_2", "new_3"]
4726 * With argument +start+ and a block given, calls the block with each index
4727 * from offset +start+ to the end; replaces the corresponding element
4728 * with the block's return value.
4730 * If start is in range (<tt>0 <= start < array.size</tt>),
4731 * replaces from offset +start+ to the end:
4733 * a = ['a', 'b', 'c', 'd']
4734 * a.fill(1) { |index| "new_#{index}" } # => ["a", "new_1", "new_2", "new_3"]
4736 * If +start+ is too large(<tt>start >= array.size</tt>), does nothing:
4738 * a = ['a', 'b', 'c', 'd']
4739 * a.fill(4) { |index| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4740 * a = ['a', 'b', 'c', 'd']
4741 * a.fill(4) { |index| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4743 * If +start+ is negative, counts from the end:
4745 * a = ['a', 'b', 'c', 'd']
4746 * a.fill(-2) { |index| "new_#{index}" } # => ["a", "b", "new_2", "new_3"]
4748 * If start is too small (<tt>start <= -array.size</tt>, replaces all elements:
4750 * a = ['a', 'b', 'c', 'd']
4751 * a.fill(-6) { |index| "new_#{index}" } # => ["new_0", "new_1", "new_2", "new_3"]
4752 * a = ['a', 'b', 'c', 'd']
4753 * a.fill(-50) { |index| "new_#{index}" } # => ["new_0", "new_1", "new_2", "new_3"]
4755 * With arguments +start+ and +length+, and a block given,
4756 * calls the block for each index specified by start length;
4757 * replaces the corresponding element with the block's return value.
4759 * If +start+ is in range, replaces +length+ elements beginning at offset +start+:
4761 * a = ['a', 'b', 'c', 'd']
4762 * a.fill(1, 1) { |index| "new_#{index}" } # => ["a", "new_1", "c", "d"]
4764 * If start is negative, counts from the end:
4766 * a = ['a', 'b', 'c', 'd']
4767 * a.fill(-2, 1) { |index| "new_#{index}" } # => ["a", "b", "new_2", "d"]
4769 * If +start+ is large (<tt>start >= array.size</tt>), extends +self+ with +nil+:
4771 * a = ['a', 'b', 'c', 'd']
4772 * a.fill(5, 0) { |index| "new_#{index}" } # => ["a", "b", "c", "d", nil]
4773 * a = ['a', 'b', 'c', 'd']
4774 * a.fill(5, 2) { |index| "new_#{index}" } # => ["a", "b", "c", "d", nil, "new_5", "new_6"]
4776 * If +length+ is zero or less, replaces no elements:
4778 * a = ['a', 'b', 'c', 'd']
4779 * a.fill(1, 0) { |index| "new_#{index}" } # => ["a", "b", "c", "d"]
4780 * a.fill(1, -1) { |index| "new_#{index}" } # => ["a", "b", "c", "d"]
4782 * With arguments +obj+ and +range+, and a block given,
4783 * calls the block with each index in the given range;
4784 * replaces the corresponding element with the block's return value.
4786 * If the range is positive and ascending (<tt>range 0 < range.begin <= range.end</tt>,
4787 * replaces elements from <tt>range.begin</tt> to <tt>range.end</tt>:
4789 * a = ['a', 'b', 'c', 'd']
4790 * a.fill(1..1) { |index| "new_#{index}" } # => ["a", "new_1", "c", "d"]
4792 * If +range.first+ is negative, does nothing:
4794 * a = ['a', 'b', 'c', 'd']
4795 * a.fill(-1..1) { |index| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4797 * If <tt>range.last</tt> is negative, counts from the end:
4799 * a = ['a', 'b', 'c', 'd']
4800 * a.fill(0..-2) { |index| "new_#{index}" } # => ["new_0", "new_1", "new_2", "d"]
4801 * a = ['a', 'b', 'c', 'd']
4802 * a.fill(1..-2) { |index| "new_#{index}" } # => ["a", "new_1", "new_2", "d"]
4804 * If <tt>range.first</tt> and <tt>range.last</tt> are both negative,
4805 * both count from the end:
4807 * a = ['a', 'b', 'c', 'd']
4808 * a.fill(-1..-1) { |index| "new_#{index}" } # => ["a", "b", "c", "new_3"]
4809 * a = ['a', 'b', 'c', 'd']
4810 * a.fill(-2..-2) { |index| "new_#{index}" } # => ["a", "b", "new_2", "d"]
4815 rb_ary_fill(int argc
, VALUE
*argv
, VALUE ary
)
4817 VALUE item
= Qundef
, arg1
, arg2
;
4818 long beg
= 0, end
= 0, len
= 0;
4820 if (rb_block_given_p()) {
4821 rb_scan_args(argc
, argv
, "02", &arg1
, &arg2
);
4822 argc
+= 1; /* hackish */
4825 rb_scan_args(argc
, argv
, "12", &item
, &arg1
, &arg2
);
4830 len
= RARRAY_LEN(ary
);
4833 if (rb_range_beg_len(arg1
, &beg
, &len
, RARRAY_LEN(ary
), 1)) {
4838 beg
= NIL_P(arg1
) ? 0 : NUM2LONG(arg1
);
4840 beg
= RARRAY_LEN(ary
) + beg
;
4841 if (beg
< 0) beg
= 0;
4843 len
= NIL_P(arg2
) ? RARRAY_LEN(ary
) - beg
: NUM2LONG(arg2
);
4850 if (beg
>= ARY_MAX_SIZE
|| len
> ARY_MAX_SIZE
- beg
) {
4851 rb_raise(rb_eArgError
, "argument too big");
4854 if (RARRAY_LEN(ary
) < end
) {
4855 if (end
>= ARY_CAPA(ary
)) {
4856 ary_resize_capa(ary
, end
);
4858 ary_mem_clear(ary
, RARRAY_LEN(ary
), end
- RARRAY_LEN(ary
));
4859 ARY_SET_LEN(ary
, end
);
4862 if (UNDEF_P(item
)) {
4866 for (i
=beg
; i
<end
; i
++) {
4867 v
= rb_yield(LONG2NUM(i
));
4868 if (i
>=RARRAY_LEN(ary
)) break;
4873 ary_memfill(ary
, beg
, len
, item
);
4880 * array + other_array -> new_array
4882 * Returns a new +Array+ containing all elements of +array+
4883 * followed by all elements of +other_array+:
4885 * a = [0, 1] + [2, 3]
4886 * a # => [0, 1, 2, 3]
4892 rb_ary_plus(VALUE x
, VALUE y
)
4895 long len
, xlen
, ylen
;
4898 xlen
= RARRAY_LEN(x
);
4899 ylen
= RARRAY_LEN(y
);
4901 z
= rb_ary_new2(len
);
4903 ary_memcpy(z
, 0, xlen
, RARRAY_CONST_PTR(x
));
4904 ary_memcpy(z
, xlen
, ylen
, RARRAY_CONST_PTR(y
));
4905 ARY_SET_LEN(z
, len
);
4910 ary_append(VALUE x
, VALUE y
)
4912 long n
= RARRAY_LEN(y
);
4914 rb_ary_splice(x
, RARRAY_LEN(x
), 0, RARRAY_CONST_PTR(y
), n
);
4922 * array.concat(*other_arrays) -> self
4924 * Adds to +array+ all elements from each +Array+ in +other_arrays+; returns +self+:
4927 * a.concat([2, 3], [4, 5]) # => [0, 1, 2, 3, 4, 5]
4931 rb_ary_concat_multi(int argc
, VALUE
*argv
, VALUE ary
)
4933 rb_ary_modify_check(ary
);
4936 rb_ary_concat(ary
, argv
[0]);
4938 else if (argc
> 1) {
4940 VALUE args
= rb_ary_hidden_new(argc
);
4941 for (i
= 0; i
< argc
; i
++) {
4942 rb_ary_concat(args
, argv
[i
]);
4944 ary_append(ary
, args
);
4952 rb_ary_concat(VALUE x
, VALUE y
)
4954 return ary_append(x
, to_ary(y
));
4959 * array * n -> new_array
4960 * array * string_separator -> new_string
4962 * When non-negative argument Integer +n+ is given,
4963 * returns a new +Array+ built by concatenating the +n+ copies of +self+:
4966 * a * 3 # => ["x", "y", "x", "y", "x", "y"]
4968 * When String argument +string_separator+ is given,
4969 * equivalent to <tt>array.join(string_separator)</tt>:
4971 * [0, [0, 1], {foo: 0}] * ', ' # => "0, 0, 1, {:foo=>0}"
4976 rb_ary_times(VALUE ary
, VALUE times
)
4982 tmp
= rb_check_string_type(times
);
4984 return rb_ary_join(ary
, tmp
);
4987 len
= NUM2LONG(times
);
4989 ary2
= ary_new(rb_cArray
, 0);
4993 rb_raise(rb_eArgError
, "negative argument");
4995 if (ARY_MAX_SIZE
/len
< RARRAY_LEN(ary
)) {
4996 rb_raise(rb_eArgError
, "argument too big");
4998 len
*= RARRAY_LEN(ary
);
5000 ary2
= ary_new(rb_cArray
, len
);
5001 ARY_SET_LEN(ary2
, len
);
5003 ptr
= RARRAY_CONST_PTR(ary
);
5004 t
= RARRAY_LEN(ary
);
5006 ary_memcpy(ary2
, 0, t
, ptr
);
5007 while (t
<= len
/2) {
5008 ary_memcpy(ary2
, t
, t
, RARRAY_CONST_PTR(ary2
));
5012 ary_memcpy(ary2
, t
, len
-t
, RARRAY_CONST_PTR(ary2
));
5021 * array.assoc(obj) -> found_array or nil
5023 * Returns the first element in +self+ that is an +Array+
5024 * whose first element <tt>==</tt> +obj+:
5026 * a = [{foo: 0}, [2, 4], [4, 5, 6], [4, 5]]
5027 * a.assoc(4) # => [4, 5, 6]
5029 * Returns +nil+ if no such element is found.
5035 rb_ary_assoc(VALUE ary
, VALUE key
)
5040 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
5041 v
= rb_check_array_type(RARRAY_AREF(ary
, i
));
5042 if (!NIL_P(v
) && RARRAY_LEN(v
) > 0 &&
5043 rb_equal(RARRAY_AREF(v
, 0), key
))
5051 * array.rassoc(obj) -> found_array or nil
5053 * Returns the first element in +self+ that is an +Array+
5054 * whose second element <tt>==</tt> +obj+:
5056 * a = [{foo: 0}, [2, 4], [4, 5, 6], [4, 5]]
5057 * a.rassoc(4) # => [2, 4]
5059 * Returns +nil+ if no such element is found.
5065 rb_ary_rassoc(VALUE ary
, VALUE value
)
5070 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
5071 v
= rb_check_array_type(RARRAY_AREF(ary
, i
));
5072 if (RB_TYPE_P(v
, T_ARRAY
) &&
5073 RARRAY_LEN(v
) > 1 &&
5074 rb_equal(RARRAY_AREF(v
, 1), value
))
5081 recursive_equal(VALUE ary1
, VALUE ary2
, int recur
)
5084 const VALUE
*p1
, *p2
;
5086 if (recur
) return Qtrue
; /* Subtle! */
5088 /* rb_equal() can evacuate ptrs */
5089 p1
= RARRAY_CONST_PTR(ary1
);
5090 p2
= RARRAY_CONST_PTR(ary2
);
5091 len1
= RARRAY_LEN(ary1
);
5093 for (i
= 0; i
< len1
; i
++) {
5095 if (rb_equal(*p1
, *p2
)) {
5096 len1
= RARRAY_LEN(ary1
);
5097 if (len1
!= RARRAY_LEN(ary2
))
5101 p1
= RARRAY_CONST_PTR(ary1
) + i
;
5102 p2
= RARRAY_CONST_PTR(ary2
) + i
;
5116 * array == other_array -> true or false
5118 * Returns +true+ if both <tt>array.size == other_array.size</tt>
5119 * and for each index +i+ in +array+, <tt>array[i] == other_array[i]</tt>:
5121 * a0 = [:foo, 'bar', 2]
5122 * a1 = [:foo, 'bar', 2.0]
5123 * a1 == a0 # => true
5124 * [] == [] # => true
5126 * Otherwise, returns +false+.
5128 * This method is different from method Array#eql?,
5129 * which compares elements using <tt>Object#eql?</tt>.
5133 rb_ary_equal(VALUE ary1
, VALUE ary2
)
5135 if (ary1
== ary2
) return Qtrue
;
5136 if (!RB_TYPE_P(ary2
, T_ARRAY
)) {
5137 if (!rb_respond_to(ary2
, idTo_ary
)) {
5140 return rb_equal(ary2
, ary1
);
5142 if (RARRAY_LEN(ary1
) != RARRAY_LEN(ary2
)) return Qfalse
;
5143 if (RARRAY_CONST_PTR(ary1
) == RARRAY_CONST_PTR(ary2
)) return Qtrue
;
5144 return rb_exec_recursive_paired(recursive_equal
, ary1
, ary2
, ary2
);
5148 recursive_eql(VALUE ary1
, VALUE ary2
, int recur
)
5152 if (recur
) return Qtrue
; /* Subtle! */
5153 for (i
=0; i
<RARRAY_LEN(ary1
); i
++) {
5154 if (!rb_eql(rb_ary_elt(ary1
, i
), rb_ary_elt(ary2
, i
)))
5162 * array.eql?(other_array) -> true or false
5164 * Returns +true+ if +self+ and +other_array+ are the same size,
5165 * and if, for each index +i+ in +self+, <tt>self[i].eql?(other_array[i])</tt>:
5167 * a0 = [:foo, 'bar', 2]
5168 * a1 = [:foo, 'bar', 2]
5169 * a1.eql?(a0) # => true
5171 * Otherwise, returns +false+.
5173 * This method is different from method Array#==,
5174 * which compares using method <tt>Object#==</tt>.
5178 rb_ary_eql(VALUE ary1
, VALUE ary2
)
5180 if (ary1
== ary2
) return Qtrue
;
5181 if (!RB_TYPE_P(ary2
, T_ARRAY
)) return Qfalse
;
5182 if (RARRAY_LEN(ary1
) != RARRAY_LEN(ary2
)) return Qfalse
;
5183 if (RARRAY_CONST_PTR(ary1
) == RARRAY_CONST_PTR(ary2
)) return Qtrue
;
5184 return rb_exec_recursive_paired(recursive_eql
, ary1
, ary2
, ary2
);
5188 rb_ary_hash_values(long len
, const VALUE
*elements
)
5194 h
= rb_hash_start(len
);
5195 h
= rb_hash_uint(h
, (st_index_t
)rb_ary_hash_values
);
5196 for (i
=0; i
<len
; i
++) {
5197 n
= rb_hash(elements
[i
]);
5198 h
= rb_hash_uint(h
, NUM2LONG(n
));
5206 * array.hash -> integer
5208 * Returns the integer hash value for +self+.
5210 * Two arrays with the same content will have the same hash code (and will compare using #eql?):
5212 * [0, 1, 2].hash == [0, 1, 2].hash # => true
5213 * [0, 1, 2].hash == [0, 1, 3].hash # => false
5218 rb_ary_hash(VALUE ary
)
5220 return rb_ary_hash_values(RARRAY_LEN(ary
), RARRAY_CONST_PTR(ary
));
5225 * array.include?(obj) -> true or false
5227 * Returns +true+ if for some index +i+ in +self+, <tt>obj == self[i]</tt>;
5228 * otherwise +false+:
5230 * [0, 1, 2].include?(2) # => true
5231 * [0, 1, 2].include?(3) # => false
5235 rb_ary_includes(VALUE ary
, VALUE item
)
5240 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
5241 e
= RARRAY_AREF(ary
, i
);
5242 if (rb_equal(e
, item
)) {
5250 rb_ary_includes_by_eql(VALUE ary
, VALUE item
)
5255 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
5256 e
= RARRAY_AREF(ary
, i
);
5257 if (rb_eql(item
, e
)) {
5265 recursive_cmp(VALUE ary1
, VALUE ary2
, int recur
)
5269 if (recur
) return Qundef
; /* Subtle! */
5270 len
= RARRAY_LEN(ary1
);
5271 if (len
> RARRAY_LEN(ary2
)) {
5272 len
= RARRAY_LEN(ary2
);
5274 for (i
=0; i
<len
; i
++) {
5275 VALUE e1
= rb_ary_elt(ary1
, i
), e2
= rb_ary_elt(ary2
, i
);
5276 VALUE v
= rb_funcallv(e1
, id_cmp
, 1, &e2
);
5277 if (v
!= INT2FIX(0)) {
5286 * array <=> other_array -> -1, 0, or 1
5288 * Returns -1, 0, or 1 as +self+ is less than, equal to, or greater than +other_array+.
5289 * For each index +i+ in +self+, evaluates <tt>result = self[i] <=> other_array[i]</tt>.
5291 * Returns -1 if any result is -1:
5293 * [0, 1, 2] <=> [0, 1, 3] # => -1
5295 * Returns 1 if any result is 1:
5297 * [0, 1, 2] <=> [0, 1, 1] # => 1
5299 * When all results are zero:
5301 * - Returns -1 if +array+ is smaller than +other_array+:
5303 * [0, 1, 2] <=> [0, 1, 2, 3] # => -1
5305 * - Returns 1 if +array+ is larger than +other_array+:
5307 * [0, 1, 2] <=> [0, 1] # => 1
5309 * - Returns 0 if +array+ and +other_array+ are the same size:
5311 * [0, 1, 2] <=> [0, 1, 2] # => 0
5316 rb_ary_cmp(VALUE ary1
, VALUE ary2
)
5321 ary2
= rb_check_array_type(ary2
);
5322 if (NIL_P(ary2
)) return Qnil
;
5323 if (ary1
== ary2
) return INT2FIX(0);
5324 v
= rb_exec_recursive_paired(recursive_cmp
, ary1
, ary2
, ary2
);
5325 if (!UNDEF_P(v
)) return v
;
5326 len
= RARRAY_LEN(ary1
) - RARRAY_LEN(ary2
);
5327 if (len
== 0) return INT2FIX(0);
5328 if (len
> 0) return INT2FIX(1);
5333 ary_add_hash(VALUE hash
, VALUE ary
)
5337 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
5338 VALUE elt
= RARRAY_AREF(ary
, i
);
5339 rb_hash_add_new_element(hash
, elt
, elt
);
5345 ary_tmp_hash_new(VALUE ary
)
5347 long size
= RARRAY_LEN(ary
);
5348 VALUE hash
= rb_hash_new_with_size(size
);
5350 RBASIC_CLEAR_CLASS(hash
);
5355 ary_make_hash(VALUE ary
)
5357 VALUE hash
= ary_tmp_hash_new(ary
);
5358 return ary_add_hash(hash
, ary
);
5362 ary_add_hash_by(VALUE hash
, VALUE ary
)
5366 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
5367 VALUE v
= rb_ary_elt(ary
, i
), k
= rb_yield(v
);
5368 rb_hash_add_new_element(hash
, k
, v
);
5374 ary_make_hash_by(VALUE ary
)
5376 VALUE hash
= ary_tmp_hash_new(ary
);
5377 return ary_add_hash_by(hash
, ary
);
5382 * array - other_array -> new_array
5384 * Returns a new +Array+ containing only those elements from +array+
5385 * that are not found in +Array+ +other_array+;
5386 * items are compared using <tt>eql?</tt>;
5387 * the order from +array+ is preserved:
5389 * [0, 1, 1, 2, 1, 1, 3, 1, 1] - [1] # => [0, 2, 3]
5390 * [0, 1, 2, 3] - [3, 0] # => [1, 2]
5391 * [0, 1, 2] - [4] # => [0, 1, 2]
5393 * Related: Array#difference.
5397 rb_ary_diff(VALUE ary1
, VALUE ary2
)
5403 ary2
= to_ary(ary2
);
5404 if (RARRAY_LEN(ary2
) == 0) { return ary_make_shared_copy(ary1
); }
5405 ary3
= rb_ary_new();
5407 if (RARRAY_LEN(ary1
) <= SMALL_ARRAY_LEN
|| RARRAY_LEN(ary2
) <= SMALL_ARRAY_LEN
) {
5408 for (i
=0; i
<RARRAY_LEN(ary1
); i
++) {
5409 VALUE elt
= rb_ary_elt(ary1
, i
);
5410 if (rb_ary_includes_by_eql(ary2
, elt
)) continue;
5411 rb_ary_push(ary3
, elt
);
5416 hash
= ary_make_hash(ary2
);
5417 for (i
=0; i
<RARRAY_LEN(ary1
); i
++) {
5418 if (rb_hash_stlike_lookup(hash
, RARRAY_AREF(ary1
, i
), NULL
)) continue;
5419 rb_ary_push(ary3
, rb_ary_elt(ary1
, i
));
5427 * array.difference(*other_arrays) -> new_array
5429 * Returns a new +Array+ containing only those elements from +self+
5430 * that are not found in any of the Arrays +other_arrays+;
5431 * items are compared using <tt>eql?</tt>; order from +self+ is preserved:
5433 * [0, 1, 1, 2, 1, 1, 3, 1, 1].difference([1]) # => [0, 2, 3]
5434 * [0, 1, 2, 3].difference([3, 0], [1, 3]) # => [2]
5435 * [0, 1, 2].difference([4]) # => [0, 1, 2]
5437 * Returns a copy of +self+ if no arguments given.
5443 rb_ary_difference_multi(int argc
, VALUE
*argv
, VALUE ary
)
5448 bool *is_hash
= ALLOCV_N(bool, t0
, argc
);
5449 ary_diff
= rb_ary_new();
5450 length
= RARRAY_LEN(ary
);
5452 for (i
= 0; i
< argc
; i
++) {
5453 argv
[i
] = to_ary(argv
[i
]);
5454 is_hash
[i
] = (length
> SMALL_ARRAY_LEN
&& RARRAY_LEN(argv
[i
]) > SMALL_ARRAY_LEN
);
5455 if (is_hash
[i
]) argv
[i
] = ary_make_hash(argv
[i
]);
5458 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
5460 VALUE elt
= rb_ary_elt(ary
, i
);
5461 for (j
= 0; j
< argc
; j
++) {
5463 if (rb_hash_stlike_lookup(argv
[j
], RARRAY_AREF(ary
, i
), NULL
))
5467 if (rb_ary_includes_by_eql(argv
[j
], elt
)) break;
5470 if (j
== argc
) rb_ary_push(ary_diff
, elt
);
5481 * array & other_array -> new_array
5483 * Returns a new +Array+ containing each element found in both +array+ and +Array+ +other_array+;
5484 * duplicates are omitted; items are compared using <tt>eql?</tt>
5485 * (items must also implement +hash+ correctly):
5487 * [0, 1, 2, 3] & [1, 2] # => [1, 2]
5488 * [0, 1, 0, 1] & [0, 1] # => [0, 1]
5490 * Preserves order from +array+:
5492 * [0, 1, 2] & [3, 2, 1, 0] # => [0, 1, 2]
5494 * Related: Array#intersection.
5499 rb_ary_and(VALUE ary1
, VALUE ary2
)
5501 VALUE hash
, ary3
, v
;
5505 ary2
= to_ary(ary2
);
5506 ary3
= rb_ary_new();
5507 if (RARRAY_LEN(ary1
) == 0 || RARRAY_LEN(ary2
) == 0) return ary3
;
5509 if (RARRAY_LEN(ary1
) <= SMALL_ARRAY_LEN
&& RARRAY_LEN(ary2
) <= SMALL_ARRAY_LEN
) {
5510 for (i
=0; i
<RARRAY_LEN(ary1
); i
++) {
5511 v
= RARRAY_AREF(ary1
, i
);
5512 if (!rb_ary_includes_by_eql(ary2
, v
)) continue;
5513 if (rb_ary_includes_by_eql(ary3
, v
)) continue;
5514 rb_ary_push(ary3
, v
);
5519 hash
= ary_make_hash(ary2
);
5521 for (i
=0; i
<RARRAY_LEN(ary1
); i
++) {
5522 v
= RARRAY_AREF(ary1
, i
);
5524 if (rb_hash_stlike_delete(hash
, &vv
, 0)) {
5525 rb_ary_push(ary3
, v
);
5534 * array.intersection(*other_arrays) -> new_array
5536 * Returns a new +Array+ containing each element found both in +self+
5537 * and in all of the given Arrays +other_arrays+;
5538 * duplicates are omitted; items are compared using <tt>eql?</tt>
5539 * (items must also implement +hash+ correctly):
5541 * [0, 1, 2, 3].intersection([0, 1, 2], [0, 1, 3]) # => [0, 1]
5542 * [0, 0, 1, 1, 2, 3].intersection([0, 1, 2], [0, 1, 3]) # => [0, 1]
5544 * Preserves order from +self+:
5546 * [0, 1, 2].intersection([2, 1, 0]) # => [0, 1, 2]
5548 * Returns a copy of +self+ if no arguments given.
5554 rb_ary_intersection_multi(int argc
, VALUE
*argv
, VALUE ary
)
5556 VALUE result
= rb_ary_dup(ary
);
5559 for (i
= 0; i
< argc
; i
++) {
5560 result
= rb_ary_and(result
, argv
[i
]);
5567 ary_hash_orset(st_data_t
*key
, st_data_t
*value
, st_data_t arg
, int existing
)
5569 if (existing
) return ST_STOP
;
5570 *key
= *value
= (VALUE
)arg
;
5575 rb_ary_union(VALUE ary_union
, VALUE ary
)
5578 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
5579 VALUE elt
= rb_ary_elt(ary
, i
);
5580 if (rb_ary_includes_by_eql(ary_union
, elt
)) continue;
5581 rb_ary_push(ary_union
, elt
);
5586 rb_ary_union_hash(VALUE hash
, VALUE ary2
)
5589 for (i
= 0; i
< RARRAY_LEN(ary2
); i
++) {
5590 VALUE elt
= RARRAY_AREF(ary2
, i
);
5591 if (!rb_hash_stlike_update(hash
, (st_data_t
)elt
, ary_hash_orset
, (st_data_t
)elt
)) {
5592 RB_OBJ_WRITTEN(hash
, Qundef
, elt
);
5599 * array | other_array -> new_array
5601 * Returns the union of +array+ and +Array+ +other_array+;
5602 * duplicates are removed; order is preserved;
5603 * items are compared using <tt>eql?</tt>:
5605 * [0, 1] | [2, 3] # => [0, 1, 2, 3]
5606 * [0, 1, 1] | [2, 2, 3] # => [0, 1, 2, 3]
5607 * [0, 1, 2] | [3, 2, 1, 0] # => [0, 1, 2, 3]
5609 * Related: Array#union.
5613 rb_ary_or(VALUE ary1
, VALUE ary2
)
5617 ary2
= to_ary(ary2
);
5618 if (RARRAY_LEN(ary1
) + RARRAY_LEN(ary2
) <= SMALL_ARRAY_LEN
) {
5619 VALUE ary3
= rb_ary_new();
5620 rb_ary_union(ary3
, ary1
);
5621 rb_ary_union(ary3
, ary2
);
5625 hash
= ary_make_hash(ary1
);
5626 rb_ary_union_hash(hash
, ary2
);
5628 return rb_hash_values(hash
);
5633 * array.union(*other_arrays) -> new_array
5635 * Returns a new +Array+ that is the union of +self+ and all given Arrays +other_arrays+;
5636 * duplicates are removed; order is preserved; items are compared using <tt>eql?</tt>:
5638 * [0, 1, 2, 3].union([4, 5], [6, 7]) # => [0, 1, 2, 3, 4, 5, 6, 7]
5639 * [0, 1, 1].union([2, 1], [3, 1]) # => [0, 1, 2, 3]
5640 * [0, 1, 2, 3].union([3, 2], [1, 0]) # => [0, 1, 2, 3]
5642 * Returns a copy of +self+ if no arguments given.
5648 rb_ary_union_multi(int argc
, VALUE
*argv
, VALUE ary
)
5654 sum
= RARRAY_LEN(ary
);
5655 for (i
= 0; i
< argc
; i
++) {
5656 argv
[i
] = to_ary(argv
[i
]);
5657 sum
+= RARRAY_LEN(argv
[i
]);
5660 if (sum
<= SMALL_ARRAY_LEN
) {
5661 VALUE ary_union
= rb_ary_new();
5663 rb_ary_union(ary_union
, ary
);
5664 for (i
= 0; i
< argc
; i
++) rb_ary_union(ary_union
, argv
[i
]);
5669 hash
= ary_make_hash(ary
);
5670 for (i
= 0; i
< argc
; i
++) rb_ary_union_hash(hash
, argv
[i
]);
5672 return rb_hash_values(hash
);
5677 * ary.intersect?(other_ary) -> true or false
5679 * Returns +true+ if the array and +other_ary+ have at least one element in
5680 * common, otherwise returns +false+:
5685 * a.intersect?(b) #=> true
5686 * a.intersect?(c) #=> false
5688 * +Array+ elements are compared using <tt>eql?</tt>
5689 * (items must also implement +hash+ correctly).
5693 rb_ary_intersect_p(VALUE ary1
, VALUE ary2
)
5695 VALUE hash
, v
, result
, shorter
, longer
;
5699 ary2
= to_ary(ary2
);
5700 if (RARRAY_LEN(ary1
) == 0 || RARRAY_LEN(ary2
) == 0) return Qfalse
;
5702 if (RARRAY_LEN(ary1
) <= SMALL_ARRAY_LEN
&& RARRAY_LEN(ary2
) <= SMALL_ARRAY_LEN
) {
5703 for (i
=0; i
<RARRAY_LEN(ary1
); i
++) {
5704 v
= RARRAY_AREF(ary1
, i
);
5705 if (rb_ary_includes_by_eql(ary2
, v
)) return Qtrue
;
5712 if (RARRAY_LEN(ary1
) > RARRAY_LEN(ary2
)) {
5717 hash
= ary_make_hash(shorter
);
5720 for (i
=0; i
<RARRAY_LEN(longer
); i
++) {
5721 v
= RARRAY_AREF(longer
, i
);
5723 if (rb_hash_stlike_lookup(hash
, vv
, 0)) {
5733 ary_max_generic(VALUE ary
, long i
, VALUE vmax
)
5735 RUBY_ASSERT(i
> 0 && i
< RARRAY_LEN(ary
));
5738 for (; i
< RARRAY_LEN(ary
); ++i
) {
5739 v
= RARRAY_AREF(ary
, i
);
5741 if (rb_cmpint(rb_funcallv(vmax
, id_cmp
, 1, &v
), vmax
, v
) < 0) {
5750 ary_max_opt_fixnum(VALUE ary
, long i
, VALUE vmax
)
5752 const long n
= RARRAY_LEN(ary
);
5753 RUBY_ASSERT(i
> 0 && i
< n
);
5754 RUBY_ASSERT(FIXNUM_P(vmax
));
5757 for (; i
< n
; ++i
) {
5758 v
= RARRAY_AREF(ary
, i
);
5761 if ((long)vmax
< (long)v
) {
5766 return ary_max_generic(ary
, i
, vmax
);
5774 ary_max_opt_float(VALUE ary
, long i
, VALUE vmax
)
5776 const long n
= RARRAY_LEN(ary
);
5777 RUBY_ASSERT(i
> 0 && i
< n
);
5778 RUBY_ASSERT(RB_FLOAT_TYPE_P(vmax
));
5781 for (; i
< n
; ++i
) {
5782 v
= RARRAY_AREF(ary
, i
);
5784 if (RB_FLOAT_TYPE_P(v
)) {
5785 if (rb_float_cmp(vmax
, v
) < 0) {
5790 return ary_max_generic(ary
, i
, vmax
);
5798 ary_max_opt_string(VALUE ary
, long i
, VALUE vmax
)
5800 const long n
= RARRAY_LEN(ary
);
5801 RUBY_ASSERT(i
> 0 && i
< n
);
5802 RUBY_ASSERT(STRING_P(vmax
));
5805 for (; i
< n
; ++i
) {
5806 v
= RARRAY_AREF(ary
, i
);
5809 if (rb_str_cmp(vmax
, v
) < 0) {
5814 return ary_max_generic(ary
, i
, vmax
);
5823 * array.max -> element
5824 * array.max {|a, b| ... } -> element
5825 * array.max(n) -> new_array
5826 * array.max(n) {|a, b| ... } -> new_array
5828 * Returns one of the following:
5830 * - The maximum-valued element from +self+.
5831 * - A new +Array+ of maximum-valued elements selected from +self+.
5833 * When no block is given, each element in +self+ must respond to method <tt><=></tt>
5836 * With no argument and no block, returns the element in +self+
5837 * having the maximum value per method <tt><=></tt>:
5839 * [0, 1, 2].max # => 2
5841 * With an argument Integer +n+ and no block, returns a new +Array+ with at most +n+ elements,
5842 * in descending order per method <tt><=></tt>:
5844 * [0, 1, 2, 3].max(3) # => [3, 2, 1]
5845 * [0, 1, 2, 3].max(6) # => [3, 2, 1, 0]
5847 * When a block is given, the block must return an Integer.
5849 * With a block and no argument, calls the block <tt>self.size-1</tt> times to compare elements;
5850 * returns the element having the maximum value per the block:
5852 * ['0', '00', '000'].max {|a, b| a.size <=> b.size } # => "000"
5854 * With an argument +n+ and a block, returns a new +Array+ with at most +n+ elements,
5855 * in descending order per the block:
5857 * ['0', '00', '000'].max(2) {|a, b| a.size <=> b.size } # => ["000", "00"]
5861 rb_ary_max(int argc
, VALUE
*argv
, VALUE ary
)
5863 VALUE result
= Qundef
, v
;
5867 if (rb_check_arity(argc
, 0, 1) && !NIL_P(num
= argv
[0]))
5868 return rb_nmin_run(ary
, num
, 0, 1, 1);
5870 const long n
= RARRAY_LEN(ary
);
5871 if (rb_block_given_p()) {
5872 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
5873 v
= RARRAY_AREF(ary
, i
);
5874 if (UNDEF_P(result
) || rb_cmpint(rb_yield_values(2, v
, result
), v
, result
) > 0) {
5880 result
= RARRAY_AREF(ary
, 0);
5882 if (FIXNUM_P(result
) && CMP_OPTIMIZABLE(INTEGER
)) {
5883 return ary_max_opt_fixnum(ary
, 1, result
);
5885 else if (STRING_P(result
) && CMP_OPTIMIZABLE(STRING
)) {
5886 return ary_max_opt_string(ary
, 1, result
);
5888 else if (RB_FLOAT_TYPE_P(result
) && CMP_OPTIMIZABLE(FLOAT
)) {
5889 return ary_max_opt_float(ary
, 1, result
);
5892 return ary_max_generic(ary
, 1, result
);
5896 if (UNDEF_P(result
)) return Qnil
;
5901 ary_min_generic(VALUE ary
, long i
, VALUE vmin
)
5903 RUBY_ASSERT(i
> 0 && i
< RARRAY_LEN(ary
));
5906 for (; i
< RARRAY_LEN(ary
); ++i
) {
5907 v
= RARRAY_AREF(ary
, i
);
5909 if (rb_cmpint(rb_funcallv(vmin
, id_cmp
, 1, &v
), vmin
, v
) > 0) {
5918 ary_min_opt_fixnum(VALUE ary
, long i
, VALUE vmin
)
5920 const long n
= RARRAY_LEN(ary
);
5921 RUBY_ASSERT(i
> 0 && i
< n
);
5922 RUBY_ASSERT(FIXNUM_P(vmin
));
5925 for (; i
< n
; ++i
) {
5926 a
= RARRAY_AREF(ary
, i
);
5929 if ((long)vmin
> (long)a
) {
5934 return ary_min_generic(ary
, i
, vmin
);
5942 ary_min_opt_float(VALUE ary
, long i
, VALUE vmin
)
5944 const long n
= RARRAY_LEN(ary
);
5945 RUBY_ASSERT(i
> 0 && i
< n
);
5946 RUBY_ASSERT(RB_FLOAT_TYPE_P(vmin
));
5949 for (; i
< n
; ++i
) {
5950 a
= RARRAY_AREF(ary
, i
);
5952 if (RB_FLOAT_TYPE_P(a
)) {
5953 if (rb_float_cmp(vmin
, a
) > 0) {
5958 return ary_min_generic(ary
, i
, vmin
);
5966 ary_min_opt_string(VALUE ary
, long i
, VALUE vmin
)
5968 const long n
= RARRAY_LEN(ary
);
5969 RUBY_ASSERT(i
> 0 && i
< n
);
5970 RUBY_ASSERT(STRING_P(vmin
));
5973 for (; i
< n
; ++i
) {
5974 a
= RARRAY_AREF(ary
, i
);
5977 if (rb_str_cmp(vmin
, a
) > 0) {
5982 return ary_min_generic(ary
, i
, vmin
);
5991 * array.min -> element
5992 * array.min { |a, b| ... } -> element
5993 * array.min(n) -> new_array
5994 * array.min(n) { |a, b| ... } -> new_array
5996 * Returns one of the following:
5998 * - The minimum-valued element from +self+.
5999 * - A new +Array+ of minimum-valued elements selected from +self+.
6001 * When no block is given, each element in +self+ must respond to method <tt><=></tt>
6004 * With no argument and no block, returns the element in +self+
6005 * having the minimum value per method <tt><=></tt>:
6007 * [0, 1, 2].min # => 0
6009 * With Integer argument +n+ and no block, returns a new +Array+ with at most +n+ elements,
6010 * in ascending order per method <tt><=></tt>:
6012 * [0, 1, 2, 3].min(3) # => [0, 1, 2]
6013 * [0, 1, 2, 3].min(6) # => [0, 1, 2, 3]
6015 * When a block is given, the block must return an Integer.
6017 * With a block and no argument, calls the block <tt>self.size-1</tt> times to compare elements;
6018 * returns the element having the minimum value per the block:
6020 * ['0', '00', '000'].min { |a, b| a.size <=> b.size } # => "0"
6022 * With an argument +n+ and a block, returns a new +Array+ with at most +n+ elements,
6023 * in ascending order per the block:
6025 * ['0', '00', '000'].min(2) {|a, b| a.size <=> b.size } # => ["0", "00"]
6029 rb_ary_min(int argc
, VALUE
*argv
, VALUE ary
)
6031 VALUE result
= Qundef
, v
;
6035 if (rb_check_arity(argc
, 0, 1) && !NIL_P(num
= argv
[0]))
6036 return rb_nmin_run(ary
, num
, 0, 0, 1);
6038 const long n
= RARRAY_LEN(ary
);
6039 if (rb_block_given_p()) {
6040 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
6041 v
= RARRAY_AREF(ary
, i
);
6042 if (UNDEF_P(result
) || rb_cmpint(rb_yield_values(2, v
, result
), v
, result
) < 0) {
6048 result
= RARRAY_AREF(ary
, 0);
6050 if (FIXNUM_P(result
) && CMP_OPTIMIZABLE(INTEGER
)) {
6051 return ary_min_opt_fixnum(ary
, 1, result
);
6053 else if (STRING_P(result
) && CMP_OPTIMIZABLE(STRING
)) {
6054 return ary_min_opt_string(ary
, 1, result
);
6056 else if (RB_FLOAT_TYPE_P(result
) && CMP_OPTIMIZABLE(FLOAT
)) {
6057 return ary_min_opt_float(ary
, 1, result
);
6060 return ary_min_generic(ary
, 1, result
);
6064 if (UNDEF_P(result
)) return Qnil
;
6070 * array.minmax -> [min_val, max_val]
6071 * array.minmax {|a, b| ... } -> [min_val, max_val]
6073 * Returns a new 2-element +Array+ containing the minimum and maximum values
6074 * from +self+, either per method <tt><=></tt> or per a given block:.
6076 * When no block is given, each element in +self+ must respond to method <tt><=></tt>
6078 * returns a new 2-element +Array+ containing the minimum and maximum values
6079 * from +self+, per method <tt><=></tt>:
6081 * [0, 1, 2].minmax # => [0, 2]
6083 * When a block is given, the block must return an Integer;
6084 * the block is called <tt>self.size-1</tt> times to compare elements;
6085 * returns a new 2-element +Array+ containing the minimum and maximum values
6086 * from +self+, per the block:
6088 * ['0', '00', '000'].minmax {|a, b| a.size <=> b.size } # => ["0", "000"]
6092 rb_ary_minmax(VALUE ary
)
6094 if (rb_block_given_p()) {
6095 return rb_call_super(0, NULL
);
6097 return rb_assoc_new(rb_ary_min(0, 0, ary
), rb_ary_max(0, 0, ary
));
6101 push_value(st_data_t key
, st_data_t val
, st_data_t ary
)
6103 rb_ary_push((VALUE
)ary
, (VALUE
)val
);
6109 * array.uniq! -> self or nil
6110 * array.uniq! {|element| ... } -> self or nil
6112 * Removes duplicate elements from +self+, the first occurrence always being retained;
6113 * returns +self+ if any elements removed, +nil+ otherwise.
6115 * With no block given, identifies and removes elements using method <tt>eql?</tt>
6118 * Returns +self+ if any elements removed:
6120 * a = [0, 0, 1, 1, 2, 2]
6121 * a.uniq! # => [0, 1, 2]
6123 * Returns +nil+ if no elements removed.
6125 * With a block given, calls the block for each element;
6126 * identifies (using method <tt>eql?</tt>) and removes
6127 * elements for which the block returns duplicate values.
6129 * Returns +self+ if any elements removed:
6131 * a = ['a', 'aa', 'aaa', 'b', 'bb', 'bbb']
6132 * a.uniq! {|element| element.size } # => ['a', 'aa', 'aaa']
6134 * Returns +nil+ if no elements removed.
6137 rb_ary_uniq_bang(VALUE ary
)
6142 rb_ary_modify_check(ary
);
6143 if (RARRAY_LEN(ary
) <= 1)
6145 if (rb_block_given_p())
6146 hash
= ary_make_hash_by(ary
);
6148 hash
= ary_make_hash(ary
);
6150 hash_size
= RHASH_SIZE(hash
);
6151 if (RARRAY_LEN(ary
) == hash_size
) {
6154 rb_ary_modify_check(ary
);
6155 ARY_SET_LEN(ary
, 0);
6156 if (ARY_SHARED_P(ary
) && !ARY_EMBED_P(ary
)) {
6157 rb_ary_unshare(ary
);
6160 ary_resize_capa(ary
, hash_size
);
6161 rb_hash_foreach(hash
, push_value
, ary
);
6168 * array.uniq -> new_array
6169 * array.uniq {|element| ... } -> new_array
6171 * Returns a new +Array+ containing those elements from +self+ that are not duplicates,
6172 * the first occurrence always being retained.
6174 * With no block given, identifies and omits duplicates using method <tt>eql?</tt>
6177 * a = [0, 0, 1, 1, 2, 2]
6178 * a.uniq # => [0, 1, 2]
6180 * With a block given, calls the block for each element;
6181 * identifies (using method <tt>eql?</tt>) and omits duplicate values,
6182 * that is, those elements for which the block returns the same value:
6184 * a = ['a', 'aa', 'aaa', 'b', 'bb', 'bbb']
6185 * a.uniq {|element| element.size } # => ["a", "aa", "aaa"]
6190 rb_ary_uniq(VALUE ary
)
6194 if (RARRAY_LEN(ary
) <= 1) {
6196 uniq
= rb_ary_dup(ary
);
6198 else if (rb_block_given_p()) {
6199 hash
= ary_make_hash_by(ary
);
6200 uniq
= rb_hash_values(hash
);
6203 hash
= ary_make_hash(ary
);
6204 uniq
= rb_hash_values(hash
);
6212 * array.compact! -> self or nil
6214 * Removes all +nil+ elements from +self+.
6216 * Returns +self+ if any elements removed, otherwise +nil+.
6220 rb_ary_compact_bang(VALUE ary
)
6226 p
= t
= (VALUE
*)RARRAY_CONST_PTR(ary
); /* WB: no new reference */
6227 end
= p
+ RARRAY_LEN(ary
);
6233 n
= p
- RARRAY_CONST_PTR(ary
);
6234 if (RARRAY_LEN(ary
) == n
) {
6237 ary_resize_smaller(ary
, n
);
6244 * array.compact -> new_array
6246 * Returns a new +Array+ containing all non-+nil+ elements from +self+:
6248 * a = [nil, 0, nil, 1, nil, 2, nil]
6249 * a.compact # => [0, 1, 2]
6253 rb_ary_compact(VALUE ary
)
6255 ary
= rb_ary_dup(ary
);
6256 rb_ary_compact_bang(ary
);
6262 * array.count -> an_integer
6263 * array.count(obj) -> an_integer
6264 * array.count {|element| ... } -> an_integer
6266 * Returns a count of specified elements.
6268 * With no argument and no block, returns the count of all elements:
6270 * [0, 1, 2].count # => 3
6273 * With argument +obj+, returns the count of elements <tt>==</tt> to +obj+:
6275 * [0, 1, 2, 0.0].count(0) # => 2
6276 * [0, 1, 2].count(3) # => 0
6278 * With no argument and a block given, calls the block with each element;
6279 * returns the count of elements for which the block returns a truthy value:
6281 * [0, 1, 2, 3].count {|element| element > 1} # => 2
6283 * With argument +obj+ and a block given, issues a warning, ignores the block,
6284 * and returns the count of elements <tt>==</tt> to +obj+.
6288 rb_ary_count(int argc
, VALUE
*argv
, VALUE ary
)
6292 if (rb_check_arity(argc
, 0, 1) == 0) {
6295 if (!rb_block_given_p())
6296 return LONG2NUM(RARRAY_LEN(ary
));
6298 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
6299 v
= RARRAY_AREF(ary
, i
);
6300 if (RTEST(rb_yield(v
))) n
++;
6304 VALUE obj
= argv
[0];
6306 if (rb_block_given_p()) {
6307 rb_warn("given block not used");
6309 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
6310 if (rb_equal(RARRAY_AREF(ary
, i
), obj
)) n
++;
6318 flatten(VALUE ary
, int level
)
6321 VALUE stack
, result
, tmp
= 0, elt
;
6322 VALUE memo
= Qfalse
;
6324 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
6325 elt
= RARRAY_AREF(ary
, i
);
6326 tmp
= rb_check_array_type(elt
);
6331 if (i
== RARRAY_LEN(ary
)) {
6335 result
= ary_new(0, RARRAY_LEN(ary
));
6336 ary_memcpy(result
, 0, i
, RARRAY_CONST_PTR(ary
));
6337 ARY_SET_LEN(result
, i
);
6339 stack
= ary_new(0, ARY_DEFAULT_SIZE
);
6340 rb_ary_push(stack
, ary
);
6341 rb_ary_push(stack
, LONG2NUM(i
+ 1));
6344 memo
= rb_obj_hide(rb_ident_hash_new());
6345 rb_hash_aset(memo
, ary
, Qtrue
);
6346 rb_hash_aset(memo
, tmp
, Qtrue
);
6353 while (i
< RARRAY_LEN(ary
)) {
6354 elt
= RARRAY_AREF(ary
, i
++);
6355 if (level
>= 0 && RARRAY_LEN(stack
) / 2 >= level
) {
6356 rb_ary_push(result
, elt
);
6359 tmp
= rb_check_array_type(elt
);
6360 if (RBASIC(result
)->klass
) {
6362 rb_hash_clear(memo
);
6364 rb_raise(rb_eRuntimeError
, "flatten reentered");
6367 rb_ary_push(result
, elt
);
6371 if (rb_hash_aref(memo
, tmp
) == Qtrue
) {
6372 rb_hash_clear(memo
);
6373 rb_raise(rb_eArgError
, "tried to flatten recursive array");
6375 rb_hash_aset(memo
, tmp
, Qtrue
);
6377 rb_ary_push(stack
, ary
);
6378 rb_ary_push(stack
, LONG2NUM(i
));
6383 if (RARRAY_LEN(stack
) == 0) {
6387 rb_hash_delete(memo
, ary
);
6389 tmp
= rb_ary_pop(stack
);
6391 ary
= rb_ary_pop(stack
);
6395 rb_hash_clear(memo
);
6398 RBASIC_SET_CLASS(result
, rb_cArray
);
6404 * array.flatten! -> self or nil
6405 * array.flatten!(level) -> self or nil
6407 * Replaces each nested +Array+ in +self+ with the elements from that +Array+;
6408 * returns +self+ if any changes, +nil+ otherwise.
6410 * With non-negative Integer argument +level+, flattens recursively through +level+ levels:
6412 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6413 * a.flatten!(1) # => [0, 1, [2, 3], 4, 5]
6414 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6415 * a.flatten!(2) # => [0, 1, 2, 3, 4, 5]
6416 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6417 * a.flatten!(3) # => [0, 1, 2, 3, 4, 5]
6418 * [0, 1, 2].flatten!(1) # => nil
6420 * With no argument, a +nil+ argument, or with negative argument +level+, flattens all levels:
6422 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6423 * a.flatten! # => [0, 1, 2, 3, 4, 5]
6424 * [0, 1, 2].flatten! # => nil
6425 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6426 * a.flatten!(-1) # => [0, 1, 2, 3, 4, 5]
6427 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6428 * a.flatten!(-2) # => [0, 1, 2, 3, 4, 5]
6429 * [0, 1, 2].flatten!(-1) # => nil
6434 rb_ary_flatten_bang(int argc
, VALUE
*argv
, VALUE ary
)
6436 int mod
= 0, level
= -1;
6439 lv
= (rb_check_arity(argc
, 0, 1) ? argv
[0] : Qnil
);
6440 rb_ary_modify_check(ary
);
6441 if (!NIL_P(lv
)) level
= NUM2INT(lv
);
6442 if (level
== 0) return Qnil
;
6444 result
= flatten(ary
, level
);
6445 if (result
== ary
) {
6448 if (!(mod
= ARY_EMBED_P(result
))) rb_obj_freeze(result
);
6449 rb_ary_replace(ary
, result
);
6450 if (mod
) ARY_SET_EMBED_LEN(result
, 0);
6457 * array.flatten -> new_array
6458 * array.flatten(level) -> new_array
6460 * Returns a new +Array+ that is a recursive flattening of +self+:
6461 * - Each non-Array element is unchanged.
6462 * - Each +Array+ is replaced by its individual elements.
6464 * With non-negative Integer argument +level+, flattens recursively through +level+ levels:
6466 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6467 * a.flatten(0) # => [0, [1, [2, 3], 4], 5]
6468 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6469 * a.flatten(1) # => [0, 1, [2, 3], 4, 5]
6470 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6471 * a.flatten(2) # => [0, 1, 2, 3, 4, 5]
6472 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6473 * a.flatten(3) # => [0, 1, 2, 3, 4, 5]
6475 * With no argument, a +nil+ argument, or with negative argument +level+, flattens all levels:
6477 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6478 * a.flatten # => [0, 1, 2, 3, 4, 5]
6479 * [0, 1, 2].flatten # => [0, 1, 2]
6480 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6481 * a.flatten(-1) # => [0, 1, 2, 3, 4, 5]
6482 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6483 * a.flatten(-2) # => [0, 1, 2, 3, 4, 5]
6484 * [0, 1, 2].flatten(-1) # => [0, 1, 2]
6489 rb_ary_flatten(int argc
, VALUE
*argv
, VALUE ary
)
6494 if (rb_check_arity(argc
, 0, 1) && !NIL_P(argv
[0])) {
6495 level
= NUM2INT(argv
[0]);
6496 if (level
== 0) return ary_make_shared_copy(ary
);
6499 result
= flatten(ary
, level
);
6500 if (result
== ary
) {
6501 result
= ary_make_shared_copy(ary
);
6507 #define RAND_UPTO(max) (long)rb_random_ulong_limited((randgen), (max)-1)
6510 rb_ary_shuffle_bang(rb_execution_context_t
*ec
, VALUE ary
, VALUE randgen
)
6515 i
= len
= RARRAY_LEN(ary
);
6516 RARRAY_PTR_USE(ary
, ptr
, {
6518 long j
= RAND_UPTO(i
);
6520 if (len
!= RARRAY_LEN(ary
) || ptr
!= RARRAY_CONST_PTR(ary
)) {
6521 rb_raise(rb_eRuntimeError
, "modified during shuffle");
6527 }); /* WB: no new reference */
6532 rb_ary_shuffle(rb_execution_context_t
*ec
, VALUE ary
, VALUE randgen
)
6534 ary
= rb_ary_dup(ary
);
6535 rb_ary_shuffle_bang(ec
, ary
, randgen
);
6540 ary_sample(rb_execution_context_t
*ec
, VALUE ary
, VALUE randgen
, VALUE nv
, VALUE to_array
)
6543 long n
, len
, i
, j
, k
, idx
[10];
6544 long rnds
[numberof(idx
)];
6545 long memo_threshold
;
6547 len
= RARRAY_LEN(ary
);
6554 return rb_ary_elt(ary
, i
);
6557 if (n
< 0) rb_raise(rb_eArgError
, "negative sample number");
6558 if (n
> len
) n
= len
;
6559 if (n
<= numberof(idx
)) {
6560 for (i
= 0; i
< n
; ++i
) {
6561 rnds
[i
] = RAND_UPTO(len
- i
);
6565 len
= RARRAY_LEN(ary
);
6566 if (len
< k
&& n
<= numberof(idx
)) {
6567 for (i
= 0; i
< n
; ++i
) {
6568 if (rnds
[i
] >= len
) return rb_ary_new_capa(0);
6571 if (n
> len
) n
= len
;
6574 return rb_ary_new_capa(0);
6577 return rb_ary_new_from_args(1, RARRAY_AREF(ary
, i
));
6582 return rb_ary_new_from_args(2, RARRAY_AREF(ary
, i
), RARRAY_AREF(ary
, j
));
6589 if (j
>= i
) l
= i
, g
= ++j
;
6590 if (k
>= l
&& (++k
>= g
)) ++k
;
6592 return rb_ary_new_from_args(3, RARRAY_AREF(ary
, i
), RARRAY_AREF(ary
, j
), RARRAY_AREF(ary
, k
));
6595 len
< 2560 ? len
/ 128 :
6596 len
< 5120 ? len
/ 64 :
6597 len
< 10240 ? len
/ 32 :
6599 if (n
<= numberof(idx
)) {
6600 long sorted
[numberof(idx
)];
6601 sorted
[0] = idx
[0] = rnds
[0];
6602 for (i
=1; i
<n
; i
++) {
6604 for (j
= 0; j
< i
; ++j
) {
6605 if (k
< sorted
[j
]) break;
6608 memmove(&sorted
[j
+1], &sorted
[j
], sizeof(sorted
[0])*(i
-j
));
6609 sorted
[j
] = idx
[i
] = k
;
6611 result
= rb_ary_new_capa(n
);
6612 RARRAY_PTR_USE(result
, ptr_result
, {
6613 for (i
=0; i
<n
; i
++) {
6614 ptr_result
[i
] = RARRAY_AREF(ary
, idx
[i
]);
6618 else if (n
<= memo_threshold
/ 2) {
6620 #undef RUBY_UNTYPED_DATA_WARNING
6621 #define RUBY_UNTYPED_DATA_WARNING 0
6622 VALUE vmemo
= Data_Wrap_Struct(0, 0, st_free_table
, 0);
6623 st_table
*memo
= st_init_numtable_with_size(n
);
6624 DATA_PTR(vmemo
) = memo
;
6625 result
= rb_ary_new_capa(n
);
6626 RARRAY_PTR_USE(result
, ptr_result
, {
6627 for (i
=0; i
<n
; i
++) {
6628 long r
= RAND_UPTO(len
-i
) + i
;
6630 if (r
> max_idx
) max_idx
= r
;
6632 len
= RARRAY_LEN(ary
);
6633 if (len
<= max_idx
) n
= 0;
6634 else if (n
> len
) n
= len
;
6635 RARRAY_PTR_USE(ary
, ptr_ary
, {
6636 for (i
=0; i
<n
; i
++) {
6637 long j2
= j
= ptr_result
[i
];
6640 if (st_lookup(memo
, (st_data_t
)i
, &value
)) i2
= (long)value
;
6641 if (st_lookup(memo
, (st_data_t
)j
, &value
)) j2
= (long)value
;
6642 st_insert(memo
, (st_data_t
)j
, (st_data_t
)i2
);
6643 ptr_result
[i
] = ptr_ary
[j2
];
6647 DATA_PTR(vmemo
) = 0;
6648 st_free_table(memo
);
6652 result
= rb_ary_dup(ary
);
6653 RBASIC_CLEAR_CLASS(result
);
6655 RARRAY_PTR_USE(result
, ptr_result
, {
6656 for (i
=0; i
<n
; i
++) {
6657 j
= RAND_UPTO(len
-i
) + i
;
6659 ptr_result
[j
] = ptr_result
[i
];
6663 RBASIC_SET_CLASS_RAW(result
, rb_cArray
);
6665 ARY_SET_LEN(result
, n
);
6671 ary_sample0(rb_execution_context_t
*ec
, VALUE ary
)
6673 return ary_sample(ec
, ary
, rb_cRandom
, Qfalse
, Qfalse
);
6677 rb_ary_cycle_size(VALUE self
, VALUE args
, VALUE eobj
)
6681 if (args
&& (RARRAY_LEN(args
) > 0)) {
6682 n
= RARRAY_AREF(args
, 0);
6684 if (RARRAY_LEN(self
) == 0) return INT2FIX(0);
6685 if (NIL_P(n
)) return DBL2NUM(HUGE_VAL
);
6687 if (mul
<= 0) return INT2FIX(0);
6689 return rb_fix_mul_fix(rb_ary_length(self
), n
);
6694 * array.cycle {|element| ... } -> nil
6695 * array.cycle(count) {|element| ... } -> nil
6696 * array.cycle -> new_enumerator
6697 * array.cycle(count) -> new_enumerator
6699 * When called with positive Integer argument +count+ and a block,
6700 * calls the block with each element, then does so again,
6701 * until it has done so +count+ times; returns +nil+:
6704 * [0, 1].cycle(2) {|element| output.push(element) } # => nil
6705 * output # => [0, 1, 0, 1]
6707 * If +count+ is zero or negative, does not call the block:
6709 * [0, 1].cycle(0) {|element| fail 'Cannot happen' } # => nil
6710 * [0, 1].cycle(-1) {|element| fail 'Cannot happen' } # => nil
6712 * When a block is given, and argument is omitted or +nil+, cycles forever:
6714 * # Prints 0 and 1 forever.
6715 * [0, 1].cycle {|element| puts element }
6716 * [0, 1].cycle(nil) {|element| puts element }
6718 * When no block is given, returns a new Enumerator:
6720 * [0, 1].cycle(2) # => #<Enumerator: [0, 1]:cycle(2)>
6721 * [0, 1].cycle # => # => #<Enumerator: [0, 1]:cycle>
6722 * [0, 1].cycle.first(5) # => [0, 1, 0, 1, 0]
6726 rb_ary_cycle(int argc
, VALUE
*argv
, VALUE ary
)
6730 rb_check_arity(argc
, 0, 1);
6732 RETURN_SIZED_ENUMERATOR(ary
, argc
, argv
, rb_ary_cycle_size
);
6733 if (argc
== 0 || NIL_P(argv
[0])) {
6737 n
= NUM2LONG(argv
[0]);
6738 if (n
<= 0) return Qnil
;
6741 while (RARRAY_LEN(ary
) > 0 && (n
< 0 || 0 < n
--)) {
6742 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
6743 rb_yield(RARRAY_AREF(ary
, i
));
6750 * Build a ruby array of the corresponding values and yield it to the
6752 * Return the class of +values+ for reentry check.
6755 yield_indexed_values(const VALUE values
, const long r
, const long *const p
)
6757 const VALUE result
= rb_ary_new2(r
);
6760 for (i
= 0; i
< r
; i
++) ARY_SET(result
, i
, RARRAY_AREF(values
, p
[i
]));
6761 ARY_SET_LEN(result
, r
);
6763 return !RBASIC(values
)->klass
;
6767 * Compute permutations of +r+ elements of the set <code>[0..n-1]</code>.
6769 * When we have a complete permutation of array indices, copy the values
6770 * at those indices into a new array and yield that array.
6772 * n: the size of the set
6773 * r: the number of elements in each permutation
6774 * p: the array (of size r) that we're filling in
6775 * used: an array of booleans: whether a given index is already used
6776 * values: the Ruby array that holds the actual values to permute
6779 permute0(const long n
, const long r
, long *const p
, char *const used
, const VALUE values
)
6781 long i
= 0, index
= 0;
6784 const char *const unused
= memchr(&used
[i
], 0, n
-i
);
6787 i
= p
[--index
]; /* pop index */
6788 used
[i
++] = 0; /* index unused */
6793 used
[i
] = 1; /* mark index used */
6795 if (index
< r
-1) { /* if not done yet */
6799 for (i
= 0; i
< n
; ++i
) {
6800 if (used
[i
]) continue;
6802 if (!yield_indexed_values(values
, r
, p
)) {
6803 rb_raise(rb_eRuntimeError
, "permute reentered");
6806 i
= p
[--index
]; /* pop index */
6807 used
[i
] = 0; /* index unused */
6814 * Returns the product of from, from-1, ..., from - how_many + 1.
6815 * https://en.wikipedia.org/wiki/Pochhammer_symbol
6818 descending_factorial(long from
, long how_many
)
6822 cnt
= LONG2FIX(from
);
6823 while (--how_many
> 0) {
6825 cnt
= rb_int_mul(cnt
, LONG2FIX(v
));
6829 cnt
= LONG2FIX(how_many
== 0);
6835 binomial_coefficient(long comb
, long size
)
6839 if (comb
> size
-comb
) {
6845 else if (comb
== 0) {
6849 for (i
= 1; i
< comb
; ++i
) {
6850 r
= rb_int_mul(r
, LONG2FIX(size
- i
));
6851 r
= rb_int_idiv(r
, LONG2FIX(i
+ 1));
6857 rb_ary_permutation_size(VALUE ary
, VALUE args
, VALUE eobj
)
6859 long n
= RARRAY_LEN(ary
);
6860 long k
= (args
&& (RARRAY_LEN(args
) > 0)) ? NUM2LONG(RARRAY_AREF(args
, 0)) : n
;
6862 return descending_factorial(n
, k
);
6867 * array.permutation {|element| ... } -> self
6868 * array.permutation(n) {|element| ... } -> self
6869 * array.permutation -> new_enumerator
6870 * array.permutation(n) -> new_enumerator
6872 * When invoked with a block, yield all permutations of elements of +self+; returns +self+.
6873 * The order of permutations is indeterminate.
6875 * When a block and an in-range positive Integer argument +n+ (<tt>0 < n <= self.size</tt>)
6876 * are given, calls the block with all +n+-tuple permutations of +self+.
6881 * a.permutation(2) {|permutation| p permutation }
6895 * a.permutation(3) {|permutation| p permutation }
6906 * When +n+ is zero, calls the block once with a new empty +Array+:
6909 * a.permutation(0) {|permutation| p permutation }
6915 * When +n+ is out of range (negative or larger than <tt>self.size</tt>),
6916 * does not call the block:
6919 * a.permutation(-1) {|permutation| fail 'Cannot happen' }
6920 * a.permutation(4) {|permutation| fail 'Cannot happen' }
6922 * When a block given but no argument,
6923 * behaves the same as <tt>a.permutation(a.size)</tt>:
6926 * a.permutation {|permutation| p permutation }
6937 * Returns a new Enumerator if no block given:
6940 * a.permutation # => #<Enumerator: [0, 1, 2]:permutation>
6941 * a.permutation(2) # => #<Enumerator: [0, 1, 2]:permutation(2)>
6946 rb_ary_permutation(int argc
, VALUE
*argv
, VALUE ary
)
6950 n
= RARRAY_LEN(ary
); /* Array length */
6951 RETURN_SIZED_ENUMERATOR(ary
, argc
, argv
, rb_ary_permutation_size
); /* Return enumerator if no block */
6953 if (rb_check_arity(argc
, 0, 1) && !NIL_P(argv
[0]))
6954 r
= NUM2LONG(argv
[0]); /* Permutation size from argument */
6956 if (r
< 0 || n
< r
) {
6957 /* no permutations: yield nothing */
6959 else if (r
== 0) { /* exactly one permutation: the zero-length array */
6960 rb_yield(rb_ary_new2(0));
6962 else if (r
== 1) { /* this is a special, easy case */
6963 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
6964 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary
, i
)));
6967 else { /* this is the general case */
6969 long *p
= ALLOCV_N(long, t0
, r
+roomof(n
, sizeof(long)));
6970 char *used
= (char*)(p
+ r
);
6971 VALUE ary0
= ary_make_shared_copy(ary
); /* private defensive copy of ary */
6972 RBASIC_CLEAR_CLASS(ary0
);
6974 MEMZERO(used
, char, n
); /* initialize array */
6976 permute0(n
, r
, p
, used
, ary0
); /* compute and yield permutations */
6978 RBASIC_SET_CLASS_RAW(ary0
, rb_cArray
);
6984 combinate0(const long len
, const long n
, long *const stack
, const VALUE values
)
6988 MEMZERO(stack
+1, long, n
);
6991 for (lev
++; lev
< n
; lev
++) {
6992 stack
[lev
+1] = stack
[lev
]+1;
6994 if (!yield_indexed_values(values
, n
, stack
+1)) {
6995 rb_raise(rb_eRuntimeError
, "combination reentered");
6998 if (lev
== 0) return;
7000 } while (stack
[lev
+1]+n
== len
+lev
+1);
7005 rb_ary_combination_size(VALUE ary
, VALUE args
, VALUE eobj
)
7007 long n
= RARRAY_LEN(ary
);
7008 long k
= NUM2LONG(RARRAY_AREF(args
, 0));
7010 return binomial_coefficient(k
, n
);
7015 * array.combination(n) {|element| ... } -> self
7016 * array.combination(n) -> new_enumerator
7018 * Calls the block, if given, with combinations of elements of +self+;
7019 * returns +self+. The order of combinations is indeterminate.
7021 * When a block and an in-range positive Integer argument +n+ (<tt>0 < n <= self.size</tt>)
7022 * are given, calls the block with all +n+-tuple combinations of +self+.
7027 * a.combination(2) {|combination| p combination }
7038 * a.combination(3) {|combination| p combination }
7044 * When +n+ is zero, calls the block once with a new empty +Array+:
7047 * a1 = a.combination(0) {|combination| p combination }
7053 * When +n+ is out of range (negative or larger than <tt>self.size</tt>),
7054 * does not call the block:
7057 * a.combination(-1) {|combination| fail 'Cannot happen' }
7058 * a.combination(4) {|combination| fail 'Cannot happen' }
7060 * Returns a new Enumerator if no block given:
7063 * a.combination(2) # => #<Enumerator: [0, 1, 2]:combination(2)>
7068 rb_ary_combination(VALUE ary
, VALUE num
)
7073 RETURN_SIZED_ENUMERATOR(ary
, 1, &num
, rb_ary_combination_size
);
7074 len
= RARRAY_LEN(ary
);
7075 if (n
< 0 || len
< n
) {
7079 rb_yield(rb_ary_new2(0));
7082 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
7083 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary
, i
)));
7087 VALUE ary0
= ary_make_shared_copy(ary
); /* private defensive copy of ary */
7089 long *stack
= ALLOCV_N(long, t0
, n
+1);
7091 RBASIC_CLEAR_CLASS(ary0
);
7092 combinate0(len
, n
, stack
, ary0
);
7094 RBASIC_SET_CLASS_RAW(ary0
, rb_cArray
);
7100 * Compute repeated permutations of +r+ elements of the set
7101 * <code>[0..n-1]</code>.
7103 * When we have a complete repeated permutation of array indices, copy the
7104 * values at those indices into a new array and yield that array.
7106 * n: the size of the set
7107 * r: the number of elements in each permutation
7108 * p: the array (of size r) that we're filling in
7109 * values: the Ruby array that holds the actual values to permute
7112 rpermute0(const long n
, const long r
, long *const p
, const VALUE values
)
7114 long i
= 0, index
= 0;
7118 if (++index
< r
-1) {
7122 for (i
= 0; i
< n
; ++i
) {
7124 if (!yield_indexed_values(values
, r
, p
)) {
7125 rb_raise(rb_eRuntimeError
, "repeated permute reentered");
7129 if (index
<= 0) return;
7130 } while ((i
= ++p
[--index
]) >= n
);
7135 rb_ary_repeated_permutation_size(VALUE ary
, VALUE args
, VALUE eobj
)
7137 long n
= RARRAY_LEN(ary
);
7138 long k
= NUM2LONG(RARRAY_AREF(args
, 0));
7144 return LONG2FIX(!k
);
7146 return rb_int_positive_pow(n
, (unsigned long)k
);
7151 * array.repeated_permutation(n) {|permutation| ... } -> self
7152 * array.repeated_permutation(n) -> new_enumerator
7154 * Calls the block with each repeated permutation of length +n+ of the elements of +self+;
7155 * each permutation is an +Array+;
7156 * returns +self+. The order of the permutations is indeterminate.
7158 * When a block and a positive Integer argument +n+ are given, calls the block with each
7159 * +n+-tuple repeated permutation of the elements of +self+.
7160 * The number of permutations is <tt>self.size**n</tt>.
7165 * a.repeated_permutation(1) {|permutation| p permutation }
7175 * a.repeated_permutation(2) {|permutation| p permutation }
7189 * If +n+ is zero, calls the block once with an empty +Array+.
7191 * If +n+ is negative, does not call the block:
7193 * a.repeated_permutation(-1) {|permutation| fail 'Cannot happen' }
7195 * Returns a new Enumerator if no block given:
7198 * a.repeated_permutation(2) # => #<Enumerator: [0, 1, 2]:permutation(2)>
7200 * Using Enumerators, it's convenient to show the permutations and counts
7201 * for some values of +n+:
7203 * e = a.repeated_permutation(0)
7206 * e = a.repeated_permutation(1)
7208 * e.to_a # => [[0], [1], [2]]
7209 * e = a.repeated_permutation(2)
7211 * e.to_a # => [[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2], [2, 0], [2, 1], [2, 2]]
7215 rb_ary_repeated_permutation(VALUE ary
, VALUE num
)
7219 n
= RARRAY_LEN(ary
); /* Array length */
7220 RETURN_SIZED_ENUMERATOR(ary
, 1, &num
, rb_ary_repeated_permutation_size
); /* Return Enumerator if no block */
7221 r
= NUM2LONG(num
); /* Permutation size from argument */
7224 /* no permutations: yield nothing */
7226 else if (r
== 0) { /* exactly one permutation: the zero-length array */
7227 rb_yield(rb_ary_new2(0));
7229 else if (r
== 1) { /* this is a special, easy case */
7230 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
7231 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary
, i
)));
7234 else { /* this is the general case */
7236 long *p
= ALLOCV_N(long, t0
, r
);
7237 VALUE ary0
= ary_make_shared_copy(ary
); /* private defensive copy of ary */
7238 RBASIC_CLEAR_CLASS(ary0
);
7240 rpermute0(n
, r
, p
, ary0
); /* compute and yield repeated permutations */
7242 RBASIC_SET_CLASS_RAW(ary0
, rb_cArray
);
7248 rcombinate0(const long n
, const long r
, long *const p
, const long rest
, const VALUE values
)
7250 long i
= 0, index
= 0;
7254 if (++index
< r
-1) {
7258 for (; i
< n
; ++i
) {
7260 if (!yield_indexed_values(values
, r
, p
)) {
7261 rb_raise(rb_eRuntimeError
, "repeated combination reentered");
7265 if (index
<= 0) return;
7266 } while ((i
= ++p
[--index
]) >= n
);
7271 rb_ary_repeated_combination_size(VALUE ary
, VALUE args
, VALUE eobj
)
7273 long n
= RARRAY_LEN(ary
);
7274 long k
= NUM2LONG(RARRAY_AREF(args
, 0));
7278 return binomial_coefficient(k
, n
+ k
- 1);
7283 * array.repeated_combination(n) {|combination| ... } -> self
7284 * array.repeated_combination(n) -> new_enumerator
7286 * Calls the block with each repeated combination of length +n+ of the elements of +self+;
7287 * each combination is an +Array+;
7288 * returns +self+. The order of the combinations is indeterminate.
7290 * When a block and a positive Integer argument +n+ are given, calls the block with each
7291 * +n+-tuple repeated combination of the elements of +self+.
7292 * The number of combinations is <tt>(n+1)(n+2)/2</tt>.
7297 * a.repeated_combination(1) {|combination| p combination }
7307 * a.repeated_combination(2) {|combination| p combination }
7318 * If +n+ is zero, calls the block once with an empty +Array+.
7320 * If +n+ is negative, does not call the block:
7322 * a.repeated_combination(-1) {|combination| fail 'Cannot happen' }
7324 * Returns a new Enumerator if no block given:
7327 * a.repeated_combination(2) # => #<Enumerator: [0, 1, 2]:combination(2)>
7329 * Using Enumerators, it's convenient to show the combinations and counts
7330 * for some values of +n+:
7332 * e = a.repeated_combination(0)
7335 * e = a.repeated_combination(1)
7337 * e.to_a # => [[0], [1], [2]]
7338 * e = a.repeated_combination(2)
7340 * e.to_a # => [[0, 0], [0, 1], [0, 2], [1, 1], [1, 2], [2, 2]]
7345 rb_ary_repeated_combination(VALUE ary
, VALUE num
)
7349 n
= NUM2LONG(num
); /* Combination size from argument */
7350 RETURN_SIZED_ENUMERATOR(ary
, 1, &num
, rb_ary_repeated_combination_size
); /* Return enumerator if no block */
7351 len
= RARRAY_LEN(ary
);
7356 rb_yield(rb_ary_new2(0));
7359 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
7360 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary
, i
)));
7363 else if (len
== 0) {
7368 long *p
= ALLOCV_N(long, t0
, n
);
7369 VALUE ary0
= ary_make_shared_copy(ary
); /* private defensive copy of ary */
7370 RBASIC_CLEAR_CLASS(ary0
);
7372 rcombinate0(len
, n
, p
, n
, ary0
); /* compute and yield repeated combinations */
7374 RBASIC_SET_CLASS_RAW(ary0
, rb_cArray
);
7381 * array.product(*other_arrays) -> new_array
7382 * array.product(*other_arrays) {|combination| ... } -> self
7384 * Computes and returns or yields all combinations of elements from all the Arrays,
7385 * including both +self+ and +other_arrays+:
7387 * - The number of combinations is the product of the sizes of all the arrays,
7388 * including both +self+ and +other_arrays+.
7389 * - The order of the returned combinations is indeterminate.
7391 * When no block is given, returns the combinations as an +Array+ of Arrays:
7397 * p.size # => 6 # a.size * a1.size
7398 * p # => [[0, 3], [0, 4], [1, 3], [1, 4], [2, 3], [2, 4]]
7399 * p = a.product(a1, a2)
7400 * p.size # => 12 # a.size * a1.size * a2.size
7401 * p # => [[0, 3, 5], [0, 3, 6], [0, 4, 5], [0, 4, 6], [1, 3, 5], [1, 3, 6], [1, 4, 5], [1, 4, 6], [2, 3, 5], [2, 3, 6], [2, 4, 5], [2, 4, 6]]
7403 * If any argument is an empty +Array+, returns an empty +Array+.
7405 * If no argument is given, returns an +Array+ of 1-element Arrays,
7406 * each containing an element of +self+:
7408 * a.product # => [[0], [1], [2]]
7410 * When a block is given, yields each combination as an +Array+; returns +self+:
7412 * a.product(a1) {|combination| p combination }
7423 * If any argument is an empty +Array+, does not call the block:
7425 * a.product(a1, a2, []) {|combination| fail 'Cannot happen' }
7427 * If no argument is given, yields each element of +self+ as a 1-element +Array+:
7429 * a.product {|combination| p combination }
7440 rb_ary_product(int argc
, VALUE
*argv
, VALUE ary
)
7442 int n
= argc
+1; /* How many arrays we're operating on */
7443 volatile VALUE t0
= rb_ary_hidden_new(n
);
7444 volatile VALUE t1
= Qundef
;
7445 VALUE
*arrays
= RARRAY_PTR(t0
); /* The arrays we're computing the product of */
7446 int *counters
= ALLOCV_N(int, t1
, n
); /* The current position in each one */
7447 VALUE result
= Qnil
; /* The array we'll be returning, when no block given */
7451 RBASIC_CLEAR_CLASS(t0
);
7453 /* initialize the arrays of arrays */
7456 for (i
= 1; i
< n
; i
++) arrays
[i
] = Qnil
;
7457 for (i
= 1; i
< n
; i
++) arrays
[i
] = to_ary(argv
[i
-1]);
7459 /* initialize the counters for the arrays */
7460 for (i
= 0; i
< n
; i
++) counters
[i
] = 0;
7462 /* Otherwise, allocate and fill in an array of results */
7463 if (rb_block_given_p()) {
7464 /* Make defensive copies of arrays; exit if any is empty */
7465 for (i
= 0; i
< n
; i
++) {
7466 if (RARRAY_LEN(arrays
[i
]) == 0) goto done
;
7467 arrays
[i
] = ary_make_shared_copy(arrays
[i
]);
7471 /* Compute the length of the result array; return [] if any is empty */
7472 for (i
= 0; i
< n
; i
++) {
7473 long k
= RARRAY_LEN(arrays
[i
]);
7475 result
= rb_ary_new2(0);
7478 if (MUL_OVERFLOW_LONG_P(resultlen
, k
))
7479 rb_raise(rb_eRangeError
, "too big to product");
7482 result
= rb_ary_new2(resultlen
);
7486 /* fill in one subarray */
7487 VALUE subarray
= rb_ary_new2(n
);
7488 for (j
= 0; j
< n
; j
++) {
7489 rb_ary_push(subarray
, rb_ary_entry(arrays
[j
], counters
[j
]));
7492 /* put it on the result array */
7493 if (NIL_P(result
)) {
7494 FL_SET(t0
, RARRAY_SHARED_ROOT_FLAG
);
7496 if (!FL_TEST(t0
, RARRAY_SHARED_ROOT_FLAG
)) {
7497 rb_raise(rb_eRuntimeError
, "product reentered");
7500 FL_UNSET(t0
, RARRAY_SHARED_ROOT_FLAG
);
7504 rb_ary_push(result
, subarray
);
7508 * Increment the last counter. If it overflows, reset to 0
7509 * and increment the one before it.
7513 while (counters
[m
] == RARRAY_LEN(arrays
[m
])) {
7515 /* If the first counter overflows, we are done */
7516 if (--m
< 0) goto done
;
7524 return NIL_P(result
) ? ary
: result
;
7529 * array.take(n) -> new_array
7531 * Returns a new +Array+ containing the first +n+ element of +self+,
7532 * where +n+ is a non-negative Integer;
7533 * does not modify +self+.
7537 * a = [0, 1, 2, 3, 4, 5]
7538 * a.take(1) # => [0]
7539 * a.take(2) # => [0, 1]
7540 * a.take(50) # => [0, 1, 2, 3, 4, 5]
7541 * a # => [0, 1, 2, 3, 4, 5]
7546 rb_ary_take(VALUE obj
, VALUE n
)
7548 long len
= NUM2LONG(n
);
7550 rb_raise(rb_eArgError
, "attempt to take negative size");
7552 return rb_ary_subseq(obj
, 0, len
);
7557 * array.take_while {|element| ... } -> new_array
7558 * array.take_while -> new_enumerator
7560 * Returns a new +Array+ containing zero or more leading elements of +self+;
7561 * does not modify +self+.
7563 * With a block given, calls the block with each successive element of +self+;
7564 * stops if the block returns +false+ or +nil+;
7565 * returns a new +Array+ containing those elements for which the block returned a truthy value:
7567 * a = [0, 1, 2, 3, 4, 5]
7568 * a.take_while {|element| element < 3 } # => [0, 1, 2]
7569 * a.take_while {|element| true } # => [0, 1, 2, 3, 4, 5]
7570 * a # => [0, 1, 2, 3, 4, 5]
7572 * With no block given, returns a new Enumerator:
7574 * [0, 1].take_while # => #<Enumerator: [0, 1]:take_while>
7579 rb_ary_take_while(VALUE ary
)
7583 RETURN_ENUMERATOR(ary
, 0, 0);
7584 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
7585 if (!RTEST(rb_yield(RARRAY_AREF(ary
, i
)))) break;
7587 return rb_ary_take(ary
, LONG2FIX(i
));
7592 * array.drop(n) -> new_array
7594 * Returns a new +Array+ containing all but the first +n+ element of +self+,
7595 * where +n+ is a non-negative Integer;
7596 * does not modify +self+.
7600 * a = [0, 1, 2, 3, 4, 5]
7601 * a.drop(0) # => [0, 1, 2, 3, 4, 5]
7602 * a.drop(1) # => [1, 2, 3, 4, 5]
7603 * a.drop(2) # => [2, 3, 4, 5]
7608 rb_ary_drop(VALUE ary
, VALUE n
)
7611 long pos
= NUM2LONG(n
);
7613 rb_raise(rb_eArgError
, "attempt to drop negative size");
7616 result
= rb_ary_subseq(ary
, pos
, RARRAY_LEN(ary
));
7617 if (NIL_P(result
)) result
= rb_ary_new();
7623 * array.drop_while {|element| ... } -> new_array
7624 * array.drop_while -> new_enumerator
7626 * Returns a new +Array+ containing zero or more trailing elements of +self+;
7627 * does not modify +self+.
7629 * With a block given, calls the block with each successive element of +self+;
7630 * stops if the block returns +false+ or +nil+;
7631 * returns a new +Array+ _omitting_ those elements for which the block returned a truthy value:
7633 * a = [0, 1, 2, 3, 4, 5]
7634 * a.drop_while {|element| element < 3 } # => [3, 4, 5]
7636 * With no block given, returns a new Enumerator:
7638 * [0, 1].drop_while # => # => #<Enumerator: [0, 1]:drop_while>
7643 rb_ary_drop_while(VALUE ary
)
7647 RETURN_ENUMERATOR(ary
, 0, 0);
7648 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
7649 if (!RTEST(rb_yield(RARRAY_AREF(ary
, i
)))) break;
7651 return rb_ary_drop(ary
, LONG2FIX(i
));
7656 * array.any? -> true or false
7657 * array.any? {|element| ... } -> true or false
7658 * array.any?(obj) -> true or false
7660 * Returns +true+ if any element of +self+ meets a given criterion.
7662 * If +self+ has no element, returns +false+ and argument or block
7665 * With no block given and no argument, returns +true+ if +self+ has any truthy element,
7666 * +false+ otherwise:
7668 * [nil, 0, false].any? # => true
7669 * [nil, false].any? # => false
7670 * [].any? # => false
7672 * With a block given and no argument, calls the block with each element in +self+;
7673 * returns +true+ if the block returns any truthy value, +false+ otherwise:
7675 * [0, 1, 2].any? {|element| element > 1 } # => true
7676 * [0, 1, 2].any? {|element| element > 2 } # => false
7678 * If argument +obj+ is given, returns +true+ if +obj+.<tt>===</tt> any element,
7679 * +false+ otherwise:
7681 * ['food', 'drink'].any?(/foo/) # => true
7682 * ['food', 'drink'].any?(/bar/) # => false
7683 * [].any?(/foo/) # => false
7684 * [0, 1, 2].any?(1) # => true
7685 * [0, 1, 2].any?(3) # => false
7687 * Related: Enumerable#any?
7691 rb_ary_any_p(int argc
, VALUE
*argv
, VALUE ary
)
7693 long i
, len
= RARRAY_LEN(ary
);
7695 rb_check_arity(argc
, 0, 1);
7696 if (!len
) return Qfalse
;
7698 if (rb_block_given_p()) {
7699 rb_warn("given block not used");
7701 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
7702 if (RTEST(rb_funcall(argv
[0], idEqq
, 1, RARRAY_AREF(ary
, i
)))) return Qtrue
;
7705 else if (!rb_block_given_p()) {
7706 for (i
= 0; i
< len
; ++i
) {
7707 if (RTEST(RARRAY_AREF(ary
, i
))) return Qtrue
;
7711 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
7712 if (RTEST(rb_yield(RARRAY_AREF(ary
, i
)))) return Qtrue
;
7720 * array.all? -> true or false
7721 * array.all? {|element| ... } -> true or false
7722 * array.all?(obj) -> true or false
7724 * Returns +true+ if all elements of +self+ meet a given criterion.
7726 * If +self+ has no element, returns +true+ and argument or block
7729 * With no block given and no argument, returns +true+ if +self+ contains only truthy elements,
7730 * +false+ otherwise:
7732 * [0, 1, :foo].all? # => true
7733 * [0, nil, 2].all? # => false
7736 * With a block given and no argument, calls the block with each element in +self+;
7737 * returns +true+ if the block returns only truthy values, +false+ otherwise:
7739 * [0, 1, 2].all? { |element| element < 3 } # => true
7740 * [0, 1, 2].all? { |element| element < 2 } # => false
7742 * If argument +obj+ is given, returns +true+ if <tt>obj.===</tt> every element, +false+ otherwise:
7744 * ['food', 'fool', 'foot'].all?(/foo/) # => true
7745 * ['food', 'drink'].all?(/bar/) # => false
7746 * [].all?(/foo/) # => true
7747 * [0, 0, 0].all?(0) # => true
7748 * [0, 1, 2].all?(1) # => false
7750 * Related: Enumerable#all?
7754 rb_ary_all_p(int argc
, VALUE
*argv
, VALUE ary
)
7756 long i
, len
= RARRAY_LEN(ary
);
7758 rb_check_arity(argc
, 0, 1);
7759 if (!len
) return Qtrue
;
7761 if (rb_block_given_p()) {
7762 rb_warn("given block not used");
7764 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
7765 if (!RTEST(rb_funcall(argv
[0], idEqq
, 1, RARRAY_AREF(ary
, i
)))) return Qfalse
;
7768 else if (!rb_block_given_p()) {
7769 for (i
= 0; i
< len
; ++i
) {
7770 if (!RTEST(RARRAY_AREF(ary
, i
))) return Qfalse
;
7774 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
7775 if (!RTEST(rb_yield(RARRAY_AREF(ary
, i
)))) return Qfalse
;
7783 * array.none? -> true or false
7784 * array.none? {|element| ... } -> true or false
7785 * array.none?(obj) -> true or false
7787 * Returns +true+ if no element of +self+ meet a given criterion.
7789 * With no block given and no argument, returns +true+ if +self+ has no truthy elements,
7790 * +false+ otherwise:
7792 * [nil, false].none? # => true
7793 * [nil, 0, false].none? # => false
7794 * [].none? # => true
7796 * With a block given and no argument, calls the block with each element in +self+;
7797 * returns +true+ if the block returns no truthy value, +false+ otherwise:
7799 * [0, 1, 2].none? {|element| element > 3 } # => true
7800 * [0, 1, 2].none? {|element| element > 1 } # => false
7802 * If argument +obj+ is given, returns +true+ if <tt>obj.===</tt> no element, +false+ otherwise:
7804 * ['food', 'drink'].none?(/bar/) # => true
7805 * ['food', 'drink'].none?(/foo/) # => false
7806 * [].none?(/foo/) # => true
7807 * [0, 1, 2].none?(3) # => true
7808 * [0, 1, 2].none?(1) # => false
7810 * Related: Enumerable#none?
7814 rb_ary_none_p(int argc
, VALUE
*argv
, VALUE ary
)
7816 long i
, len
= RARRAY_LEN(ary
);
7818 rb_check_arity(argc
, 0, 1);
7819 if (!len
) return Qtrue
;
7821 if (rb_block_given_p()) {
7822 rb_warn("given block not used");
7824 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
7825 if (RTEST(rb_funcall(argv
[0], idEqq
, 1, RARRAY_AREF(ary
, i
)))) return Qfalse
;
7828 else if (!rb_block_given_p()) {
7829 for (i
= 0; i
< len
; ++i
) {
7830 if (RTEST(RARRAY_AREF(ary
, i
))) return Qfalse
;
7834 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
7835 if (RTEST(rb_yield(RARRAY_AREF(ary
, i
)))) return Qfalse
;
7843 * array.one? -> true or false
7844 * array.one? {|element| ... } -> true or false
7845 * array.one?(obj) -> true or false
7847 * Returns +true+ if exactly one element of +self+ meets a given criterion.
7849 * With no block given and no argument, returns +true+ if +self+ has exactly one truthy element,
7850 * +false+ otherwise:
7852 * [nil, 0].one? # => true
7853 * [0, 0].one? # => false
7854 * [nil, nil].one? # => false
7855 * [].one? # => false
7857 * With a block given and no argument, calls the block with each element in +self+;
7858 * returns +true+ if the block a truthy value for exactly one element, +false+ otherwise:
7860 * [0, 1, 2].one? {|element| element > 0 } # => false
7861 * [0, 1, 2].one? {|element| element > 1 } # => true
7862 * [0, 1, 2].one? {|element| element > 2 } # => false
7864 * If argument +obj+ is given, returns +true+ if <tt>obj.===</tt> exactly one element,
7865 * +false+ otherwise:
7867 * [0, 1, 2].one?(0) # => true
7868 * [0, 0, 1].one?(0) # => false
7869 * [1, 1, 2].one?(0) # => false
7870 * ['food', 'drink'].one?(/bar/) # => false
7871 * ['food', 'drink'].one?(/foo/) # => true
7872 * [].one?(/foo/) # => false
7874 * Related: Enumerable#one?
7878 rb_ary_one_p(int argc
, VALUE
*argv
, VALUE ary
)
7880 long i
, len
= RARRAY_LEN(ary
);
7881 VALUE result
= Qfalse
;
7883 rb_check_arity(argc
, 0, 1);
7884 if (!len
) return Qfalse
;
7886 if (rb_block_given_p()) {
7887 rb_warn("given block not used");
7889 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
7890 if (RTEST(rb_funcall(argv
[0], idEqq
, 1, RARRAY_AREF(ary
, i
)))) {
7891 if (result
) return Qfalse
;
7896 else if (!rb_block_given_p()) {
7897 for (i
= 0; i
< len
; ++i
) {
7898 if (RTEST(RARRAY_AREF(ary
, i
))) {
7899 if (result
) return Qfalse
;
7905 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
7906 if (RTEST(rb_yield(RARRAY_AREF(ary
, i
)))) {
7907 if (result
) return Qfalse
;
7917 * array.dig(index, *identifiers) -> object
7919 * Finds and returns the object in nested objects
7920 * that is specified by +index+ and +identifiers+.
7921 * The nested objects may be instances of various classes.
7922 * See {Dig Methods}[rdoc-ref:dig_methods.rdoc].
7926 * a = [:foo, [:bar, :baz, [:bat, :bam]]]
7927 * a.dig(1) # => [:bar, :baz, [:bat, :bam]]
7928 * a.dig(1, 2) # => [:bat, :bam]
7929 * a.dig(1, 2, 0) # => :bat
7930 * a.dig(1, 2, 3) # => nil
7935 rb_ary_dig(int argc
, VALUE
*argv
, VALUE self
)
7937 rb_check_arity(argc
, 1, UNLIMITED_ARGUMENTS
);
7938 self
= rb_ary_at(self
, *argv
);
7939 if (!--argc
) return self
;
7941 return rb_obj_dig(argc
, argv
, self
, Qnil
);
7945 finish_exact_sum(long n
, VALUE r
, VALUE v
, int z
)
7948 v
= rb_fix_plus(LONG2FIX(n
), v
);
7950 v
= rb_rational_plus(r
, v
);
7953 v
= rb_fix_plus(LONG2FIX(0), v
);
7960 * array.sum(init = 0) -> object
7961 * array.sum(init = 0) {|element| ... } -> object
7963 * When no block is given, returns the object equivalent to:
7966 * array.each {|element| sum += element }
7969 * For example, <tt>[e1, e2, e3].sum</tt> returns <tt>init + e1 + e2 + e3</tt>.
7975 * a.sum(100) # => 106
7977 * The elements need not be numeric, but must be <tt>+</tt>-compatible
7978 * with each other and with +init+:
7980 * a = ['abc', 'def', 'ghi']
7981 * a.sum('jkl') # => "jklabcdefghi"
7983 * When a block is given, it is called with each element
7984 * and the block's return value (instead of the element itself) is used as the addend:
7986 * a = ['zero', 1, :two]
7987 * s = a.sum('Coerced and concatenated: ') {|element| element.to_s }
7988 * s # => "Coerced and concatenated: zero1two"
7992 * - Array#join and Array#flatten may be faster than Array#sum
7993 * for an +Array+ of Strings or an +Array+ of Arrays.
7994 * - Array#sum method may not respect method redefinition of "+" methods such as Integer#+.
7999 rb_ary_sum(int argc
, VALUE
*argv
, VALUE ary
)
8005 v
= (rb_check_arity(argc
, 0, 1) ? argv
[0] : LONG2FIX(0));
8007 block_given
= rb_block_given_p();
8009 if (RARRAY_LEN(ary
) == 0)
8015 if (!FIXNUM_P(v
) && !RB_BIGNUM_TYPE_P(v
) && !RB_TYPE_P(v
, T_RATIONAL
)) {
8017 goto init_is_a_value
;
8020 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
8021 e
= RARRAY_AREF(ary
, i
);
8025 n
+= FIX2LONG(e
); /* should not overflow long type */
8027 v
= rb_big_plus(LONG2NUM(n
), v
);
8031 else if (RB_BIGNUM_TYPE_P(e
))
8032 v
= rb_big_plus(e
, v
);
8033 else if (RB_TYPE_P(e
, T_RATIONAL
)) {
8037 r
= rb_rational_plus(r
, e
);
8042 v
= finish_exact_sum(n
, r
, v
, argc
!=0);
8046 v
= finish_exact_sum(n
, r
, v
, i
!=0);
8048 if (RB_FLOAT_TYPE_P(e
)) {
8050 * Kahan-Babuska balancing compensated summation algorithm
8051 * See https://link.springer.com/article/10.1007/s00607-005-0139-x
8058 goto has_float_value
;
8059 for (; i
< RARRAY_LEN(ary
); i
++) {
8060 e
= RARRAY_AREF(ary
, i
);
8063 if (RB_FLOAT_TYPE_P(e
))
8065 x
= RFLOAT_VALUE(e
);
8066 else if (FIXNUM_P(e
))
8068 else if (RB_BIGNUM_TYPE_P(e
))
8070 else if (RB_TYPE_P(e
, T_RATIONAL
))
8075 if (isnan(f
)) continue;
8081 if (isinf(f
) && signbit(x
) != signbit(f
))
8087 if (isinf(f
)) continue;
8090 if (fabs(f
) >= fabs(x
))
8103 goto has_some_value
;
8105 for (; i
< RARRAY_LEN(ary
); i
++) {
8106 e
= RARRAY_AREF(ary
, i
);
8110 v
= rb_funcall(v
, idPLUS
, 1, e
);
8117 rb_ary_deconstruct(VALUE ary
)
8123 * An +Array+ is an ordered, integer-indexed collection of objects, called _elements_.
8124 * Any object (even another array) may be an array element,
8125 * and an array can contain objects of different types.
8127 * == +Array+ Indexes
8129 * +Array+ indexing starts at 0, as in C or Java.
8131 * A positive index is an offset from the first element:
8133 * - Index 0 indicates the first element.
8134 * - Index 1 indicates the second element.
8137 * A negative index is an offset, backwards, from the end of the array:
8139 * - Index -1 indicates the last element.
8140 * - Index -2 indicates the next-to-last element.
8143 * A non-negative index is <i>in range</i> if and only if it is smaller than
8144 * the size of the array. For a 3-element array:
8146 * - Indexes 0 through 2 are in range.
8147 * - Index 3 is out of range.
8149 * A negative index is <i>in range</i> if and only if its absolute value is
8150 * not larger than the size of the array. For a 3-element array:
8152 * - Indexes -1 through -3 are in range.
8153 * - Index -4 is out of range.
8155 * Although the effective index into an array is always an integer,
8156 * some methods (both within and outside of class +Array+)
8157 * accept one or more non-integer arguments that are
8158 * {integer-convertible objects}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
8161 * == Creating Arrays
8163 * You can create an +Array+ object explicitly with:
8165 * - An {array literal}[rdoc-ref:literals.rdoc@Array+Literals]:
8167 * [1, 'one', :one, [2, 'two', :two]]
8169 * - A {%w or %W: string-array Literal}[rdoc-ref:literals.rdoc@25w+and+-25W-3A+String-Array+Literals]:
8171 * %w[foo bar baz] # => ["foo", "bar", "baz"]
8172 * %w[1 % *] # => ["1", "%", "*"]
8174 * - A {%i pr %I: symbol-array Literal}[rdoc-ref:literals.rdoc@25i+and+-25I-3A+Symbol-Array+Literals]:
8176 * %i[foo bar baz] # => [:foo, :bar, :baz]
8177 * %i[1 % *] # => [:"1", :%, :*]
8179 * - \Method Kernel#Array:
8181 * Array(["a", "b"]) # => ["a", "b"]
8182 * Array(1..5) # => [1, 2, 3, 4, 5]
8183 * Array(key: :value) # => [[:key, :value]]
8184 * Array(nil) # => []
8186 * Array({:a => "a", :b => "b"}) # => [[:a, "a"], [:b, "b"]]
8188 * - \Method Array.new:
8191 * Array.new(3) # => [nil, nil, nil]
8192 * Array.new(4) {Hash.new} # => [{}, {}, {}, {}]
8193 * Array.new(3, true) # => [true, true, true]
8195 * Note that the last example above populates the array
8196 * with references to the same object.
8197 * This is recommended only in cases where that object is a natively immutable object
8198 * such as a symbol, a numeric, +nil+, +true+, or +false+.
8200 * Another way to create an array with various objects, using a block;
8201 * this usage is safe for mutable objects such as hashes, strings or
8204 * Array.new(4) {|i| i.to_s } # => ["0", "1", "2", "3"]
8206 * Here is a way to create a multi-dimensional array:
8208 * Array.new(3) {Array.new(3)}
8209 * # => [[nil, nil, nil], [nil, nil, nil], [nil, nil, nil]]
8211 * A number of Ruby methods, both in the core and in the standard library,
8212 * provide instance method +to_a+, which converts an object to an array.
8220 * - OptionParser#to_a
8225 * - Benchmark::Tms#to_a
8227 * - Enumerator::Lazy#to_a
8229 * - Gem::NameTuple#to_a
8230 * - Gem::Platform#to_a
8231 * - Gem::RequestSet::Lockfile::Tokenizer#to_a
8232 * - Gem::SourceList#to_a
8233 * - OpenSSL::X509::Extension#to_a
8234 * - OpenSSL::X509::Name#to_a
8236 * - Rinda::RingFinger#to_a
8237 * - Ripper::Lexer::Elem#to_a
8238 * - RubyVM::InstructionSequence#to_a
8243 * In addition to the methods it mixes in through the Enumerable module, the
8244 * +Array+ class has proprietary methods for accessing, searching and otherwise
8245 * manipulating arrays.
8247 * Some of the more common ones are illustrated below.
8249 * == Accessing Elements
8251 * Elements in an array can be retrieved using the Array#[] method. It can
8252 * take a single integer argument (a numeric index), a pair of arguments
8253 * (start and length) or a range. Negative indices start counting from the end,
8254 * with -1 being the last element.
8256 * arr = [1, 2, 3, 4, 5, 6]
8260 * arr[2, 3] #=> [3, 4, 5]
8261 * arr[1..4] #=> [2, 3, 4, 5]
8262 * arr[1..-3] #=> [2, 3, 4]
8264 * Another way to access a particular array element is by using the #at method
8268 * The #slice method works in an identical manner to Array#[].
8270 * To raise an error for indices outside of the array bounds or else to
8271 * provide a default value when that happens, you can use #fetch.
8273 * arr = ['a', 'b', 'c', 'd', 'e', 'f']
8274 * arr.fetch(100) #=> IndexError: index 100 outside of array bounds: -6...6
8275 * arr.fetch(100, "oops") #=> "oops"
8277 * The special methods #first and #last will return the first and last
8278 * elements of an array, respectively.
8283 * To return the first +n+ elements of an array, use #take
8285 * arr.take(3) #=> [1, 2, 3]
8287 * #drop does the opposite of #take, by returning the elements after +n+
8288 * elements have been dropped:
8290 * arr.drop(3) #=> [4, 5, 6]
8292 * == Obtaining Information about an +Array+
8294 * Arrays keep track of their own length at all times. To query an array
8295 * about the number of elements it contains, use #length, #count or #size.
8297 * browsers = ['Chrome', 'Firefox', 'Safari', 'Opera', 'IE']
8298 * browsers.length #=> 5
8299 * browsers.count #=> 5
8301 * To check whether an array contains any elements at all
8303 * browsers.empty? #=> false
8305 * To check whether a particular item is included in the array
8307 * browsers.include?('Konqueror') #=> false
8309 * == Adding Items to Arrays
8311 * Items can be added to the end of an array by using either #push or #<<
8313 * arr = [1, 2, 3, 4]
8314 * arr.push(5) #=> [1, 2, 3, 4, 5]
8315 * arr << 6 #=> [1, 2, 3, 4, 5, 6]
8317 * #unshift will add a new item to the beginning of an array.
8319 * arr.unshift(0) #=> [0, 1, 2, 3, 4, 5, 6]
8321 * With #insert you can add a new element to an array at any position.
8323 * arr.insert(3, 'apple') #=> [0, 1, 2, 'apple', 3, 4, 5, 6]
8325 * Using the #insert method, you can also insert multiple values at once:
8327 * arr.insert(3, 'orange', 'pear', 'grapefruit')
8328 * #=> [0, 1, 2, "orange", "pear", "grapefruit", "apple", 3, 4, 5, 6]
8330 * == Removing Items from an +Array+
8332 * The method #pop removes the last element in an array and returns it:
8334 * arr = [1, 2, 3, 4, 5, 6]
8336 * arr #=> [1, 2, 3, 4, 5]
8338 * To retrieve and at the same time remove the first item, use #shift:
8341 * arr #=> [2, 3, 4, 5]
8343 * To delete an element at a particular index:
8345 * arr.delete_at(2) #=> 4
8348 * To delete a particular element anywhere in an array, use #delete:
8350 * arr = [1, 2, 2, 3]
8351 * arr.delete(2) #=> 2
8354 * A useful method if you need to remove +nil+ values from an array is
8357 * arr = ['foo', 0, nil, 'bar', 7, 'baz', nil]
8358 * arr.compact #=> ['foo', 0, 'bar', 7, 'baz']
8359 * arr #=> ['foo', 0, nil, 'bar', 7, 'baz', nil]
8360 * arr.compact! #=> ['foo', 0, 'bar', 7, 'baz']
8361 * arr #=> ['foo', 0, 'bar', 7, 'baz']
8363 * Another common need is to remove duplicate elements from an array.
8365 * It has the non-destructive #uniq, and destructive method #uniq!
8367 * arr = [2, 5, 6, 556, 6, 6, 8, 9, 0, 123, 556]
8368 * arr.uniq #=> [2, 5, 6, 556, 8, 9, 0, 123]
8370 * == Iterating over Arrays
8372 * Like all classes that include the Enumerable module, +Array+ has an each
8373 * method, which defines what elements should be iterated over and how. In
8374 * case of Array's #each, all elements in the +Array+ instance are yielded to
8375 * the supplied block in sequence.
8377 * Note that this operation leaves the array unchanged.
8379 * arr = [1, 2, 3, 4, 5]
8380 * arr.each {|a| print a -= 10, " "}
8381 * # prints: -9 -8 -7 -6 -5
8382 * #=> [1, 2, 3, 4, 5]
8384 * Another sometimes useful iterator is #reverse_each which will iterate over
8385 * the elements in the array in reverse order.
8387 * words = %w[first second third fourth fifth sixth]
8389 * words.reverse_each {|word| str += "#{word} "}
8390 * p str #=> "sixth fifth fourth third second first "
8392 * The #map method can be used to create a new array based on the original
8393 * array, but with the values modified by the supplied block:
8395 * arr.map {|a| 2*a} #=> [2, 4, 6, 8, 10]
8396 * arr #=> [1, 2, 3, 4, 5]
8397 * arr.map! {|a| a**2} #=> [1, 4, 9, 16, 25]
8398 * arr #=> [1, 4, 9, 16, 25]
8401 * == Selecting Items from an +Array+
8403 * Elements can be selected from an array according to criteria defined in a
8404 * block. The selection can happen in a destructive or a non-destructive
8405 * manner. While the destructive operations will modify the array they were
8406 * called on, the non-destructive methods usually return a new array with the
8407 * selected elements, but leave the original array unchanged.
8409 * === Non-destructive Selection
8411 * arr = [1, 2, 3, 4, 5, 6]
8412 * arr.select {|a| a > 3} #=> [4, 5, 6]
8413 * arr.reject {|a| a < 3} #=> [3, 4, 5, 6]
8414 * arr.drop_while {|a| a < 4} #=> [4, 5, 6]
8415 * arr #=> [1, 2, 3, 4, 5, 6]
8417 * === Destructive Selection
8419 * #select! and #reject! are the corresponding destructive methods to #select
8422 * Similar to #select vs. #reject, #delete_if and #keep_if have the exact
8423 * opposite result when supplied with the same block:
8425 * arr.delete_if {|a| a < 4} #=> [4, 5, 6]
8428 * arr = [1, 2, 3, 4, 5, 6]
8429 * arr.keep_if {|a| a < 4} #=> [1, 2, 3]
8434 * First, what's elsewhere. \Class +Array+:
8436 * - Inherits from {class Object}[rdoc-ref:Object@What-27s+Here].
8437 * - Includes {module Enumerable}[rdoc-ref:Enumerable@What-27s+Here],
8438 * which provides dozens of additional methods.
8440 * Here, class +Array+ provides methods that are useful for:
8442 * - {Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array]
8443 * - {Querying}[rdoc-ref:Array@Methods+for+Querying]
8444 * - {Comparing}[rdoc-ref:Array@Methods+for+Comparing]
8445 * - {Fetching}[rdoc-ref:Array@Methods+for+Fetching]
8446 * - {Assigning}[rdoc-ref:Array@Methods+for+Assigning]
8447 * - {Deleting}[rdoc-ref:Array@Methods+for+Deleting]
8448 * - {Combining}[rdoc-ref:Array@Methods+for+Combining]
8449 * - {Iterating}[rdoc-ref:Array@Methods+for+Iterating]
8450 * - {Converting}[rdoc-ref:Array@Methods+for+Converting]
8451 * - {And more....}[rdoc-ref:Array@Other+Methods]
8453 * === Methods for Creating an +Array+
8455 * - ::[]: Returns a new array populated with given objects.
8456 * - ::new: Returns a new array.
8457 * - ::try_convert: Returns a new array created from a given object.
8459 * === Methods for Querying
8461 * - #length, #size: Returns the count of elements.
8462 * - #include?: Returns whether any element <tt>==</tt> a given object.
8463 * - #empty?: Returns whether there are no elements.
8464 * - #all?: Returns whether all elements meet a given criterion.
8465 * - #any?: Returns whether any element meets a given criterion.
8466 * - #none?: Returns whether no element <tt>==</tt> a given object.
8467 * - #one?: Returns whether exactly one element <tt>==</tt> a given object.
8468 * - #count: Returns the count of elements that meet a given criterion.
8469 * - #find_index, #index: Returns the index of the first element that meets a given criterion.
8470 * - #rindex: Returns the index of the last element that meets a given criterion.
8471 * - #hash: Returns the integer hash code.
8473 * === Methods for Comparing
8475 * - #<=>: Returns -1, 0, or 1 * as +self+ is less than, equal to, or
8476 * greater than a given object.
8477 * - #==: Returns whether each element in +self+ is <tt>==</tt> to the corresponding element
8478 * in a given object.
8479 * - #eql?: Returns whether each element in +self+ is <tt>eql?</tt> to the corresponding
8480 * element in a given object.
8482 * === Methods for Fetching
8484 * These methods do not modify +self+.
8486 * - #[]: Returns one or more elements.
8487 * - #fetch: Returns the element at a given offset.
8488 * - #first: Returns one or more leading elements.
8489 * - #last: Returns one or more trailing elements.
8490 * - #max: Returns one or more maximum-valued elements,
8491 * as determined by <tt><=></tt> or a given block.
8492 * - #min: Returns one or more minimum-valued elements,
8493 * as determined by <tt><=></tt> or a given block.
8494 * - #minmax: Returns the minimum-valued and maximum-valued elements,
8495 * as determined by <tt><=></tt> or a given block.
8496 * - #assoc: Returns the first element that is an array
8497 * whose first element <tt>==</tt> a given object.
8498 * - #rassoc: Returns the first element that is an array
8499 * whose second element <tt>==</tt> a given object.
8500 * - #at: Returns the element at a given offset.
8501 * - #values_at: Returns the elements at given offsets.
8502 * - #dig: Returns the object in nested objects
8503 * that is specified by a given index and additional arguments.
8504 * - #drop: Returns trailing elements as determined by a given index.
8505 * - #take: Returns leading elements as determined by a given index.
8506 * - #drop_while: Returns trailing elements as determined by a given block.
8507 * - #take_while: Returns leading elements as determined by a given block.
8508 * - #slice: Returns consecutive elements as determined by a given argument.
8509 * - #sort: Returns all elements in an order determined by <tt><=></tt> or a given block.
8510 * - #reverse: Returns all elements in reverse order.
8511 * - #compact: Returns an array containing all non-+nil+ elements.
8512 * - #select, #filter: Returns an array containing elements selected by a given block.
8513 * - #uniq: Returns an array containing non-duplicate elements.
8514 * - #rotate: Returns all elements with some rotated from one end to the other.
8515 * - #bsearch: Returns an element selected via a binary search
8516 * as determined by a given block.
8517 * - #bsearch_index: Returns the index of an element selected via a binary search
8518 * as determined by a given block.
8519 * - #sample: Returns one or more random elements.
8520 * - #shuffle: Returns elements in a random order.
8522 * === Methods for Assigning
8524 * These methods add, replace, or reorder elements in +self+.
8526 * - #[]=: Assigns specified elements with a given object.
8527 * - #push, #append, #<<: Appends trailing elements.
8528 * - #unshift, #prepend: Prepends leading elements.
8529 * - #insert: Inserts given objects at a given offset; does not replace elements.
8530 * - #concat: Appends all elements from given arrays.
8531 * - #fill: Replaces specified elements with specified objects.
8532 * - #replace: Replaces the content of +self+ with the content of a given array.
8533 * - #reverse!: Replaces +self+ with its elements reversed.
8534 * - #rotate!: Replaces +self+ with its elements rotated.
8535 * - #shuffle!: Replaces +self+ with its elements in random order.
8536 * - #sort!: Replaces +self+ with its elements sorted,
8537 * as determined by <tt><=></tt> or a given block.
8538 * - #sort_by!: Replaces +self+ with its elements sorted, as determined by a given block.
8540 * === Methods for Deleting
8542 * Each of these methods removes elements from +self+:
8544 * - #pop: Removes and returns the last element.
8545 * - #shift: Removes and returns the first element.
8546 * - #compact!: Removes all +nil+ elements.
8547 * - #delete: Removes elements equal to a given object.
8548 * - #delete_at: Removes the element at a given offset.
8549 * - #delete_if: Removes elements specified by a given block.
8550 * - #keep_if: Removes elements not specified by a given block.
8551 * - #reject!: Removes elements specified by a given block.
8552 * - #select!, #filter!: Removes elements not specified by a given block.
8553 * - #slice!: Removes and returns a sequence of elements.
8554 * - #uniq!: Removes duplicates.
8556 * === Methods for Combining
8558 * - #&: Returns an array containing elements found both in +self+ and a given array.
8559 * - #intersection: Returns an array containing elements found both in +self+
8560 * and in each given array.
8561 * - #+: Returns an array containing all elements of +self+ followed by all elements of a given array.
8562 * - #-: Returns an array containing all elements of +self+ that are not found in a given array.
8563 * - #|: Returns an array containing all elements of +self+ and all elements of a given array,
8564 * duplicates removed.
8565 * - #union: Returns an array containing all elements of +self+ and all elements of given arrays,
8566 * duplicates removed.
8567 * - #difference: Returns an array containing all elements of +self+ that are not found
8568 * in any of the given arrays..
8569 * - #product: Returns or yields all combinations of elements from +self+ and given arrays.
8571 * === Methods for Iterating
8573 * - #each: Passes each element to a given block.
8574 * - #reverse_each: Passes each element, in reverse order, to a given block.
8575 * - #each_index: Passes each element index to a given block.
8576 * - #cycle: Calls a given block with each element, then does so again,
8577 * for a specified number of times, or forever.
8578 * - #combination: Calls a given block with combinations of elements of +self+;
8579 * a combination does not use the same element more than once.
8580 * - #permutation: Calls a given block with permutations of elements of +self+;
8581 * a permutation does not use the same element more than once.
8582 * - #repeated_combination: Calls a given block with combinations of elements of +self+;
8583 * a combination may use the same element more than once.
8584 * - #repeated_permutation: Calls a given block with permutations of elements of +self+;
8585 * a permutation may use the same element more than once.
8587 * === Methods for Converting
8589 * - #map, #collect: Returns an array containing the block return-value for each element.
8590 * - #map!, #collect!: Replaces each element with a block return-value.
8591 * - #flatten: Returns an array that is a recursive flattening of +self+.
8592 * - #flatten!: Replaces each nested array in +self+ with the elements from that array.
8593 * - #inspect, #to_s: Returns a new String containing the elements.
8594 * - #join: Returns a newsString containing the elements joined by the field separator.
8595 * - #to_a: Returns +self+ or a new array containing all elements.
8596 * - #to_ary: Returns +self+.
8597 * - #to_h: Returns a new hash formed from the elements.
8598 * - #transpose: Transposes +self+, which must be an array of arrays.
8599 * - #zip: Returns a new array of arrays containing +self+ and given arrays;
8600 * follow the link for details.
8604 * - #*: Returns one of the following:
8606 * - With integer argument +n+, a new array that is the concatenation
8607 * of +n+ copies of +self+.
8608 * - With string argument +field_separator+, a new string that is equivalent to
8609 * <tt>join(field_separator)</tt>.
8611 * - #abbrev: Returns a hash of unambiguous abbreviations for elements.
8612 * - #pack: Packs the elements into a binary sequence.
8613 * - #sum: Returns a sum of elements according to either <tt>+</tt> or a given block.
8619 rb_cArray
= rb_define_class("Array", rb_cObject
);
8620 rb_include_module(rb_cArray
, rb_mEnumerable
);
8622 rb_define_alloc_func(rb_cArray
, empty_ary_alloc
);
8623 rb_define_singleton_method(rb_cArray
, "new", rb_ary_s_new
, -1);
8624 rb_define_singleton_method(rb_cArray
, "[]", rb_ary_s_create
, -1);
8625 rb_define_singleton_method(rb_cArray
, "try_convert", rb_ary_s_try_convert
, 1);
8626 rb_define_method(rb_cArray
, "initialize", rb_ary_initialize
, -1);
8627 rb_define_method(rb_cArray
, "initialize_copy", rb_ary_replace
, 1);
8629 rb_define_method(rb_cArray
, "inspect", rb_ary_inspect
, 0);
8630 rb_define_alias(rb_cArray
, "to_s", "inspect");
8631 rb_define_method(rb_cArray
, "to_a", rb_ary_to_a
, 0);
8632 rb_define_method(rb_cArray
, "to_h", rb_ary_to_h
, 0);
8633 rb_define_method(rb_cArray
, "to_ary", rb_ary_to_ary_m
, 0);
8635 rb_define_method(rb_cArray
, "==", rb_ary_equal
, 1);
8636 rb_define_method(rb_cArray
, "eql?", rb_ary_eql
, 1);
8637 rb_define_method(rb_cArray
, "hash", rb_ary_hash
, 0);
8639 rb_define_method(rb_cArray
, "[]", rb_ary_aref
, -1);
8640 rb_define_method(rb_cArray
, "[]=", rb_ary_aset
, -1);
8641 rb_define_method(rb_cArray
, "at", rb_ary_at
, 1);
8642 rb_define_method(rb_cArray
, "fetch", rb_ary_fetch
, -1);
8643 rb_define_method(rb_cArray
, "concat", rb_ary_concat_multi
, -1);
8644 rb_define_method(rb_cArray
, "union", rb_ary_union_multi
, -1);
8645 rb_define_method(rb_cArray
, "difference", rb_ary_difference_multi
, -1);
8646 rb_define_method(rb_cArray
, "intersection", rb_ary_intersection_multi
, -1);
8647 rb_define_method(rb_cArray
, "intersect?", rb_ary_intersect_p
, 1);
8648 rb_define_method(rb_cArray
, "<<", rb_ary_push
, 1);
8649 rb_define_method(rb_cArray
, "push", rb_ary_push_m
, -1);
8650 rb_define_alias(rb_cArray
, "append", "push");
8651 rb_define_method(rb_cArray
, "pop", rb_ary_pop_m
, -1);
8652 rb_define_method(rb_cArray
, "shift", rb_ary_shift_m
, -1);
8653 rb_define_method(rb_cArray
, "unshift", rb_ary_unshift_m
, -1);
8654 rb_define_alias(rb_cArray
, "prepend", "unshift");
8655 rb_define_method(rb_cArray
, "insert", rb_ary_insert
, -1);
8656 rb_define_method(rb_cArray
, "each_index", rb_ary_each_index
, 0);
8657 rb_define_method(rb_cArray
, "reverse_each", rb_ary_reverse_each
, 0);
8658 rb_define_method(rb_cArray
, "length", rb_ary_length
, 0);
8659 rb_define_method(rb_cArray
, "size", rb_ary_length
, 0);
8660 rb_define_method(rb_cArray
, "empty?", rb_ary_empty_p
, 0);
8661 rb_define_method(rb_cArray
, "find_index", rb_ary_index
, -1);
8662 rb_define_method(rb_cArray
, "index", rb_ary_index
, -1);
8663 rb_define_method(rb_cArray
, "rindex", rb_ary_rindex
, -1);
8664 rb_define_method(rb_cArray
, "join", rb_ary_join_m
, -1);
8665 rb_define_method(rb_cArray
, "reverse", rb_ary_reverse_m
, 0);
8666 rb_define_method(rb_cArray
, "reverse!", rb_ary_reverse_bang
, 0);
8667 rb_define_method(rb_cArray
, "rotate", rb_ary_rotate_m
, -1);
8668 rb_define_method(rb_cArray
, "rotate!", rb_ary_rotate_bang
, -1);
8669 rb_define_method(rb_cArray
, "sort", rb_ary_sort
, 0);
8670 rb_define_method(rb_cArray
, "sort!", rb_ary_sort_bang
, 0);
8671 rb_define_method(rb_cArray
, "sort_by!", rb_ary_sort_by_bang
, 0);
8672 rb_define_method(rb_cArray
, "collect", rb_ary_collect
, 0);
8673 rb_define_method(rb_cArray
, "collect!", rb_ary_collect_bang
, 0);
8674 rb_define_method(rb_cArray
, "map", rb_ary_collect
, 0);
8675 rb_define_method(rb_cArray
, "map!", rb_ary_collect_bang
, 0);
8676 rb_define_method(rb_cArray
, "select", rb_ary_select
, 0);
8677 rb_define_method(rb_cArray
, "select!", rb_ary_select_bang
, 0);
8678 rb_define_method(rb_cArray
, "filter", rb_ary_select
, 0);
8679 rb_define_method(rb_cArray
, "filter!", rb_ary_select_bang
, 0);
8680 rb_define_method(rb_cArray
, "keep_if", rb_ary_keep_if
, 0);
8681 rb_define_method(rb_cArray
, "values_at", rb_ary_values_at
, -1);
8682 rb_define_method(rb_cArray
, "delete", rb_ary_delete
, 1);
8683 rb_define_method(rb_cArray
, "delete_at", rb_ary_delete_at_m
, 1);
8684 rb_define_method(rb_cArray
, "delete_if", rb_ary_delete_if
, 0);
8685 rb_define_method(rb_cArray
, "reject", rb_ary_reject
, 0);
8686 rb_define_method(rb_cArray
, "reject!", rb_ary_reject_bang
, 0);
8687 rb_define_method(rb_cArray
, "zip", rb_ary_zip
, -1);
8688 rb_define_method(rb_cArray
, "transpose", rb_ary_transpose
, 0);
8689 rb_define_method(rb_cArray
, "replace", rb_ary_replace
, 1);
8690 rb_define_method(rb_cArray
, "clear", rb_ary_clear
, 0);
8691 rb_define_method(rb_cArray
, "fill", rb_ary_fill
, -1);
8692 rb_define_method(rb_cArray
, "include?", rb_ary_includes
, 1);
8693 rb_define_method(rb_cArray
, "<=>", rb_ary_cmp
, 1);
8695 rb_define_method(rb_cArray
, "slice", rb_ary_aref
, -1);
8696 rb_define_method(rb_cArray
, "slice!", rb_ary_slice_bang
, -1);
8698 rb_define_method(rb_cArray
, "assoc", rb_ary_assoc
, 1);
8699 rb_define_method(rb_cArray
, "rassoc", rb_ary_rassoc
, 1);
8701 rb_define_method(rb_cArray
, "+", rb_ary_plus
, 1);
8702 rb_define_method(rb_cArray
, "*", rb_ary_times
, 1);
8704 rb_define_method(rb_cArray
, "-", rb_ary_diff
, 1);
8705 rb_define_method(rb_cArray
, "&", rb_ary_and
, 1);
8706 rb_define_method(rb_cArray
, "|", rb_ary_or
, 1);
8708 rb_define_method(rb_cArray
, "max", rb_ary_max
, -1);
8709 rb_define_method(rb_cArray
, "min", rb_ary_min
, -1);
8710 rb_define_method(rb_cArray
, "minmax", rb_ary_minmax
, 0);
8712 rb_define_method(rb_cArray
, "uniq", rb_ary_uniq
, 0);
8713 rb_define_method(rb_cArray
, "uniq!", rb_ary_uniq_bang
, 0);
8714 rb_define_method(rb_cArray
, "compact", rb_ary_compact
, 0);
8715 rb_define_method(rb_cArray
, "compact!", rb_ary_compact_bang
, 0);
8716 rb_define_method(rb_cArray
, "flatten", rb_ary_flatten
, -1);
8717 rb_define_method(rb_cArray
, "flatten!", rb_ary_flatten_bang
, -1);
8718 rb_define_method(rb_cArray
, "count", rb_ary_count
, -1);
8719 rb_define_method(rb_cArray
, "cycle", rb_ary_cycle
, -1);
8720 rb_define_method(rb_cArray
, "permutation", rb_ary_permutation
, -1);
8721 rb_define_method(rb_cArray
, "combination", rb_ary_combination
, 1);
8722 rb_define_method(rb_cArray
, "repeated_permutation", rb_ary_repeated_permutation
, 1);
8723 rb_define_method(rb_cArray
, "repeated_combination", rb_ary_repeated_combination
, 1);
8724 rb_define_method(rb_cArray
, "product", rb_ary_product
, -1);
8726 rb_define_method(rb_cArray
, "take", rb_ary_take
, 1);
8727 rb_define_method(rb_cArray
, "take_while", rb_ary_take_while
, 0);
8728 rb_define_method(rb_cArray
, "drop", rb_ary_drop
, 1);
8729 rb_define_method(rb_cArray
, "drop_while", rb_ary_drop_while
, 0);
8730 rb_define_method(rb_cArray
, "bsearch", rb_ary_bsearch
, 0);
8731 rb_define_method(rb_cArray
, "bsearch_index", rb_ary_bsearch_index
, 0);
8732 rb_define_method(rb_cArray
, "any?", rb_ary_any_p
, -1);
8733 rb_define_method(rb_cArray
, "all?", rb_ary_all_p
, -1);
8734 rb_define_method(rb_cArray
, "none?", rb_ary_none_p
, -1);
8735 rb_define_method(rb_cArray
, "one?", rb_ary_one_p
, -1);
8736 rb_define_method(rb_cArray
, "dig", rb_ary_dig
, -1);
8737 rb_define_method(rb_cArray
, "sum", rb_ary_sum
, -1);
8739 rb_define_method(rb_cArray
, "deconstruct", rb_ary_deconstruct
, 0);
8742 #include "array.rbinc"