Ruby 2.7.0p0(2019-12-25revision647ee6f091eafcce70ffb75ddf7e121e192ab217)

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