Ruby: array.c Source File

Ruby 3.0.5p211 (2022-11-24 revision ba5cf0f7c52d4d35cc6a173c89eda98ceffa2dcf)

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