Ruby 2.1.5p273(2014-11-13revision48405)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

array.c
Go to the documentation of this file.
1 /**********************************************************************
2
3 array.c -
4
5 $Author: nagachika $
6 created at: Fri Aug 6 09:46:12 JST 1993
7
8 Copyright (C) 1993-2007 Yukihiro Matsumoto
9 Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
10 Copyright (C) 2000 Information-technology Promotion Agency, Japan
11
12 **********************************************************************/
13
14 #include "ruby/ruby.h"
15 #include "ruby/util.h"
16 #include "ruby/st.h"
17 #include "ruby/encoding.h"
18 #include "internal.h"
19 #include "probes.h"
20 #include "id.h"
21
22 #ifndef ARRAY_DEBUG
23 # define NDEBUG
24 #endif
25 #include <assert.h>
26
27 VALUE rb_cArray;
28
29 static ID id_cmp, id_div, id_power;
30
31 #define ARY_DEFAULT_SIZE 16
32 #define ARY_MAX_SIZE (LONG_MAX / (int)sizeof(VALUE))
33
34 void
35 rb_mem_clear(register VALUE *mem, register long size)
36 {
37 while (size--) {
38 *mem++ = Qnil;
39 }
40 }
41
42 static void
43 ary_mem_clear(VALUE ary, long beg, long size)
44 {
45 RARRAY_PTR_USE(ary, ptr, {
46 rb_mem_clear(ptr + beg, size);
47 });
48 }
49
50 static inline void
51 memfill(register VALUE *mem, register long size, register VALUE val)
52 {
53 while (size--) {
54 *mem++ = val;
55 }
56 }
57
58 static void
59 ary_memfill(VALUE ary, long beg, long size, VALUE val)
60 {
61 RARRAY_PTR_USE(ary, ptr, {
62 memfill(ptr + beg, size, val);
63 RB_OBJ_WRITTEN(ary, Qundef, val);
64 });
65 }
66
67 static void
68 ary_memcpy(VALUE ary, long beg, long argc, const VALUE *argv)
69 {
70 #if 1
71 if (OBJ_PROMOTED(ary)) {
72 if (argc > (int)(128/sizeof(VALUE)) /* is magic number (cache line size) */) {
73 rb_gc_writebarrier_remember_promoted(ary);
74 RARRAY_PTR_USE(ary, ptr, {
75 MEMCPY(ptr+beg, argv, VALUE, argc);
76 });
77 }
78 else {
79 int i;
80 RARRAY_PTR_USE(ary, ptr, {
81 for (i=0; i<argc; i++) {
82 RB_OBJ_WRITE(ary, &ptr[i+beg], argv[i]);
83 }
84 });
85 }
86 }
87 else {
88 RARRAY_PTR_USE(ary, ptr, {
89 MEMCPY(ptr+beg, argv, VALUE, argc);
90 });
91 }
92 #else
93 /* giveup write barrier (traditional way) */
94 MEMCPY(RARRAY_PTR(ary)+beg, argv, VALUE, argc);
95 #endif
96 }
97
98 # define ARY_SHARED_P(ary) \
99 (assert(!FL_TEST((ary), ELTS_SHARED) || !FL_TEST((ary), RARRAY_EMBED_FLAG)), \
100 FL_TEST((ary),ELTS_SHARED)!=0)
101 # define ARY_EMBED_P(ary) \
102 (assert(!FL_TEST((ary), ELTS_SHARED) || !FL_TEST((ary), RARRAY_EMBED_FLAG)), \
103 FL_TEST((ary), RARRAY_EMBED_FLAG)!=0)
104
105 #define ARY_HEAP_PTR(a) (assert(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.ptr)
106 #define ARY_HEAP_LEN(a) (assert(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.len)
107 #define ARY_EMBED_PTR(a) (assert(ARY_EMBED_P(a)), RARRAY(a)->as.ary)
108 #define ARY_EMBED_LEN(a) \
109 (assert(ARY_EMBED_P(a)), \
110 (long)((RBASIC(a)->flags >> RARRAY_EMBED_LEN_SHIFT) & \
111 (RARRAY_EMBED_LEN_MASK >> RARRAY_EMBED_LEN_SHIFT)))
112 #define ARY_HEAP_SIZE(a) (assert(!ARY_EMBED_P(a)), assert(ARY_OWNS_HEAP_P(a)), RARRAY(a)->as.heap.aux.capa * sizeof(VALUE))
113
114 #define ARY_OWNS_HEAP_P(a) (!FL_TEST((a), ELTS_SHARED|RARRAY_EMBED_FLAG))
115 #define FL_SET_EMBED(a) do { \
116 assert(!ARY_SHARED_P(a)); \
117 FL_SET((a), RARRAY_EMBED_FLAG); \
118 } while (0)
119 #define FL_UNSET_EMBED(ary) FL_UNSET((ary), RARRAY_EMBED_FLAG|RARRAY_EMBED_LEN_MASK)
120 #define FL_SET_SHARED(ary) do { \
121 assert(!ARY_EMBED_P(ary)); \
122 FL_SET((ary), ELTS_SHARED); \
123 } while (0)
124 #define FL_UNSET_SHARED(ary) FL_UNSET((ary), ELTS_SHARED)
125
126 #define ARY_SET_PTR(ary, p) do { \
127 assert(!ARY_EMBED_P(ary)); \
128 assert(!OBJ_FROZEN(ary)); \
129 RARRAY(ary)->as.heap.ptr = (p); \
130 } while (0)
131 #define ARY_SET_EMBED_LEN(ary, n) do { \
132 long tmp_n = (n); \
133 assert(ARY_EMBED_P(ary)); \
134 assert(!OBJ_FROZEN(ary)); \
135 RBASIC(ary)->flags &= ~RARRAY_EMBED_LEN_MASK; \
136 RBASIC(ary)->flags |= (tmp_n) << RARRAY_EMBED_LEN_SHIFT; \
137 } while (0)
138 #define ARY_SET_HEAP_LEN(ary, n) do { \
139 assert(!ARY_EMBED_P(ary)); \
140 RARRAY(ary)->as.heap.len = (n); \
141 } while (0)
142 #define ARY_SET_LEN(ary, n) do { \
143 if (ARY_EMBED_P(ary)) { \
144 ARY_SET_EMBED_LEN((ary), (n)); \
145 } \
146 else { \
147 ARY_SET_HEAP_LEN((ary), (n)); \
148 } \
149 assert(RARRAY_LEN(ary) == (n)); \
150 } while (0)
151 #define ARY_INCREASE_PTR(ary, n) do { \
152 assert(!ARY_EMBED_P(ary)); \
153 assert(!OBJ_FROZEN(ary)); \
154 RARRAY(ary)->as.heap.ptr += (n); \
155 } while (0)
156 #define ARY_INCREASE_LEN(ary, n) do { \
157 assert(!OBJ_FROZEN(ary)); \
158 if (ARY_EMBED_P(ary)) { \
159 ARY_SET_EMBED_LEN((ary), RARRAY_LEN(ary)+(n)); \
160 } \
161 else { \
162 RARRAY(ary)->as.heap.len += (n); \
163 } \
164 } while (0)
165
166 #define ARY_CAPA(ary) (ARY_EMBED_P(ary) ? RARRAY_EMBED_LEN_MAX : \
167 ARY_SHARED_ROOT_P(ary) ? RARRAY_LEN(ary) : RARRAY(ary)->as.heap.aux.capa)
168 #define ARY_SET_CAPA(ary, n) do { \
169 assert(!ARY_EMBED_P(ary)); \
170 assert(!ARY_SHARED_P(ary)); \
171 assert(!OBJ_FROZEN(ary)); \
172 RARRAY(ary)->as.heap.aux.capa = (n); \
173 } while (0)
174
175 #define ARY_SHARED(ary) (assert(ARY_SHARED_P(ary)), RARRAY(ary)->as.heap.aux.shared)
176 #define ARY_SET_SHARED(ary, value) do { \
177 const VALUE _ary_ = (ary); \
178 const VALUE _value_ = (value); \
179 assert(!ARY_EMBED_P(_ary_)); \
180 assert(ARY_SHARED_P(_ary_)); \
181 assert(ARY_SHARED_ROOT_P(_value_)); \
182 RB_OBJ_WRITE(_ary_, &RARRAY(_ary_)->as.heap.aux.shared, _value_); \
183 } while (0)
184 #define RARRAY_SHARED_ROOT_FLAG FL_USER5
185 #define ARY_SHARED_ROOT_P(ary) (FL_TEST((ary), RARRAY_SHARED_ROOT_FLAG))
186 #define ARY_SHARED_NUM(ary) \
187 (assert(ARY_SHARED_ROOT_P(ary)), RARRAY(ary)->as.heap.aux.capa)
188 #define ARY_SHARED_OCCUPIED(ary) (ARY_SHARED_NUM(ary) == 1)
189 #define ARY_SET_SHARED_NUM(ary, value) do { \
190 assert(ARY_SHARED_ROOT_P(ary)); \
191 RARRAY(ary)->as.heap.aux.capa = (value); \
192 } while (0)
193 #define FL_SET_SHARED_ROOT(ary) do { \
194 assert(!ARY_EMBED_P(ary)); \
195 FL_SET((ary), RARRAY_SHARED_ROOT_FLAG); \
196 } while (0)
197
198 static void
199 ary_resize_capa(VALUE ary, long capacity)
200 {
201 assert(RARRAY_LEN(ary) <= capacity);
202 assert(!OBJ_FROZEN(ary));
203 assert(!ARY_SHARED_P(ary));
204 if (capacity > RARRAY_EMBED_LEN_MAX) {
205 if (ARY_EMBED_P(ary)) {
206 long len = ARY_EMBED_LEN(ary);
207 VALUE *ptr = ALLOC_N(VALUE, (capacity));
208 MEMCPY(ptr, ARY_EMBED_PTR(ary), VALUE, len);
209 FL_UNSET_EMBED(ary);
210 ARY_SET_PTR(ary, ptr);
211 ARY_SET_HEAP_LEN(ary, len);
212 }
213 else {
214 SIZED_REALLOC_N(RARRAY(ary)->as.heap.ptr, VALUE, capacity, RARRAY(ary)->as.heap.aux.capa);
215 }
216 ARY_SET_CAPA(ary, (capacity));
217 }
218 else {
219 if (!ARY_EMBED_P(ary)) {
220 long len = RARRAY_LEN(ary);
221 const VALUE *ptr = RARRAY_CONST_PTR(ary);
222
223 if (len > capacity) len = capacity;
224 MEMCPY((VALUE *)RARRAY(ary)->as.ary, ptr, VALUE, len);
225 FL_SET_EMBED(ary);
226 ARY_SET_LEN(ary, len);
227 ruby_xfree((VALUE *)ptr);
228 }
229 }
230 }
231
232 static inline void
233 ary_shrink_capa(VALUE ary)
234 {
235 long capacity = ARY_HEAP_LEN(ary);
236 long old_capa = RARRAY(ary)->as.heap.aux.capa;
237 assert(!ARY_SHARED_P(ary));
238 assert(old_capa >= capacity);
239 if (old_capa > capacity)
240 REALLOC_N(RARRAY(ary)->as.heap.ptr, VALUE, capacity);
241 }
242
243 static void
244 ary_double_capa(VALUE ary, long min)
245 {
246 long new_capa = ARY_CAPA(ary) / 2;
247
248 if (new_capa < ARY_DEFAULT_SIZE) {
249 new_capa = ARY_DEFAULT_SIZE;
250 }
251 if (new_capa >= ARY_MAX_SIZE - min) {
252 new_capa = (ARY_MAX_SIZE - min) / 2;
253 }
254 new_capa += min;
255 ary_resize_capa(ary, new_capa);
256 }
257
258 static void
259 rb_ary_decrement_share(VALUE shared)
260 {
261 if (shared) {
262 long num = ARY_SHARED_NUM(shared) - 1;
263 if (num == 0) {
264 rb_ary_free(shared);
265 rb_gc_force_recycle(shared);
266 }
267 else if (num > 0) {
268 ARY_SET_SHARED_NUM(shared, num);
269 }
270 }
271 }
272
273 static void
274 rb_ary_unshare(VALUE ary)
275 {
276 VALUE shared = RARRAY(ary)->as.heap.aux.shared;
277 rb_ary_decrement_share(shared);
278 FL_UNSET_SHARED(ary);
279 }
280
281 static inline void
282 rb_ary_unshare_safe(VALUE ary)
283 {
284 if (ARY_SHARED_P(ary) && !ARY_EMBED_P(ary)) {
285 rb_ary_unshare(ary);
286 }
287 }
288
289 static VALUE
290 rb_ary_increment_share(VALUE shared)
291 {
292 long num = ARY_SHARED_NUM(shared);
293 if (num >= 0) {
294 ARY_SET_SHARED_NUM(shared, num + 1);
295 }
296 return shared;
297 }
298
299 static void
300 rb_ary_set_shared(VALUE ary, VALUE shared)
301 {
302 rb_ary_increment_share(shared);
303 FL_SET_SHARED(ary);
304 ARY_SET_SHARED(ary, shared);
305 }
306
307 static inline void
308 rb_ary_modify_check(VALUE ary)
309 {
310 rb_check_frozen(ary);
311 }
312
313 void
314 rb_ary_modify(VALUE ary)
315 {
316 rb_ary_modify_check(ary);
317 if (ARY_SHARED_P(ary)) {
318 long shared_len, len = RARRAY_LEN(ary);
319 VALUE shared = ARY_SHARED(ary);
320 if (len <= RARRAY_EMBED_LEN_MAX) {
321 const VALUE *ptr = ARY_HEAP_PTR(ary);
322 FL_UNSET_SHARED(ary);
323 FL_SET_EMBED(ary);
324 MEMCPY((VALUE *)ARY_EMBED_PTR(ary), ptr, VALUE, len);
325 rb_ary_decrement_share(shared);
326 ARY_SET_EMBED_LEN(ary, len);
327 }
328 else if (ARY_SHARED_OCCUPIED(shared) && len > ((shared_len = RARRAY_LEN(shared))>>1)) {
329 long shift = RARRAY_CONST_PTR(ary) - RARRAY_CONST_PTR(shared);
330 FL_UNSET_SHARED(ary);
331 ARY_SET_PTR(ary, RARRAY_CONST_PTR(shared));
332 ARY_SET_CAPA(ary, shared_len);
333 RARRAY_PTR_USE(ary, ptr, {
334 MEMMOVE(ptr, ptr+shift, VALUE, len);
335 });
336 FL_SET_EMBED(shared);
337 rb_ary_decrement_share(shared);
338 }
339 else {
340 VALUE *ptr = ALLOC_N(VALUE, len);
341 MEMCPY(ptr, RARRAY_CONST_PTR(ary), VALUE, len);
342 rb_ary_unshare(ary);
343 ARY_SET_CAPA(ary, len);
344 ARY_SET_PTR(ary, ptr);
345 }
346
347 /* TODO: age2 promotion, OBJ_PROMOTED() checks not infant. */
348 if (OBJ_PROMOTED(ary) && !OBJ_PROMOTED(shared)) {
349 rb_gc_writebarrier_remember_promoted(ary);
350 }
351 }
352 }
353
354 static void
355 ary_ensure_room_for_push(VALUE ary, long add_len)
356 {
357 long new_len = RARRAY_LEN(ary) + add_len;
358 long capa;
359
360 if (ARY_SHARED_P(ary)) {
361 if (new_len > RARRAY_EMBED_LEN_MAX) {
362 VALUE shared = ARY_SHARED(ary);
363 if (ARY_SHARED_OCCUPIED(shared)) {
364 if (RARRAY_CONST_PTR(ary) - RARRAY_CONST_PTR(shared) + new_len <= RARRAY_LEN(shared)) {
365 rb_ary_modify_check(ary);
366 }
367 else {
368 /* if array is shared, then it is likely it participate in push/shift pattern */
369 rb_ary_modify(ary);
370 capa = ARY_CAPA(ary);
371 if (new_len > capa - (capa >> 6)) {
372 ary_double_capa(ary, new_len);
373 }
374 }
375 return;
376 }
377 }
378 }
379 rb_ary_modify(ary);
380 capa = ARY_CAPA(ary);
381 if (new_len > capa) {
382 ary_double_capa(ary, new_len);
383 }
384 }
385
386 /*
387 * call-seq:
388 * ary.freeze -> ary
389 *
390 * Calls Object#freeze on +ary+ to prevent any further
391 * modification. A RuntimeError will be raised if a modification
392 * attempt is made.
393 *
394 */
395
396 VALUE
397 rb_ary_freeze(VALUE ary)
398 {
399 return rb_obj_freeze(ary);
400 }
401
402 /*
403 * call-seq:
404 * ary.frozen? -> true or false
405 *
406 * Return +true+ if this array is frozen (or temporarily frozen
407 * while being sorted). See also Object#frozen?
408 */
409
410 static VALUE
411 rb_ary_frozen_p(VALUE ary)
412 {
413 if (OBJ_FROZEN(ary)) return Qtrue;
414 return Qfalse;
415 }
416
417 /* This can be used to take a snapshot of an array (with
418 e.g. rb_ary_replace) and check later whether the array has been
419 modified from the snapshot. The snapshot is cheap, though if
420 something does modify the array it will pay the cost of copying
421 it. If Array#pop or Array#shift has been called, the array will
422 be still shared with the snapshot, but the array length will
423 differ. */
424 VALUE
425 rb_ary_shared_with_p(VALUE ary1, VALUE ary2)
426 {
427 if (!ARY_EMBED_P(ary1) && ARY_SHARED_P(ary1) &&
428 !ARY_EMBED_P(ary2) && ARY_SHARED_P(ary2) &&
429 RARRAY(ary1)->as.heap.aux.shared == RARRAY(ary2)->as.heap.aux.shared &&
430 RARRAY(ary1)->as.heap.len == RARRAY(ary2)->as.heap.len) {
431 return Qtrue;
432 }
433 return Qfalse;
434 }
435
436 static VALUE
437 ary_alloc(VALUE klass)
438 {
439 NEWOBJ_OF(ary, struct RArray, klass, T_ARRAY | RARRAY_EMBED_FLAG | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0));
440 /* Created array is:
441 * FL_SET_EMBED((VALUE)ary);
442 * ARY_SET_EMBED_LEN((VALUE)ary, 0);
443 */
444 return (VALUE)ary;
445 }
446
447 static VALUE
448 empty_ary_alloc(VALUE klass)
449 {
450 if (RUBY_DTRACE_ARRAY_CREATE_ENABLED()) {
451 RUBY_DTRACE_ARRAY_CREATE(0, rb_sourcefile(), rb_sourceline());
452 }
453
454 return ary_alloc(klass);
455 }
456
457 static VALUE
458 ary_new(VALUE klass, long capa)
459 {
460 VALUE ary,*ptr;
461
462 if (capa < 0) {
463 rb_raise(rb_eArgError, "negative array size (or size too big)");
464 }
465 if (capa > ARY_MAX_SIZE) {
466 rb_raise(rb_eArgError, "array size too big");
467 }
468
469 if (RUBY_DTRACE_ARRAY_CREATE_ENABLED()) {
470 RUBY_DTRACE_ARRAY_CREATE(capa, rb_sourcefile(), rb_sourceline());
471 }
472
473 if (capa > RARRAY_EMBED_LEN_MAX) {
474 ptr = ALLOC_N(VALUE, capa);
475 ary = ary_alloc(klass);
476 FL_UNSET_EMBED(ary);
477 ARY_SET_PTR(ary, ptr);
478 ARY_SET_CAPA(ary, capa);
479 ARY_SET_HEAP_LEN(ary, 0);
480 }
481 else {
482 ary = ary_alloc(klass);
483 }
484
485 return ary;
486 }
487
488 VALUE
489 rb_ary_new_capa(long capa)
490 {
491 return ary_new(rb_cArray, capa);
492 }
493
494 VALUE
495 rb_ary_new(void)
496 {
497 return rb_ary_new2(RARRAY_EMBED_LEN_MAX);
498 }
499
500 VALUE
501 rb_ary_new_from_args(long n, ...)
502 {
503 va_list ar;
504 VALUE ary;
505 long i;
506
507 ary = rb_ary_new2(n);
508
509 va_start(ar, n);
510 for (i=0; i<n; i++) {
511 RARRAY_ASET(ary, i, va_arg(ar, VALUE));
512 }
513 va_end(ar);
514
515 ARY_SET_LEN(ary, n);
516 return ary;
517 }
518
519 VALUE
520 rb_ary_new_from_values(long n, const VALUE *elts)
521 {
522 VALUE ary;
523
524 ary = rb_ary_new2(n);
525 if (n > 0 && elts) {
526 ary_memcpy(ary, 0, n, elts);
527 ARY_SET_LEN(ary, n);
528 }
529
530 return ary;
531 }
532
533 VALUE
534 rb_ary_tmp_new(long capa)
535 {
536 return ary_new(0, capa);
537 }
538
539 void
540 rb_ary_free(VALUE ary)
541 {
542 if (ARY_OWNS_HEAP_P(ary)) {
543 ruby_sized_xfree((void *)ARY_HEAP_PTR(ary), ARY_HEAP_SIZE(ary));
544 }
545 }
546
547 RUBY_FUNC_EXPORTED size_t
548 rb_ary_memsize(VALUE ary)
549 {
550 if (ARY_OWNS_HEAP_P(ary)) {
551 return RARRAY(ary)->as.heap.aux.capa * sizeof(VALUE);
552 }
553 else {
554 return 0;
555 }
556 }
557
558 static inline void
559 ary_discard(VALUE ary)
560 {
561 rb_ary_free(ary);
562 RBASIC(ary)->flags |= RARRAY_EMBED_FLAG;
563 RBASIC(ary)->flags &= ~RARRAY_EMBED_LEN_MASK;
564 }
565
566 static VALUE
567 ary_make_shared(VALUE ary)
568 {
569 assert(!ARY_EMBED_P(ary));
570 if (ARY_SHARED_P(ary)) {
571 return ARY_SHARED(ary);
572 }
573 else if (ARY_SHARED_ROOT_P(ary)) {
574 return ary;
575 }
576 else if (OBJ_FROZEN(ary)) {
577 ary_shrink_capa(ary);
578 FL_SET_SHARED_ROOT(ary);
579 ARY_SET_SHARED_NUM(ary, 1);
580 return ary;
581 }
582 else {
583 long capa = ARY_CAPA(ary), len = RARRAY_LEN(ary);
584 NEWOBJ_OF(shared, struct RArray, 0, T_ARRAY); /* keep shared ary as non-WB-protected */
585 FL_UNSET_EMBED(shared);
586
587 ARY_SET_LEN((VALUE)shared, capa);
588 ARY_SET_PTR((VALUE)shared, RARRAY_CONST_PTR(ary));
589 ary_mem_clear((VALUE)shared, len, capa - len);
590 FL_SET_SHARED_ROOT(shared);
591 ARY_SET_SHARED_NUM((VALUE)shared, 1);
592 FL_SET_SHARED(ary);
593 ARY_SET_SHARED(ary, (VALUE)shared);
594 OBJ_FREEZE(shared);
595 return (VALUE)shared;
596 }
597 }
598
599 static VALUE
600 ary_make_substitution(VALUE ary)
601 {
602 long len = RARRAY_LEN(ary);
603
604 if (len <= RARRAY_EMBED_LEN_MAX) {
605 VALUE subst = rb_ary_new2(len);
606 ary_memcpy(subst, 0, len, RARRAY_CONST_PTR(ary));
607 ARY_SET_EMBED_LEN(subst, len);
608 return subst;
609 }
610 else {
611 return rb_ary_increment_share(ary_make_shared(ary));
612 }
613 }
614
615 VALUE
616 rb_assoc_new(VALUE car, VALUE cdr)
617 {
618 return rb_ary_new3(2, car, cdr);
619 }
620
621 static VALUE
622 to_ary(VALUE ary)
623 {
624 return rb_convert_type(ary, T_ARRAY, "Array", "to_ary");
625 }
626
627 VALUE
628 rb_check_array_type(VALUE ary)
629 {
630 return rb_check_convert_type(ary, T_ARRAY, "Array", "to_ary");
631 }
632
633 /*
634 * call-seq:
635 * Array.try_convert(obj) -> array or nil
636 *
637 * Tries to convert +obj+ into an array, using +to_ary+ method. Returns the
638 * converted array or +nil+ if +obj+ cannot be converted for any reason.
639 * This method can be used to check if an argument is an array.
640 *
641 * Array.try_convert([1]) #=> [1]
642 * Array.try_convert("1") #=> nil
643 *
644 * if tmp = Array.try_convert(arg)
645 * # the argument is an array
646 * elsif tmp = String.try_convert(arg)
647 * # the argument is a string
648 * end
649 *
650 */
651
652 static VALUE
653 rb_ary_s_try_convert(VALUE dummy, VALUE ary)
654 {
655 return rb_check_array_type(ary);
656 }
657
658 /*
659 * call-seq:
660 * Array.new(size=0, obj=nil)
661 * Array.new(array)
662 * Array.new(size) {|index| block }
663 *
664 * Returns a new array.
665 *
666 * In the first form, if no arguments are sent, the new array will be empty.
667 * When a +size+ and an optional +obj+ are sent, an array is created with
668 * +size+ copies of +obj+. Take notice that all elements will reference the
669 * same object +obj+.
670 *
671 * The second form creates a copy of the array passed as a parameter (the
672 * array is generated by calling to_ary on the parameter).
673 *
674 * first_array = ["Matz", "Guido"]
675 *
676 * second_array = Array.new(first_array) #=> ["Matz", "Guido"]
677 *
678 * first_array.equal? second_array #=> false
679 *
680 * In the last form, an array of the given size is created. Each element in
681 * this array is created by passing the element's index to the given block
682 * and storing the return value.
683 *
684 * Array.new(3){ |index| index ** 2 }
685 * # => [0, 1, 4]
686 *
687 * == Common gotchas
688 *
689 * When sending the second parameter, the same object will be used as the
690 * value for all the array elements:
691 *
692 * a = Array.new(2, Hash.new)
693 * # => [{}, {}]
694 *
695 * a[0]['cat'] = 'feline'
696 * a # => [{"cat"=>"feline"}, {"cat"=>"feline"}]
697 *
698 * a[1]['cat'] = 'Felix'
699 * a # => [{"cat"=>"Felix"}, {"cat"=>"Felix"}]
700 *
701 * Since all the Array elements store the same hash, changes to one of them
702 * will affect them all.
703 *
704 * If multiple copies are what you want, you should use the block
705 * version which uses the result of that block each time an element
706 * of the array needs to be initialized:
707 *
708 * a = Array.new(2) { Hash.new }
709 * a[0]['cat'] = 'feline'
710 * a # => [{"cat"=>"feline"}, {}]
711 *
712 */
713
714 static VALUE
715 rb_ary_initialize(int argc, VALUE *argv, VALUE ary)
716 {
717 long len;
718 VALUE size, val;
719
720 rb_ary_modify(ary);
721 if (argc == 0) {
722 if (ARY_OWNS_HEAP_P(ary) && RARRAY_CONST_PTR(ary) != 0) {
723 ruby_sized_xfree((void *)RARRAY_CONST_PTR(ary), ARY_HEAP_SIZE(ary));
724 }
725 rb_ary_unshare_safe(ary);
726 FL_SET_EMBED(ary);
727 ARY_SET_EMBED_LEN(ary, 0);
728 if (rb_block_given_p()) {
729 rb_warning("given block not used");
730 }
731 return ary;
732 }
733 rb_scan_args(argc, argv, "02", &size, &val);
734 if (argc == 1 && !FIXNUM_P(size)) {
735 val = rb_check_array_type(size);
736 if (!NIL_P(val)) {
737 rb_ary_replace(ary, val);
738 return ary;
739 }
740 }
741
742 len = NUM2LONG(size);
743 if (len < 0) {
744 rb_raise(rb_eArgError, "negative array size");
745 }
746 if (len > ARY_MAX_SIZE) {
747 rb_raise(rb_eArgError, "array size too big");
748 }
749 rb_ary_modify(ary);
750 ary_resize_capa(ary, len);
751 if (rb_block_given_p()) {
752 long i;
753
754 if (argc == 2) {
755 rb_warn("block supersedes default value argument");
756 }
757 for (i=0; i<len; i++) {
758 rb_ary_store(ary, i, rb_yield(LONG2NUM(i)));
759 ARY_SET_LEN(ary, i + 1);
760 }
761 }
762 else {
763 ary_memfill(ary, 0, len, val);
764 ARY_SET_LEN(ary, len);
765 }
766 return ary;
767 }
768
769 /*
770 * Returns a new array populated with the given objects.
771 *
772 * Array.[]( 1, 'a', /^A/ ) # => [1, "a", /^A/]
773 * Array[ 1, 'a', /^A/ ] # => [1, "a", /^A/]
774 * [ 1, 'a', /^A/ ] # => [1, "a", /^A/]
775 */
776
777 static VALUE
778 rb_ary_s_create(int argc, VALUE *argv, VALUE klass)
779 {
780 VALUE ary = ary_new(klass, argc);
781 if (argc > 0 && argv) {
782 ary_memcpy(ary, 0, argc, argv);
783 ARY_SET_LEN(ary, argc);
784 }
785
786 return ary;
787 }
788
789 void
790 rb_ary_store(VALUE ary, long idx, VALUE val)
791 {
792 long len = RARRAY_LEN(ary);
793
794 if (idx < 0) {
795 idx += len;
796 if (idx < 0) {
797 rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
798 idx - len, -len);
799 }
800 }
801 else if (idx >= ARY_MAX_SIZE) {
802 rb_raise(rb_eIndexError, "index %ld too big", idx);
803 }
804
805 rb_ary_modify(ary);
806 if (idx >= ARY_CAPA(ary)) {
807 ary_double_capa(ary, idx);
808 }
809 if (idx > len) {
810 ary_mem_clear(ary, len, idx - len + 1);
811 }
812
813 if (idx >= len) {
814 ARY_SET_LEN(ary, idx + 1);
815 }
816 RARRAY_ASET(ary, idx, val);
817 }
818
819 static VALUE
820 ary_make_partial(VALUE ary, VALUE klass, long offset, long len)
821 {
822 assert(offset >= 0);
823 assert(len >= 0);
824 assert(offset+len <= RARRAY_LEN(ary));
825
826 if (len <= RARRAY_EMBED_LEN_MAX) {
827 VALUE result = ary_alloc(klass);
828 ary_memcpy(result, 0, len, RARRAY_CONST_PTR(ary) + offset);
829 ARY_SET_EMBED_LEN(result, len);
830 return result;
831 }
832 else {
833 VALUE shared, result = ary_alloc(klass);
834 FL_UNSET_EMBED(result);
835
836 shared = ary_make_shared(ary);
837 ARY_SET_PTR(result, RARRAY_CONST_PTR(ary));
838 ARY_SET_LEN(result, RARRAY_LEN(ary));
839 rb_ary_set_shared(result, shared);
840
841 ARY_INCREASE_PTR(result, offset);
842 ARY_SET_LEN(result, len);
843 return result;
844 }
845 }
846
847 static VALUE
848 ary_make_shared_copy(VALUE ary)
849 {
850 return ary_make_partial(ary, rb_obj_class(ary), 0, RARRAY_LEN(ary));
851 }
852
853 enum ary_take_pos_flags
854 {
855 ARY_TAKE_FIRST = 0,
856 ARY_TAKE_LAST = 1
857 };
858
859 static VALUE
860 ary_take_first_or_last(int argc, VALUE *argv, VALUE ary, enum ary_take_pos_flags last)
861 {
862 VALUE nv;
863 long n;
864 long len;
865 long offset = 0;
866
867 rb_scan_args(argc, argv, "1", &nv);
868 n = NUM2LONG(nv);
869 len = RARRAY_LEN(ary);
870 if (n > len) {
871 n = len;
872 }
873 else if (n < 0) {
874 rb_raise(rb_eArgError, "negative array size");
875 }
876 if (last) {
877 offset = len - n;
878 }
879 return ary_make_partial(ary, rb_cArray, offset, n);
880 }
881
882 /*
883 * call-seq:
884 * ary << obj -> ary
885 *
886 * Append---Pushes the given object on to the end of this array. This
887 * expression returns the array itself, so several appends
888 * may be chained together.
889 *
890 * [ 1, 2 ] << "c" << "d" << [ 3, 4 ]
891 * #=> [ 1, 2, "c", "d", [ 3, 4 ] ]
892 *
893 */
894
895 VALUE
896 rb_ary_push(VALUE ary, VALUE item)
897 {
898 long idx = RARRAY_LEN(ary);
899
900 ary_ensure_room_for_push(ary, 1);
901 RARRAY_ASET(ary, idx, item);
902 ARY_SET_LEN(ary, idx + 1);
903 return ary;
904 }
905
906 VALUE
907 rb_ary_cat(VALUE ary, const VALUE *ptr, long len)
908 {
909 long oldlen = RARRAY_LEN(ary);
910
911 ary_ensure_room_for_push(ary, len);
912 ary_memcpy(ary, oldlen, len, ptr);
913 ARY_SET_LEN(ary, oldlen + len);
914 return ary;
915 }
916
917 /*
918 * call-seq:
919 * ary.push(obj, ... ) -> ary
920 *
921 * Append --- Pushes the given object(s) on to the end of this array. This
922 * expression returns the array itself, so several appends
923 * may be chained together. See also Array#pop for the opposite
924 * effect.
925 *
926 * a = [ "a", "b", "c" ]
927 * a.push("d", "e", "f")
928 * #=> ["a", "b", "c", "d", "e", "f"]
929 * [1, 2, 3,].push(4).push(5)
930 * #=> [1, 2, 3, 4, 5]
931 */
932
933 static VALUE
934 rb_ary_push_m(int argc, VALUE *argv, VALUE ary)
935 {
936 return rb_ary_cat(ary, argv, argc);
937 }
938
939 VALUE
940 rb_ary_pop(VALUE ary)
941 {
942 long n;
943 rb_ary_modify_check(ary);
944 n = RARRAY_LEN(ary);
945 if (n == 0) return Qnil;
946 if (ARY_OWNS_HEAP_P(ary) &&
947 n * 3 < ARY_CAPA(ary) &&
948 ARY_CAPA(ary) > ARY_DEFAULT_SIZE)
949 {
950 ary_resize_capa(ary, n * 2);
951 }
952 --n;
953 ARY_SET_LEN(ary, n);
954 return RARRAY_AREF(ary, n);
955 }
956
957 /*
958 * call-seq:
959 * ary.pop -> obj or nil
960 * ary.pop(n) -> new_ary
961 *
962 * Removes the last element from +self+ and returns it, or
963 * +nil+ if the array is empty.
964 *
965 * If a number +n+ is given, returns an array of the last +n+ elements
966 * (or less) just like <code>array.slice!(-n, n)</code> does. See also
967 * Array#push for the opposite effect.
968 *
969 * a = [ "a", "b", "c", "d" ]
970 * a.pop #=> "d"
971 * a.pop(2) #=> ["b", "c"]
972 * a #=> ["a"]
973 */
974
975 static VALUE
976 rb_ary_pop_m(int argc, VALUE *argv, VALUE ary)
977 {
978 VALUE result;
979
980 if (argc == 0) {
981 return rb_ary_pop(ary);
982 }
983
984 rb_ary_modify_check(ary);
985 result = ary_take_first_or_last(argc, argv, ary, ARY_TAKE_LAST);
986 ARY_INCREASE_LEN(ary, -RARRAY_LEN(result));
987 return result;
988 }
989
990 VALUE
991 rb_ary_shift(VALUE ary)
992 {
993 VALUE top;
994 long len = RARRAY_LEN(ary);
995
996 rb_ary_modify_check(ary);
997 if (len == 0) return Qnil;
998 top = RARRAY_AREF(ary, 0);
999 if (!ARY_SHARED_P(ary)) {
1000 if (len < ARY_DEFAULT_SIZE) {
1001 RARRAY_PTR_USE(ary, ptr, {
1002 MEMMOVE(ptr, ptr+1, VALUE, len-1);
1003 }); /* WB: no new reference */
1004 ARY_INCREASE_LEN(ary, -1);
1005 return top;
1006 }
1007 assert(!ARY_EMBED_P(ary)); /* ARY_EMBED_LEN_MAX < ARY_DEFAULT_SIZE */
1008
1009 RARRAY_ASET(ary, 0, Qnil);
1010 ary_make_shared(ary);
1011 }
1012 else if (ARY_SHARED_OCCUPIED(ARY_SHARED(ary))) {
1013 RARRAY_ASET(ary, 0, Qnil);
1014 }
1015 ARY_INCREASE_PTR(ary, 1); /* shift ptr */
1016 ARY_INCREASE_LEN(ary, -1);
1017
1018 return top;
1019 }
1020
1021 /*
1022 * call-seq:
1023 * ary.shift -> obj or nil
1024 * ary.shift(n) -> new_ary
1025 *
1026 * Removes the first element of +self+ and returns it (shifting all
1027 * other elements down by one). Returns +nil+ if the array
1028 * is empty.
1029 *
1030 * If a number +n+ is given, returns an array of the first +n+ elements
1031 * (or less) just like <code>array.slice!(0, n)</code> does. With +ary+
1032 * containing only the remainder elements, not including what was shifted to
1033 * +new_ary+. See also Array#unshift for the opposite effect.
1034 *
1035 * args = [ "-m", "-q", "filename" ]
1036 * args.shift #=> "-m"
1037 * args #=> ["-q", "filename"]
1038 *
1039 * args = [ "-m", "-q", "filename" ]
1040 * args.shift(2) #=> ["-m", "-q"]
1041 * args #=> ["filename"]
1042 */
1043
1044 static VALUE
1045 rb_ary_shift_m(int argc, VALUE *argv, VALUE ary)
1046 {
1047 VALUE result;
1048 long n;
1049
1050 if (argc == 0) {
1051 return rb_ary_shift(ary);
1052 }
1053
1054 rb_ary_modify_check(ary);
1055 result = ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST);
1056 n = RARRAY_LEN(result);
1057 if (ARY_SHARED_P(ary)) {
1058 if (ARY_SHARED_OCCUPIED(ARY_SHARED(ary))) {
1059 ary_mem_clear(ary, 0, n);
1060 }
1061 ARY_INCREASE_PTR(ary, n);
1062 }
1063 else {
1064 RARRAY_PTR_USE(ary, ptr, {
1065 MEMMOVE(ptr, ptr + n, VALUE, RARRAY_LEN(ary)-n);
1066 }); /* WB: no new reference */
1067 }
1068 ARY_INCREASE_LEN(ary, -n);
1069
1070 return result;
1071 }
1072
1073 static void
1074 ary_ensure_room_for_unshift(VALUE ary, int argc)
1075 {
1076 long len = RARRAY_LEN(ary);
1077 long new_len = len + argc;
1078 long capa;
1079 const VALUE *head, *sharedp;
1080
1081 if (ARY_SHARED_P(ary)) {
1082 VALUE shared = ARY_SHARED(ary);
1083 capa = RARRAY_LEN(shared);
1084 if (ARY_SHARED_OCCUPIED(shared) && capa > new_len) {
1085 head = RARRAY_CONST_PTR(ary);
1086 sharedp = RARRAY_CONST_PTR(shared);
1087 goto makeroom_if_need;
1088 }
1089 }
1090
1091 rb_ary_modify(ary);
1092 capa = ARY_CAPA(ary);
1093 if (capa - (capa >> 6) <= new_len) {
1094 ary_double_capa(ary, new_len);
1095 }
1096
1097 /* use shared array for big "queues" */
1098 if (new_len > ARY_DEFAULT_SIZE * 4) {
1099 /* make a room for unshifted items */
1100 capa = ARY_CAPA(ary);
1101 ary_make_shared(ary);
1102
1103 head = sharedp = RARRAY_CONST_PTR(ary);
1104 goto makeroom;
1105 makeroom_if_need:
1106 if (head - sharedp < argc) {
1107 long room;
1108 makeroom:
1109 room = capa - new_len;
1110 room -= room >> 4;
1111 MEMMOVE((VALUE *)sharedp + argc + room, head, VALUE, len);
1112 head = sharedp + argc + room;
1113 }
1114 ARY_SET_PTR(ary, head - argc);
1115 }
1116 else {
1117 /* sliding items */
1118 RARRAY_PTR_USE(ary, ptr, {
1119 MEMMOVE(ptr + argc, ptr, VALUE, len);
1120 });
1121 }
1122 }
1123
1124 /*
1125 * call-seq:
1126 * ary.unshift(obj, ...) -> ary
1127 *
1128 * Prepends objects to the front of +self+, moving other elements upwards.
1129 * See also Array#shift for the opposite effect.
1130 *
1131 * a = [ "b", "c", "d" ]
1132 * a.unshift("a") #=> ["a", "b", "c", "d"]
1133 * a.unshift(1, 2) #=> [ 1, 2, "a", "b", "c", "d"]
1134 */
1135
1136 static VALUE
1137 rb_ary_unshift_m(int argc, VALUE *argv, VALUE ary)
1138 {
1139 long len = RARRAY_LEN(ary);
1140
1141 if (argc == 0) {
1142 rb_ary_modify_check(ary);
1143 return ary;
1144 }
1145
1146 ary_ensure_room_for_unshift(ary, argc);
1147 ary_memcpy(ary, 0, argc, argv);
1148 ARY_SET_LEN(ary, len + argc);
1149 return ary;
1150 }
1151
1152 VALUE
1153 rb_ary_unshift(VALUE ary, VALUE item)
1154 {
1155 return rb_ary_unshift_m(1,&item,ary);
1156 }
1157
1158 /* faster version - use this if you don't need to treat negative offset */
1159 static inline VALUE
1160 rb_ary_elt(VALUE ary, long offset)
1161 {
1162 long len = RARRAY_LEN(ary);
1163 if (len == 0) return Qnil;
1164 if (offset < 0 || len <= offset) {
1165 return Qnil;
1166 }
1167 return RARRAY_AREF(ary, offset);
1168 }
1169
1170 VALUE
1171 rb_ary_entry(VALUE ary, long offset)
1172 {
1173 if (offset < 0) {
1174 offset += RARRAY_LEN(ary);
1175 }
1176 return rb_ary_elt(ary, offset);
1177 }
1178
1179 VALUE
1180 rb_ary_subseq(VALUE ary, long beg, long len)
1181 {
1182 VALUE klass;
1183 long alen = RARRAY_LEN(ary);
1184
1185 if (beg > alen) return Qnil;
1186 if (beg < 0 || len < 0) return Qnil;
1187
1188 if (alen < len || alen < beg + len) {
1189 len = alen - beg;
1190 }
1191 klass = rb_obj_class(ary);
1192 if (len == 0) return ary_new(klass, 0);
1193
1194 return ary_make_partial(ary, klass, beg, len);
1195 }
1196
1197 /*
1198 * call-seq:
1199 * ary[index] -> obj or nil
1200 * ary[start, length] -> new_ary or nil
1201 * ary[range] -> new_ary or nil
1202 * ary.slice(index) -> obj or nil
1203 * ary.slice(start, length) -> new_ary or nil
1204 * ary.slice(range) -> new_ary or nil
1205 *
1206 * Element Reference --- Returns the element at +index+, or returns a
1207 * subarray starting at the +start+ index and continuing for +length+
1208 * elements, or returns a subarray specified by +range+ of indices.
1209 *
1210 * Negative indices count backward from the end of the array (-1 is the last
1211 * element). For +start+ and +range+ cases the starting index is just before
1212 * an element. Additionally, an empty array is returned when the starting
1213 * index for an element range is at the end of the array.
1214 *
1215 * Returns +nil+ if the index (or starting index) are out of range.
1216 *
1217 * a = [ "a", "b", "c", "d", "e" ]
1218 * a[2] + a[0] + a[1] #=> "cab"
1219 * a[6] #=> nil
1220 * a[1, 2] #=> [ "b", "c" ]
1221 * a[1..3] #=> [ "b", "c", "d" ]
1222 * a[4..7] #=> [ "e" ]
1223 * a[6..10] #=> nil
1224 * a[-3, 3] #=> [ "c", "d", "e" ]
1225 * # special cases
1226 * a[5] #=> nil
1227 * a[6, 1] #=> nil
1228 * a[5, 1] #=> []
1229 * a[5..10] #=> []
1230 *
1231 */
1232
1233 VALUE
1234 rb_ary_aref(int argc, VALUE *argv, VALUE ary)
1235 {
1236 VALUE arg;
1237 long beg, len;
1238
1239 if (argc == 2) {
1240 beg = NUM2LONG(argv[0]);
1241 len = NUM2LONG(argv[1]);
1242 if (beg < 0) {
1243 beg += RARRAY_LEN(ary);
1244 }
1245 return rb_ary_subseq(ary, beg, len);
1246 }
1247 if (argc != 1) {
1248 rb_scan_args(argc, argv, "11", NULL, NULL);
1249 }
1250 arg = argv[0];
1251 /* special case - speeding up */
1252 if (FIXNUM_P(arg)) {
1253 return rb_ary_entry(ary, FIX2LONG(arg));
1254 }
1255 /* check if idx is Range */
1256 switch (rb_range_beg_len(arg, &beg, &len, RARRAY_LEN(ary), 0)) {
1257 case Qfalse:
1258 break;
1259 case Qnil:
1260 return Qnil;
1261 default:
1262 return rb_ary_subseq(ary, beg, len);
1263 }
1264 return rb_ary_entry(ary, NUM2LONG(arg));
1265 }
1266
1267 /*
1268 * call-seq:
1269 * ary.at(index) -> obj or nil
1270 *
1271 * Returns the element at +index+. A negative index counts from the end of
1272 * +self+. Returns +nil+ if the index is out of range. See also
1273 * Array#[].
1274 *
1275 * a = [ "a", "b", "c", "d", "e" ]
1276 * a.at(0) #=> "a"
1277 * a.at(-1) #=> "e"
1278 */
1279
1280 static VALUE
1281 rb_ary_at(VALUE ary, VALUE pos)
1282 {
1283 return rb_ary_entry(ary, NUM2LONG(pos));
1284 }
1285
1286 /*
1287 * call-seq:
1288 * ary.first -> obj or nil
1289 * ary.first(n) -> new_ary
1290 *
1291 * Returns the first element, or the first +n+ elements, of the array.
1292 * If the array is empty, the first form returns +nil+, and the
1293 * second form returns an empty array. See also Array#last for
1294 * the opposite effect.
1295 *
1296 * a = [ "q", "r", "s", "t" ]
1297 * a.first #=> "q"
1298 * a.first(2) #=> ["q", "r"]
1299 */
1300
1301 static VALUE
1302 rb_ary_first(int argc, VALUE *argv, VALUE ary)
1303 {
1304 if (argc == 0) {
1305 if (RARRAY_LEN(ary) == 0) return Qnil;
1306 return RARRAY_AREF(ary, 0);
1307 }
1308 else {
1309 return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST);
1310 }
1311 }
1312
1313 /*
1314 * call-seq:
1315 * ary.last -> obj or nil
1316 * ary.last(n) -> new_ary
1317 *
1318 * Returns the last element(s) of +self+. If the array is empty,
1319 * the first form returns +nil+.
1320 *
1321 * See also Array#first for the opposite effect.
1322 *
1323 * a = [ "w", "x", "y", "z" ]
1324 * a.last #=> "z"
1325 * a.last(2) #=> ["y", "z"]
1326 */
1327
1328 VALUE
1329 rb_ary_last(int argc, VALUE *argv, VALUE ary)
1330 {
1331 if (argc == 0) {
1332 long len = RARRAY_LEN(ary);
1333 if (len == 0) return Qnil;
1334 return RARRAY_AREF(ary, len-1);
1335 }
1336 else {
1337 return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_LAST);
1338 }
1339 }
1340
1341 /*
1342 * call-seq:
1343 * ary.fetch(index) -> obj
1344 * ary.fetch(index, default) -> obj
1345 * ary.fetch(index) { |index| block } -> obj
1346 *
1347 * Tries to return the element at position +index+, but throws an IndexError
1348 * exception if the referenced +index+ lies outside of the array bounds. This
1349 * error can be prevented by supplying a second argument, which will act as a
1350 * +default+ value.
1351 *
1352 * Alternatively, if a block is given it will only be executed when an
1353 * invalid +index+ is referenced. Negative values of +index+ count from the
1354 * end of the array.
1355 *
1356 * a = [ 11, 22, 33, 44 ]
1357 * a.fetch(1) #=> 22
1358 * a.fetch(-1) #=> 44
1359 * a.fetch(4, 'cat') #=> "cat"
1360 * a.fetch(100) { |i| puts "#{i} is out of bounds" }
1361 * #=> "100 is out of bounds"
1362 */
1363
1364 static VALUE
1365 rb_ary_fetch(int argc, VALUE *argv, VALUE ary)
1366 {
1367 VALUE pos, ifnone;
1368 long block_given;
1369 long idx;
1370
1371 rb_scan_args(argc, argv, "11", &pos, &ifnone);
1372 block_given = rb_block_given_p();
1373 if (block_given && argc == 2) {
1374 rb_warn("block supersedes default value argument");
1375 }
1376 idx = NUM2LONG(pos);
1377
1378 if (idx < 0) {
1379 idx += RARRAY_LEN(ary);
1380 }
1381 if (idx < 0 || RARRAY_LEN(ary) <= idx) {
1382 if (block_given) return rb_yield(pos);
1383 if (argc == 1) {
1384 rb_raise(rb_eIndexError, "index %ld outside of array bounds: %ld...%ld",
1385 idx - (idx < 0 ? RARRAY_LEN(ary) : 0), -RARRAY_LEN(ary), RARRAY_LEN(ary));
1386 }
1387 return ifnone;
1388 }
1389 return RARRAY_AREF(ary, idx);
1390 }
1391
1392 /*
1393 * call-seq:
1394 * ary.find_index(obj) -> int or nil
1395 * ary.find_index { |item| block } -> int or nil
1396 * ary.find_index -> Enumerator
1397 * ary.index(obj) -> int or nil
1398 * ary.index { |item| block } -> int or nil
1399 * ary.index -> Enumerator
1400 *
1401 * Returns the _index_ of the first object in +ary+ such that the object is
1402 * <code>==</code> to +obj+.
1403 *
1404 * If a block is given instead of an argument, returns the _index_ of the
1405 * first object for which the block returns +true+. Returns +nil+ if no
1406 * match is found.
1407 *
1408 * See also Array#rindex.
1409 *
1410 * An Enumerator is returned if neither a block nor argument is given.
1411 *
1412 * a = [ "a", "b", "c" ]
1413 * a.index("b") #=> 1
1414 * a.index("z") #=> nil
1415 * a.index { |x| x == "b" } #=> 1
1416 */
1417
1418 static VALUE
1419 rb_ary_index(int argc, VALUE *argv, VALUE ary)
1420 {
1421 const VALUE *ptr;
1422 VALUE val;
1423 long i, len;
1424
1425 if (argc == 0) {
1426 RETURN_ENUMERATOR(ary, 0, 0);
1427 for (i=0; i<RARRAY_LEN(ary); i++) {
1428 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) {
1429 return LONG2NUM(i);
1430 }
1431 }
1432 return Qnil;
1433 }
1434 rb_check_arity(argc, 0, 1);
1435 val = argv[0];
1436 if (rb_block_given_p())
1437 rb_warn("given block not used");
1438 len = RARRAY_LEN(ary);
1439 ptr = RARRAY_CONST_PTR(ary);
1440 for (i=0; i<len; i++) {
1441 VALUE e = ptr[i];
1442 switch (rb_equal_opt(e, val)) {
1443 case Qundef:
1444 if (!rb_equal(e, val)) break;
1445 case Qtrue:
1446 return LONG2NUM(i);
1447 case Qfalse:
1448 continue;
1449 }
1450 len = RARRAY_LEN(ary);
1451 ptr = RARRAY_CONST_PTR(ary);
1452 }
1453 return Qnil;
1454 }
1455
1456 /*
1457 * call-seq:
1458 * ary.rindex(obj) -> int or nil
1459 * ary.rindex { |item| block } -> int or nil
1460 * ary.rindex -> Enumerator
1461 *
1462 * Returns the _index_ of the last object in +self+ <code>==</code> to +obj+.
1463 *
1464 * If a block is given instead of an argument, returns the _index_ of the
1465 * first object for which the block returns +true+, starting from the last
1466 * object.
1467 *
1468 * Returns +nil+ if no match is found.
1469 *
1470 * See also Array#index.
1471 *
1472 * If neither block nor argument is given, an Enumerator is returned instead.
1473 *
1474 * a = [ "a", "b", "b", "b", "c" ]
1475 * a.rindex("b") #=> 3
1476 * a.rindex("z") #=> nil
1477 * a.rindex { |x| x == "b" } #=> 3
1478 */
1479
1480 static VALUE
1481 rb_ary_rindex(int argc, VALUE *argv, VALUE ary)
1482 {
1483 const VALUE *ptr;
1484 VALUE val;
1485 long i = RARRAY_LEN(ary), len;
1486
1487 if (argc == 0) {
1488 RETURN_ENUMERATOR(ary, 0, 0);
1489 while (i--) {
1490 if (RTEST(rb_yield(RARRAY_AREF(ary, i))))
1491 return LONG2NUM(i);
1492 if (i > (len = RARRAY_LEN(ary))) {
1493 i = len;
1494 }
1495 }
1496 return Qnil;
1497 }
1498 rb_check_arity(argc, 0, 1);
1499 val = argv[0];
1500 if (rb_block_given_p())
1501 rb_warn("given block not used");
1502 ptr = RARRAY_CONST_PTR(ary);
1503 while (i--) {
1504 VALUE e = ptr[i];
1505 switch (rb_equal_opt(e, val)) {
1506 case Qundef:
1507 if (!rb_equal(e, val)) break;
1508 case Qtrue:
1509 return LONG2NUM(i);
1510 case Qfalse:
1511 continue;
1512 }
1513 if (i > (len = RARRAY_LEN(ary))) {
1514 i = len;
1515 }
1516 ptr = RARRAY_CONST_PTR(ary);
1517 }
1518 return Qnil;
1519 }
1520
1521 VALUE
1522 rb_ary_to_ary(VALUE obj)
1523 {
1524 VALUE tmp = rb_check_array_type(obj);
1525
1526 if (!NIL_P(tmp)) return tmp;
1527 return rb_ary_new3(1, obj);
1528 }
1529
1530 static void
1531 rb_ary_splice(VALUE ary, long beg, long len, VALUE rpl)
1532 {
1533 long rlen;
1534 long olen;
1535
1536 if (len < 0) rb_raise(rb_eIndexError, "negative length (%ld)", len);
1537 olen = RARRAY_LEN(ary);
1538 if (beg < 0) {
1539 beg += olen;
1540 if (beg < 0) {
1541 rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
1542 beg - olen, -olen);
1543 }
1544 }
1545 if (olen < len || olen < beg + len) {
1546 len = olen - beg;
1547 }
1548
1549 if (rpl == Qundef) {
1550 rlen = 0;
1551 }
1552 else {
1553 rpl = rb_ary_to_ary(rpl);
1554 rlen = RARRAY_LEN(rpl);
1555 olen = RARRAY_LEN(ary); /* ary may be resized in rpl.to_ary too */
1556 }
1557 if (beg >= olen) {
1558 if (beg > ARY_MAX_SIZE - rlen) {
1559 rb_raise(rb_eIndexError, "index %ld too big", beg);
1560 }
1561 ary_ensure_room_for_push(ary, rlen-len); /* len is 0 or negative */
1562 len = beg + rlen;
1563 ary_mem_clear(ary, olen, beg - olen);
1564 if (rlen > 0) {
1565 ary_memcpy(ary, beg, rlen, RARRAY_CONST_PTR(rpl));
1566 }
1567 ARY_SET_LEN(ary, len);
1568 }
1569 else {
1570 long alen;
1571
1572 rb_ary_modify(ary);
1573 alen = olen + rlen - len;
1574 if (alen >= ARY_CAPA(ary)) {
1575 ary_double_capa(ary, alen);
1576 }
1577
1578 if (len != rlen) {
1579 RARRAY_PTR_USE(ary, ptr,
1580 MEMMOVE(ptr + beg + rlen, ptr + beg + len,
1581 VALUE, olen - (beg + len)));
1582 ARY_SET_LEN(ary, alen);
1583 }
1584 if (rlen > 0) {
1585 MEMMOVE(RARRAY_PTR(ary) + beg, RARRAY_CONST_PTR(rpl), VALUE, rlen);
1586 }
1587 }
1588 RB_GC_GUARD(rpl);
1589 }
1590
1591 void
1592 rb_ary_set_len(VALUE ary, long len)
1593 {
1594 long capa;
1595
1596 rb_ary_modify_check(ary);
1597 if (ARY_SHARED_P(ary)) {
1598 rb_raise(rb_eRuntimeError, "can't set length of shared ");
1599 }
1600 if (len > (capa = (long)ARY_CAPA(ary))) {
1601 rb_bug("probable buffer overflow: %ld for %ld", len, capa);
1602 }
1603 ARY_SET_LEN(ary, len);
1604 }
1605
1614 VALUE
1615 rb_ary_resize(VALUE ary, long len)
1616 {
1617 long olen;
1618
1619 rb_ary_modify(ary);
1620 olen = RARRAY_LEN(ary);
1621 if (len == olen) return ary;
1622 if (len > ARY_MAX_SIZE) {
1623 rb_raise(rb_eIndexError, "index %ld too big", len);
1624 }
1625 if (len > olen) {
1626 if (len >= ARY_CAPA(ary)) {
1627 ary_double_capa(ary, len);
1628 }
1629 ary_mem_clear(ary, olen, len - olen);
1630 ARY_SET_LEN(ary, len);
1631 }
1632 else if (ARY_EMBED_P(ary)) {
1633 ARY_SET_EMBED_LEN(ary, len);
1634 }
1635 else if (len <= RARRAY_EMBED_LEN_MAX) {
1636 VALUE tmp[RARRAY_EMBED_LEN_MAX];
1637 MEMCPY(tmp, ARY_HEAP_PTR(ary), VALUE, len);
1638 ary_discard(ary);
1639 MEMCPY((VALUE *)ARY_EMBED_PTR(ary), tmp, VALUE, len); /* WB: no new reference */
1640 ARY_SET_EMBED_LEN(ary, len);
1641 }
1642 else {
1643 if (olen > len + ARY_DEFAULT_SIZE) {
1644 SIZED_REALLOC_N(RARRAY(ary)->as.heap.ptr, VALUE, len, RARRAY(ary)->as.heap.aux.capa);
1645 ARY_SET_CAPA(ary, len);
1646 }
1647 ARY_SET_HEAP_LEN(ary, len);
1648 }
1649 return ary;
1650 }
1651
1652 /*
1653 * call-seq:
1654 * ary[index] = obj -> obj
1655 * ary[start, length] = obj or other_ary or nil -> obj or other_ary or nil
1656 * ary[range] = obj or other_ary or nil -> obj or other_ary or nil
1657 *
1658 * Element Assignment --- Sets the element at +index+, or replaces a subarray
1659 * from the +start+ index for +length+ elements, or replaces a subarray
1660 * specified by the +range+ of indices.
1661 *
1662 * If indices are greater than the current capacity of the array, the array
1663 * grows automatically. Elements are inserted into the array at +start+ if
1664 * +length+ is zero.
1665 *
1666 * Negative indices will count backward from the end of the array. For
1667 * +start+ and +range+ cases the starting index is just before an element.
1668 *
1669 * An IndexError is raised if a negative index points past the beginning of
1670 * the array.
1671 *
1672 * See also Array#push, and Array#unshift.
1673 *
1674 * a = Array.new
1675 * a[4] = "4"; #=> [nil, nil, nil, nil, "4"]
1676 * a[0, 3] = [ 'a', 'b', 'c' ] #=> ["a", "b", "c", nil, "4"]
1677 * a[1..2] = [ 1, 2 ] #=> ["a", 1, 2, nil, "4"]
1678 * a[0, 2] = "?" #=> ["?", 2, nil, "4"]
1679 * a[0..2] = "A" #=> ["A", "4"]
1680 * a[-1] = "Z" #=> ["A", "Z"]
1681 * a[1..-1] = nil #=> ["A", nil]
1682 * a[1..-1] = [] #=> ["A"]
1683 * a[0, 0] = [ 1, 2 ] #=> [1, 2, "A"]
1684 * a[3, 0] = "B" #=> [1, 2, "A", "B"]
1685 */
1686
1687 static VALUE
1688 rb_ary_aset(int argc, VALUE *argv, VALUE ary)
1689 {
1690 long offset, beg, len;
1691
1692 if (argc == 3) {
1693 rb_ary_modify_check(ary);
1694 beg = NUM2LONG(argv[0]);
1695 len = NUM2LONG(argv[1]);
1696 rb_ary_splice(ary, beg, len, argv[2]);
1697 return argv[2];
1698 }
1699 rb_check_arity(argc, 2, 2);
1700 rb_ary_modify_check(ary);
1701 if (FIXNUM_P(argv[0])) {
1702 offset = FIX2LONG(argv[0]);
1703 goto fixnum;
1704 }
1705 if (rb_range_beg_len(argv[0], &beg, &len, RARRAY_LEN(ary), 1)) {
1706 /* check if idx is Range */
1707 rb_ary_splice(ary, beg, len, argv[1]);
1708 return argv[1];
1709 }
1710
1711 offset = NUM2LONG(argv[0]);
1712 fixnum:
1713 rb_ary_store(ary, offset, argv[1]);
1714 return argv[1];
1715 }
1716
1717 /*
1718 * call-seq:
1719 * ary.insert(index, obj...) -> ary
1720 *
1721 * Inserts the given values before the element with the given +index+.
1722 *
1723 * Negative indices count backwards from the end of the array, where +-1+ is
1724 * the last element.
1725 *
1726 * a = %w{ a b c d }
1727 * a.insert(2, 99) #=> ["a", "b", 99, "c", "d"]
1728 * a.insert(-2, 1, 2, 3) #=> ["a", "b", 99, "c", 1, 2, 3, "d"]
1729 */
1730
1731 static VALUE
1732 rb_ary_insert(int argc, VALUE *argv, VALUE ary)
1733 {
1734 long pos;
1735
1736 rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
1737 rb_ary_modify_check(ary);
1738 if (argc == 1) return ary;
1739 pos = NUM2LONG(argv[0]);
1740 if (pos == -1) {
1741 pos = RARRAY_LEN(ary);
1742 }
1743 if (pos < 0) {
1744 pos++;
1745 }
1746 rb_ary_splice(ary, pos, 0, rb_ary_new4(argc - 1, argv + 1));
1747 return ary;
1748 }
1749
1750 static VALUE
1751 rb_ary_length(VALUE ary);
1752
1753 static VALUE
1754 ary_enum_length(VALUE ary, VALUE args, VALUE eobj)
1755 {
1756 return rb_ary_length(ary);
1757 }
1758
1759 /*
1760 * call-seq:
1761 * ary.each { |item| block } -> ary
1762 * ary.each -> Enumerator
1763 *
1764 * Calls the given block once for each element in +self+, passing that element
1765 * as a parameter.
1766 *
1767 * An Enumerator is returned if no block is given.
1768 *
1769 * a = [ "a", "b", "c" ]
1770 * a.each {|x| print x, " -- " }
1771 *
1772 * produces:
1773 *
1774 * a -- b -- c --
1775 */
1776
1777 VALUE
1778 rb_ary_each(VALUE array)
1779 {
1780 long i;
1781 volatile VALUE ary = array;
1782
1783 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
1784 for (i=0; i<RARRAY_LEN(ary); i++) {
1785 rb_yield(RARRAY_AREF(ary, i));
1786 }
1787 return ary;
1788 }
1789
1790 /*
1791 * call-seq:
1792 * ary.each_index { |index| block } -> ary
1793 * ary.each_index -> Enumerator
1794 *
1795 * Same as Array#each, but passes the +index+ of the element instead of the
1796 * element itself.
1797 *
1798 * An Enumerator is returned if no block is given.
1799 *
1800 * a = [ "a", "b", "c" ]
1801 * a.each_index {|x| print x, " -- " }
1802 *
1803 * produces:
1804 *
1805 * 0 -- 1 -- 2 --
1806 */
1807
1808 static VALUE
1809 rb_ary_each_index(VALUE ary)
1810 {
1811 long i;
1812 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
1813
1814 for (i=0; i<RARRAY_LEN(ary); i++) {
1815 rb_yield(LONG2NUM(i));
1816 }
1817 return ary;
1818 }
1819
1820 /*
1821 * call-seq:
1822 * ary.reverse_each { |item| block } -> ary
1823 * ary.reverse_each -> Enumerator
1824 *
1825 * Same as Array#each, but traverses +self+ in reverse order.
1826 *
1827 * a = [ "a", "b", "c" ]
1828 * a.reverse_each {|x| print x, " " }
1829 *
1830 * produces:
1831 *
1832 * c b a
1833 */
1834
1835 static VALUE
1836 rb_ary_reverse_each(VALUE ary)
1837 {
1838 long len;
1839
1840 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
1841 len = RARRAY_LEN(ary);
1842 while (len--) {
1843 long nlen;
1844 rb_yield(RARRAY_AREF(ary, len));
1845 nlen = RARRAY_LEN(ary);
1846 if (nlen < len) {
1847 len = nlen;
1848 }
1849 }
1850 return ary;
1851 }
1852
1853 /*
1854 * call-seq:
1855 * ary.length -> int
1856 *
1857 * Returns the number of elements in +self+. May be zero.
1858 *
1859 * [ 1, 2, 3, 4, 5 ].length #=> 5
1860 * [].length #=> 0
1861 */
1862
1863 static VALUE
1864 rb_ary_length(VALUE ary)
1865 {
1866 long len = RARRAY_LEN(ary);
1867 return LONG2NUM(len);
1868 }
1869
1870 /*
1871 * call-seq:
1872 * ary.empty? -> true or false
1873 *
1874 * Returns +true+ if +self+ contains no elements.
1875 *
1876 * [].empty? #=> true
1877 */
1878
1879 static VALUE
1880 rb_ary_empty_p(VALUE ary)
1881 {
1882 if (RARRAY_LEN(ary) == 0)
1883 return Qtrue;
1884 return Qfalse;
1885 }
1886
1887 VALUE
1888 rb_ary_dup(VALUE ary)
1889 {
1890 long len = RARRAY_LEN(ary);
1891 VALUE dup = rb_ary_new2(len);
1892 ary_memcpy(dup, 0, len, RARRAY_CONST_PTR(ary));
1893 ARY_SET_LEN(dup, len);
1894 return dup;
1895 }
1896
1897 VALUE
1898 rb_ary_resurrect(VALUE ary)
1899 {
1900 return rb_ary_new4(RARRAY_LEN(ary), RARRAY_CONST_PTR(ary));
1901 }
1902
1903 extern VALUE rb_output_fs;
1904
1905 static void ary_join_1(VALUE obj, VALUE ary, VALUE sep, long i, VALUE result, int *first);
1906
1907 static VALUE
1908 recursive_join(VALUE obj, VALUE argp, int recur)
1909 {
1910 VALUE *arg = (VALUE *)argp;
1911 VALUE ary = arg[0];
1912 VALUE sep = arg[1];
1913 VALUE result = arg[2];
1914 int *first = (int *)arg[3];
1915
1916 if (recur) {
1917 rb_raise(rb_eArgError, "recursive array join");
1918 }
1919 else {
1920 ary_join_1(obj, ary, sep, 0, result, first);
1921 }
1922 return Qnil;
1923 }
1924
1925 static void
1926 ary_join_0(VALUE ary, VALUE sep, long max, VALUE result)
1927 {
1928 long i;
1929 VALUE val;
1930
1931 if (max > 0) rb_enc_copy(result, RARRAY_AREF(ary, 0));
1932 for (i=0; i<max; i++) {
1933 val = RARRAY_AREF(ary, i);
1934 if (i > 0 && !NIL_P(sep))
1935 rb_str_buf_append(result, sep);
1936 rb_str_buf_append(result, val);
1937 if (OBJ_TAINTED(val)) OBJ_TAINT(result);
1938 }
1939 }
1940
1941 static void
1942 ary_join_1(VALUE obj, VALUE ary, VALUE sep, long i, VALUE result, int *first)
1943 {
1944 VALUE val, tmp;
1945
1946 for (; i<RARRAY_LEN(ary); i++) {
1947 if (i > 0 && !NIL_P(sep))
1948 rb_str_buf_append(result, sep);
1949
1950 val = RARRAY_AREF(ary, i);
1951 if (RB_TYPE_P(val, T_STRING)) {
1952 str_join:
1953 rb_str_buf_append(result, val);
1954 *first = FALSE;
1955 }
1956 else if (RB_TYPE_P(val, T_ARRAY)) {
1957 obj = val;
1958 ary_join:
1959 if (val == ary) {
1960 rb_raise(rb_eArgError, "recursive array join");
1961 }
1962 else {
1963 VALUE args[4];
1964
1965 args[0] = val;
1966 args[1] = sep;
1967 args[2] = result;
1968 args[3] = (VALUE)first;
1969 rb_exec_recursive(recursive_join, obj, (VALUE)args);
1970 }
1971 }
1972 else {
1973 tmp = rb_check_string_type(val);
1974 if (!NIL_P(tmp)) {
1975 val = tmp;
1976 goto str_join;
1977 }
1978 tmp = rb_check_convert_type(val, T_ARRAY, "Array", "to_ary");
1979 if (!NIL_P(tmp)) {
1980 obj = val;
1981 val = tmp;
1982 goto ary_join;
1983 }
1984 val = rb_obj_as_string(val);
1985 if (*first) {
1986 rb_enc_copy(result, val);
1987 *first = FALSE;
1988 }
1989 goto str_join;
1990 }
1991 }
1992 }
1993
1994 VALUE
1995 rb_ary_join(VALUE ary, VALUE sep)
1996 {
1997 long len = 1, i;
1998 int taint = FALSE;
1999 VALUE val, tmp, result;
2000
2001 if (RARRAY_LEN(ary) == 0) return rb_usascii_str_new(0, 0);
2002 if (OBJ_TAINTED(ary)) taint = TRUE;
2003
2004 if (!NIL_P(sep)) {
2005 StringValue(sep);
2006 len += RSTRING_LEN(sep) * (RARRAY_LEN(ary) - 1);
2007 }
2008 for (i=0; i<RARRAY_LEN(ary); i++) {
2009 val = RARRAY_AREF(ary, i);
2010 tmp = rb_check_string_type(val);
2011
2012 if (NIL_P(tmp) || tmp != val) {
2013 int first;
2014 result = rb_str_buf_new(len + (RARRAY_LEN(ary)-i)*10);
2015 rb_enc_associate(result, rb_usascii_encoding());
2016 if (taint) OBJ_TAINT(result);
2017 ary_join_0(ary, sep, i, result);
2018 first = i == 0;
2019 ary_join_1(ary, ary, sep, i, result, &first);
2020 return result;
2021 }
2022
2023 len += RSTRING_LEN(tmp);
2024 }
2025
2026 result = rb_str_buf_new(len);
2027 if (taint) OBJ_TAINT(result);
2028 ary_join_0(ary, sep, RARRAY_LEN(ary), result);
2029
2030 return result;
2031 }
2032
2033 /*
2034 * call-seq:
2035 * ary.join(separator=$,) -> str
2036 *
2037 * Returns a string created by converting each element of the array to
2038 * a string, separated by the given +separator+.
2039 * If the +separator+ is +nil+, it uses current $,.
2040 * If both the +separator+ and $, are nil, it uses empty string.
2041 *
2042 * [ "a", "b", "c" ].join #=> "abc"
2043 * [ "a", "b", "c" ].join("-") #=> "a-b-c"
2044 */
2045
2046 static VALUE
2047 rb_ary_join_m(int argc, VALUE *argv, VALUE ary)
2048 {
2049 VALUE sep;
2050
2051 rb_scan_args(argc, argv, "01", &sep);
2052 if (NIL_P(sep)) sep = rb_output_fs;
2053
2054 return rb_ary_join(ary, sep);
2055 }
2056
2057 static VALUE
2058 inspect_ary(VALUE ary, VALUE dummy, int recur)
2059 {
2060 int tainted = OBJ_TAINTED(ary);
2061 long i;
2062 VALUE s, str;
2063
2064 if (recur) return rb_usascii_str_new_cstr("[...]");
2065 str = rb_str_buf_new2("[");
2066 for (i=0; i<RARRAY_LEN(ary); i++) {
2067 s = rb_inspect(RARRAY_AREF(ary, i));
2068 if (OBJ_TAINTED(s)) tainted = TRUE;
2069 if (i > 0) rb_str_buf_cat2(str, ", ");
2070 else rb_enc_copy(str, s);
2071 rb_str_buf_append(str, s);
2072 }
2073 rb_str_buf_cat2(str, "]");
2074 if (tainted) OBJ_TAINT(str);
2075 return str;
2076 }
2077
2078 /*
2079 * call-seq:
2080 * ary.inspect -> string
2081 * ary.to_s -> string
2082 *
2083 * Creates a string representation of +self+.
2084 *
2085 * [ "a", "b", "c" ].to_s #=> "[\"a\", \"b\", \"c\"]"
2086 */
2087
2088 static VALUE
2089 rb_ary_inspect(VALUE ary)
2090 {
2091 if (RARRAY_LEN(ary) == 0) return rb_usascii_str_new2("[]");
2092 return rb_exec_recursive(inspect_ary, ary, 0);
2093 }
2094
2095 VALUE
2096 rb_ary_to_s(VALUE ary)
2097 {
2098 return rb_ary_inspect(ary);
2099 }
2100
2101 /*
2102 * call-seq:
2103 * ary.to_a -> ary
2104 *
2105 * Returns +self+.
2106 *
2107 * If called on a subclass of Array, converts the receiver to an Array object.
2108 */
2109
2110 static VALUE
2111 rb_ary_to_a(VALUE ary)
2112 {
2113 if (rb_obj_class(ary) != rb_cArray) {
2114 VALUE dup = rb_ary_new2(RARRAY_LEN(ary));
2115 rb_ary_replace(dup, ary);
2116 return dup;
2117 }
2118 return ary;
2119 }
2120
2121 /*
2122 * call-seq:
2123 * ary.to_h -> hash
2124 *
2125 * Returns the result of interpreting <i>ary</i> as an array of
2126 * <tt>[key, value]</tt> pairs.
2127 *
2128 * [[:foo, :bar], [1, 2]].to_h
2129 * # => {:foo => :bar, 1 => 2}
2130 */
2131
2132 static VALUE
2133 rb_ary_to_h(VALUE ary)
2134 {
2135 long i;
2136 VALUE hash = rb_hash_new();
2137 for (i=0; i<RARRAY_LEN(ary); i++) {
2138 VALUE key_value_pair = rb_check_array_type(rb_ary_elt(ary, i));
2139 if (NIL_P(key_value_pair)) {
2140 rb_raise(rb_eTypeError, "wrong element type %s at %ld (expected array)",
2141 rb_builtin_class_name(rb_ary_elt(ary, i)), i);
2142 }
2143 if (RARRAY_LEN(key_value_pair) != 2) {
2144 rb_raise(rb_eArgError, "wrong array length at %ld (expected 2, was %ld)",
2145 i, RARRAY_LEN(key_value_pair));
2146 }
2147 rb_hash_aset(hash, RARRAY_AREF(key_value_pair, 0), RARRAY_AREF(key_value_pair, 1));
2148 }
2149 return hash;
2150 }
2151
2152 /*
2153 * call-seq:
2154 * ary.to_ary -> ary
2155 *
2156 * Returns +self+.
2157 */
2158
2159 static VALUE
2160 rb_ary_to_ary_m(VALUE ary)
2161 {
2162 return ary;
2163 }
2164
2165 static void
2166 ary_reverse(VALUE *p1, VALUE *p2)
2167 {
2168 while (p1 < p2) {
2169 VALUE tmp = *p1;
2170 *p1++ = *p2;
2171 *p2-- = tmp;
2172 }
2173 }
2174
2175 VALUE
2176 rb_ary_reverse(VALUE ary)
2177 {
2178 VALUE *p2;
2179 long len = RARRAY_LEN(ary);
2180
2181 rb_ary_modify(ary);
2182 if (len > 1) {
2183 RARRAY_PTR_USE(ary, p1, {
2184 p2 = p1 + len - 1; /* points last item */
2185 ary_reverse(p1, p2);
2186 }); /* WB: no new reference */
2187 }
2188 return ary;
2189 }
2190
2191 /*
2192 * call-seq:
2193 * ary.reverse! -> ary
2194 *
2195 * Reverses +self+ in place.
2196 *
2197 * a = [ "a", "b", "c" ]
2198 * a.reverse! #=> ["c", "b", "a"]
2199 * a #=> ["c", "b", "a"]
2200 */
2201
2202 static VALUE
2203 rb_ary_reverse_bang(VALUE ary)
2204 {
2205 return rb_ary_reverse(ary);
2206 }
2207
2208 /*
2209 * call-seq:
2210 * ary.reverse -> new_ary
2211 *
2212 * Returns a new array containing +self+'s elements in reverse order.
2213 *
2214 * [ "a", "b", "c" ].reverse #=> ["c", "b", "a"]
2215 * [ 1 ].reverse #=> [1]
2216 */
2217
2218 static VALUE
2219 rb_ary_reverse_m(VALUE ary)
2220 {
2221 long len = RARRAY_LEN(ary);
2222 VALUE dup = rb_ary_new2(len);
2223
2224 if (len > 0) {
2225 const VALUE *p1 = RARRAY_CONST_PTR(ary);
2226 VALUE *p2 = (VALUE *)RARRAY_CONST_PTR(dup) + len - 1;
2227 do *p2-- = *p1++; while (--len > 0);
2228 }
2229 ARY_SET_LEN(dup, RARRAY_LEN(ary));
2230 return dup;
2231 }
2232
2233 static inline long
2234 rotate_count(long cnt, long len)
2235 {
2236 return (cnt < 0) ? (len - (~cnt % len) - 1) : (cnt % len);
2237 }
2238
2239 VALUE
2240 rb_ary_rotate(VALUE ary, long cnt)
2241 {
2242 rb_ary_modify(ary);
2243
2244 if (cnt != 0) {
2245 VALUE *ptr = RARRAY_PTR(ary);
2246 long len = RARRAY_LEN(ary);
2247
2248 if (len > 0 && (cnt = rotate_count(cnt, len)) > 0) {
2249 --len;
2250 if (cnt < len) ary_reverse(ptr + cnt, ptr + len);
2251 if (--cnt > 0) ary_reverse(ptr, ptr + cnt);
2252 if (len > 0) ary_reverse(ptr, ptr + len);
2253 return ary;
2254 }
2255 }
2256
2257 return Qnil;
2258 }
2259
2260 /*
2261 * call-seq:
2262 * ary.rotate!(count=1) -> ary
2263 *
2264 * Rotates +self+ in place so that the element at +count+ comes first, and
2265 * returns +self+.
2266 *
2267 * If +count+ is negative then it rotates in the opposite direction, starting
2268 * from the end of the array where +-1+ is the last element.
2269 *
2270 * a = [ "a", "b", "c", "d" ]
2271 * a.rotate! #=> ["b", "c", "d", "a"]
2272 * a #=> ["b", "c", "d", "a"]
2273 * a.rotate!(2) #=> ["d", "a", "b", "c"]
2274 * a.rotate!(-3) #=> ["a", "b", "c", "d"]
2275 */
2276
2277 static VALUE
2278 rb_ary_rotate_bang(int argc, VALUE *argv, VALUE ary)
2279 {
2280 long n = 1;
2281
2282 switch (argc) {
2283 case 1: n = NUM2LONG(argv[0]);
2284 case 0: break;
2285 default: rb_scan_args(argc, argv, "01", NULL);
2286 }
2287 rb_ary_rotate(ary, n);
2288 return ary;
2289 }
2290
2291 /*
2292 * call-seq:
2293 * ary.rotate(count=1) -> new_ary
2294 *
2295 * Returns a new array by rotating +self+ so that the element at +count+ is
2296 * the first element of the new array.
2297 *
2298 * If +count+ is negative then it rotates in the opposite direction, starting
2299 * from the end of +self+ where +-1+ is the last element.
2300 *
2301 * a = [ "a", "b", "c", "d" ]
2302 * a.rotate #=> ["b", "c", "d", "a"]
2303 * a #=> ["a", "b", "c", "d"]
2304 * a.rotate(2) #=> ["c", "d", "a", "b"]
2305 * a.rotate(-3) #=> ["b", "c", "d", "a"]
2306 */
2307
2308 static VALUE
2309 rb_ary_rotate_m(int argc, VALUE *argv, VALUE ary)
2310 {
2311 VALUE rotated;
2312 const VALUE *ptr;
2313 long len, cnt = 1;
2314
2315 switch (argc) {
2316 case 1: cnt = NUM2LONG(argv[0]);
2317 case 0: break;
2318 default: rb_scan_args(argc, argv, "01", NULL);
2319 }
2320
2321 len = RARRAY_LEN(ary);
2322 rotated = rb_ary_new2(len);
2323 if (len > 0) {
2324 cnt = rotate_count(cnt, len);
2325 ptr = RARRAY_CONST_PTR(ary);
2326 len -= cnt;
2327 ary_memcpy(rotated, 0, len, ptr + cnt);
2328 ary_memcpy(rotated, len, cnt, ptr);
2329 }
2330 ARY_SET_LEN(rotated, RARRAY_LEN(ary));
2331 return rotated;
2332 }
2333
2334 struct ary_sort_data {
2335 VALUE ary;
2336 int opt_methods;
2337 int opt_inited;
2338 };
2339
2340 enum {
2341 sort_opt_Fixnum,
2342 sort_opt_String,
2343 sort_optimizable_count
2344 };
2345
2346 #define STRING_P(s) (RB_TYPE_P((s), T_STRING) && CLASS_OF(s) == rb_cString)
2347
2348 #define SORT_OPTIMIZABLE_BIT(type) (1U << TOKEN_PASTE(sort_opt_,type))
2349 #define SORT_OPTIMIZABLE(data, type) \
2350 (((data)->opt_inited & SORT_OPTIMIZABLE_BIT(type)) ? \
2351 ((data)->opt_methods & SORT_OPTIMIZABLE_BIT(type)) : \
2352 (((data)->opt_inited |= SORT_OPTIMIZABLE_BIT(type)), \
2353 rb_method_basic_definition_p(TOKEN_PASTE(rb_c,type), id_cmp) && \
2354 ((data)->opt_methods |= SORT_OPTIMIZABLE_BIT(type))))
2355
2356 static VALUE
2357 sort_reentered(VALUE ary)
2358 {
2359 if (RBASIC(ary)->klass) {
2360 rb_raise(rb_eRuntimeError, "sort reentered");
2361 }
2362 return Qnil;
2363 }
2364
2365 static int
2366 sort_1(const void *ap, const void *bp, void *dummy)
2367 {
2368 struct ary_sort_data *data = dummy;
2369 VALUE retval = sort_reentered(data->ary);
2370 VALUE a = *(const VALUE *)ap, b = *(const VALUE *)bp;
2371 int n;
2372
2373 retval = rb_yield_values(2, a, b);
2374 n = rb_cmpint(retval, a, b);
2375 sort_reentered(data->ary);
2376 return n;
2377 }
2378
2379 static int
2380 sort_2(const void *ap, const void *bp, void *dummy)
2381 {
2382 struct ary_sort_data *data = dummy;
2383 VALUE retval = sort_reentered(data->ary);
2384 VALUE a = *(const VALUE *)ap, b = *(const VALUE *)bp;
2385 int n;
2386
2387 if (FIXNUM_P(a) && FIXNUM_P(b) && SORT_OPTIMIZABLE(data, Fixnum)) {
2388 if ((long)a > (long)b) return 1;
2389 if ((long)a < (long)b) return -1;
2390 return 0;
2391 }
2392 if (STRING_P(a) && STRING_P(b) && SORT_OPTIMIZABLE(data, String)) {
2393 return rb_str_cmp(a, b);
2394 }
2395
2396 retval = rb_funcallv(a, id_cmp, 1, &b);
2397 n = rb_cmpint(retval, a, b);
2398 sort_reentered(data->ary);
2399
2400 return n;
2401 }
2402
2403 /*
2404 * call-seq:
2405 * ary.sort! -> ary
2406 * ary.sort! { |a, b| block } -> ary
2407 *
2408 * Sorts +self+ in place.
2409 *
2410 * Comparisons for the sort will be done using the <code><=></code> operator
2411 * or using an optional code block.
2412 *
2413 * The block must implement a comparison between +a+ and +b+, and return
2414 * +-1+, when +a+ follows +b+, +0+ when +a+ and +b+ are equivalent, or ++1+
2415 * if +b+ follows +a+.
2416 *
2417 * See also Enumerable#sort_by.
2418 *
2419 * a = [ "d", "a", "e", "c", "b" ]
2420 * a.sort! #=> ["a", "b", "c", "d", "e"]
2421 * a.sort! { |x,y| y <=> x } #=> ["e", "d", "c", "b", "a"]
2422 */
2423
2424 VALUE
2425 rb_ary_sort_bang(VALUE ary)
2426 {
2427 rb_ary_modify(ary);
2428 assert(!ARY_SHARED_P(ary));
2429 if (RARRAY_LEN(ary) > 1) {
2430 VALUE tmp = ary_make_substitution(ary); /* only ary refers tmp */
2431 struct ary_sort_data data;
2432 long len = RARRAY_LEN(ary);
2433
2434 RBASIC_CLEAR_CLASS(tmp);
2435 data.ary = tmp;
2436 data.opt_methods = 0;
2437 data.opt_inited = 0;
2438 RARRAY_PTR_USE(tmp, ptr, {
2439 ruby_qsort(ptr, len, sizeof(VALUE),
2440 rb_block_given_p()?sort_1:sort_2, &data);
2441 }); /* WB: no new reference */
2442 rb_ary_modify(ary);
2443 if (ARY_EMBED_P(tmp)) {
2444 if (ARY_SHARED_P(ary)) { /* ary might be destructively operated in the given block */
2445 rb_ary_unshare(ary);
2446 }
2447 FL_SET_EMBED(ary);
2448 ary_memcpy(ary, 0, ARY_EMBED_LEN(tmp), ARY_EMBED_PTR(tmp));
2449 ARY_SET_LEN(ary, ARY_EMBED_LEN(tmp));
2450 }
2451 else {
2452 if (!ARY_EMBED_P(ary) && ARY_HEAP_PTR(ary) == ARY_HEAP_PTR(tmp)) {
2453 FL_UNSET_SHARED(ary);
2454 ARY_SET_CAPA(ary, RARRAY_LEN(tmp));
2455 }
2456 else {
2457 assert(!ARY_SHARED_P(tmp));
2458 if (ARY_EMBED_P(ary)) {
2459 FL_UNSET_EMBED(ary);
2460 }
2461 else if (ARY_SHARED_P(ary)) {
2462 /* ary might be destructively operated in the given block */
2463 rb_ary_unshare(ary);
2464 }
2465 else {
2466 ruby_sized_xfree((void *)ARY_HEAP_PTR(ary), ARY_HEAP_SIZE(ary));
2467 }
2468 ARY_SET_PTR(ary, RARRAY_CONST_PTR(tmp));
2469 ARY_SET_HEAP_LEN(ary, len);
2470 ARY_SET_CAPA(ary, RARRAY_LEN(tmp));
2471 }
2472 /* tmp was lost ownership for the ptr */
2473 FL_UNSET(tmp, FL_FREEZE);
2474 FL_SET_EMBED(tmp);
2475 ARY_SET_EMBED_LEN(tmp, 0);
2476 FL_SET(tmp, FL_FREEZE);
2477 }
2478 /* tmp will be GC'ed. */
2479 RBASIC_SET_CLASS_RAW(tmp, rb_cArray); /* rb_cArray must be marked */
2480 }
2481 return ary;
2482 }
2483
2484 /*
2485 * call-seq:
2486 * ary.sort -> new_ary
2487 * ary.sort { |a, b| block } -> new_ary
2488 *
2489 * Returns a new array created by sorting +self+.
2490 *
2491 * Comparisons for the sort will be done using the <code><=></code> operator
2492 * or using an optional code block.
2493 *
2494 * The block must implement a comparison between +a+ and +b+, and return
2495 * +-1+, when +a+ follows +b+, +0+ when +a+ and +b+ are equivalent, or ++1+
2496 * if +b+ follows +a+.
2497 *
2498 *
2499 * See also Enumerable#sort_by.
2500 *
2501 * a = [ "d", "a", "e", "c", "b" ]
2502 * a.sort #=> ["a", "b", "c", "d", "e"]
2503 * a.sort { |x,y| y <=> x } #=> ["e", "d", "c", "b", "a"]
2504 */
2505
2506 VALUE
2507 rb_ary_sort(VALUE ary)
2508 {
2509 ary = rb_ary_dup(ary);
2510 rb_ary_sort_bang(ary);
2511 return ary;
2512 }
2513
2514 /*
2515 * call-seq:
2516 * ary.bsearch {|x| block } -> elem
2517 *
2518 * By using binary search, finds a value from this array which meets
2519 * the given condition in O(log n) where n is the size of the array.
2520 *
2521 * You can use this method in two use cases: a find-minimum mode and
2522 * a find-any mode. In either case, the elements of the array must be
2523 * monotone (or sorted) with respect to the block.
2524 *
2525 * In find-minimum mode (this is a good choice for typical use case),
2526 * the block must return true or false, and there must be an index i
2527 * (0 <= i <= ary.size) so that:
2528 *
2529 * - the block returns false for any element whose index is less than
2530 * i, and
2531 * - the block returns true for any element whose index is greater
2532 * than or equal to i.
2533 *
2534 * This method returns the i-th element. If i is equal to ary.size,
2535 * it returns nil.
2536 *
2537 * ary = [0, 4, 7, 10, 12]
2538 * ary.bsearch {|x| x >= 4 } #=> 4
2539 * ary.bsearch {|x| x >= 6 } #=> 7
2540 * ary.bsearch {|x| x >= -1 } #=> 0
2541 * ary.bsearch {|x| x >= 100 } #=> nil
2542 *
2543 * In find-any mode (this behaves like libc's bsearch(3)), the block
2544 * must return a number, and there must be two indices i and j
2545 * (0 <= i <= j <= ary.size) so that:
2546 *
2547 * - the block returns a positive number for ary[k] if 0 <= k < i,
2548 * - the block returns zero for ary[k] if i <= k < j, and
2549 * - the block returns a negative number for ary[k] if
2550 * j <= k < ary.size.
2551 *
2552 * Under this condition, this method returns any element whose index
2553 * is within i...j. If i is equal to j (i.e., there is no element
2554 * that satisfies the block), this method returns nil.
2555 *
2556 * ary = [0, 4, 7, 10, 12]
2557 * # try to find v such that 4 <= v < 8
2558 * ary.bsearch {|x| 1 - x / 4 } #=> 4 or 7
2559 * # try to find v such that 8 <= v < 10
2560 * ary.bsearch {|x| 4 - x / 2 } #=> nil
2561 *
2562 * You must not mix the two modes at a time; the block must always
2563 * return either true/false, or always return a number. It is
2564 * undefined which value is actually picked up at each iteration.
2565 */
2566
2567 static VALUE
2568 rb_ary_bsearch(VALUE ary)
2569 {
2570 long low = 0, high = RARRAY_LEN(ary), mid;
2571 int smaller = 0, satisfied = 0;
2572 VALUE v, val;
2573
2574 RETURN_ENUMERATOR(ary, 0, 0);
2575 while (low < high) {
2576 mid = low + ((high - low) / 2);
2577 val = rb_ary_entry(ary, mid);
2578 v = rb_yield(val);
2579 if (FIXNUM_P(v)) {
2580 if (FIX2INT(v) == 0) return val;
2581 smaller = FIX2INT(v) < 0;
2582 }
2583 else if (v == Qtrue) {
2584 satisfied = 1;
2585 smaller = 1;
2586 }
2587 else if (v == Qfalse || v == Qnil) {
2588 smaller = 0;
2589 }
2590 else if (rb_obj_is_kind_of(v, rb_cNumeric)) {
2591 const VALUE zero = INT2FIX(0);
2592 switch (rb_cmpint(rb_funcallv(v, id_cmp, 1, &zero), v, INT2FIX(0))) {
2593 case 0: return val;
2594 case 1: smaller = 1; break;
2595 case -1: smaller = 0;
2596 }
2597 }
2598 else {
2599 rb_raise(rb_eTypeError, "wrong argument type %s"
2600 " (must be numeric, true, false or nil)",
2601 rb_obj_classname(v));
2602 }
2603 if (smaller) {
2604 high = mid;
2605 }
2606 else {
2607 low = mid + 1;
2608 }
2609 }
2610 if (low == RARRAY_LEN(ary)) return Qnil;
2611 if (!satisfied) return Qnil;
2612 return rb_ary_entry(ary, low);
2613 }
2614
2615
2616 static VALUE
2617 sort_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, dummy))
2618 {
2619 return rb_yield(i);
2620 }
2621
2622 /*
2623 * call-seq:
2624 * ary.sort_by! { |obj| block } -> ary
2625 * ary.sort_by! -> Enumerator
2626 *
2627 * Sorts +self+ in place using a set of keys generated by mapping the
2628 * values in +self+ through the given block.
2629 *
2630 * If no block is given, an Enumerator is returned instead.
2631 *
2632 */
2633
2634 static VALUE
2635 rb_ary_sort_by_bang(VALUE ary)
2636 {
2637 VALUE sorted;
2638
2639 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
2640 rb_ary_modify(ary);
2641 sorted = rb_block_call(ary, rb_intern("sort_by"), 0, 0, sort_by_i, 0);
2642 rb_ary_replace(ary, sorted);
2643 return ary;
2644 }
2645
2646
2647 /*
2648 * call-seq:
2649 * ary.collect { |item| block } -> new_ary
2650 * ary.map { |item| block } -> new_ary
2651 * ary.collect -> Enumerator
2652 * ary.map -> Enumerator
2653 *
2654 * Invokes the given block once for each element of +self+.
2655 *
2656 * Creates a new array containing the values returned by the block.
2657 *
2658 * See also Enumerable#collect.
2659 *
2660 * If no block is given, an Enumerator is returned instead.
2661 *
2662 * a = [ "a", "b", "c", "d" ]
2663 * a.collect { |x| x + "!" } #=> ["a!", "b!", "c!", "d!"]
2664 * a.map.with_index{ |x, i| x * i } #=> ["", "b", "cc", "ddd"]
2665 * a #=> ["a", "b", "c", "d"]
2666 */
2667
2668 static VALUE
2669 rb_ary_collect(VALUE ary)
2670 {
2671 long i;
2672 VALUE collect;
2673
2674 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
2675 collect = rb_ary_new2(RARRAY_LEN(ary));
2676 for (i = 0; i < RARRAY_LEN(ary); i++) {
2677 rb_ary_push(collect, rb_yield(RARRAY_AREF(ary, i)));
2678 }
2679 return collect;
2680 }
2681
2682
2683 /*
2684 * call-seq:
2685 * ary.collect! {|item| block } -> ary
2686 * ary.map! {|item| block } -> ary
2687 * ary.collect! -> Enumerator
2688 * ary.map! -> Enumerator
2689 *
2690 * Invokes the given block once for each element of +self+, replacing the
2691 * element with the value returned by the block.
2692 *
2693 * See also Enumerable#collect.
2694 *
2695 * If no block is given, an Enumerator is returned instead.
2696 *
2697 * a = [ "a", "b", "c", "d" ]
2698 * a.map! {|x| x + "!" }
2699 * a #=> [ "a!", "b!", "c!", "d!" ]
2700 * a.collect!.with_index {|x, i| x[0...i] }
2701 * a #=> ["", "b", "c!", "d!"]
2702 */
2703
2704 static VALUE
2705 rb_ary_collect_bang(VALUE ary)
2706 {
2707 long i;
2708
2709 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
2710 rb_ary_modify(ary);
2711 for (i = 0; i < RARRAY_LEN(ary); i++) {
2712 rb_ary_store(ary, i, rb_yield(RARRAY_AREF(ary, i)));
2713 }
2714 return ary;
2715 }
2716
2717 VALUE
2718 rb_get_values_at(VALUE obj, long olen, int argc, VALUE *argv, VALUE (*func) (VALUE, long))
2719 {
2720 VALUE result = rb_ary_new2(argc);
2721 long beg, len, i, j;
2722
2723 for (i=0; i<argc; i++) {
2724 if (FIXNUM_P(argv[i])) {
2725 rb_ary_push(result, (*func)(obj, FIX2LONG(argv[i])));
2726 continue;
2727 }
2728 /* check if idx is Range */
2729 if (rb_range_beg_len(argv[i], &beg, &len, olen, 1)) {
2730 long end = olen < beg+len ? olen : beg+len;
2731 for (j = beg; j < end; j++) {
2732 rb_ary_push(result, (*func)(obj, j));
2733 }
2734 if (beg + len > j)
2735 rb_ary_resize(result, RARRAY_LEN(result) + (beg + len) - j);
2736 continue;
2737 }
2738 rb_ary_push(result, (*func)(obj, NUM2LONG(argv[i])));
2739 }
2740 return result;
2741 }
2742
2743 /*
2744 * call-seq:
2745 * ary.values_at(selector, ...) -> new_ary
2746 *
2747 * Returns an array containing the elements in +self+ corresponding to the
2748 * given +selector+(s).
2749 *
2750 * The selectors may be either integer indices or ranges.
2751 *
2752 * See also Array#select.
2753 *
2754 * a = %w{ a b c d e f }
2755 * a.values_at(1, 3, 5) # => ["b", "d", "f"]
2756 * a.values_at(1, 3, 5, 7) # => ["b", "d", "f", nil]
2757 * a.values_at(-1, -2, -2, -7) # => ["f", "e", "e", nil]
2758 * a.values_at(4..6, 3...6) # => ["e", "f", nil, "d", "e", "f"]
2759 */
2760
2761 static VALUE
2762 rb_ary_values_at(int argc, VALUE *argv, VALUE ary)
2763 {
2764 return rb_get_values_at(ary, RARRAY_LEN(ary), argc, argv, rb_ary_entry);
2765 }
2766
2767
2768 /*
2769 * call-seq:
2770 * ary.select { |item| block } -> new_ary
2771 * ary.select -> Enumerator
2772 *
2773 * Returns a new array containing all elements of +ary+
2774 * for which the given +block+ returns a true value.
2775 *
2776 * If no block is given, an Enumerator is returned instead.
2777 *
2778 * [1,2,3,4,5].select { |num| num.even? } #=> [2, 4]
2779 *
2780 * a = %w{ a b c d e f }
2781 * a.select { |v| v =~ /[aeiou]/ } #=> ["a", "e"]
2782 *
2783 * See also Enumerable#select.
2784 */
2785
2786 static VALUE
2787 rb_ary_select(VALUE ary)
2788 {
2789 VALUE result;
2790 long i;
2791
2792 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
2793 result = rb_ary_new2(RARRAY_LEN(ary));
2794 for (i = 0; i < RARRAY_LEN(ary); i++) {
2795 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) {
2796 rb_ary_push(result, rb_ary_elt(ary, i));
2797 }
2798 }
2799 return result;
2800 }
2801
2802 /*
2803 * call-seq:
2804 * ary.select! {|item| block } -> ary or nil
2805 * ary.select! -> Enumerator
2806 *
2807 * Invokes the given block passing in successive elements from +self+,
2808 * deleting elements for which the block returns a +false+ value.
2809 *
2810 * If changes were made, it will return +self+, otherwise it returns +nil+.
2811 *
2812 * See also Array#keep_if
2813 *
2814 * If no block is given, an Enumerator is returned instead.
2815 *
2816 */
2817
2818 static VALUE
2819 rb_ary_select_bang(VALUE ary)
2820 {
2821 long i1, i2;
2822
2823 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
2824 rb_ary_modify(ary);
2825 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
2826 VALUE v = RARRAY_AREF(ary, i1);
2827 if (!RTEST(rb_yield(v))) continue;
2828 if (i1 != i2) {
2829 rb_ary_store(ary, i2, v);
2830 }
2831 i2++;
2832 }
2833
2834 if (i1 == i2) return Qnil;
2835 if (i2 < i1)
2836 ARY_SET_LEN(ary, i2);
2837 return ary;
2838 }
2839
2840 /*
2841 * call-seq:
2842 * ary.keep_if { |item| block } -> ary
2843 * ary.keep_if -> Enumerator
2844 *
2845 * Deletes every element of +self+ for which the given block evaluates to
2846 * +false+.
2847 *
2848 * See also Array#select!
2849 *
2850 * If no block is given, an Enumerator is returned instead.
2851 *
2852 * a = %w{ a b c d e f }
2853 * a.keep_if { |v| v =~ /[aeiou]/ } #=> ["a", "e"]
2854 */
2855
2856 static VALUE
2857 rb_ary_keep_if(VALUE ary)
2858 {
2859 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
2860 rb_ary_select_bang(ary);
2861 return ary;
2862 }
2863
2864 static void
2865 ary_resize_smaller(VALUE ary, long len)
2866 {
2867 rb_ary_modify(ary);
2868 if (RARRAY_LEN(ary) > len) {
2869 ARY_SET_LEN(ary, len);
2870 if (len * 2 < ARY_CAPA(ary) &&
2871 ARY_CAPA(ary) > ARY_DEFAULT_SIZE) {
2872 ary_resize_capa(ary, len * 2);
2873 }
2874 }
2875 }
2876
2877 /*
2878 * call-seq:
2879 * ary.delete(obj) -> item or nil
2880 * ary.delete(obj) { block } -> item or result of block
2881 *
2882 * Deletes all items from +self+ that are equal to +obj+.
2883 *
2884 * Returns the last deleted item, or +nil+ if no matching item is found.
2885 *
2886 * If the optional code block is given, the result of the block is returned if
2887 * the item is not found. (To remove +nil+ elements and get an informative
2888 * return value, use Array#compact!)
2889 *
2890 * a = [ "a", "b", "b", "b", "c" ]
2891 * a.delete("b") #=> "b"
2892 * a #=> ["a", "c"]
2893 * a.delete("z") #=> nil
2894 * a.delete("z") { "not found" } #=> "not found"
2895 */
2896
2897 VALUE
2898 rb_ary_delete(VALUE ary, VALUE item)
2899 {
2900 VALUE v = item;
2901 long i1, i2;
2902
2903 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
2904 VALUE e = RARRAY_AREF(ary, i1);
2905
2906 if (rb_equal(e, item)) {
2907 v = e;
2908 continue;
2909 }
2910 if (i1 != i2) {
2911 rb_ary_store(ary, i2, e);
2912 }
2913 i2++;
2914 }
2915 if (RARRAY_LEN(ary) == i2) {
2916 if (rb_block_given_p()) {
2917 return rb_yield(item);
2918 }
2919 return Qnil;
2920 }
2921
2922 ary_resize_smaller(ary, i2);
2923
2924 return v;
2925 }
2926
2927 void
2928 rb_ary_delete_same(VALUE ary, VALUE item)
2929 {
2930 long i1, i2;
2931
2932 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
2933 VALUE e = RARRAY_AREF(ary, i1);
2934
2935 if (e == item) {
2936 continue;
2937 }
2938 if (i1 != i2) {
2939 rb_ary_store(ary, i2, e);
2940 }
2941 i2++;
2942 }
2943 if (RARRAY_LEN(ary) == i2) {
2944 return;
2945 }
2946
2947 ary_resize_smaller(ary, i2);
2948 }
2949
2950 VALUE
2951 rb_ary_delete_at(VALUE ary, long pos)
2952 {
2953 long len = RARRAY_LEN(ary);
2954 VALUE del;
2955
2956 if (pos >= len) return Qnil;
2957 if (pos < 0) {
2958 pos += len;
2959 if (pos < 0) return Qnil;
2960 }
2961
2962 rb_ary_modify(ary);
2963 del = RARRAY_AREF(ary, pos);
2964 RARRAY_PTR_USE(ary, ptr, {
2965 MEMMOVE(ptr+pos, ptr+pos+1, VALUE, len-pos-1);
2966 });
2967 ARY_INCREASE_LEN(ary, -1);
2968
2969 return del;
2970 }
2971
2972 /*
2973 * call-seq:
2974 * ary.delete_at(index) -> obj or nil
2975 *
2976 * Deletes the element at the specified +index+, returning that element, or
2977 * +nil+ if the +index+ is out of range.
2978 *
2979 * See also Array#slice!
2980 *
2981 * a = ["ant", "bat", "cat", "dog"]
2982 * a.delete_at(2) #=> "cat"
2983 * a #=> ["ant", "bat", "dog"]
2984 * a.delete_at(99) #=> nil
2985 */
2986
2987 static VALUE
2988 rb_ary_delete_at_m(VALUE ary, VALUE pos)
2989 {
2990 return rb_ary_delete_at(ary, NUM2LONG(pos));
2991 }
2992
2993 /*
2994 * call-seq:
2995 * ary.slice!(index) -> obj or nil
2996 * ary.slice!(start, length) -> new_ary or nil
2997 * ary.slice!(range) -> new_ary or nil
2998 *
2999 * Deletes the element(s) given by an +index+ (optionally up to +length+
3000 * elements) or by a +range+.
3001 *
3002 * Returns the deleted object (or objects), or +nil+ if the +index+ is out of
3003 * range.
3004 *
3005 * a = [ "a", "b", "c" ]
3006 * a.slice!(1) #=> "b"
3007 * a #=> ["a", "c"]
3008 * a.slice!(-1) #=> "c"
3009 * a #=> ["a"]
3010 * a.slice!(100) #=> nil
3011 * a #=> ["a"]
3012 */
3013
3014 static VALUE
3015 rb_ary_slice_bang(int argc, VALUE *argv, VALUE ary)
3016 {
3017 VALUE arg1, arg2;
3018 long pos, len, orig_len;
3019
3020 rb_ary_modify_check(ary);
3021 if (argc == 2) {
3022 pos = NUM2LONG(argv[0]);
3023 len = NUM2LONG(argv[1]);
3024 delete_pos_len:
3025 if (len < 0) return Qnil;
3026 orig_len = RARRAY_LEN(ary);
3027 if (pos < 0) {
3028 pos += orig_len;
3029 if (pos < 0) return Qnil;
3030 }
3031 else if (orig_len < pos) return Qnil;
3032 if (orig_len < pos + len) {
3033 len = orig_len - pos;
3034 }
3035 if (len == 0) return rb_ary_new2(0);
3036 arg2 = rb_ary_new4(len, RARRAY_CONST_PTR(ary)+pos);
3037 RBASIC_SET_CLASS(arg2, rb_obj_class(ary));
3038 rb_ary_splice(ary, pos, len, Qundef);
3039 return arg2;
3040 }
3041
3042 if (argc != 1) {
3043 /* error report */
3044 rb_scan_args(argc, argv, "11", NULL, NULL);
3045 }
3046 arg1 = argv[0];
3047
3048 if (!FIXNUM_P(arg1)) {
3049 switch (rb_range_beg_len(arg1, &pos, &len, RARRAY_LEN(ary), 0)) {
3050 case Qtrue:
3051 /* valid range */
3052 goto delete_pos_len;
3053 case Qnil:
3054 /* invalid range */
3055 return Qnil;
3056 default:
3057 /* not a range */
3058 break;
3059 }
3060 }
3061
3062 return rb_ary_delete_at(ary, NUM2LONG(arg1));
3063 }
3064
3065 static VALUE
3066 ary_reject(VALUE orig, VALUE result)
3067 {
3068 long i;
3069
3070 for (i = 0; i < RARRAY_LEN(orig); i++) {
3071 VALUE v = RARRAY_AREF(orig, i);
3072 if (!RTEST(rb_yield(v))) {
3073 rb_ary_push(result, v);
3074 }
3075 }
3076 return result;
3077 }
3078
3079 static VALUE
3080 ary_reject_bang(VALUE ary)
3081 {
3082 long i;
3083 VALUE result = Qnil;
3084
3085 rb_ary_modify_check(ary);
3086 for (i = 0; i < RARRAY_LEN(ary); ) {
3087 VALUE v = RARRAY_AREF(ary, i);
3088 if (RTEST(rb_yield(v))) {
3089 rb_ary_delete_at(ary, i);
3090 result = ary;
3091 }
3092 else {
3093 i++;
3094 }
3095 }
3096 return result;
3097 }
3098
3099 /*
3100 * call-seq:
3101 * ary.reject! { |item| block } -> ary or nil
3102 * ary.reject! -> Enumerator
3103 *
3104 * Equivalent to Array#delete_if, deleting elements from +self+ for which the
3105 * block evaluates to +true+, but returns +nil+ if no changes were made.
3106 *
3107 * The array is changed instantly every time the block is called, not after
3108 * the iteration is over.
3109 *
3110 * See also Enumerable#reject and Array#delete_if.
3111 *
3112 * If no block is given, an Enumerator is returned instead.
3113 */
3114
3115 static VALUE
3116 rb_ary_reject_bang(VALUE ary)
3117 {
3118 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3119 return ary_reject_bang(ary);
3120 }
3121
3122 /*
3123 * call-seq:
3124 * ary.reject {|item| block } -> new_ary
3125 * ary.reject -> Enumerator
3126 *
3127 * Returns a new array containing the items in +self+ for which the given
3128 * block is not +true+.
3129 *
3130 * See also Array#delete_if
3131 *
3132 * If no block is given, an Enumerator is returned instead.
3133 */
3134
3135 static VALUE
3136 rb_ary_reject(VALUE ary)
3137 {
3138 VALUE rejected_ary;
3139
3140 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3141 rejected_ary = rb_ary_new();
3142 ary_reject(ary, rejected_ary);
3143 return rejected_ary;
3144 }
3145
3146 /*
3147 * call-seq:
3148 * ary.delete_if { |item| block } -> ary
3149 * ary.delete_if -> Enumerator
3150 *
3151 * Deletes every element of +self+ for which block evaluates to +true+.
3152 *
3153 * The array is changed instantly every time the block is called, not after
3154 * the iteration is over.
3155 *
3156 * See also Array#reject!
3157 *
3158 * If no block is given, an Enumerator is returned instead.
3159 *
3160 * scores = [ 97, 42, 75 ]
3161 * scores.delete_if {|score| score < 80 } #=> [97]
3162 */
3163
3164 static VALUE
3165 rb_ary_delete_if(VALUE ary)
3166 {
3167 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3168 ary_reject_bang(ary);
3169 return ary;
3170 }
3171
3172 static VALUE
3173 take_i(RB_BLOCK_CALL_FUNC_ARGLIST(val, cbarg))
3174 {
3175 VALUE *args = (VALUE *)cbarg;
3176 if (args[1]-- == 0) rb_iter_break();
3177 if (argc > 1) val = rb_ary_new4(argc, argv);
3178 rb_ary_push(args[0], val);
3179 return Qnil;
3180 }
3181
3182 static VALUE
3183 take_items(VALUE obj, long n)
3184 {
3185 VALUE result = rb_check_array_type(obj);
3186 VALUE args[2];
3187
3188 if (!NIL_P(result)) return rb_ary_subseq(result, 0, n);
3189 result = rb_ary_new2(n);
3190 args[0] = result; args[1] = (VALUE)n;
3191 if (rb_check_block_call(obj, idEach, 0, 0, take_i, (VALUE)args) == Qundef)
3192 rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (must respond to :each)",
3193 rb_obj_class(obj));
3194 return result;
3195 }
3196
3197
3198 /*
3199 * call-seq:
3200 * ary.zip(arg, ...) -> new_ary
3201 * ary.zip(arg, ...) { |arr| block } -> nil
3202 *
3203 * Converts any arguments to arrays, then merges elements of +self+ with
3204 * corresponding elements from each argument.
3205 *
3206 * This generates a sequence of <code>ary.size</code> _n_-element arrays,
3207 * where _n_ is one more than the count of arguments.
3208 *
3209 * If the size of any argument is less than the size of the initial array,
3210 * +nil+ values are supplied.
3211 *
3212 * If a block is given, it is invoked for each output +array+, otherwise an
3213 * array of arrays is returned.
3214 *
3215 * a = [ 4, 5, 6 ]
3216 * b = [ 7, 8, 9 ]
3217 * [1, 2, 3].zip(a, b) #=> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
3218 * [1, 2].zip(a, b) #=> [[1, 4, 7], [2, 5, 8]]
3219 * a.zip([1, 2], [8]) #=> [[4, 1, 8], [5, 2, nil], [6, nil, nil]]
3220 */
3221
3222 static VALUE
3223 rb_ary_zip(int argc, VALUE *argv, VALUE ary)
3224 {
3225 int i, j;
3226 long len = RARRAY_LEN(ary);
3227 VALUE result = Qnil;
3228
3229 for (i=0; i<argc; i++) {
3230 argv[i] = take_items(argv[i], len);
3231 }
3232
3233 if (rb_block_given_p()) {
3234 int arity = rb_block_arity();
3235
3236 if (arity > 1 && argc+1 < 0x100) {
3237 VALUE *tmp = ALLOCA_N(VALUE, argc+1);
3238
3239 for (i=0; i<RARRAY_LEN(ary); i++) {
3240 tmp[0] = RARRAY_AREF(ary, i);
3241 for (j=0; j<argc; j++) {
3242 tmp[j+1] = rb_ary_elt(argv[j], i);
3243 }
3244 rb_yield_values2(argc+1, tmp);
3245 }
3246 }
3247 else {
3248 for (i=0; i<RARRAY_LEN(ary); i++) {
3249 VALUE tmp = rb_ary_new2(argc+1);
3250
3251 rb_ary_push(tmp, RARRAY_AREF(ary, i));
3252 for (j=0; j<argc; j++) {
3253 rb_ary_push(tmp, rb_ary_elt(argv[j], i));
3254 }
3255 rb_yield(tmp);
3256 }
3257 }
3258 }
3259 else {
3260 result = rb_ary_new_capa(len);
3261
3262 for (i=0; i<len; i++) {
3263 VALUE tmp = rb_ary_new_capa(argc+1);
3264
3265 rb_ary_push(tmp, RARRAY_AREF(ary, i));
3266 for (j=0; j<argc; j++) {
3267 rb_ary_push(tmp, rb_ary_elt(argv[j], i));
3268 }
3269 rb_ary_push(result, tmp);
3270 }
3271 }
3272
3273 return result;
3274 }
3275
3276 /*
3277 * call-seq:
3278 * ary.transpose -> new_ary
3279 *
3280 * Assumes that +self+ is an array of arrays and transposes the rows and
3281 * columns.
3282 *
3283 * a = [[1,2], [3,4], [5,6]]
3284 * a.transpose #=> [[1, 3, 5], [2, 4, 6]]
3285 *
3286 * If the length of the subarrays don't match, an IndexError is raised.
3287 */
3288
3289 static VALUE
3290 rb_ary_transpose(VALUE ary)
3291 {
3292 long elen = -1, alen, i, j;
3293 VALUE tmp, result = 0;
3294
3295 alen = RARRAY_LEN(ary);
3296 if (alen == 0) return rb_ary_dup(ary);
3297 for (i=0; i<alen; i++) {
3298 tmp = to_ary(rb_ary_elt(ary, i));
3299 if (elen < 0) { /* first element */
3300 elen = RARRAY_LEN(tmp);
3301 result = rb_ary_new2(elen);
3302 for (j=0; j<elen; j++) {
3303 rb_ary_store(result, j, rb_ary_new2(alen));
3304 }
3305 }
3306 else if (elen != RARRAY_LEN(tmp)) {
3307 rb_raise(rb_eIndexError, "element size differs (%ld should be %ld)",
3308 RARRAY_LEN(tmp), elen);
3309 }
3310 for (j=0; j<elen; j++) {
3311 rb_ary_store(rb_ary_elt(result, j), i, rb_ary_elt(tmp, j));
3312 }
3313 }
3314 return result;
3315 }
3316
3317 /*
3318 * call-seq:
3319 * ary.replace(other_ary) -> ary
3320 * ary.initialize_copy(other_ary) -> ary
3321 *
3322 * Replaces the contents of +self+ with the contents of +other_ary+,
3323 * truncating or expanding if necessary.
3324 *
3325 * a = [ "a", "b", "c", "d", "e" ]
3326 * a.replace([ "x", "y", "z" ]) #=> ["x", "y", "z"]
3327 * a #=> ["x", "y", "z"]
3328 */
3329
3330 VALUE
3331 rb_ary_replace(VALUE copy, VALUE orig)
3332 {
3333 rb_ary_modify_check(copy);
3334 orig = to_ary(orig);
3335 if (copy == orig) return copy;
3336
3337 if (RARRAY_LEN(orig) <= RARRAY_EMBED_LEN_MAX) {
3338 VALUE shared = 0;
3339
3340 if (ARY_OWNS_HEAP_P(copy)) {
3341 RARRAY_PTR_USE(copy, ptr, ruby_sized_xfree(ptr, ARY_HEAP_SIZE(copy)));
3342 }
3343 else if (ARY_SHARED_P(copy)) {
3344 shared = ARY_SHARED(copy);
3345 FL_UNSET_SHARED(copy);
3346 }
3347 FL_SET_EMBED(copy);
3348 ary_memcpy(copy, 0, RARRAY_LEN(orig), RARRAY_CONST_PTR(orig));
3349 if (shared) {
3350 rb_ary_decrement_share(shared);
3351 }
3352 ARY_SET_LEN(copy, RARRAY_LEN(orig));
3353 }
3354 else {
3355 VALUE shared = ary_make_shared(orig);
3356 if (ARY_OWNS_HEAP_P(copy)) {
3357 RARRAY_PTR_USE(copy, ptr, ruby_sized_xfree(ptr, ARY_HEAP_SIZE(copy)));
3358 }
3359 else {
3360 rb_ary_unshare_safe(copy);
3361 }
3362 FL_UNSET_EMBED(copy);
3363 ARY_SET_PTR(copy, RARRAY_CONST_PTR(orig));
3364 ARY_SET_LEN(copy, RARRAY_LEN(orig));
3365 rb_ary_set_shared(copy, shared);
3366 }
3367 return copy;
3368 }
3369
3370 /*
3371 * call-seq:
3372 * ary.clear -> ary
3373 *
3374 * Removes all elements from +self+.
3375 *
3376 * a = [ "a", "b", "c", "d", "e" ]
3377 * a.clear #=> [ ]
3378 */
3379
3380 VALUE
3381 rb_ary_clear(VALUE ary)
3382 {
3383 rb_ary_modify_check(ary);
3384 ARY_SET_LEN(ary, 0);
3385 if (ARY_SHARED_P(ary)) {
3386 if (!ARY_EMBED_P(ary)) {
3387 rb_ary_unshare(ary);
3388 FL_SET_EMBED(ary);
3389 }
3390 }
3391 else if (ARY_DEFAULT_SIZE * 2 < ARY_CAPA(ary)) {
3392 ary_resize_capa(ary, ARY_DEFAULT_SIZE * 2);
3393 }
3394 return ary;
3395 }
3396
3397 /*
3398 * call-seq:
3399 * ary.fill(obj) -> ary
3400 * ary.fill(obj, start [, length]) -> ary
3401 * ary.fill(obj, range ) -> ary
3402 * ary.fill { |index| block } -> ary
3403 * ary.fill(start [, length] ) { |index| block } -> ary
3404 * ary.fill(range) { |index| block } -> ary
3405 *
3406 * The first three forms set the selected elements of +self+ (which
3407 * may be the entire array) to +obj+.
3408 *
3409 * A +start+ of +nil+ is equivalent to zero.
3410 *
3411 * A +length+ of +nil+ is equivalent to the length of the array.
3412 *
3413 * The last three forms fill the array with the value of the given block,
3414 * which is passed the absolute index of each element to be filled.
3415 *
3416 * Negative values of +start+ count from the end of the array, where +-1+ is
3417 * the last element.
3418 *
3419 * a = [ "a", "b", "c", "d" ]
3420 * a.fill("x") #=> ["x", "x", "x", "x"]
3421 * a.fill("z", 2, 2) #=> ["x", "x", "z", "z"]
3422 * a.fill("y", 0..1) #=> ["y", "y", "z", "z"]
3423 * a.fill { |i| i*i } #=> [0, 1, 4, 9]
3424 * a.fill(-2) { |i| i*i*i } #=> [0, 1, 8, 27]
3425 */
3426
3427 static VALUE
3428 rb_ary_fill(int argc, VALUE *argv, VALUE ary)
3429 {
3430 VALUE item, arg1, arg2;
3431 long beg = 0, end = 0, len = 0;
3432 int block_p = FALSE;
3433
3434 if (rb_block_given_p()) {
3435 block_p = TRUE;
3436 rb_scan_args(argc, argv, "02", &arg1, &arg2);
3437 argc += 1; /* hackish */
3438 }
3439 else {
3440 rb_scan_args(argc, argv, "12", &item, &arg1, &arg2);
3441 }
3442 switch (argc) {
3443 case 1:
3444 beg = 0;
3445 len = RARRAY_LEN(ary);
3446 break;
3447 case 2:
3448 if (rb_range_beg_len(arg1, &beg, &len, RARRAY_LEN(ary), 1)) {
3449 break;
3450 }
3451 /* fall through */
3452 case 3:
3453 beg = NIL_P(arg1) ? 0 : NUM2LONG(arg1);
3454 if (beg < 0) {
3455 beg = RARRAY_LEN(ary) + beg;
3456 if (beg < 0) beg = 0;
3457 }
3458 len = NIL_P(arg2) ? RARRAY_LEN(ary) - beg : NUM2LONG(arg2);
3459 break;
3460 }
3461 rb_ary_modify(ary);
3462 if (len < 0) {
3463 return ary;
3464 }
3465 if (beg >= ARY_MAX_SIZE || len > ARY_MAX_SIZE - beg) {
3466 rb_raise(rb_eArgError, "argument too big");
3467 }
3468 end = beg + len;
3469 if (RARRAY_LEN(ary) < end) {
3470 if (end >= ARY_CAPA(ary)) {
3471 ary_resize_capa(ary, end);
3472 }
3473 ary_mem_clear(ary, RARRAY_LEN(ary), end - RARRAY_LEN(ary));
3474 ARY_SET_LEN(ary, end);
3475 }
3476
3477 if (block_p) {
3478 VALUE v;
3479 long i;
3480
3481 for (i=beg; i<end; i++) {
3482 v = rb_yield(LONG2NUM(i));
3483 if (i>=RARRAY_LEN(ary)) break;
3484 RARRAY_ASET(ary, i, v);
3485 }
3486 }
3487 else {
3488 ary_memfill(ary, beg, len, item);
3489 }
3490 return ary;
3491 }
3492
3493 /*
3494 * call-seq:
3495 * ary + other_ary -> new_ary
3496 *
3497 * Concatenation --- Returns a new array built by concatenating the
3498 * two arrays together to produce a third array.
3499 *
3500 * [ 1, 2, 3 ] + [ 4, 5 ] #=> [ 1, 2, 3, 4, 5 ]
3501 * a = [ "a", "b", "c" ]
3502 * c = a + [ "d", "e", "f" ]
3503 * c #=> [ "a", "b", "c", "d", "e", "f" ]
3504 * a #=> [ "a", "b", "c" ]
3505 *
3506 * See also Array#concat.
3507 */
3508
3509 VALUE
3510 rb_ary_plus(VALUE x, VALUE y)
3511 {
3512 VALUE z;
3513 long len, xlen, ylen;
3514
3515 y = to_ary(y);
3516 xlen = RARRAY_LEN(x);
3517 ylen = RARRAY_LEN(y);
3518 len = xlen + ylen;
3519 z = rb_ary_new2(len);
3520
3521 ary_memcpy(z, 0, xlen, RARRAY_CONST_PTR(x));
3522 ary_memcpy(z, xlen, ylen, RARRAY_CONST_PTR(y));
3523 ARY_SET_LEN(z, len);
3524 return z;
3525 }
3526
3527 /*
3528 * call-seq:
3529 * ary.concat(other_ary) -> ary
3530 *
3531 * Appends the elements of +other_ary+ to +self+.
3532 *
3533 * [ "a", "b" ].concat( ["c", "d"] ) #=> [ "a", "b", "c", "d" ]
3534 * a = [ 1, 2, 3 ]
3535 * a.concat( [ 4, 5 ] )
3536 * a #=> [ 1, 2, 3, 4, 5 ]
3537 *
3538 * See also Array#+.
3539 */
3540
3541 VALUE
3542 rb_ary_concat(VALUE x, VALUE y)
3543 {
3544 rb_ary_modify_check(x);
3545 y = to_ary(y);
3546 if (RARRAY_LEN(y) > 0) {
3547 rb_ary_splice(x, RARRAY_LEN(x), 0, y);
3548 }
3549 return x;
3550 }
3551
3552
3553 /*
3554 * call-seq:
3555 * ary * int -> new_ary
3556 * ary * str -> new_string
3557 *
3558 * Repetition --- With a String argument, equivalent to
3559 * <code>ary.join(str)</code>.
3560 *
3561 * Otherwise, returns a new array built by concatenating the +int+ copies of
3562 * +self+.
3563 *
3564 *
3565 * [ 1, 2, 3 ] * 3 #=> [ 1, 2, 3, 1, 2, 3, 1, 2, 3 ]
3566 * [ 1, 2, 3 ] * "," #=> "1,2,3"
3567 *
3568 */
3569
3570 static VALUE
3571 rb_ary_times(VALUE ary, VALUE times)
3572 {
3573 VALUE ary2, tmp;
3574 const VALUE *ptr;
3575 long t, len;
3576
3577 tmp = rb_check_string_type(times);
3578 if (!NIL_P(tmp)) {
3579 return rb_ary_join(ary, tmp);
3580 }
3581
3582 len = NUM2LONG(times);
3583 if (len == 0) {
3584 ary2 = ary_new(rb_obj_class(ary), 0);
3585 goto out;
3586 }
3587 if (len < 0) {
3588 rb_raise(rb_eArgError, "negative argument");
3589 }
3590 if (ARY_MAX_SIZE/len < RARRAY_LEN(ary)) {
3591 rb_raise(rb_eArgError, "argument too big");
3592 }
3593 len *= RARRAY_LEN(ary);
3594
3595 ary2 = ary_new(rb_obj_class(ary), len);
3596 ARY_SET_LEN(ary2, len);
3597
3598 ptr = RARRAY_CONST_PTR(ary);
3599 t = RARRAY_LEN(ary);
3600 if (0 < t) {
3601 ary_memcpy(ary2, 0, t, ptr);
3602 while (t <= len/2) {
3603 ary_memcpy(ary2, t, t, RARRAY_CONST_PTR(ary2));
3604 t *= 2;
3605 }
3606 if (t < len) {
3607 ary_memcpy(ary2, t, len-t, RARRAY_CONST_PTR(ary2));
3608 }
3609 }
3610 out:
3611 OBJ_INFECT(ary2, ary);
3612
3613 return ary2;
3614 }
3615
3616 /*
3617 * call-seq:
3618 * ary.assoc(obj) -> new_ary or nil
3619 *
3620 * Searches through an array whose elements are also arrays comparing +obj+
3621 * with the first element of each contained array using <code>obj.==</code>.
3622 *
3623 * Returns the first contained array that matches (that is, the first
3624 * associated array), or +nil+ if no match is found.
3625 *
3626 * See also Array#rassoc
3627 *
3628 * s1 = [ "colors", "red", "blue", "green" ]
3629 * s2 = [ "letters", "a", "b", "c" ]
3630 * s3 = "foo"
3631 * a = [ s1, s2, s3 ]
3632 * a.assoc("letters") #=> [ "letters", "a", "b", "c" ]
3633 * a.assoc("foo") #=> nil
3634 */
3635
3636 VALUE
3637 rb_ary_assoc(VALUE ary, VALUE key)
3638 {
3639 long i;
3640 VALUE v;
3641
3642 for (i = 0; i < RARRAY_LEN(ary); ++i) {
3643 v = rb_check_array_type(RARRAY_AREF(ary, i));
3644 if (!NIL_P(v) && RARRAY_LEN(v) > 0 &&
3645 rb_equal(RARRAY_AREF(v, 0), key))
3646 return v;
3647 }
3648 return Qnil;
3649 }
3650
3651 /*
3652 * call-seq:
3653 * ary.rassoc(obj) -> new_ary or nil
3654 *
3655 * Searches through the array whose elements are also arrays.
3656 *
3657 * Compares +obj+ with the second element of each contained array using
3658 * <code>obj.==</code>.
3659 *
3660 * Returns the first contained array that matches +obj+.
3661 *
3662 * See also Array#assoc.
3663 *
3664 * a = [ [ 1, "one"], [2, "two"], [3, "three"], ["ii", "two"] ]
3665 * a.rassoc("two") #=> [2, "two"]
3666 * a.rassoc("four") #=> nil
3667 */
3668
3669 VALUE
3670 rb_ary_rassoc(VALUE ary, VALUE value)
3671 {
3672 long i;
3673 VALUE v;
3674
3675 for (i = 0; i < RARRAY_LEN(ary); ++i) {
3676 v = RARRAY_AREF(ary, i);
3677 if (RB_TYPE_P(v, T_ARRAY) &&
3678 RARRAY_LEN(v) > 1 &&
3679 rb_equal(RARRAY_AREF(v, 1), value))
3680 return v;
3681 }
3682 return Qnil;
3683 }
3684
3685 static VALUE
3686 recursive_equal(VALUE ary1, VALUE ary2, int recur)
3687 {
3688 long i, len1;
3689 const VALUE *p1, *p2;
3690
3691 if (recur) return Qtrue; /* Subtle! */
3692
3693 p1 = RARRAY_CONST_PTR(ary1);
3694 p2 = RARRAY_CONST_PTR(ary2);
3695 len1 = RARRAY_LEN(ary1);
3696
3697 for (i = 0; i < len1; i++) {
3698 if (*p1 != *p2) {
3699 if (rb_equal(*p1, *p2)) {
3700 len1 = RARRAY_LEN(ary1);
3701 if (len1 != RARRAY_LEN(ary2))
3702 return Qfalse;
3703 if (len1 < i)
3704 return Qtrue;
3705 p1 = RARRAY_CONST_PTR(ary1) + i;
3706 p2 = RARRAY_CONST_PTR(ary2) + i;
3707 }
3708 else {
3709 return Qfalse;
3710 }
3711 }
3712 p1++;
3713 p2++;
3714 }
3715 return Qtrue;
3716 }
3717
3718 /*
3719 * call-seq:
3720 * ary == other_ary -> bool
3721 *
3722 * Equality --- Two arrays are equal if they contain the same number of
3723 * elements and if each element is equal to (according to Object#==) the
3724 * corresponding element in +other_ary+.
3725 *
3726 * [ "a", "c" ] == [ "a", "c", 7 ] #=> false
3727 * [ "a", "c", 7 ] == [ "a", "c", 7 ] #=> true
3728 * [ "a", "c", 7 ] == [ "a", "d", "f" ] #=> false
3729 *
3730 */
3731
3732 static VALUE
3733 rb_ary_equal(VALUE ary1, VALUE ary2)
3734 {
3735 if (ary1 == ary2) return Qtrue;
3736 if (!RB_TYPE_P(ary2, T_ARRAY)) {
3737 if (!rb_respond_to(ary2, rb_intern("to_ary"))) {
3738 return Qfalse;
3739 }
3740 return rb_equal(ary2, ary1);
3741 }
3742 if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return Qfalse;
3743 if (RARRAY_CONST_PTR(ary1) == RARRAY_CONST_PTR(ary2)) return Qtrue;
3744 return rb_exec_recursive_paired(recursive_equal, ary1, ary2, ary2);
3745 }
3746
3747 static VALUE
3748 recursive_eql(VALUE ary1, VALUE ary2, int recur)
3749 {
3750 long i;
3751
3752 if (recur) return Qtrue; /* Subtle! */
3753 for (i=0; i<RARRAY_LEN(ary1); i++) {
3754 if (!rb_eql(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i)))
3755 return Qfalse;
3756 }
3757 return Qtrue;
3758 }
3759
3760 /*
3761 * call-seq:
3762 * ary.eql?(other) -> true or false
3763 *
3764 * Returns +true+ if +self+ and +other+ are the same object,
3765 * or are both arrays with the same content (according to Object#eql?).
3766 */
3767
3768 static VALUE
3769 rb_ary_eql(VALUE ary1, VALUE ary2)
3770 {
3771 if (ary1 == ary2) return Qtrue;
3772 if (!RB_TYPE_P(ary2, T_ARRAY)) return Qfalse;
3773 if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return Qfalse;
3774 if (RARRAY_CONST_PTR(ary1) == RARRAY_CONST_PTR(ary2)) return Qtrue;
3775 return rb_exec_recursive_paired(recursive_eql, ary1, ary2, ary2);
3776 }
3777
3778 /*
3779 * call-seq:
3780 * ary.hash -> fixnum
3781 *
3782 * Compute a hash-code for this array.
3783 *
3784 * Two arrays with the same content will have the same hash code (and will
3785 * compare using #eql?).
3786 */
3787
3788 static VALUE
3789 rb_ary_hash(VALUE ary)
3790 {
3791 long i;
3792 st_index_t h;
3793 VALUE n;
3794
3795 h = rb_hash_start(RARRAY_LEN(ary));
3796 h = rb_hash_uint(h, (st_index_t)rb_ary_hash);
3797 for (i=0; i<RARRAY_LEN(ary); i++) {
3798 n = rb_hash(RARRAY_AREF(ary, i));
3799 h = rb_hash_uint(h, NUM2LONG(n));
3800 }
3801 h = rb_hash_end(h);
3802 return LONG2FIX(h);
3803 }
3804
3805 /*
3806 * call-seq:
3807 * ary.include?(object) -> true or false
3808 *
3809 * Returns +true+ if the given +object+ is present in +self+ (that is, if any
3810 * element <code>==</code> +object+), otherwise returns +false+.
3811 *
3812 * a = [ "a", "b", "c" ]
3813 * a.include?("b") #=> true
3814 * a.include?("z") #=> false
3815 */
3816
3817 VALUE
3818 rb_ary_includes(VALUE ary, VALUE item)
3819 {
3820 long i;
3821
3822 for (i=0; i<RARRAY_LEN(ary); i++) {
3823 if (rb_equal(RARRAY_AREF(ary, i), item)) {
3824 return Qtrue;
3825 }
3826 }
3827 return Qfalse;
3828 }
3829
3830
3831 static VALUE
3832 recursive_cmp(VALUE ary1, VALUE ary2, int recur)
3833 {
3834 long i, len;
3835
3836 if (recur) return Qundef; /* Subtle! */
3837 len = RARRAY_LEN(ary1);
3838 if (len > RARRAY_LEN(ary2)) {
3839 len = RARRAY_LEN(ary2);
3840 }
3841 for (i=0; i<len; i++) {
3842 VALUE e1 = rb_ary_elt(ary1, i), e2 = rb_ary_elt(ary2, i);
3843 VALUE v = rb_funcallv(e1, id_cmp, 1, &e2);
3844 if (v != INT2FIX(0)) {
3845 return v;
3846 }
3847 }
3848 return Qundef;
3849 }
3850
3851 /*
3852 * call-seq:
3853 * ary <=> other_ary -> -1, 0, +1 or nil
3854 *
3855 * Comparison --- Returns an integer (+-1+, +0+, or <code>+1</code>) if this
3856 * array is less than, equal to, or greater than +other_ary+.
3857 *
3858 * +nil+ is returned if the two values are incomparable.
3859 *
3860 * Each object in each array is compared (using the <=> operator).
3861 *
3862 * Arrays are compared in an "element-wise" manner; the first two elements
3863 * that are not equal will determine the return value for the whole
3864 * comparison.
3865 *
3866 * If all the values are equal, then the return is based on a comparison of
3867 * the array lengths. Thus, two arrays are "equal" according to Array#<=> if,
3868 * and only if, they have the same length and the value of each element is
3869 * equal to the value of the corresponding element in the other array.
3870 *
3871 * [ "a", "a", "c" ] <=> [ "a", "b", "c" ] #=> -1
3872 * [ 1, 2, 3, 4, 5, 6 ] <=> [ 1, 2 ] #=> +1
3873 *
3874 */
3875
3876 VALUE
3877 rb_ary_cmp(VALUE ary1, VALUE ary2)
3878 {
3879 long len;
3880 VALUE v;
3881
3882 ary2 = rb_check_array_type(ary2);
3883 if (NIL_P(ary2)) return Qnil;
3884 if (ary1 == ary2) return INT2FIX(0);
3885 v = rb_exec_recursive_paired(recursive_cmp, ary1, ary2, ary2);
3886 if (v != Qundef) return v;
3887 len = RARRAY_LEN(ary1) - RARRAY_LEN(ary2);
3888 if (len == 0) return INT2FIX(0);
3889 if (len > 0) return INT2FIX(1);
3890 return INT2FIX(-1);
3891 }
3892
3893 static VALUE
3894 ary_add_hash(VALUE hash, VALUE ary)
3895 {
3896 long i;
3897
3898 for (i=0; i<RARRAY_LEN(ary); i++) {
3899 VALUE elt = RARRAY_AREF(ary, i);
3900 if (rb_hash_lookup2(hash, elt, Qundef) == Qundef) {
3901 rb_hash_aset(hash, elt, elt);
3902 }
3903 }
3904 return hash;
3905 }
3906
3907 static inline VALUE
3908 ary_tmp_hash_new(void)
3909 {
3910 VALUE hash = rb_hash_new();
3911
3912 RBASIC_CLEAR_CLASS(hash);
3913 return hash;
3914 }
3915
3916 static VALUE
3917 ary_make_hash(VALUE ary)
3918 {
3919 VALUE hash = ary_tmp_hash_new();
3920 return ary_add_hash(hash, ary);
3921 }
3922
3923 static VALUE
3924 ary_add_hash_by(VALUE hash, VALUE ary)
3925 {
3926 long i;
3927
3928 for (i = 0; i < RARRAY_LEN(ary); ++i) {
3929 VALUE v = rb_ary_elt(ary, i), k = rb_yield(v);
3930 if (rb_hash_lookup2(hash, k, Qundef) == Qundef) {
3931 rb_hash_aset(hash, k, v);
3932 }
3933 }
3934 return hash;
3935 }
3936
3937 static VALUE
3938 ary_make_hash_by(VALUE ary)
3939 {
3940 VALUE hash = ary_tmp_hash_new();
3941 return ary_add_hash_by(hash, ary);
3942 }
3943
3944 static inline void
3945 ary_recycle_hash(VALUE hash)
3946 {
3947 if (RHASH(hash)->ntbl) {
3948 st_table *tbl = RHASH(hash)->ntbl;
3949 RHASH(hash)->ntbl = 0;
3950 st_free_table(tbl);
3951 }
3952 RB_GC_GUARD(hash);
3953 }
3954
3955 /*
3956 * call-seq:
3957 * ary - other_ary -> new_ary
3958 *
3959 * Array Difference
3960 *
3961 * Returns a new array that is a copy of the original array, removing any
3962 * items that also appear in +other_ary+. The order is preserved from the
3963 * original array.
3964 *
3965 * It compares elements using their #hash and #eql? methods for efficiency.
3966 *
3967 * [ 1, 1, 2, 2, 3, 3, 4, 5 ] - [ 1, 2, 4 ] #=> [ 3, 3, 5 ]
3968 *
3969 * If you need set-like behavior, see the library class Set.
3970 */
3971
3972 static VALUE
3973 rb_ary_diff(VALUE ary1, VALUE ary2)
3974 {
3975 VALUE ary3;
3976 VALUE hash;
3977 long i;
3978
3979 hash = ary_make_hash(to_ary(ary2));
3980 ary3 = rb_ary_new();
3981
3982 for (i=0; i<RARRAY_LEN(ary1); i++) {
3983 if (st_lookup(rb_hash_tbl_raw(hash), RARRAY_AREF(ary1, i), 0)) continue;
3984 rb_ary_push(ary3, rb_ary_elt(ary1, i));
3985 }
3986 ary_recycle_hash(hash);
3987 return ary3;
3988 }
3989
3990 /*
3991 * call-seq:
3992 * ary & other_ary -> new_ary
3993 *
3994 * Set Intersection --- Returns a new array containing elements common to the
3995 * two arrays, excluding any duplicates. The order is preserved from the
3996 * original array.
3997 *
3998 * It compares elements using their #hash and #eql? methods for efficiency.
3999 *
4000 * [ 1, 1, 3, 5 ] & [ 1, 2, 3 ] #=> [ 1, 3 ]
4001 * [ 'a', 'b', 'b', 'z' ] & [ 'a', 'b', 'c' ] #=> [ 'a', 'b' ]
4002 *
4003 * See also Array#uniq.
4004 */
4005
4006
4007 static VALUE
4008 rb_ary_and(VALUE ary1, VALUE ary2)
4009 {
4010 VALUE hash, ary3, v;
4011 st_table *table;
4012 st_data_t vv;
4013 long i;
4014
4015 ary2 = to_ary(ary2);
4016 ary3 = rb_ary_new();
4017 if (RARRAY_LEN(ary2) == 0) return ary3;
4018 hash = ary_make_hash(ary2);
4019 table = rb_hash_tbl_raw(hash);
4020
4021 for (i=0; i<RARRAY_LEN(ary1); i++) {
4022 v = RARRAY_AREF(ary1, i);
4023 vv = (st_data_t)v;
4024 if (st_delete(table, &vv, 0)) {
4025 rb_ary_push(ary3, v);
4026 }
4027 }
4028 ary_recycle_hash(hash);
4029
4030 return ary3;
4031 }
4032
4033 static int
4034 ary_hash_orset(st_data_t *key, st_data_t *value, st_data_t arg, int existing)
4035 {
4036 if (existing) return ST_STOP;
4037 *key = *value = (VALUE)arg;
4038 return ST_CONTINUE;
4039 }
4040
4041 /*
4042 * call-seq:
4043 * ary | other_ary -> new_ary
4044 *
4045 * Set Union --- Returns a new array by joining +ary+ with +other_ary+,
4046 * excluding any duplicates and preserving the order from the original array.
4047 *
4048 * It compares elements using their #hash and #eql? methods for efficiency.
4049 *
4050 * [ "a", "b", "c" ] | [ "c", "d", "a" ] #=> [ "a", "b", "c", "d" ]
4051 *
4052 * See also Array#uniq.
4053 */
4054
4055 static VALUE
4056 rb_ary_or(VALUE ary1, VALUE ary2)
4057 {
4058 VALUE hash, ary3;
4059 long i;
4060
4061 ary2 = to_ary(ary2);
4062 hash = ary_make_hash(ary1);
4063
4064 for (i=0; i<RARRAY_LEN(ary2); i++) {
4065 VALUE elt = RARRAY_AREF(ary2, i);
4066 if (!st_update(RHASH_TBL_RAW(hash), (st_data_t)elt, ary_hash_orset, (st_data_t)elt)) {
4067 RB_OBJ_WRITTEN(hash, Qundef, elt);
4068 }
4069 }
4070 ary3 = rb_hash_values(hash);
4071 ary_recycle_hash(hash);
4072 return ary3;
4073 }
4074
4075 static int
4076 push_value(st_data_t key, st_data_t val, st_data_t ary)
4077 {
4078 rb_ary_push((VALUE)ary, (VALUE)val);
4079 return ST_CONTINUE;
4080 }
4081
4082 /*
4083 * call-seq:
4084 * ary.uniq! -> ary or nil
4085 * ary.uniq! { |item| ... } -> ary or nil
4086 *
4087 * Removes duplicate elements from +self+.
4088 *
4089 * If a block is given, it will use the return value of the block for
4090 * comparison.
4091 *
4092 * It compares values using their #hash and #eql? methods for efficiency.
4093 *
4094 * Returns +nil+ if no changes are made (that is, no duplicates are found).
4095 *
4096 * a = [ "a", "a", "b", "b", "c" ]
4097 * a.uniq! # => ["a", "b", "c"]
4098 *
4099 * b = [ "a", "b", "c" ]
4100 * b.uniq! # => nil
4101 *
4102 * c = [["student","sam"], ["student","george"], ["teacher","matz"]]
4103 * c.uniq! { |s| s.first } # => [["student", "sam"], ["teacher", "matz"]]
4104 *
4105 */
4106
4107 static VALUE
4108 rb_ary_uniq_bang(VALUE ary)
4109 {
4110 VALUE hash;
4111 long hash_size;
4112
4113 rb_ary_modify_check(ary);
4114 if (RARRAY_LEN(ary) <= 1)
4115 return Qnil;
4116 if (rb_block_given_p())
4117 hash = ary_make_hash_by(ary);
4118 else
4119 hash = ary_make_hash(ary);
4120
4121 hash_size = RHASH_SIZE(hash);
4122 if (RARRAY_LEN(ary) == hash_size) {
4123 return Qnil;
4124 }
4125 rb_ary_modify_check(ary);
4126 ARY_SET_LEN(ary, 0);
4127 if (ARY_SHARED_P(ary) && !ARY_EMBED_P(ary)) {
4128 rb_ary_unshare(ary);
4129 FL_SET_EMBED(ary);
4130 }
4131 ary_resize_capa(ary, hash_size);
4132 st_foreach(rb_hash_tbl_raw(hash), push_value, ary);
4133 ary_recycle_hash(hash);
4134
4135 return ary;
4136 }
4137
4138 /*
4139 * call-seq:
4140 * ary.uniq -> new_ary
4141 * ary.uniq { |item| ... } -> new_ary
4142 *
4143 * Returns a new array by removing duplicate values in +self+.
4144 *
4145 * If a block is given, it will use the return value of the block for comparison.
4146 *
4147 * It compares values using their #hash and #eql? methods for efficiency.
4148 *
4149 * a = [ "a", "a", "b", "b", "c" ]
4150 * a.uniq # => ["a", "b", "c"]
4151 *
4152 * b = [["student","sam"], ["student","george"], ["teacher","matz"]]
4153 * b.uniq { |s| s.first } # => [["student", "sam"], ["teacher", "matz"]]
4154 *
4155 */
4156
4157 static VALUE
4158 rb_ary_uniq(VALUE ary)
4159 {
4160 VALUE hash, uniq;
4161
4162 if (RARRAY_LEN(ary) <= 1)
4163 return rb_ary_dup(ary);
4164 if (rb_block_given_p()) {
4165 hash = ary_make_hash_by(ary);
4166 uniq = rb_hash_values(hash);
4167 }
4168 else {
4169 hash = ary_make_hash(ary);
4170 uniq = rb_hash_values(hash);
4171 }
4172 RBASIC_SET_CLASS(uniq, rb_obj_class(ary));
4173 ary_recycle_hash(hash);
4174
4175 return uniq;
4176 }
4177
4178 /*
4179 * call-seq:
4180 * ary.compact! -> ary or nil
4181 *
4182 * Removes +nil+ elements from the array.
4183 *
4184 * Returns +nil+ if no changes were made, otherwise returns the array.
4185 *
4186 * [ "a", nil, "b", nil, "c" ].compact! #=> [ "a", "b", "c" ]
4187 * [ "a", "b", "c" ].compact! #=> nil
4188 */
4189
4190 static VALUE
4191 rb_ary_compact_bang(VALUE ary)
4192 {
4193 VALUE *p, *t, *end;
4194 long n;
4195
4196 rb_ary_modify(ary);
4197 p = t = (VALUE *)RARRAY_CONST_PTR(ary); /* WB: no new reference */
4198 end = p + RARRAY_LEN(ary);
4199
4200 while (t < end) {
4201 if (NIL_P(*t)) t++;
4202 else *p++ = *t++;
4203 }
4204 n = p - RARRAY_CONST_PTR(ary);
4205 if (RARRAY_LEN(ary) == n) {
4206 return Qnil;
4207 }
4208 ary_resize_smaller(ary, n);
4209
4210 return ary;
4211 }
4212
4213 /*
4214 * call-seq:
4215 * ary.compact -> new_ary
4216 *
4217 * Returns a copy of +self+ with all +nil+ elements removed.
4218 *
4219 * [ "a", nil, "b", nil, "c", nil ].compact
4220 * #=> [ "a", "b", "c" ]
4221 */
4222
4223 static VALUE
4224 rb_ary_compact(VALUE ary)
4225 {
4226 ary = rb_ary_dup(ary);
4227 rb_ary_compact_bang(ary);
4228 return ary;
4229 }
4230
4231 /*
4232 * call-seq:
4233 * ary.count -> int
4234 * ary.count(obj) -> int
4235 * ary.count { |item| block } -> int
4236 *
4237 * Returns the number of elements.
4238 *
4239 * If an argument is given, counts the number of elements which equal +obj+
4240 * using <code>==</code>.
4241 *
4242 * If a block is given, counts the number of elements for which the block
4243 * returns a true value.
4244 *
4245 * ary = [1, 2, 4, 2]
4246 * ary.count #=> 4
4247 * ary.count(2) #=> 2
4248 * ary.count { |x| x%2 == 0 } #=> 3
4249 *
4250 */
4251
4252 static VALUE
4253 rb_ary_count(int argc, VALUE *argv, VALUE ary)
4254 {
4255 long i, n = 0;
4256
4257 if (argc == 0) {
4258 VALUE v;
4259
4260 if (!rb_block_given_p())
4261 return LONG2NUM(RARRAY_LEN(ary));
4262
4263 for (i = 0; i < RARRAY_LEN(ary); i++) {
4264 v = RARRAY_AREF(ary, i);
4265 if (RTEST(rb_yield(v))) n++;
4266 }
4267 }
4268 else {
4269 VALUE obj;
4270
4271 rb_scan_args(argc, argv, "1", &obj);
4272 if (rb_block_given_p()) {
4273 rb_warn("given block not used");
4274 }
4275 for (i = 0; i < RARRAY_LEN(ary); i++) {
4276 if (rb_equal(RARRAY_AREF(ary, i), obj)) n++;
4277 }
4278 }
4279
4280 return LONG2NUM(n);
4281 }
4282
4283 static VALUE
4284 flatten(VALUE ary, int level, int *modified)
4285 {
4286 long i = 0;
4287 VALUE stack, result, tmp, elt;
4288 st_table *memo;
4289 st_data_t id;
4290
4291 stack = ary_new(0, ARY_DEFAULT_SIZE);
4292 result = ary_new(0, RARRAY_LEN(ary));
4293 memo = st_init_numtable();
4294 st_insert(memo, (st_data_t)ary, (st_data_t)Qtrue);
4295 *modified = 0;
4296
4297 while (1) {
4298 while (i < RARRAY_LEN(ary)) {
4299 elt = RARRAY_AREF(ary, i++);
4300 tmp = rb_check_array_type(elt);
4301 if (RBASIC(result)->klass) {
4302 rb_raise(rb_eRuntimeError, "flatten reentered");
4303 }
4304 if (NIL_P(tmp) || (level >= 0 && RARRAY_LEN(stack) / 2 >= level)) {
4305 rb_ary_push(result, elt);
4306 }
4307 else {
4308 *modified = 1;
4309 id = (st_data_t)tmp;
4310 if (st_lookup(memo, id, 0)) {
4311 st_free_table(memo);
4312 rb_raise(rb_eArgError, "tried to flatten recursive array");
4313 }
4314 st_insert(memo, id, (st_data_t)Qtrue);
4315 rb_ary_push(stack, ary);
4316 rb_ary_push(stack, LONG2NUM(i));
4317 ary = tmp;
4318 i = 0;
4319 }
4320 }
4321 if (RARRAY_LEN(stack) == 0) {
4322 break;
4323 }
4324 id = (st_data_t)ary;
4325 st_delete(memo, &id, 0);
4326 tmp = rb_ary_pop(stack);
4327 i = NUM2LONG(tmp);
4328 ary = rb_ary_pop(stack);
4329 }
4330
4331 st_free_table(memo);
4332
4333 RBASIC_SET_CLASS(result, rb_class_of(ary));
4334 return result;
4335 }
4336
4337 /*
4338 * call-seq:
4339 * ary.flatten! -> ary or nil
4340 * ary.flatten!(level) -> ary or nil
4341 *
4342 * Flattens +self+ in place.
4343 *
4344 * Returns +nil+ if no modifications were made (i.e., the array contains no
4345 * subarrays.)
4346 *
4347 * The optional +level+ argument determines the level of recursion to flatten.
4348 *
4349 * a = [ 1, 2, [3, [4, 5] ] ]
4350 * a.flatten! #=> [1, 2, 3, 4, 5]
4351 * a.flatten! #=> nil
4352 * a #=> [1, 2, 3, 4, 5]
4353 * a = [ 1, 2, [3, [4, 5] ] ]
4354 * a.flatten!(1) #=> [1, 2, 3, [4, 5]]
4355 */
4356
4357 static VALUE
4358 rb_ary_flatten_bang(int argc, VALUE *argv, VALUE ary)
4359 {
4360 int mod = 0, level = -1;
4361 VALUE result, lv;
4362
4363 rb_scan_args(argc, argv, "01", &lv);
4364 rb_ary_modify_check(ary);
4365 if (!NIL_P(lv)) level = NUM2INT(lv);
4366 if (level == 0) return Qnil;
4367
4368 result = flatten(ary, level, &mod);
4369 if (mod == 0) {
4370 ary_discard(result);
4371 return Qnil;
4372 }
4373 if (!(mod = ARY_EMBED_P(result))) rb_obj_freeze(result);
4374 rb_ary_replace(ary, result);
4375 if (mod) ARY_SET_EMBED_LEN(result, 0);
4376
4377 return ary;
4378 }
4379
4380 /*
4381 * call-seq:
4382 * ary.flatten -> new_ary
4383 * ary.flatten(level) -> new_ary
4384 *
4385 * Returns a new array that is a one-dimensional flattening of +self+
4386 * (recursively).
4387 *
4388 * That is, for every element that is an array, extract its elements into
4389 * the new array.
4390 *
4391 * The optional +level+ argument determines the level of recursion to
4392 * flatten.
4393 *
4394 * s = [ 1, 2, 3 ] #=> [1, 2, 3]
4395 * t = [ 4, 5, 6, [7, 8] ] #=> [4, 5, 6, [7, 8]]
4396 * a = [ s, t, 9, 10 ] #=> [[1, 2, 3], [4, 5, 6, [7, 8]], 9, 10]
4397 * a.flatten #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
4398 * a = [ 1, 2, [3, [4, 5] ] ]
4399 * a.flatten(1) #=> [1, 2, 3, [4, 5]]
4400 */
4401
4402 static VALUE
4403 rb_ary_flatten(int argc, VALUE *argv, VALUE ary)
4404 {
4405 int mod = 0, level = -1;
4406 VALUE result, lv;
4407
4408 rb_scan_args(argc, argv, "01", &lv);
4409 if (!NIL_P(lv)) level = NUM2INT(lv);
4410 if (level == 0) return ary_make_shared_copy(ary);
4411
4412 result = flatten(ary, level, &mod);
4413 OBJ_INFECT(result, ary);
4414
4415 return result;
4416 }
4417
4418 #define OPTHASH_GIVEN_P(opts) \
4419 (argc > 0 && !NIL_P((opts) = rb_check_hash_type(argv[argc-1])) && (--argc, 1))
4420 static ID id_random;
4421
4422 #define RAND_UPTO(max) (long)rb_random_ulong_limited((randgen), (max)-1)
4423
4424 /*
4425 * call-seq:
4426 * ary.shuffle! -> ary
4427 * ary.shuffle!(random: rng) -> ary
4428 *
4429 * Shuffles elements in +self+ in place.
4430 *
4431 * The optional +rng+ argument will be used as the random number generator.
4432 */
4433
4434 static VALUE
4435 rb_ary_shuffle_bang(int argc, VALUE *argv, VALUE ary)
4436 {
4437 VALUE opts, randgen = rb_cRandom;
4438 long i, len;
4439
4440 if (OPTHASH_GIVEN_P(opts)) {
4441 VALUE rnd;
4442 ID keyword_ids[1];
4443
4444 keyword_ids[0] = id_random;
4445 rb_get_kwargs(opts, keyword_ids, 0, 1, &rnd);
4446 if (rnd != Qundef) {
4447 randgen = rnd;
4448 }
4449 }
4450 rb_check_arity(argc, 0, 0);
4451 rb_ary_modify(ary);
4452 i = len = RARRAY_LEN(ary);
4453 RARRAY_PTR_USE(ary, ptr, {
4454 while (i) {
4455 long j = RAND_UPTO(i);
4456 VALUE tmp;
4457 if (len != RARRAY_LEN(ary) || ptr != RARRAY_CONST_PTR(ary)) {
4458 rb_raise(rb_eRuntimeError, "modified during shuffle");
4459 }
4460 tmp = ptr[--i];
4461 ptr[i] = ptr[j];
4462 ptr[j] = tmp;
4463 }
4464 }); /* WB: no new reference */
4465 return ary;
4466 }
4467
4468
4469 /*
4470 * call-seq:
4471 * ary.shuffle -> new_ary
4472 * ary.shuffle(random: rng) -> new_ary
4473 *
4474 * Returns a new array with elements of +self+ shuffled.
4475 *
4476 * a = [ 1, 2, 3 ] #=> [1, 2, 3]
4477 * a.shuffle #=> [2, 3, 1]
4478 *
4479 * The optional +rng+ argument will be used as the random number generator.
4480 *
4481 * a.shuffle(random: Random.new(1)) #=> [1, 3, 2]
4482 */
4483
4484 static VALUE
4485 rb_ary_shuffle(int argc, VALUE *argv, VALUE ary)
4486 {
4487 ary = rb_ary_dup(ary);
4488 rb_ary_shuffle_bang(argc, argv, ary);
4489 return ary;
4490 }
4491
4492
4493 /*
4494 * call-seq:
4495 * ary.sample -> obj
4496 * ary.sample(random: rng) -> obj
4497 * ary.sample(n) -> new_ary
4498 * ary.sample(n, random: rng) -> new_ary
4499 *
4500 * Choose a random element or +n+ random elements from the array.
4501 *
4502 * The elements are chosen by using random and unique indices into the array
4503 * in order to ensure that an element doesn't repeat itself unless the array
4504 * already contained duplicate elements.
4505 *
4506 * If the array is empty the first form returns +nil+ and the second form
4507 * returns an empty array.
4508 *
4509 * The optional +rng+ argument will be used as the random number generator.
4510 *
4511 * a = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
4512 * a.sample #=> 7
4513 * a.sample(4) #=> [6, 4, 2, 5]
4514 */
4515
4516
4517 static VALUE
4518 rb_ary_sample(int argc, VALUE *argv, VALUE ary)
4519 {
4520 VALUE nv, result;
4521 VALUE opts, randgen = rb_cRandom;
4522 long n, len, i, j, k, idx[10];
4523 long rnds[numberof(idx)];
4524
4525 if (OPTHASH_GIVEN_P(opts)) {
4526 VALUE rnd;
4527 ID keyword_ids[1];
4528
4529 keyword_ids[0] = id_random;
4530 rb_get_kwargs(opts, keyword_ids, 0, 1, &rnd);
4531 if (rnd != Qundef) {
4532 randgen = rnd;
4533 }
4534 }
4535 len = RARRAY_LEN(ary);
4536 if (argc == 0) {
4537 if (len < 2)
4538 i = 0;
4539 else
4540 i = RAND_UPTO(len);
4541
4542 return rb_ary_elt(ary, i);
4543 }
4544 rb_scan_args(argc, argv, "1", &nv);
4545 n = NUM2LONG(nv);
4546 if (n < 0) rb_raise(rb_eArgError, "negative sample number");
4547 if (n > len) n = len;
4548 if (n <= numberof(idx)) {
4549 for (i = 0; i < n; ++i) {
4550 rnds[i] = RAND_UPTO(len - i);
4551 }
4552 }
4553 k = len;
4554 len = RARRAY_LEN(ary);
4555 if (len < k && n <= numberof(idx)) {
4556 for (i = 0; i < n; ++i) {
4557 if (rnds[i] >= len) return rb_ary_new_capa(0);
4558 }
4559 }
4560 if (n > len) n = len;
4561 switch (n) {
4562 case 0:
4563 return rb_ary_new_capa(0);
4564 case 1:
4565 i = rnds[0];
4566 return rb_ary_new_from_values(1, &RARRAY_AREF(ary, i));
4567 case 2:
4568 i = rnds[0];
4569 j = rnds[1];
4570 if (j >= i) j++;
4571 return rb_ary_new_from_args(2, RARRAY_AREF(ary, i), RARRAY_AREF(ary, j));
4572 case 3:
4573 i = rnds[0];
4574 j = rnds[1];
4575 k = rnds[2];
4576 {
4577 long l = j, g = i;
4578 if (j >= i) l = i, g = ++j;
4579 if (k >= l && (++k >= g)) ++k;
4580 }
4581 return rb_ary_new_from_args(3, RARRAY_AREF(ary, i), RARRAY_AREF(ary, j), RARRAY_AREF(ary, k));
4582 }
4583 if (n <= numberof(idx)) {
4584 long sorted[numberof(idx)];
4585 sorted[0] = idx[0] = rnds[0];
4586 for (i=1; i<n; i++) {
4587 k = rnds[i];
4588 for (j = 0; j < i; ++j) {
4589 if (k < sorted[j]) break;
4590 ++k;
4591 }
4592 memmove(&sorted[j+1], &sorted[j], sizeof(sorted[0])*(i-j));
4593 sorted[j] = idx[i] = k;
4594 }
4595 result = rb_ary_new_capa(n);
4596 RARRAY_PTR_USE(result, ptr_result, {
4597 for (i=0; i<n; i++) {
4598 ptr_result[i] = RARRAY_AREF(ary, idx[i]);
4599 }
4600 });
4601 }
4602 else {
4603 result = rb_ary_dup(ary);
4604 RBASIC_CLEAR_CLASS(result);
4605 RB_GC_GUARD(ary);
4606 RARRAY_PTR_USE(result, ptr_result, {
4607 for (i=0; i<n; i++) {
4608 j = RAND_UPTO(len-i) + i;
4609 nv = ptr_result[j];
4610 ptr_result[j] = ptr_result[i];
4611 ptr_result[i] = nv;
4612 }
4613 });
4614 RBASIC_SET_CLASS_RAW(result, rb_cArray);
4615 }
4616 ARY_SET_LEN(result, n);
4617
4618 return result;
4619 }
4620
4621 static VALUE
4622 rb_ary_cycle_size(VALUE self, VALUE args, VALUE eobj)
4623 {
4624 long mul;
4625 VALUE n = Qnil;
4626 if (args && (RARRAY_LEN(args) > 0)) {
4627 n = RARRAY_AREF(args, 0);
4628 }
4629 if (RARRAY_LEN(self) == 0) return INT2FIX(0);
4630 if (n == Qnil) return DBL2NUM(INFINITY);
4631 mul = NUM2LONG(n);
4632 if (mul <= 0) return INT2FIX(0);
4633 n = LONG2FIX(mul);
4634 return rb_funcallv(rb_ary_length(self), '*', 1, &n);
4635 }
4636
4637 /*
4638 * call-seq:
4639 * ary.cycle(n=nil) { |obj| block } -> nil
4640 * ary.cycle(n=nil) -> Enumerator
4641 *
4642 * Calls the given block for each element +n+ times or forever if +nil+ is
4643 * given.
4644 *
4645 * Does nothing if a non-positive number is given or the array is empty.
4646 *
4647 * Returns +nil+ if the loop has finished without getting interrupted.
4648 *
4649 * If no block is given, an Enumerator is returned instead.
4650 *
4651 * a = ["a", "b", "c"]
4652 * a.cycle { |x| puts x } # print, a, b, c, a, b, c,.. forever.
4653 * a.cycle(2) { |x| puts x } # print, a, b, c, a, b, c.
4654 *
4655 */
4656
4657 static VALUE
4658 rb_ary_cycle(int argc, VALUE *argv, VALUE ary)
4659 {
4660 long n, i;
4661 VALUE nv = Qnil;
4662
4663 rb_scan_args(argc, argv, "01", &nv);
4664
4665 RETURN_SIZED_ENUMERATOR(ary, argc, argv, rb_ary_cycle_size);
4666 if (NIL_P(nv)) {
4667 n = -1;
4668 }
4669 else {
4670 n = NUM2LONG(nv);
4671 if (n <= 0) return Qnil;
4672 }
4673
4674 while (RARRAY_LEN(ary) > 0 && (n < 0 || 0 < n--)) {
4675 for (i=0; i<RARRAY_LEN(ary); i++) {
4676 rb_yield(RARRAY_AREF(ary, i));
4677 }
4678 }
4679 return Qnil;
4680 }
4681
4682 #define tmpbuf(n, size) rb_str_tmp_new((n)*(size))
4683 #define tmpbuf_discard(s) (rb_str_resize((s), 0L), RBASIC_SET_CLASS_RAW(s, rb_cString))
4684 #define tmpary(n) rb_ary_tmp_new(n)
4685 #define tmpary_discard(a) (ary_discard(a), RBASIC_SET_CLASS_RAW(a, rb_cArray))
4686
4687 /*
4688 * Build a ruby array of the corresponding values and yield it to the
4689 * associated block.
4690 * Return the class of +values+ for reentry check.
4691 */
4692 static int
4693 yield_indexed_values(const VALUE values, const long r, const long *const p)
4694 {
4695 const VALUE result = rb_ary_new2(r);
4696 VALUE *const result_array = RARRAY_PTR(result);
4697 const VALUE *const values_array = RARRAY_CONST_PTR(values);
4698 long i;
4699
4700 for (i = 0; i < r; i++) result_array[i] = values_array[p[i]];
4701 ARY_SET_LEN(result, r);
4702 rb_yield(result);
4703 return !RBASIC(values)->klass;
4704 }
4705
4706 /*
4707 * Recursively compute permutations of +r+ elements of the set
4708 * <code>[0..n-1]</code>.
4709 *
4710 * When we have a complete permutation of array indexes, copy the values
4711 * at those indexes into a new array and yield that array.
4712 *
4713 * n: the size of the set
4714 * r: the number of elements in each permutation
4715 * p: the array (of size r) that we're filling in
4716 * index: what index we're filling in now
4717 * used: an array of booleans: whether a given index is already used
4718 * values: the Ruby array that holds the actual values to permute
4719 */
4720 static void
4721 permute0(long n, long r, long *p, long index, char *used, VALUE values)
4722 {
4723 long i;
4724 for (i = 0; i < n; i++) {
4725 if (used[i] == 0) {
4726 p[index] = i;
4727 if (index < r-1) { /* if not done yet */
4728 used[i] = 1; /* mark index used */
4729 permute0(n, r, p, index+1, /* recurse */
4730 used, values);
4731 used[i] = 0; /* index unused */
4732 }
4733 else {
4734 if (!yield_indexed_values(values, r, p)) {
4735 rb_raise(rb_eRuntimeError, "permute reentered");
4736 }
4737 }
4738 }
4739 }
4740 }
4741
4742 /*
4743 * Returns the product of from, from-1, ..., from - how_many + 1.
4744 * http://en.wikipedia.org/wiki/Pochhammer_symbol
4745 */
4746 static VALUE
4747 descending_factorial(long from, long how_many)
4748 {
4749 VALUE cnt = LONG2FIX(how_many >= 0);
4750 while (how_many-- > 0) {
4751 VALUE v = LONG2FIX(from--);
4752 cnt = rb_funcallv(cnt, '*', 1, &v);
4753 }
4754 return cnt;
4755 }
4756
4757 static VALUE
4758 binomial_coefficient(long comb, long size)
4759 {
4760 VALUE r, v;
4761 if (comb > size-comb) {
4762 comb = size-comb;
4763 }
4764 if (comb < 0) {
4765 return LONG2FIX(0);
4766 }
4767 r = descending_factorial(size, comb);
4768 v = descending_factorial(comb, comb);
4769 return rb_funcallv(r, id_div, 1, &v);
4770 }
4771
4772 static VALUE
4773 rb_ary_permutation_size(VALUE ary, VALUE args, VALUE eobj)
4774 {
4775 long n = RARRAY_LEN(ary);
4776 long k = (args && (RARRAY_LEN(args) > 0)) ? NUM2LONG(RARRAY_AREF(args, 0)) : n;
4777
4778 return descending_factorial(n, k);
4779 }
4780
4781 /*
4782 * call-seq:
4783 * ary.permutation { |p| block } -> ary
4784 * ary.permutation -> Enumerator
4785 * ary.permutation(n) { |p| block } -> ary
4786 * ary.permutation(n) -> Enumerator
4787 *
4788 * When invoked with a block, yield all permutations of length +n+ of the
4789 * elements of the array, then return the array itself.
4790 *
4791 * If +n+ is not specified, yield all permutations of all elements.
4792 *
4793 * The implementation makes no guarantees about the order in which the
4794 * permutations are yielded.
4795 *
4796 * If no block is given, an Enumerator is returned instead.
4797 *
4798 * Examples:
4799 *
4800 * a = [1, 2, 3]
4801 * a.permutation.to_a #=> [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
4802 * a.permutation(1).to_a #=> [[1],[2],[3]]
4803 * a.permutation(2).to_a #=> [[1,2],[1,3],[2,1],[2,3],[3,1],[3,2]]
4804 * a.permutation(3).to_a #=> [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
4805 * a.permutation(0).to_a #=> [[]] # one permutation of length 0
4806 * a.permutation(4).to_a #=> [] # no permutations of length 4
4807 */
4808
4809 static VALUE
4810 rb_ary_permutation(int argc, VALUE *argv, VALUE ary)
4811 {
4812 VALUE num;
4813 long r, n, i;
4814
4815 n = RARRAY_LEN(ary); /* Array length */
4816 RETURN_SIZED_ENUMERATOR(ary, argc, argv, rb_ary_permutation_size); /* Return enumerator if no block */
4817 rb_scan_args(argc, argv, "01", &num);
4818 r = NIL_P(num) ? n : NUM2LONG(num); /* Permutation size from argument */
4819
4820 if (r < 0 || n < r) {
4821 /* no permutations: yield nothing */
4822 }
4823 else if (r == 0) { /* exactly one permutation: the zero-length array */
4824 rb_yield(rb_ary_new2(0));
4825 }
4826 else if (r == 1) { /* this is a special, easy case */
4827 for (i = 0; i < RARRAY_LEN(ary); i++) {
4828 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
4829 }
4830 }
4831 else { /* this is the general case */
4832 volatile VALUE t0 = tmpbuf(r,sizeof(long));
4833 long *p = (long*)RSTRING_PTR(t0);
4834 volatile VALUE t1 = tmpbuf(n,sizeof(char));
4835 char *used = (char*)RSTRING_PTR(t1);
4836 VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
4837 RBASIC_CLEAR_CLASS(ary0);
4838
4839 MEMZERO(used, char, n); /* initialize array */
4840
4841 permute0(n, r, p, 0, used, ary0); /* compute and yield permutations */
4842 tmpbuf_discard(t0);
4843 tmpbuf_discard(t1);
4844 RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
4845 }
4846 return ary;
4847 }
4848
4849 static VALUE
4850 rb_ary_combination_size(VALUE ary, VALUE args, VALUE eobj)
4851 {
4852 long n = RARRAY_LEN(ary);
4853 long k = NUM2LONG(RARRAY_AREF(args, 0));
4854
4855 return binomial_coefficient(k, n);
4856 }
4857
4858 /*
4859 * call-seq:
4860 * ary.combination(n) { |c| block } -> ary
4861 * ary.combination(n) -> Enumerator
4862 *
4863 * When invoked with a block, yields all combinations of length +n+ of elements
4864 * from the array and then returns the array itself.
4865 *
4866 * The implementation makes no guarantees about the order in which the
4867 * combinations are yielded.
4868 *
4869 * If no block is given, an Enumerator is returned instead.
4870 *
4871 * Examples:
4872 *
4873 * a = [1, 2, 3, 4]
4874 * a.combination(1).to_a #=> [[1],[2],[3],[4]]
4875 * a.combination(2).to_a #=> [[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]]
4876 * a.combination(3).to_a #=> [[1,2,3],[1,2,4],[1,3,4],[2,3,4]]
4877 * a.combination(4).to_a #=> [[1,2,3,4]]
4878 * a.combination(0).to_a #=> [[]] # one combination of length 0
4879 * a.combination(5).to_a #=> [] # no combinations of length 5
4880 *
4881 */
4882
4883 static VALUE
4884 rb_ary_combination(VALUE ary, VALUE num)
4885 {
4886 long n, i, len;
4887
4888 n = NUM2LONG(num);
4889 RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_combination_size);
4890 len = RARRAY_LEN(ary);
4891 if (n < 0 || len < n) {
4892 /* yield nothing */
4893 }
4894 else if (n == 0) {
4895 rb_yield(rb_ary_new2(0));
4896 }
4897 else if (n == 1) {
4898 for (i = 0; i < len; i++) {
4899 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
4900 }
4901 }
4902 else {
4903 VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
4904 volatile VALUE t0;
4905 long *stack = ALLOCV_N(long, t0, n+1);
4906 long lev = 0;
4907
4908 RBASIC_CLEAR_CLASS(ary0);
4909 MEMZERO(stack+1, long, n);
4910 stack[0] = -1;
4911 for (;;) {
4912 for (lev++; lev < n; lev++) {
4913 stack[lev+1] = stack[lev]+1;
4914 }
4915 if (!yield_indexed_values(ary0, n, stack+1)) {
4916 rb_raise(rb_eRuntimeError, "combination reentered");
4917 }
4918 do {
4919 if (lev == 0) goto done;
4920 stack[lev--]++;
4921 } while (stack[lev+1]+n == len+lev+1);
4922 }
4923 done:
4924 ALLOCV_END(t0);
4925 RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
4926 }
4927 return ary;
4928 }
4929
4930 /*
4931 * Recursively compute repeated permutations of +r+ elements of the set
4932 * <code>[0..n-1]</code>.
4933 *
4934 * When we have a complete repeated permutation of array indexes, copy the
4935 * values at those indexes into a new array and yield that array.
4936 *
4937 * n: the size of the set
4938 * r: the number of elements in each permutation
4939 * p: the array (of size r) that we're filling in
4940 * index: what index we're filling in now
4941 * values: the Ruby array that holds the actual values to permute
4942 */
4943 static void
4944 rpermute0(long n, long r, long *p, long index, VALUE values)
4945 {
4946 long i;
4947 for (i = 0; i < n; i++) {
4948 p[index] = i;
4949 if (index < r-1) { /* if not done yet */
4950 rpermute0(n, r, p, index+1, values); /* recurse */
4951 }
4952 else {
4953 if (!yield_indexed_values(values, r, p)) {
4954 rb_raise(rb_eRuntimeError, "repeated permute reentered");
4955 }
4956 }
4957 }
4958 }
4959
4960 static VALUE
4961 rb_ary_repeated_permutation_size(VALUE ary, VALUE args, VALUE eobj)
4962 {
4963 long n = RARRAY_LEN(ary);
4964 long k = NUM2LONG(RARRAY_AREF(args, 0));
4965 VALUE v;
4966
4967 if (k < 0) {
4968 return LONG2FIX(0);
4969 }
4970
4971 v = LONG2NUM(k);
4972 return rb_funcallv(LONG2NUM(n), id_power, 1, &v);
4973 }
4974
4975 /*
4976 * call-seq:
4977 * ary.repeated_permutation(n) { |p| block } -> ary
4978 * ary.repeated_permutation(n) -> Enumerator
4979 *
4980 * When invoked with a block, yield all repeated permutations of length +n+ of
4981 * the elements of the array, then return the array itself.
4982 *
4983 * The implementation makes no guarantees about the order in which the repeated
4984 * permutations are yielded.
4985 *
4986 * If no block is given, an Enumerator is returned instead.
4987 *
4988 * Examples:
4989 *
4990 * a = [1, 2]
4991 * a.repeated_permutation(1).to_a #=> [[1], [2]]
4992 * a.repeated_permutation(2).to_a #=> [[1,1],[1,2],[2,1],[2,2]]
4993 * a.repeated_permutation(3).to_a #=> [[1,1,1],[1,1,2],[1,2,1],[1,2,2],
4994 * # [2,1,1],[2,1,2],[2,2,1],[2,2,2]]
4995 * a.repeated_permutation(0).to_a #=> [[]] # one permutation of length 0
4996 */
4997
4998 static VALUE
4999 rb_ary_repeated_permutation(VALUE ary, VALUE num)
5000 {
5001 long r, n, i;
5002
5003 n = RARRAY_LEN(ary); /* Array length */
5004 RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_repeated_permutation_size); /* Return Enumerator if no block */
5005 r = NUM2LONG(num); /* Permutation size from argument */
5006
5007 if (r < 0) {
5008 /* no permutations: yield nothing */
5009 }
5010 else if (r == 0) { /* exactly one permutation: the zero-length array */
5011 rb_yield(rb_ary_new2(0));
5012 }
5013 else if (r == 1) { /* this is a special, easy case */
5014 for (i = 0; i < RARRAY_LEN(ary); i++) {
5015 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
5016 }
5017 }
5018 else { /* this is the general case */
5019 volatile VALUE t0 = tmpbuf(r, sizeof(long));
5020 long *p = (long*)RSTRING_PTR(t0);
5021 VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
5022 RBASIC_CLEAR_CLASS(ary0);
5023
5024 rpermute0(n, r, p, 0, ary0); /* compute and yield repeated permutations */
5025 tmpbuf_discard(t0);
5026 RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
5027 }
5028 return ary;
5029 }
5030
5031 static void
5032 rcombinate0(long n, long r, long *p, long index, long rest, VALUE values)
5033 {
5034 if (rest > 0) {
5035 for (; index < n; ++index) {
5036 p[r-rest] = index;
5037 rcombinate0(n, r, p, index, rest-1, values);
5038 }
5039 }
5040 else {
5041 if (!yield_indexed_values(values, r, p)) {
5042 rb_raise(rb_eRuntimeError, "repeated combination reentered");
5043 }
5044 }
5045 }
5046
5047 static VALUE
5048 rb_ary_repeated_combination_size(VALUE ary, VALUE args, VALUE eobj)
5049 {
5050 long n = RARRAY_LEN(ary);
5051 long k = NUM2LONG(RARRAY_AREF(args, 0));
5052 if (k == 0) {
5053 return LONG2FIX(1);
5054 }
5055 return binomial_coefficient(k, n + k - 1);
5056 }
5057
5058 /*
5059 * call-seq:
5060 * ary.repeated_combination(n) { |c| block } -> ary
5061 * ary.repeated_combination(n) -> Enumerator
5062 *
5063 * When invoked with a block, yields all repeated combinations of length +n+ of
5064 * elements from the array and then returns the array itself.
5065 *
5066 * The implementation makes no guarantees about the order in which the repeated
5067 * combinations are yielded.
5068 *
5069 * If no block is given, an Enumerator is returned instead.
5070 *
5071 * Examples:
5072 *
5073 * a = [1, 2, 3]
5074 * a.repeated_combination(1).to_a #=> [[1], [2], [3]]
5075 * a.repeated_combination(2).to_a #=> [[1,1],[1,2],[1,3],[2,2],[2,3],[3,3]]
5076 * a.repeated_combination(3).to_a #=> [[1,1,1],[1,1,2],[1,1,3],[1,2,2],[1,2,3],
5077 * # [1,3,3],[2,2,2],[2,2,3],[2,3,3],[3,3,3]]
5078 * 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],
5079 * # [1,1,3,3],[1,2,2,2],[1,2,2,3],[1,2,3,3],[1,3,3,3],
5080 * # [2,2,2,2],[2,2,2,3],[2,2,3,3],[2,3,3,3],[3,3,3,3]]
5081 * a.repeated_combination(0).to_a #=> [[]] # one combination of length 0
5082 *
5083 */
5084
5085 static VALUE
5086 rb_ary_repeated_combination(VALUE ary, VALUE num)
5087 {
5088 long n, i, len;
5089
5090 n = NUM2LONG(num); /* Combination size from argument */
5091 RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_repeated_combination_size); /* Return enumerator if no block */
5092 len = RARRAY_LEN(ary);
5093 if (n < 0) {
5094 /* yield nothing */
5095 }
5096 else if (n == 0) {
5097 rb_yield(rb_ary_new2(0));
5098 }
5099 else if (n == 1) {
5100 for (i = 0; i < len; i++) {
5101 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
5102 }
5103 }
5104 else if (len == 0) {
5105 /* yield nothing */
5106 }
5107 else {
5108 volatile VALUE t0 = tmpbuf(n, sizeof(long));
5109 long *p = (long*)RSTRING_PTR(t0);
5110 VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
5111 RBASIC_CLEAR_CLASS(ary0);
5112
5113 rcombinate0(len, n, p, 0, n, ary0); /* compute and yield repeated combinations */
5114 tmpbuf_discard(t0);
5115 RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
5116 }
5117 return ary;
5118 }
5119
5120 /*
5121 * call-seq:
5122 * ary.product(other_ary, ...) -> new_ary
5123 * ary.product(other_ary, ...) { |p| block } -> ary
5124 *
5125 * Returns an array of all combinations of elements from all arrays.
5126 *
5127 * The length of the returned array is the product of the length of +self+ and
5128 * the argument arrays.
5129 *
5130 * If given a block, #product will yield all combinations and return +self+
5131 * instead.
5132 *
5133 * [1,2,3].product([4,5]) #=> [[1,4],[1,5],[2,4],[2,5],[3,4],[3,5]]
5134 * [1,2].product([1,2]) #=> [[1,1],[1,2],[2,1],[2,2]]
5135 * [1,2].product([3,4],[5,6]) #=> [[1,3,5],[1,3,6],[1,4,5],[1,4,6],
5136 * # [2,3,5],[2,3,6],[2,4,5],[2,4,6]]
5137 * [1,2].product() #=> [[1],[2]]
5138 * [1,2].product([]) #=> []
5139 */
5140
5141 static VALUE
5142 rb_ary_product(int argc, VALUE *argv, VALUE ary)
5143 {
5144 int n = argc+1; /* How many arrays we're operating on */
5145 volatile VALUE t0 = tmpary(n);
5146 volatile VALUE t1 = tmpbuf(n, sizeof(int));
5147 VALUE *arrays = RARRAY_PTR(t0); /* The arrays we're computing the product of */
5148 int *counters = (int*)RSTRING_PTR(t1); /* The current position in each one */
5149 VALUE result = Qnil; /* The array we'll be returning, when no block given */
5150 long i,j;
5151 long resultlen = 1;
5152
5153 RBASIC_CLEAR_CLASS(t0);
5154 RBASIC_CLEAR_CLASS(t1);
5155
5156 /* initialize the arrays of arrays */
5157 ARY_SET_LEN(t0, n);
5158 arrays[0] = ary;
5159 for (i = 1; i < n; i++) arrays[i] = Qnil;
5160 for (i = 1; i < n; i++) arrays[i] = to_ary(argv[i-1]);
5161
5162 /* initialize the counters for the arrays */
5163 for (i = 0; i < n; i++) counters[i] = 0;
5164
5165 /* Otherwise, allocate and fill in an array of results */
5166 if (rb_block_given_p()) {
5167 /* Make defensive copies of arrays; exit if any is empty */
5168 for (i = 0; i < n; i++) {
5169 if (RARRAY_LEN(arrays[i]) == 0) goto done;
5170 arrays[i] = ary_make_shared_copy(arrays[i]);
5171 }
5172 }
5173 else {
5174 /* Compute the length of the result array; return [] if any is empty */
5175 for (i = 0; i < n; i++) {
5176 long k = RARRAY_LEN(arrays[i]);
5177 if (k == 0) {
5178 result = rb_ary_new2(0);
5179 goto done;
5180 }
5181 if (MUL_OVERFLOW_LONG_P(resultlen, k))
5182 rb_raise(rb_eRangeError, "too big to product");
5183 resultlen *= k;
5184 }
5185 result = rb_ary_new2(resultlen);
5186 }
5187 for (;;) {
5188 int m;
5189 /* fill in one subarray */
5190 VALUE subarray = rb_ary_new2(n);
5191 for (j = 0; j < n; j++) {
5192 rb_ary_push(subarray, rb_ary_entry(arrays[j], counters[j]));
5193 }
5194
5195 /* put it on the result array */
5196 if (NIL_P(result)) {
5197 FL_SET(t0, FL_USER5);
5198 rb_yield(subarray);
5199 if (! FL_TEST(t0, FL_USER5)) {
5200 rb_raise(rb_eRuntimeError, "product reentered");
5201 }
5202 else {
5203 FL_UNSET(t0, FL_USER5);
5204 }
5205 }
5206 else {
5207 rb_ary_push(result, subarray);
5208 }
5209
5210 /*
5211 * Increment the last counter. If it overflows, reset to 0
5212 * and increment the one before it.
5213 */
5214 m = n-1;
5215 counters[m]++;
5216 while (counters[m] == RARRAY_LEN(arrays[m])) {
5217 counters[m] = 0;
5218 /* If the first counter overflows, we are done */
5219 if (--m < 0) goto done;
5220 counters[m]++;
5221 }
5222 }
5223 done:
5224 tmpary_discard(t0);
5225 tmpbuf_discard(t1);
5226
5227 return NIL_P(result) ? ary : result;
5228 }
5229
5230 /*
5231 * call-seq:
5232 * ary.take(n) -> new_ary
5233 *
5234 * Returns first +n+ elements from the array.
5235 *
5236 * If a negative number is given, raises an ArgumentError.
5237 *
5238 * See also Array#drop
5239 *
5240 * a = [1, 2, 3, 4, 5, 0]
5241 * a.take(3) #=> [1, 2, 3]
5242 *
5243 */
5244
5245 static VALUE
5246 rb_ary_take(VALUE obj, VALUE n)
5247 {
5248 long len = NUM2LONG(n);
5249 if (len < 0) {
5250 rb_raise(rb_eArgError, "attempt to take negative size");
5251 }
5252 return rb_ary_subseq(obj, 0, len);
5253 }
5254
5255 /*
5256 * call-seq:
5257 * ary.take_while { |arr| block } -> new_ary
5258 * ary.take_while -> Enumerator
5259 *
5260 * Passes elements to the block until the block returns +nil+ or +false+, then
5261 * stops iterating and returns an array of all prior elements.
5262 *
5263 * If no block is given, an Enumerator is returned instead.
5264 *
5265 * See also Array#drop_while
5266 *
5267 * a = [1, 2, 3, 4, 5, 0]
5268 * a.take_while { |i| i < 3 } #=> [1, 2]
5269 *
5270 */
5271
5272 static VALUE
5273 rb_ary_take_while(VALUE ary)
5274 {
5275 long i;
5276
5277 RETURN_ENUMERATOR(ary, 0, 0);
5278 for (i = 0; i < RARRAY_LEN(ary); i++) {
5279 if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) break;
5280 }
5281 return rb_ary_take(ary, LONG2FIX(i));
5282 }
5283
5284 /*
5285 * call-seq:
5286 * ary.drop(n) -> new_ary
5287 *
5288 * Drops first +n+ elements from +ary+ and returns the rest of the elements in
5289 * an array.
5290 *
5291 * If a negative number is given, raises an ArgumentError.
5292 *
5293 * See also Array#take
5294 *
5295 * a = [1, 2, 3, 4, 5, 0]
5296 * a.drop(3) #=> [4, 5, 0]
5297 *
5298 */
5299
5300 static VALUE
5301 rb_ary_drop(VALUE ary, VALUE n)
5302 {
5303 VALUE result;
5304 long pos = NUM2LONG(n);
5305 if (pos < 0) {
5306 rb_raise(rb_eArgError, "attempt to drop negative size");
5307 }
5308
5309 result = rb_ary_subseq(ary, pos, RARRAY_LEN(ary));
5310 if (result == Qnil) result = rb_ary_new();
5311 return result;
5312 }
5313
5314 /*
5315 * call-seq:
5316 * ary.drop_while { |arr| block } -> new_ary
5317 * ary.drop_while -> Enumerator
5318 *
5319 * Drops elements up to, but not including, the first element for which the
5320 * block returns +nil+ or +false+ and returns an array containing the
5321 * remaining elements.
5322 *
5323 * If no block is given, an Enumerator is returned instead.
5324 *
5325 * See also Array#take_while
5326 *
5327 * a = [1, 2, 3, 4, 5, 0]
5328 * a.drop_while {|i| i < 3 } #=> [3, 4, 5, 0]
5329 *
5330 */
5331
5332 static VALUE
5333 rb_ary_drop_while(VALUE ary)
5334 {
5335 long i;
5336
5337 RETURN_ENUMERATOR(ary, 0, 0);
5338 for (i = 0; i < RARRAY_LEN(ary); i++) {
5339 if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) break;
5340 }
5341 return rb_ary_drop(ary, LONG2FIX(i));
5342 }
5343
5344 /*
5345 * Arrays are ordered, integer-indexed collections of any object.
5346 *
5347 * Array indexing starts at 0, as in C or Java. A negative index is assumed
5348 * to be relative to the end of the array---that is, an index of -1 indicates
5349 * the last element of the array, -2 is the next to last element in the
5350 * array, and so on.
5351 *
5352 * == Creating Arrays
5353 *
5354 * A new array can be created by using the literal constructor
5355 * <code>[]</code>. Arrays can contain different types of objects. For
5356 * example, the array below contains an Integer, a String and a Float:
5357 *
5358 * ary = [1, "two", 3.0] #=> [1, "two", 3.0]
5359 *
5360 * An array can also be created by explicitly calling Array.new with zero, one
5361 * (the initial size of the Array) or two arguments (the initial size and a
5362 * default object).
5363 *
5364 * ary = Array.new #=> []
5365 * Array.new(3) #=> [nil, nil, nil]
5366 * Array.new(3, true) #=> [true, true, true]
5367 *
5368 * Note that the second argument populates the array with references to the
5369 * same object. Therefore, it is only recommended in cases when you need to
5370 * instantiate arrays with natively immutable objects such as Symbols,
5371 * numbers, true or false.
5372 *
5373 * To create an array with separate objects a block can be passed instead.
5374 * This method is safe to use with mutable objects such as hashes, strings or
5375 * other arrays:
5376 *
5377 * Array.new(4) { Hash.new } #=> [{}, {}, {}, {}]
5378 *
5379 * This is also a quick way to build up multi-dimensional arrays:
5380 *
5381 * empty_table = Array.new(3) { Array.new(3) }
5382 * #=> [[nil, nil, nil], [nil, nil, nil], [nil, nil, nil]]
5383 *
5384 * An array can also be created by using the Array() method, provided by
5385 * Kernel, which tries to call #to_ary, then #to_a on its argument.
5386 *
5387 * Array({:a => "a", :b => "b"}) #=> [[:a, "a"], [:b, "b"]]
5388 *
5389 * == Example Usage
5390 *
5391 * In addition to the methods it mixes in through the Enumerable module, the
5392 * Array class has proprietary methods for accessing, searching and otherwise
5393 * manipulating arrays.
5394 *
5395 * Some of the more common ones are illustrated below.
5396 *
5397 * == Accessing Elements
5398 *
5399 * Elements in an array can be retrieved using the Array#[] method. It can
5400 * take a single integer argument (a numeric index), a pair of arguments
5401 * (start and length) or a range. Negative indices start counting from the end,
5402 * with -1 being the last element.
5403 *
5404 * arr = [1, 2, 3, 4, 5, 6]
5405 * arr[2] #=> 3
5406 * arr[100] #=> nil
5407 * arr[-3] #=> 4
5408 * arr[2, 3] #=> [3, 4, 5]
5409 * arr[1..4] #=> [2, 3, 4, 5]
5410 * arr[1..-3] #=> [2, 3, 4]
5411 *
5412 * Another way to access a particular array element is by using the #at method
5413 *
5414 * arr.at(0) #=> 1
5415 *
5416 * The #slice method works in an identical manner to Array#[].
5417 *
5418 * To raise an error for indices outside of the array bounds or else to
5419 * provide a default value when that happens, you can use #fetch.
5420 *
5421 * arr = ['a', 'b', 'c', 'd', 'e', 'f']
5422 * arr.fetch(100) #=> IndexError: index 100 outside of array bounds: -6...6
5423 * arr.fetch(100, "oops") #=> "oops"
5424 *
5425 * The special methods #first and #last will return the first and last
5426 * elements of an array, respectively.
5427 *
5428 * arr.first #=> 1
5429 * arr.last #=> 6
5430 *
5431 * To return the first +n+ elements of an array, use #take
5432 *
5433 * arr.take(3) #=> [1, 2, 3]
5434 *
5435 * #drop does the opposite of #take, by returning the elements after +n+
5436 * elements have been dropped:
5437 *
5438 * arr.drop(3) #=> [4, 5, 6]
5439 *
5440 * == Obtaining Information about an Array
5441 *
5442 * Arrays keep track of their own length at all times. To query an array
5443 * about the number of elements it contains, use #length, #count or #size.
5444 *
5445 * browsers = ['Chrome', 'Firefox', 'Safari', 'Opera', 'IE']
5446 * browsers.length #=> 5
5447 * browsers.count #=> 5
5448 *
5449 * To check whether an array contains any elements at all
5450 *
5451 * browsers.empty? #=> false
5452 *
5453 * To check whether a particular item is included in the array
5454 *
5455 * browsers.include?('Konqueror') #=> false
5456 *
5457 * == Adding Items to Arrays
5458 *
5459 * Items can be added to the end of an array by using either #push or #<<
5460 *
5461 * arr = [1, 2, 3, 4]
5462 * arr.push(5) #=> [1, 2, 3, 4, 5]
5463 * arr << 6 #=> [1, 2, 3, 4, 5, 6]
5464 *
5465 * #unshift will add a new item to the beginning of an array.
5466 *
5467 * arr.unshift(0) #=> [0, 1, 2, 3, 4, 5, 6]
5468 *
5469 * With #insert you can add a new element to an array at any position.
5470 *
5471 * arr.insert(3, 'apple') #=> [0, 1, 2, 'apple', 3, 4, 5, 6]
5472 *
5473 * Using the #insert method, you can also insert multiple values at once:
5474 *
5475 * arr.insert(3, 'orange', 'pear', 'grapefruit')
5476 * #=> [0, 1, 2, "orange", "pear", "grapefruit", "apple", 3, 4, 5, 6]
5477 *
5478 * == Removing Items from an Array
5479 *
5480 * The method #pop removes the last element in an array and returns it:
5481 *
5482 * arr = [1, 2, 3, 4, 5, 6]
5483 * arr.pop #=> 6
5484 * arr #=> [1, 2, 3, 4, 5]
5485 *
5486 * To retrieve and at the same time remove the first item, use #shift:
5487 *
5488 * arr.shift #=> 1
5489 * arr #=> [2, 3, 4, 5]
5490 *
5491 * To delete an element at a particular index:
5492 *
5493 * arr.delete_at(2) #=> 4
5494 * arr #=> [2, 3, 5]
5495 *
5496 * To delete a particular element anywhere in an array, use #delete:
5497 *
5498 * arr = [1, 2, 2, 3]
5499 * arr.delete(2) #=> 2
5500 * arr #=> [1,3]
5501 *
5502 * A useful method if you need to remove +nil+ values from an array is
5503 * #compact:
5504 *
5505 * arr = ['foo', 0, nil, 'bar', 7, 'baz', nil]
5506 * arr.compact #=> ['foo', 0, 'bar', 7, 'baz']
5507 * arr #=> ['foo', 0, nil, 'bar', 7, 'baz', nil]
5508 * arr.compact! #=> ['foo', 0, 'bar', 7, 'baz']
5509 * arr #=> ['foo', 0, 'bar', 7, 'baz']
5510 *
5511 * Another common need is to remove duplicate elements from an array.
5512 *
5513 * It has the non-destructive #uniq, and destructive method #uniq!
5514 *
5515 * arr = [2, 5, 6, 556, 6, 6, 8, 9, 0, 123, 556]
5516 * arr.uniq #=> [2, 5, 6, 556, 8, 9, 0, 123]
5517 *
5518 * == Iterating over Arrays
5519 *
5520 * Like all classes that include the Enumerable module, Array has an each
5521 * method, which defines what elements should be iterated over and how. In
5522 * case of Array's #each, all elements in the Array instance are yielded to
5523 * the supplied block in sequence.
5524 *
5525 * Note that this operation leaves the array unchanged.
5526 *
5527 * arr = [1, 2, 3, 4, 5]
5528 * arr.each { |a| print a -= 10, " " }
5529 * # prints: -9 -8 -7 -6 -5
5530 * #=> [1, 2, 3, 4, 5]
5531 *
5532 * Another sometimes useful iterator is #reverse_each which will iterate over
5533 * the elements in the array in reverse order.
5534 *
5535 * words = %w[first second third fourth fifth sixth]
5536 * str = ""
5537 * words.reverse_each { |word| str += "#{word} " }
5538 * p str #=> "sixth fifth fourth third second first "
5539 *
5540 * The #map method can be used to create a new array based on the original
5541 * array, but with the values modified by the supplied block:
5542 *
5543 * arr.map { |a| 2*a } #=> [2, 4, 6, 8, 10]
5544 * arr #=> [1, 2, 3, 4, 5]
5545 * arr.map! { |a| a**2 } #=> [1, 4, 9, 16, 25]
5546 * arr #=> [1, 4, 9, 16, 25]
5547 *
5548 * == Selecting Items from an Array
5549 *
5550 * Elements can be selected from an array according to criteria defined in a
5551 * block. The selection can happen in a destructive or a non-destructive
5552 * manner. While the destructive operations will modify the array they were
5553 * called on, the non-destructive methods usually return a new array with the
5554 * selected elements, but leave the original array unchanged.
5555 *
5556 * === Non-destructive Selection
5557 *
5558 * arr = [1, 2, 3, 4, 5, 6]
5559 * arr.select { |a| a > 3 } #=> [4, 5, 6]
5560 * arr.reject { |a| a < 3 } #=> [3, 4, 5, 6]
5561 * arr.drop_while { |a| a < 4 } #=> [4, 5, 6]
5562 * arr #=> [1, 2, 3, 4, 5, 6]
5563 *
5564 * === Destructive Selection
5565 *
5566 * #select! and #reject! are the corresponding destructive methods to #select
5567 * and #reject
5568 *
5569 * Similar to #select vs. #reject, #delete_if and #keep_if have the exact
5570 * opposite result when supplied with the same block:
5571 *
5572 * arr.delete_if { |a| a < 4 } #=> [4, 5, 6]
5573 * arr #=> [4, 5, 6]
5574 *
5575 * arr = [1, 2, 3, 4, 5, 6]
5576 * arr.keep_if { |a| a < 4 } #=> [1, 2, 3]
5577 * arr #=> [1, 2, 3]
5578 *
5579 */
5580
5581 void
5582 Init_Array(void)
5583 {
5584 #undef rb_intern
5585 #define rb_intern(str) rb_intern_const(str)
5586
5587 rb_cArray = rb_define_class("Array", rb_cObject);
5588 rb_include_module(rb_cArray, rb_mEnumerable);
5589
5590 rb_define_alloc_func(rb_cArray, empty_ary_alloc);
5591 rb_define_singleton_method(rb_cArray, "[]", rb_ary_s_create, -1);
5592 rb_define_singleton_method(rb_cArray, "try_convert", rb_ary_s_try_convert, 1);
5593 rb_define_method(rb_cArray, "initialize", rb_ary_initialize, -1);
5594 rb_define_method(rb_cArray, "initialize_copy", rb_ary_replace, 1);
5595
5596 rb_define_method(rb_cArray, "inspect", rb_ary_inspect, 0);
5597 rb_define_alias(rb_cArray, "to_s", "inspect");
5598 rb_define_method(rb_cArray, "to_a", rb_ary_to_a, 0);
5599 rb_define_method(rb_cArray, "to_h", rb_ary_to_h, 0);
5600 rb_define_method(rb_cArray, "to_ary", rb_ary_to_ary_m, 0);
5601 rb_define_method(rb_cArray, "frozen?", rb_ary_frozen_p, 0);
5602
5603 rb_define_method(rb_cArray, "==", rb_ary_equal, 1);
5604 rb_define_method(rb_cArray, "eql?", rb_ary_eql, 1);
5605 rb_define_method(rb_cArray, "hash", rb_ary_hash, 0);
5606
5607 rb_define_method(rb_cArray, "[]", rb_ary_aref, -1);
5608 rb_define_method(rb_cArray, "[]=", rb_ary_aset, -1);
5609 rb_define_method(rb_cArray, "at", rb_ary_at, 1);
5610 rb_define_method(rb_cArray, "fetch", rb_ary_fetch, -1);
5611 rb_define_method(rb_cArray, "first", rb_ary_first, -1);
5612 rb_define_method(rb_cArray, "last", rb_ary_last, -1);
5613 rb_define_method(rb_cArray, "concat", rb_ary_concat, 1);
5614 rb_define_method(rb_cArray, "<<", rb_ary_push, 1);
5615 rb_define_method(rb_cArray, "push", rb_ary_push_m, -1);
5616 rb_define_method(rb_cArray, "pop", rb_ary_pop_m, -1);
5617 rb_define_method(rb_cArray, "shift", rb_ary_shift_m, -1);
5618 rb_define_method(rb_cArray, "unshift", rb_ary_unshift_m, -1);
5619 rb_define_method(rb_cArray, "insert", rb_ary_insert, -1);
5620 rb_define_method(rb_cArray, "each", rb_ary_each, 0);
5621 rb_define_method(rb_cArray, "each_index", rb_ary_each_index, 0);
5622 rb_define_method(rb_cArray, "reverse_each", rb_ary_reverse_each, 0);
5623 rb_define_method(rb_cArray, "length", rb_ary_length, 0);
5624 rb_define_alias(rb_cArray, "size", "length");
5625 rb_define_method(rb_cArray, "empty?", rb_ary_empty_p, 0);
5626 rb_define_method(rb_cArray, "find_index", rb_ary_index, -1);
5627 rb_define_method(rb_cArray, "index", rb_ary_index, -1);
5628 rb_define_method(rb_cArray, "rindex", rb_ary_rindex, -1);
5629 rb_define_method(rb_cArray, "join", rb_ary_join_m, -1);
5630 rb_define_method(rb_cArray, "reverse", rb_ary_reverse_m, 0);
5631 rb_define_method(rb_cArray, "reverse!", rb_ary_reverse_bang, 0);
5632 rb_define_method(rb_cArray, "rotate", rb_ary_rotate_m, -1);
5633 rb_define_method(rb_cArray, "rotate!", rb_ary_rotate_bang, -1);
5634 rb_define_method(rb_cArray, "sort", rb_ary_sort, 0);
5635 rb_define_method(rb_cArray, "sort!", rb_ary_sort_bang, 0);
5636 rb_define_method(rb_cArray, "sort_by!", rb_ary_sort_by_bang, 0);
5637 rb_define_method(rb_cArray, "collect", rb_ary_collect, 0);
5638 rb_define_method(rb_cArray, "collect!", rb_ary_collect_bang, 0);
5639 rb_define_method(rb_cArray, "map", rb_ary_collect, 0);
5640 rb_define_method(rb_cArray, "map!", rb_ary_collect_bang, 0);
5641 rb_define_method(rb_cArray, "select", rb_ary_select, 0);
5642 rb_define_method(rb_cArray, "select!", rb_ary_select_bang, 0);
5643 rb_define_method(rb_cArray, "keep_if", rb_ary_keep_if, 0);
5644 rb_define_method(rb_cArray, "values_at", rb_ary_values_at, -1);
5645 rb_define_method(rb_cArray, "delete", rb_ary_delete, 1);
5646 rb_define_method(rb_cArray, "delete_at", rb_ary_delete_at_m, 1);
5647 rb_define_method(rb_cArray, "delete_if", rb_ary_delete_if, 0);
5648 rb_define_method(rb_cArray, "reject", rb_ary_reject, 0);
5649 rb_define_method(rb_cArray, "reject!", rb_ary_reject_bang, 0);
5650 rb_define_method(rb_cArray, "zip", rb_ary_zip, -1);
5651 rb_define_method(rb_cArray, "transpose", rb_ary_transpose, 0);
5652 rb_define_method(rb_cArray, "replace", rb_ary_replace, 1);
5653 rb_define_method(rb_cArray, "clear", rb_ary_clear, 0);
5654 rb_define_method(rb_cArray, "fill", rb_ary_fill, -1);
5655 rb_define_method(rb_cArray, "include?", rb_ary_includes, 1);
5656 rb_define_method(rb_cArray, "<=>", rb_ary_cmp, 1);
5657
5658 rb_define_method(rb_cArray, "slice", rb_ary_aref, -1);
5659 rb_define_method(rb_cArray, "slice!", rb_ary_slice_bang, -1);
5660
5661 rb_define_method(rb_cArray, "assoc", rb_ary_assoc, 1);
5662 rb_define_method(rb_cArray, "rassoc", rb_ary_rassoc, 1);
5663
5664 rb_define_method(rb_cArray, "+", rb_ary_plus, 1);
5665 rb_define_method(rb_cArray, "*", rb_ary_times, 1);
5666
5667 rb_define_method(rb_cArray, "-", rb_ary_diff, 1);
5668 rb_define_method(rb_cArray, "&", rb_ary_and, 1);
5669 rb_define_method(rb_cArray, "|", rb_ary_or, 1);
5670
5671 rb_define_method(rb_cArray, "uniq", rb_ary_uniq, 0);
5672 rb_define_method(rb_cArray, "uniq!", rb_ary_uniq_bang, 0);
5673 rb_define_method(rb_cArray, "compact", rb_ary_compact, 0);
5674 rb_define_method(rb_cArray, "compact!", rb_ary_compact_bang, 0);
5675 rb_define_method(rb_cArray, "flatten", rb_ary_flatten, -1);
5676 rb_define_method(rb_cArray, "flatten!", rb_ary_flatten_bang, -1);
5677 rb_define_method(rb_cArray, "count", rb_ary_count, -1);
5678 rb_define_method(rb_cArray, "shuffle!", rb_ary_shuffle_bang, -1);
5679 rb_define_method(rb_cArray, "shuffle", rb_ary_shuffle, -1);
5680 rb_define_method(rb_cArray, "sample", rb_ary_sample, -1);
5681 rb_define_method(rb_cArray, "cycle", rb_ary_cycle, -1);
5682 rb_define_method(rb_cArray, "permutation", rb_ary_permutation, -1);
5683 rb_define_method(rb_cArray, "combination", rb_ary_combination, 1);
5684 rb_define_method(rb_cArray, "repeated_permutation", rb_ary_repeated_permutation, 1);
5685 rb_define_method(rb_cArray, "repeated_combination", rb_ary_repeated_combination, 1);
5686 rb_define_method(rb_cArray, "product", rb_ary_product, -1);
5687
5688 rb_define_method(rb_cArray, "take", rb_ary_take, 1);
5689 rb_define_method(rb_cArray, "take_while", rb_ary_take_while, 0);
5690 rb_define_method(rb_cArray, "drop", rb_ary_drop, 1);
5691 rb_define_method(rb_cArray, "drop_while", rb_ary_drop_while, 0);
5692 rb_define_method(rb_cArray, "bsearch", rb_ary_bsearch, 0);
5693
5694 id_cmp = rb_intern("<=>");
5695 id_random = rb_intern("random");
5696 id_div = rb_intern("div");
5697 id_power = rb_intern("**");
5698 }
rb_ary_transpose
static VALUE rb_ary_transpose(VALUE ary)
Definition: array.c:3290
RBASIC_CLEAR_CLASS
#define RBASIC_CLEAR_CLASS(obj)
Definition: internal.h:607
id_cmp
static ID id_cmp
Definition: array.c:29
take_i
static VALUE take_i(RB_BLOCK_CALL_FUNC_ARGLIST(val, cbarg))
Definition: array.c:3173
ary_reverse
static void ary_reverse(VALUE *p1, VALUE *p2)
Definition: array.c:2166
rb_builtin_class_name
const char * rb_builtin_class_name(VALUE x)
Definition: error.c:451
rb_hash
VALUE rb_hash(VALUE obj)
Definition: hash.c:106
RUBY_DTRACE_ARRAY_CREATE
#define RUBY_DTRACE_ARRAY_CREATE(arg0, arg1, arg2)
Definition: probes.h:43
recursive_cmp
static VALUE recursive_cmp(VALUE ary1, VALUE ary2, int recur)
Definition: array.c:3832
rb_ary_unshift
VALUE rb_ary_unshift(VALUE ary, VALUE item)
Definition: array.c:1153
ary_ensure_room_for_push
static void ary_ensure_room_for_push(VALUE ary, long add_len)
Definition: array.c:355
ary_join_1
static void ary_join_1(VALUE obj, VALUE ary, VALUE sep, long i, VALUE result, int *first)
Definition: array.c:1942
zero
static double zero(void)
Definition: isinf.c:51
ary_reject
static VALUE ary_reject(VALUE orig, VALUE result)
Definition: array.c:3066
rb_ary_pop
VALUE rb_ary_pop(VALUE ary)
Definition: array.c:940
rb_ary_entry
VALUE rb_ary_entry(VALUE ary, long offset)
Definition: array.c:1171
ary_take_pos_flags
ary_take_pos_flags
Definition: array.c:853
RARRAY_LEN
#define RARRAY_LEN(a)
Definition: ruby.h:878
rb_bug
void rb_bug(const char *fmt,...)
Definition: error.c:327
rb_ary_new_capa
VALUE rb_ary_new_capa(long capa)
Definition: array.c:489
rb_ary_keep_if
static VALUE rb_ary_keep_if(VALUE ary)
Definition: array.c:2857
FALSE
#define FALSE
Definition: nkf.h:174
rb_enc_copy
void rb_enc_copy(VALUE obj1, VALUE obj2)
Definition: encoding.c:916
ARY_HEAP_SIZE
#define ARY_HEAP_SIZE(a)
Definition: array.c:112
rb_ary_freeze
VALUE rb_ary_freeze(VALUE ary)
Definition: array.c:397
rb_ary_times
static VALUE rb_ary_times(VALUE ary, VALUE times)
Definition: array.c:3571
st_table
Definition: st.h:69
ST_STOP
Definition: st.h:100
rb_ary_drop_while
static VALUE rb_ary_drop_while(VALUE ary)
Definition: array.c:5333
rb_ary_s_create
static VALUE rb_ary_s_create(int argc, VALUE *argv, VALUE klass)
Definition: array.c:778
rb_ary_at
static VALUE rb_ary_at(VALUE ary, VALUE pos)
Definition: array.c:1281
ARY_SET_EMBED_LEN
#define ARY_SET_EMBED_LEN(ary, n)
Definition: array.c:131
rb_yield_values
VALUE rb_yield_values(int n,...)
Definition: vm_eval.c:953
NUM2INT
#define NUM2INT(x)
Definition: ruby.h:630
rb_ary_splice
static void rb_ary_splice(VALUE ary, long beg, long len, VALUE rpl)
Definition: array.c:1531
rb_check_block_call
VALUE rb_check_block_call(VALUE, ID, int, const VALUE *, rb_block_call_func_t, VALUE)
RB_OBJ_WRITTEN
#define RB_OBJ_WRITTEN(a, oldv, b)
Definition: ruby.h:1214
max
static int max(int a, int b)
Definition: strftime.c:141
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:1655
ARY_MAX_SIZE
#define ARY_MAX_SIZE
Definition: array.c:32
ruby.h
rb_ary_combination
static VALUE rb_ary_combination(VALUE ary, VALUE num)
Definition: array.c:4884
rb_ary_sort
VALUE rb_ary_sort(VALUE ary)
Definition: array.c:2507
rb_usascii_str_new2
#define rb_usascii_str_new2
Definition: intern.h:846
rb_ary_subseq
VALUE rb_ary_subseq(VALUE ary, long beg, long len)
Definition: array.c:1180
rb_ary_sample
static VALUE rb_ary_sample(int argc, VALUE *argv, VALUE ary)
Definition: array.c:4518
FL_SET_EMBED
#define FL_SET_EMBED(a)
Definition: array.c:115
rb_ary_compact
static VALUE rb_ary_compact(VALUE ary)
Definition: array.c:4224
ary_mem_clear
static void ary_mem_clear(VALUE ary, long beg, long size)
Definition: array.c:43
rb_ary_delete_at
VALUE rb_ary_delete_at(VALUE ary, long pos)
Definition: array.c:2951
rb_get_kwargs
int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *values)
Definition: class.c:1918
Qtrue
#define Qtrue
Definition: ruby.h:426
st_insert
int st_insert(st_table *, st_data_t, st_data_t)
rb_hash_end
st_index_t rb_hash_end(st_index_t)
take_items
static VALUE take_items(VALUE obj, long n)
Definition: array.c:3183
rb_ary_shift
VALUE rb_ary_shift(VALUE ary)
Definition: array.c:991
rb_ary_reverse_each
static VALUE rb_ary_reverse_each(VALUE ary)
Definition: array.c:1836
FL_UNSET_SHARED
#define FL_UNSET_SHARED(ary)
Definition: array.c:124
probes.h
ST_CONTINUE
Definition: st.h:100
rb_ary_each
VALUE rb_ary_each(VALUE array)
Definition: array.c:1778
id
const int id
Definition: nkf.c:209
rb_cRandom
RUBY_EXTERN VALUE rb_cRandom
Definition: ruby.h:1577
rb_ary_frozen_p
static VALUE rb_ary_frozen_p(VALUE ary)
Definition: array.c:411
RAND_UPTO
#define RAND_UPTO(max)
Definition: array.c:4422
ary_memfill
static void ary_memfill(VALUE ary, long beg, long size, VALUE val)
Definition: array.c:59
rb_eTypeError
VALUE rb_eTypeError
Definition: error.c:548
rb_ary_last
VALUE rb_ary_last(int argc, VALUE *argv, VALUE ary)
Definition: array.c:1329
rb_ary_reverse_m
static VALUE rb_ary_reverse_m(VALUE ary)
Definition: array.c:2219
ARY_SET_CAPA
#define ARY_SET_CAPA(ary, n)
Definition: array.c:168
rb_mem_clear
void rb_mem_clear(register VALUE *mem, register long size)
Definition: array.c:35
permute0
static void permute0(long n, long r, long *p, long index, char *used, VALUE values)
Definition: array.c:4721
rb_check_arity
#define rb_check_arity
Definition: intern.h:296
rb_ary_push
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:896
SIZED_REALLOC_N
#define SIZED_REALLOC_N(var, type, n, old_n)
Definition: internal.h:471
rb_str_buf_new2
VALUE rb_str_buf_new2(const char *)
ary_make_partial
static VALUE ary_make_partial(VALUE ary, VALUE klass, long offset, long len)
Definition: array.c:820
st_free_table
void st_free_table(st_table *)
Definition: st.c:334
ARY_OWNS_HEAP_P
#define ARY_OWNS_HEAP_P(a)
Definition: array.c:114
rb_ary_rassoc
VALUE rb_ary_rassoc(VALUE ary, VALUE value)
Definition: array.c:3670
rb_hash_tbl_raw
struct st_table * rb_hash_tbl_raw(VALUE hash)
Definition: hash.c:351
rb_ary_tmp_new
VALUE rb_ary_tmp_new(long capa)
Definition: array.c:534
rb_ary_take_while
static VALUE rb_ary_take_while(VALUE ary)
Definition: array.c:5273
OBJ_PROMOTED
#define OBJ_PROMOTED(x)
Definition: ruby.h:1189
rb_ary_shared_with_p
VALUE rb_ary_shared_with_p(VALUE ary1, VALUE ary2)
Definition: array.c:425
ruby_sized_xfree
void ruby_sized_xfree(void *x, size_t size)
Definition: gc.c:6234
RBASIC_SET_CLASS
#define RBASIC_SET_CLASS(obj, cls)
Definition: internal.h:609
ary_ensure_room_for_unshift
static void ary_ensure_room_for_unshift(VALUE ary, int argc)
Definition: array.c:1074
ary_join_0
static void ary_join_0(VALUE ary, VALUE sep, long max, VALUE result)
Definition: array.c:1926
rb_raise
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:1857
rb_ary_unshift_m
static VALUE rb_ary_unshift_m(int argc, VALUE *argv, VALUE ary)
Definition: array.c:1137
rb_ary_reject_bang
static VALUE rb_ary_reject_bang(VALUE ary)
Definition: array.c:3116
rb_enc_associate
VALUE rb_enc_associate(VALUE obj, rb_encoding *enc)
Definition: encoding.c:826
rb_ary_clear
VALUE rb_ary_clear(VALUE ary)
Definition: array.c:3381
FL_SET_SHARED_ROOT
#define FL_SET_SHARED_ROOT(ary)
Definition: array.c:193
MUL_OVERFLOW_LONG_P
#define MUL_OVERFLOW_LONG_P(a, b)
Definition: internal.h:69
rb_convert_type
VALUE rb_convert_type(VALUE, int, const char *, const char *)
Definition: object.c:2616
rb_exec_recursive
VALUE rb_exec_recursive(VALUE(*)(VALUE, VALUE, int), VALUE, VALUE)
Definition: thread.c:4982
RB_GC_GUARD
#define RB_GC_GUARD(v)
Definition: ruby.h:523
rb_define_alloc_func
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
rb_obj_is_kind_of
VALUE rb_obj_is_kind_of(VALUE, VALUE)
Definition: object.c:652
sort_2
static int sort_2(const void *ap, const void *bp, void *dummy)
Definition: array.c:2380
ary_sort_data::opt_inited
int opt_inited
Definition: array.c:2337
rb_include_module
void rb_include_module(VALUE klass, VALUE module)
Definition: class.c:827
ARY_SHARED_ROOT_P
#define ARY_SHARED_ROOT_P(ary)
Definition: array.c:185
rb_block_call
VALUE rb_block_call(VALUE, ID, int, const VALUE *, rb_block_call_func_t, VALUE)
ARY_SHARED_NUM
#define ARY_SHARED_NUM(ary)
Definition: array.c:186
T_ARRAY
#define T_ARRAY
Definition: ruby.h:484
st_index_t
st_data_t st_index_t
Definition: st.h:48
rb_range_beg_len
VALUE rb_range_beg_len(VALUE, long *, long *, long, int)
Definition: range.c:1005
st_update
int st_update(st_table *table, st_data_t key, st_update_callback_func *func, st_data_t arg)
Definition: st.c:867
rb_str_cmp
int rb_str_cmp(VALUE, VALUE)
Definition: string.c:2486
rb_ary_slice_bang
static VALUE rb_ary_slice_bang(int argc, VALUE *argv, VALUE ary)
Definition: array.c:3015
rb_ary_reject
static VALUE rb_ary_reject(VALUE ary)
Definition: array.c:3136
rb_ary_rotate
VALUE rb_ary_rotate(VALUE ary, long cnt)
Definition: array.c:2240
last
unsigned int last
Definition: nkf.c:4310
FIXNUM_P
#define FIXNUM_P(f)
Definition: ruby.h:347
ARY_SHARED_P
#define ARY_SHARED_P(ary)
Definition: array.c:98
rb_ary_each_index
static VALUE rb_ary_each_index(VALUE ary)
Definition: array.c:1809
rb_str_buf_append
VALUE rb_str_buf_append(VALUE, VALUE)
Definition: string.c:2282
rb_cmpint
int rb_cmpint(VALUE val, VALUE a, VALUE b)
Definition: bignum.c:2909
rb_ary_fetch
static VALUE rb_ary_fetch(int argc, VALUE *argv, VALUE ary)
Definition: array.c:1365
rb_ary_reverse_bang
static VALUE rb_ary_reverse_bang(VALUE ary)
Definition: array.c:2203
ary_hash_orset
static int ary_hash_orset(st_data_t *key, st_data_t *value, st_data_t arg, int existing)
Definition: array.c:4034
OBJ_TAINTED
#define OBJ_TAINTED(x)
Definition: ruby.h:1176
rb_eRangeError
VALUE rb_eRangeError
Definition: error.c:552
rb_obj_classname
const char * rb_obj_classname(VALUE)
Definition: variable.c:406
rb_equal_opt
VALUE rb_equal_opt(VALUE obj1, VALUE obj2)
Definition: vm_insnhelper.c:901
rb_ary_delete_at_m
static VALUE rb_ary_delete_at_m(VALUE ary, VALUE pos)
Definition: array.c:2988
rb_gc_force_recycle
void rb_gc_force_recycle(VALUE p)
Definition: gc.c:4897
rb_class_of
static VALUE rb_class_of(VALUE obj)
Definition: ruby.h:1630
rb_ary_new2
#define rb_ary_new2
Definition: intern.h:90
head
#define head
Definition: st.c:107
rb_ary_unshare
static void rb_ary_unshare(VALUE ary)
Definition: array.c:274
memmove
RUBY_EXTERN void * memmove(void *, const void *, size_t)
Definition: memmove.c:7
rb_ary_join_m
static VALUE rb_ary_join_m(int argc, VALUE *argv, VALUE ary)
Definition: array.c:2047
id.h
rb_ary_first
static VALUE rb_ary_first(int argc, VALUE *argv, VALUE ary)
Definition: array.c:1302
st_data_t
RUBY_SYMBOL_EXPORT_BEGIN typedef unsigned long st_data_t
Definition: st.h:20
NEWOBJ_OF
#define NEWOBJ_OF(obj, type, klass, flags)
Definition: ruby.h:694
RB_BLOCK_CALL_FUNC_ARGLIST
#define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)
Definition: ruby.h:1511
rb_ary_count
static VALUE rb_ary_count(int argc, VALUE *argv, VALUE ary)
Definition: array.c:4253
ARY_DEFAULT_SIZE
#define ARY_DEFAULT_SIZE
Definition: array.c:31
rb_ary_sort_by_bang
static VALUE rb_ary_sort_by_bang(VALUE ary)
Definition: array.c:2635
ARY_HEAP_PTR
#define ARY_HEAP_PTR(a)
Definition: array.c:105
OPTHASH_GIVEN_P
#define OPTHASH_GIVEN_P(opts)
Definition: array.c:4418
RBASIC_SET_CLASS_RAW
#define RBASIC_SET_CLASS_RAW(obj, cls)
Definition: internal.h:608
RUBY_DTRACE_ARRAY_CREATE_ENABLED
#define RUBY_DTRACE_ARRAY_CREATE_ENABLED()
Definition: probes.h:42
RB_TYPE_P
#define RB_TYPE_P(obj, type)
Definition: ruby.h:1664
rb_ary_aset
static VALUE rb_ary_aset(int argc, VALUE *argv, VALUE ary)
Definition: array.c:1688
rb_ary_assoc
VALUE rb_ary_assoc(VALUE ary, VALUE key)
Definition: array.c:3637
RHASH
#define RHASH(obj)
Definition: ruby.h:1124
rb_ary_elt
static VALUE rb_ary_elt(VALUE ary, long offset)
Definition: array.c:1160
st_lookup
int st_lookup(st_table *, st_data_t, st_data_t *)
MEMZERO
#define MEMZERO(p, type, n)
Definition: ruby.h:1351
rb_iter_break
void rb_iter_break(void)
Definition: vm.c:1154
FL_TEST
#define FL_TEST(x, f)
Definition: ruby.h:1169
ary_enum_length
static VALUE ary_enum_length(VALUE ary, VALUE args, VALUE eobj)
Definition: array.c:1754
rb_ary_inspect
static VALUE rb_ary_inspect(VALUE ary)
Definition: array.c:2089
rb_ary_compact_bang
static VALUE rb_ary_compact_bang(VALUE ary)
Definition: array.c:4191
rb_ary_select
static VALUE rb_ary_select(VALUE ary)
Definition: array.c:2787
ary_memcpy
static void ary_memcpy(VALUE ary, long beg, long argc, const VALUE *argv)
Definition: array.c:68
tmpbuf_discard
#define tmpbuf_discard(s)
Definition: array.c:4683
rb_ary_free
void rb_ary_free(VALUE ary)
Definition: array.c:540
RARRAY
#define RARRAY(obj)
Definition: ruby.h:1123
ALLOC_N
#define ALLOC_N(type, n)
Definition: ruby.h:1333
rb_block_given_p
int rb_block_given_p(void)
Definition: eval.c:712
rb_hash_aset
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
Definition: hash.c:1393
tmpary
#define tmpary(n)
Definition: array.c:4684
ary_make_shared_copy
static VALUE ary_make_shared_copy(VALUE ary)
Definition: array.c:848
rb_ary_cat
VALUE rb_ary_cat(VALUE ary, const VALUE *ptr, long len)
Definition: array.c:907
val
#define val
rb_cObject
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:1553
rb_ary_or
static VALUE rb_ary_or(VALUE ary1, VALUE ary2)
Definition: array.c:4056
rb_eRuntimeError
VALUE rb_eRuntimeError
Definition: error.c:547
rb_exec_recursive_paired
VALUE rb_exec_recursive_paired(VALUE(*)(VALUE, VALUE, int), VALUE, VALUE, VALUE)
Definition: thread.c:4993
RGENGC_WB_PROTECTED_ARRAY
#define RGENGC_WB_PROTECTED_ARRAY
Definition: ruby.h:711
ary_alloc
static VALUE ary_alloc(VALUE klass)
Definition: array.c:437
tmpary_discard
#define tmpary_discard(a)
Definition: array.c:4685
rb_ary_replace
VALUE rb_ary_replace(VALUE copy, VALUE orig)
Definition: array.c:3331
rb_obj_as_string
VALUE rb_obj_as_string(VALUE)
Definition: string.c:1011
rb_ary_new
VALUE rb_ary_new(void)
Definition: array.c:495
rb_str_buf_cat2
VALUE rb_str_buf_cat2(VALUE, const char *)
Definition: string.c:2134
rb_ary_zip
static VALUE rb_ary_zip(int argc, VALUE *argv, VALUE ary)
Definition: array.c:3223
RArray
Definition: ruby.h:860
to_ary
static VALUE to_ary(VALUE ary)
Definition: array.c:622
NIL_P
#define NIL_P(v)
Definition: ruby.h:438
rb_ary_to_s
VALUE rb_ary_to_s(VALUE ary)
Definition: array.c:2096
binomial_coefficient
static VALUE binomial_coefficient(long comb, long size)
Definition: array.c:4758
rb_define_class
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:630
FL_SET_SHARED
#define FL_SET_SHARED(ary)
Definition: array.c:120
ary_sort_data
Definition: array.c:2334
st_delete
int st_delete(st_table *, st_data_t *, st_data_t *)
rb_ary_product
static VALUE rb_ary_product(int argc, VALUE *argv, VALUE ary)
Definition: array.c:5142
rb_ary_insert
static VALUE rb_ary_insert(int argc, VALUE *argv, VALUE ary)
Definition: array.c:1732
rb_ary_new_from_args
VALUE rb_ary_new_from_args(long n,...)
Definition: array.c:501
rb_ary_store
void rb_ary_store(VALUE ary, long idx, VALUE val)
Definition: array.c:790
rb_ary_permutation
static VALUE rb_ary_permutation(int argc, VALUE *argv, VALUE ary)
Definition: array.c:4810
ary_resize_smaller
static void ary_resize_smaller(VALUE ary, long len)
Definition: array.c:2865
cnt
rb_atomic_t cnt[RUBY_NSIG]
Definition: signal.c:496
OBJ_FROZEN
#define OBJ_FROZEN(x)
Definition: ruby.h:1185
rb_ary_shuffle_bang
static VALUE rb_ary_shuffle_bang(int argc, VALUE *argv, VALUE ary)
Definition: array.c:4435
argc
int argc
Definition: ruby.c:131
ary_discard
static void ary_discard(VALUE ary)
Definition: array.c:559
rcombinate0
static void rcombinate0(long n, long r, long *p, long index, long rest, VALUE values)
Definition: array.c:5032
Qfalse
#define Qfalse
Definition: ruby.h:425
rb_ary_uniq_bang
static VALUE rb_ary_uniq_bang(VALUE ary)
Definition: array.c:4108
ALLOCV_N
#define ALLOCV_N(type, v, n)
Definition: ruby.h:1348
rb_sourcefile
#define rb_sourcefile()
Definition: tcltklib.c:98
ary_take_first_or_last
static VALUE ary_take_first_or_last(int argc, VALUE *argv, VALUE ary, enum ary_take_pos_flags last)
Definition: array.c:860
ALLOCA_N
#define ALLOCA_N(type, n)
Definition: ruby.h:1337
recursive_join
static VALUE recursive_join(VALUE obj, VALUE argp, int recur)
Definition: array.c:1908
rb_ary_combination_size
static VALUE rb_ary_combination_size(VALUE ary, VALUE args, VALUE eobj)
Definition: array.c:4850
rb_ary_take
static VALUE rb_ary_take(VALUE obj, VALUE n)
Definition: array.c:5246
rb_ary_select_bang
static VALUE rb_ary_select_bang(VALUE ary)
Definition: array.c:2819
RUBY_FUNC_EXPORTED
#define RUBY_FUNC_EXPORTED
Definition: defines.h:246
MEMCPY
#define MEMCPY(p1, p2, type, n)
Definition: ruby.h:1352
rb_ary_new4
#define rb_ary_new4
Definition: intern.h:92
inspect_ary
static VALUE inspect_ary(VALUE ary, VALUE dummy, int recur)
Definition: array.c:2058
OBJ_FREEZE
#define OBJ_FREEZE(x)
Definition: ruby.h:1186
ary_sort_data::ary
VALUE ary
Definition: array.c:2335
ALLOCV_END
#define ALLOCV_END(v)
Definition: ruby.h:1349
rb_eIndexError
VALUE rb_eIndexError
Definition: error.c:550
encoding.h
numberof
#define numberof(array)
Definition: etc.c:595
descending_factorial
static VALUE descending_factorial(long from, long how_many)
Definition: array.c:4747
rb_ary_collect
static VALUE rb_ary_collect(VALUE ary)
Definition: array.c:2669
id_random
static ID id_random
Definition: array.c:4420
rb_ary_hash
static VALUE rb_ary_hash(VALUE ary)
Definition: array.c:3789
id_power
static ID id_power
Definition: array.c:29
rb_ary_to_ary
VALUE rb_ary_to_ary(VALUE obj)
Definition: array.c:1522
rb_define_alias
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
Definition: class.c:1697
RSTRING_LEN
#define RSTRING_LEN(str)
Definition: ruby.h:841
ary_shrink_capa
static void ary_shrink_capa(VALUE ary)
Definition: array.c:233
rb_yield
VALUE rb_yield(VALUE)
Definition: vm_eval.c:942
RARRAY_CONST_PTR
#define RARRAY_CONST_PTR(a)
Definition: ruby.h:886
REALLOC_N
#define REALLOC_N(var, type, n)
Definition: ruby.h:1335
func
SSL_METHOD *(* func)(void)
Definition: ossl_ssl.c:113
util.h
TRUE
#define TRUE
Definition: nkf.h:175
rb_mEnumerable
VALUE rb_mEnumerable
Definition: enum.c:20
rb_eql
int rb_eql(VALUE, VALUE)
Definition: object.c:100
RARRAY_PTR_USE
#define RARRAY_PTR_USE(ary, ptr_name, expr)
Definition: ruby.h:894
ARY_TAKE_FIRST
Definition: array.c:855
rb_ary_rindex
static VALUE rb_ary_rindex(int argc, VALUE *argv, VALUE ary)
Definition: array.c:1481
ary_resize_capa
static void ary_resize_capa(VALUE ary, long capacity)
Definition: array.c:199
rb_ary_modify
void rb_ary_modify(VALUE ary)
Definition: array.c:314
rb_ary_delete
VALUE rb_ary_delete(VALUE ary, VALUE item)
Definition: array.c:2898
MEMMOVE
#define MEMMOVE(p1, p2, type, n)
Definition: ruby.h:1353
rb_hash_values
VALUE rb_hash_values(VALUE hash)
Definition: hash.c:1827
rb_hash_new
VALUE rb_hash_new(void)
Definition: hash.c:298
sort_1
static int sort_1(const void *ap, const void *bp, void *dummy)
Definition: array.c:2366
ruby_xfree
void ruby_xfree(void *x)
Definition: gc.c:6242
FL_USER5
#define FL_USER5
Definition: ruby.h:1149
sort_opt_String
Definition: array.c:2342
rb_scan_args
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1728
rb_ary_to_ary_m
static VALUE rb_ary_to_ary_m(VALUE ary)
Definition: array.c:2160
rb_assoc_new
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Definition: array.c:616
PRIsVALUE
#define PRIsVALUE
Definition: ruby.h:137
internal.h
rb_get_values_at
VALUE rb_get_values_at(VALUE obj, long olen, int argc, VALUE *argv, VALUE(*func)(VALUE, long))
Definition: array.c:2718
ID
unsigned long ID
Definition: ruby.h:89
rb_block_arity
int rb_block_arity(void)
Definition: proc.c:860
RHASH_SIZE
#define RHASH_SIZE(h)
Definition: ruby.h:930
rb_usascii_encoding
rb_encoding * rb_usascii_encoding(void)
Definition: encoding.c:1257
ary_make_hash
static VALUE ary_make_hash(VALUE ary)
Definition: array.c:3917
Qnil
#define Qnil
Definition: ruby.h:427
rb_ary_delete_if
static VALUE rb_ary_delete_if(VALUE ary)
Definition: array.c:3165
rb_ary_repeated_combination_size
static VALUE rb_ary_repeated_combination_size(VALUE ary, VALUE args, VALUE eobj)
Definition: array.c:5048
OBJ_TAINT
#define OBJ_TAINT(x)
Definition: ruby.h:1177
VALUE
unsigned long VALUE
Definition: ruby.h:88
ARY_SET_LEN
#define ARY_SET_LEN(ary, n)
Definition: array.c:142
ruby_qsort
void ruby_qsort(void *, const size_t, const size_t, int(*)(const void *, const void *, void *), void *)
rb_ary_to_h
static VALUE rb_ary_to_h(VALUE ary)
Definition: array.c:2133
result
static VALUE result
Definition: nkf.c:40
ARY_SET_PTR
#define ARY_SET_PTR(ary, p)
Definition: array.c:126
FL_UNSET_EMBED
#define FL_UNSET_EMBED(ary)
Definition: array.c:119
RETURN_SIZED_ENUMERATOR
#define RETURN_SIZED_ENUMERATOR(obj, argc, argv, size_fn)
Definition: intern.h:237
RBASIC
#define RBASIC(obj)
Definition: ruby.h:1116
RARRAY_EMBED_FLAG
#define RARRAY_EMBED_FLAG
Definition: ruby.h:874
ary_sort_data::opt_methods
int opt_methods
Definition: array.c:2336
RARRAY_EMBED_LEN_MASK
#define RARRAY_EMBED_LEN_MASK
Definition: ruby.h:876
ary_make_substitution
static VALUE ary_make_substitution(VALUE ary)
Definition: array.c:600
FIX2INT
#define FIX2INT(x)
Definition: ruby.h:632
rb_ary_values_at
static VALUE rb_ary_values_at(int argc, VALUE *argv, VALUE ary)
Definition: array.c:2762
empty_ary_alloc
static VALUE empty_ary_alloc(VALUE klass)
Definition: array.c:448
rb_ary_drop
static VALUE rb_ary_drop(VALUE ary, VALUE n)
Definition: array.c:5301
rb_ary_collect_bang
static VALUE rb_ary_collect_bang(VALUE ary)
Definition: array.c:2705
rb_ary_memsize
RUBY_FUNC_EXPORTED size_t rb_ary_memsize(VALUE ary)
Definition: array.c:548
memfill
static void memfill(register VALUE *mem, register long size, register VALUE val)
Definition: array.c:51
rb_ary_new3
#define rb_ary_new3
Definition: intern.h:91
INFINITY
#define INFINITY
Definition: missing.h:141
shift
static void shift(struct cparse_params *v, long act, VALUE tok, VALUE val)
Definition: cparse.c:662
rb_cNumeric
RUBY_EXTERN VALUE rb_cNumeric
Definition: ruby.h:1575
st_init_numtable
st_table * st_init_numtable(void)
Definition: st.c:272
rb_ary_increment_share
static VALUE rb_ary_increment_share(VALUE shared)
Definition: array.c:290
ary_add_hash
static VALUE ary_add_hash(VALUE hash, VALUE ary)
Definition: array.c:3894
rpermute0
static void rpermute0(long n, long r, long *p, long index, VALUE values)
Definition: array.c:4944
rb_ary_diff
static VALUE rb_ary_diff(VALUE ary1, VALUE ary2)
Definition: array.c:3973
FL_UNSET
#define FL_UNSET(x, f)
Definition: ruby.h:1173
ary_tmp_hash_new
static VALUE ary_tmp_hash_new(void)
Definition: array.c:3908
rb_ary_index
static VALUE rb_ary_index(int argc, VALUE *argv, VALUE ary)
Definition: array.c:1419
LONG2NUM
#define LONG2NUM(x)
Definition: ruby.h:1309
rb_respond_to
int rb_respond_to(VALUE, ID)
Definition: vm_method.c:1639
rb_ary_new_from_values
VALUE rb_ary_new_from_values(long n, const VALUE *elts)
Definition: array.c:520
rb_ary_shift_m
static VALUE rb_ary_shift_m(int argc, VALUE *argv, VALUE ary)
Definition: array.c:1045
SORT_OPTIMIZABLE
#define SORT_OPTIMIZABLE(data, type)
Definition: array.c:2349
flatten
static VALUE flatten(VALUE ary, int level, int *modified)
Definition: array.c:4284
rb_ary_cycle_size
static VALUE rb_ary_cycle_size(VALUE self, VALUE args, VALUE eobj)
Definition: array.c:4622
recur
#define recur(fmt)
Definition: date_strptime.c:147
RSTRING_PTR
#define RSTRING_PTR(str)
Definition: ruby.h:845
top
unsigned int top
Definition: nkf.c:4309
ARY_EMBED_LEN
#define ARY_EMBED_LEN(a)
Definition: array.c:108
rb_ary_resize
VALUE rb_ary_resize(VALUE ary, long len)
expands or shrinks ary to len elements.
Definition: array.c:1615
RARRAY_ASET
#define RARRAY_ASET(a, i, v)
Definition: ruby.h:902
rb_ary_flatten_bang
static VALUE rb_ary_flatten_bang(int argc, VALUE *argv, VALUE ary)
Definition: array.c:4358
rb_equal
VALUE rb_equal(VALUE, VALUE)
Definition: object.c:89
ARY_EMBED_P
#define ARY_EMBED_P(ary)
Definition: array.c:101
ARY_SET_HEAP_LEN
#define ARY_SET_HEAP_LEN(ary, n)
Definition: array.c:138
yield_indexed_values
static int yield_indexed_values(const VALUE values, const long r, const long *const p)
Definition: array.c:4693
size
int size
Definition: encoding.c:49
rb_funcallv
VALUE rb_funcallv(VALUE, ID, int, const VALUE *)
Calls a method.
Definition: vm_eval.c:806
rb_yield_values2
VALUE rb_yield_values2(int n, const VALUE *argv)
Definition: vm_eval.c:975
rb_ary_fill
static VALUE rb_ary_fill(int argc, VALUE *argv, VALUE ary)
Definition: array.c:3428
rb_hash_lookup2
VALUE rb_hash_lookup2(VALUE hash, VALUE key, VALUE def)
Definition: hash.c:708
INT2FIX
#define INT2FIX(i)
Definition: ruby.h:231
ARY_SHARED
#define ARY_SHARED(ary)
Definition: array.c:175
UNLIMITED_ARGUMENTS
#define UNLIMITED_ARGUMENTS
Definition: intern.h:44
recursive_equal
static VALUE recursive_equal(VALUE ary1, VALUE ary2, int recur)
Definition: array.c:3686
rb_ary_modify_check
static void rb_ary_modify_check(VALUE ary)
Definition: array.c:308
rb_sourceline
int rb_sourceline(void)
Definition: vm.c:1001
RARRAY_AREF
#define RARRAY_AREF(a, i)
Definition: ruby.h:901
rb_check_convert_type
VALUE rb_check_convert_type(VALUE, int, const char *, const char *)
Definition: object.c:2631
mul
#define mul(x, y)
Definition: date_strftime.c:25
rb_ary_plus
VALUE rb_ary_plus(VALUE x, VALUE y)
Definition: array.c:3510
rb_ary_s_try_convert
static VALUE rb_ary_s_try_convert(VALUE dummy, VALUE ary)
Definition: array.c:653
ARY_TAKE_LAST
Definition: array.c:856
ary_double_capa
static void ary_double_capa(VALUE ary, long min)
Definition: array.c:244
rb_ary_rotate_m
static VALUE rb_ary_rotate_m(int argc, VALUE *argv, VALUE ary)
Definition: array.c:2309
id_div
static ID id_div
Definition: array.c:29
rb_check_array_type
VALUE rb_check_array_type(VALUE ary)
Definition: array.c:628
rb_ary_to_a
static VALUE rb_ary_to_a(VALUE ary)
Definition: array.c:2111
RARRAY_PTR
#define RARRAY_PTR(a)
Definition: ruby.h:907
RHASH_TBL_RAW
#define RHASH_TBL_RAW(h)
Definition: internal.h:478
FL_WB_PROTECTED
#define FL_WB_PROTECTED
Definition: ruby.h:1134
sort_optimizable_count
Definition: array.c:2343
rb_check_string_type
VALUE rb_check_string_type(VALUE)
Definition: string.c:1679
key
uint8_t key[16]
Definition: random.c:1250
rb_ary_includes
VALUE rb_ary_includes(VALUE ary, VALUE item)
Definition: array.c:3818
ARY_INCREASE_PTR
#define ARY_INCREASE_PTR(ary, n)
Definition: array.c:151
LONG2FIX
#define LONG2FIX(i)
Definition: ruby.h:232
rb_ary_equal
static VALUE rb_ary_equal(VALUE ary1, VALUE ary2)
Definition: array.c:3733
rb_gc_writebarrier_remember_promoted
void rb_gc_writebarrier_remember_promoted(VALUE obj)
Definition: gc.c:4782
rb_output_fs
VALUE rb_output_fs
Definition: intern.h:517
push_value
static int push_value(st_data_t key, st_data_t val, st_data_t ary)
Definition: array.c:4076
RTEST
#define RTEST(v)
Definition: ruby.h:437
T_STRING
#define T_STRING
Definition: ruby.h:482
sort_opt_Fixnum
Definition: array.c:2341
rb_ary_repeated_permutation_size
static VALUE rb_ary_repeated_permutation_size(VALUE ary, VALUE args, VALUE eobj)
Definition: array.c:4961
OBJ_INFECT
#define OBJ_INFECT(x, s)
Definition: ruby.h:1180
rb_hash_uint
st_index_t rb_hash_uint(st_index_t, st_index_t)
ARY_INCREASE_LEN
#define ARY_INCREASE_LEN(ary, n)
Definition: array.c:156
sort_reentered
static VALUE sort_reentered(VALUE ary)
Definition: array.c:2357
ary_make_hash_by
static VALUE ary_make_hash_by(VALUE ary)
Definition: array.c:3938
rb_ary_sort_bang
VALUE rb_ary_sort_bang(VALUE ary)
Definition: array.c:2425
rotate_count
static long rotate_count(long cnt, long len)
Definition: array.c:2234
rb_ary_set_shared
static void rb_ary_set_shared(VALUE ary, VALUE shared)
Definition: array.c:300
rb_ary_length
static VALUE rb_ary_length(VALUE ary)
Definition: array.c:1864
rb_ary_dup
VALUE rb_ary_dup(VALUE ary)
Definition: array.c:1888
RARRAY_EMBED_LEN_MAX
#define RARRAY_EMBED_LEN_MAX
Definition: ruby.h:859
rb_ary_repeated_combination
static VALUE rb_ary_repeated_combination(VALUE ary, VALUE num)
Definition: array.c:5086
st.h
rb_cArray
VALUE rb_cArray
Definition: array.c:27
rb_ary_concat
VALUE rb_ary_concat(VALUE x, VALUE y)
Definition: array.c:3542
hash
static unsigned int hash(const char *str, unsigned int len)
Definition: lex.c:56
RETURN_ENUMERATOR
#define RETURN_ENUMERATOR(obj, argc, argv)
Definition: intern.h:242
rb_ary_join
VALUE rb_ary_join(VALUE ary, VALUE sep)
Definition: array.c:1995
rb_ary_repeated_permutation
static VALUE rb_ary_repeated_permutation(VALUE ary, VALUE num)
Definition: array.c:4999
ARY_SET_SHARED_NUM
#define ARY_SET_SHARED_NUM(ary, value)
Definition: array.c:189
ARY_SET_SHARED
#define ARY_SET_SHARED(ary, value)
Definition: array.c:176
rb_ary_empty_p
static VALUE rb_ary_empty_p(VALUE ary)
Definition: array.c:1880
rb_ary_rotate_bang
static VALUE rb_ary_rotate_bang(int argc, VALUE *argv, VALUE ary)
Definition: array.c:2278
ary_recycle_hash
static void ary_recycle_hash(VALUE hash)
Definition: array.c:3945
ary_make_shared
static VALUE ary_make_shared(VALUE ary)
Definition: array.c:567
recursive_eql
static VALUE recursive_eql(VALUE ary1, VALUE ary2, int recur)
Definition: array.c:3748
assert
#define assert(condition)
Definition: ossl.h:45
FL_SET
#define FL_SET(x, f)
Definition: ruby.h:1172
rb_ary_flatten
static VALUE rb_ary_flatten(int argc, VALUE *argv, VALUE ary)
Definition: array.c:4403
ary_add_hash_by
static VALUE ary_add_hash_by(VALUE hash, VALUE ary)
Definition: array.c:3924
rb_ary_permutation_size
static VALUE rb_ary_permutation_size(VALUE ary, VALUE args, VALUE eobj)
Definition: array.c:4773
rb_ary_reverse
VALUE rb_ary_reverse(VALUE ary)
Definition: array.c:2176
FL_FREEZE
#define FL_FREEZE
Definition: ruby.h:1140
tmpbuf
#define tmpbuf(n, size)
Definition: array.c:4682
ary_reject_bang
static VALUE ary_reject_bang(VALUE ary)
Definition: array.c:3080
rb_inspect
VALUE rb_inspect(VALUE)
Definition: object.c:470
rb_ary_initialize
static VALUE rb_ary_initialize(int argc, VALUE *argv, VALUE ary)
Definition: array.c:715
rb_ary_cycle
static VALUE rb_ary_cycle(int argc, VALUE *argv, VALUE ary)
Definition: array.c:4658
rb_warning
void rb_warning(const char *fmt,...)
Definition: error.c:236
rb_check_frozen
#define rb_check_frozen(obj)
Definition: intern.h:277
rb_ary_decrement_share
static void rb_ary_decrement_share(VALUE shared)
Definition: array.c:259
rb_obj_freeze
VALUE rb_obj_freeze(VALUE)
Definition: object.c:1076
rb_ary_cmp
VALUE rb_ary_cmp(VALUE ary1, VALUE ary2)
Definition: array.c:3877
Init_Array
void Init_Array(void)
Definition: array.c:5582
rb_ary_eql
static VALUE rb_ary_eql(VALUE ary1, VALUE ary2)
Definition: array.c:3769
ARY_EMBED_PTR
#define ARY_EMBED_PTR(a)
Definition: array.c:107
rb_ary_uniq
static VALUE rb_ary_uniq(VALUE ary)
Definition: array.c:4158
ARY_HEAP_LEN
#define ARY_HEAP_LEN(a)
Definition: array.c:106
rb_ary_resurrect
VALUE rb_ary_resurrect(VALUE ary)
Definition: array.c:1898
sort_by_i
static VALUE sort_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, dummy))
Definition: array.c:2617
rb_intern
#define rb_intern(str)
rb_str_buf_new
VALUE rb_str_buf_new(long)
Definition: string.c:891
rb_usascii_str_new
VALUE rb_usascii_str_new(const char *, long)
Definition: string.c:540
mod
#define mod(x, y)
Definition: date_strftime.c:28
ary_new
static VALUE ary_new(VALUE klass, long capa)
Definition: array.c:458
ARY_SHARED_OCCUPIED
#define ARY_SHARED_OCCUPIED(ary)
Definition: array.c:188
NULL
#define NULL
Definition: _sdbm.c:103
FIX2LONG
#define FIX2LONG(x)
Definition: ruby.h:345
Qundef
#define Qundef
Definition: ruby.h:428
rb_ary_pop_m
static VALUE rb_ary_pop_m(int argc, VALUE *argv, VALUE ary)
Definition: array.c:976
ARY_CAPA
#define ARY_CAPA(ary)
Definition: array.c:166
rb_define_method
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1488
st_foreach
int st_foreach(st_table *, int(*)(ANYARGS), st_data_t)
Definition: st.c:1034
rb_ary_delete_same
void rb_ary_delete_same(VALUE ary, VALUE item)
Definition: array.c:2928
rb_warn
void rb_warn(const char *fmt,...)
Definition: error.c:223
bp
#define bp()
Definition: vm_debug.h:25
rb_ary_and
static VALUE rb_ary_and(VALUE ary1, VALUE ary2)
Definition: array.c:4008
rb_eArgError
VALUE rb_eArgError
Definition: error.c:549
rb_ary_shuffle
static VALUE rb_ary_shuffle(int argc, VALUE *argv, VALUE ary)
Definition: array.c:4485
NUM2LONG
#define NUM2LONG(x)
Definition: ruby.h:600
STRING_P
#define STRING_P(s)
Definition: array.c:2346
rb_hash_start
st_index_t rb_hash_start(st_index_t)
Definition: random.c:1296
rb_ary_push_m
static VALUE rb_ary_push_m(int argc, VALUE *argv, VALUE ary)
Definition: array.c:934
RB_OBJ_WRITE
#define RB_OBJ_WRITE(a, slot, b)
Definition: ruby.h:1213
rb_usascii_str_new_cstr
VALUE rb_usascii_str_new_cstr(const char *)
Definition: string.c:569
rb_ary_aref
VALUE rb_ary_aref(int argc, VALUE *argv, VALUE ary)
Definition: array.c:1234
argv
char ** argv
Definition: ruby.c:132
DBL2NUM
#define DBL2NUM(dbl)
Definition: ruby.h:815
StringValue
#define StringValue(v)
Definition: ruby.h:539
rb_ary_unshare_safe
static void rb_ary_unshare_safe(VALUE ary)
Definition: array.c:282
rb_ary_set_len
void rb_ary_set_len(VALUE ary, long len)
Definition: array.c:1592
rb_obj_class
VALUE rb_obj_class(VALUE)
Definition: object.c:226
rb_ary_bsearch
static VALUE rb_ary_bsearch(VALUE ary)
Definition: array.c:2568