00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "ruby/ruby.h"
00015 #include "ruby/util.h"
00016 #include "ruby/st.h"
00017 #include "ruby/encoding.h"
00018 #include "internal.h"
00019 #include "probes.h"
00020 #include "id.h"
00021
00022 #ifndef ARRAY_DEBUG
00023 # define NDEBUG
00024 #endif
00025 #include <assert.h>
00026
00027 VALUE rb_cArray;
00028
00029 static ID id_cmp, id_div, id_power;
00030
00031 #define ARY_DEFAULT_SIZE 16
00032 #define ARY_MAX_SIZE (LONG_MAX / (int)sizeof(VALUE))
00033
00034 void
00035 rb_mem_clear(register VALUE *mem, register long size)
00036 {
00037 while (size--) {
00038 *mem++ = Qnil;
00039 }
00040 }
00041
00042 static void
00043 ary_mem_clear(VALUE ary, long beg, long size)
00044 {
00045 RARRAY_PTR_USE(ary, ptr, {
00046 rb_mem_clear(ptr + beg, size);
00047 });
00048 }
00049
00050 static inline void
00051 memfill(register VALUE *mem, register long size, register VALUE val)
00052 {
00053 while (size--) {
00054 *mem++ = val;
00055 }
00056 }
00057
00058 static void
00059 ary_memfill(VALUE ary, long beg, long size, VALUE val)
00060 {
00061 RARRAY_PTR_USE(ary, ptr, {
00062 memfill(ptr + beg, size, val);
00063 RB_OBJ_WRITTEN(ary, Qundef, val);
00064 });
00065 }
00066
00067 static void
00068 ary_memcpy(VALUE ary, long beg, long argc, const VALUE *argv)
00069 {
00070 #if 1
00071 if (OBJ_PROMOTED(ary)) {
00072 if (argc > (int)(128/sizeof(VALUE)) ) {
00073 rb_gc_writebarrier_remember_promoted(ary);
00074 RARRAY_PTR_USE(ary, ptr, {
00075 MEMCPY(ptr+beg, argv, VALUE, argc);
00076 });
00077 }
00078 else {
00079 int i;
00080 RARRAY_PTR_USE(ary, ptr, {
00081 for (i=0; i<argc; i++) {
00082 RB_OBJ_WRITE(ary, &ptr[i+beg], argv[i]);
00083 }
00084 });
00085 }
00086 }
00087 else {
00088 RARRAY_PTR_USE(ary, ptr, {
00089 MEMCPY(ptr+beg, argv, VALUE, argc);
00090 });
00091 }
00092 #else
00093
00094 MEMCPY(RARRAY_PTR(ary)+beg, argv, VALUE, argc);
00095 #endif
00096 }
00097
00098 # define ARY_SHARED_P(ary) \
00099 (assert(!FL_TEST((ary), ELTS_SHARED) || !FL_TEST((ary), RARRAY_EMBED_FLAG)), \
00100 FL_TEST((ary),ELTS_SHARED)!=0)
00101 # define ARY_EMBED_P(ary) \
00102 (assert(!FL_TEST((ary), ELTS_SHARED) || !FL_TEST((ary), RARRAY_EMBED_FLAG)), \
00103 FL_TEST((ary), RARRAY_EMBED_FLAG)!=0)
00104
00105 #define ARY_HEAP_PTR(a) (assert(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.ptr)
00106 #define ARY_HEAP_LEN(a) (assert(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.len)
00107 #define ARY_EMBED_PTR(a) (assert(ARY_EMBED_P(a)), RARRAY(a)->as.ary)
00108 #define ARY_EMBED_LEN(a) \
00109 (assert(ARY_EMBED_P(a)), \
00110 (long)((RBASIC(a)->flags >> RARRAY_EMBED_LEN_SHIFT) & \
00111 (RARRAY_EMBED_LEN_MASK >> RARRAY_EMBED_LEN_SHIFT)))
00112 #define ARY_HEAP_SIZE(a) (assert(!ARY_EMBED_P(a)), assert(ARY_OWNS_HEAP_P(a)), RARRAY(a)->as.heap.aux.capa * sizeof(VALUE))
00113
00114 #define ARY_OWNS_HEAP_P(a) (!FL_TEST((a), ELTS_SHARED|RARRAY_EMBED_FLAG))
00115 #define FL_SET_EMBED(a) do { \
00116 assert(!ARY_SHARED_P(a)); \
00117 FL_SET((a), RARRAY_EMBED_FLAG); \
00118 } while (0)
00119 #define FL_UNSET_EMBED(ary) FL_UNSET((ary), RARRAY_EMBED_FLAG|RARRAY_EMBED_LEN_MASK)
00120 #define FL_SET_SHARED(ary) do { \
00121 assert(!ARY_EMBED_P(ary)); \
00122 FL_SET((ary), ELTS_SHARED); \
00123 } while (0)
00124 #define FL_UNSET_SHARED(ary) FL_UNSET((ary), ELTS_SHARED)
00125
00126 #define ARY_SET_PTR(ary, p) do { \
00127 assert(!ARY_EMBED_P(ary)); \
00128 assert(!OBJ_FROZEN(ary)); \
00129 RARRAY(ary)->as.heap.ptr = (p); \
00130 } while (0)
00131 #define ARY_SET_EMBED_LEN(ary, n) do { \
00132 long tmp_n = (n); \
00133 assert(ARY_EMBED_P(ary)); \
00134 assert(!OBJ_FROZEN(ary)); \
00135 RBASIC(ary)->flags &= ~RARRAY_EMBED_LEN_MASK; \
00136 RBASIC(ary)->flags |= (tmp_n) << RARRAY_EMBED_LEN_SHIFT; \
00137 } while (0)
00138 #define ARY_SET_HEAP_LEN(ary, n) do { \
00139 assert(!ARY_EMBED_P(ary)); \
00140 RARRAY(ary)->as.heap.len = (n); \
00141 } while (0)
00142 #define ARY_SET_LEN(ary, n) do { \
00143 if (ARY_EMBED_P(ary)) { \
00144 ARY_SET_EMBED_LEN((ary), (n)); \
00145 } \
00146 else { \
00147 ARY_SET_HEAP_LEN((ary), (n)); \
00148 } \
00149 assert(RARRAY_LEN(ary) == (n)); \
00150 } while (0)
00151 #define ARY_INCREASE_PTR(ary, n) do { \
00152 assert(!ARY_EMBED_P(ary)); \
00153 assert(!OBJ_FROZEN(ary)); \
00154 RARRAY(ary)->as.heap.ptr += (n); \
00155 } while (0)
00156 #define ARY_INCREASE_LEN(ary, n) do { \
00157 assert(!OBJ_FROZEN(ary)); \
00158 if (ARY_EMBED_P(ary)) { \
00159 ARY_SET_EMBED_LEN((ary), RARRAY_LEN(ary)+(n)); \
00160 } \
00161 else { \
00162 RARRAY(ary)->as.heap.len += (n); \
00163 } \
00164 } while (0)
00165
00166 #define ARY_CAPA(ary) (ARY_EMBED_P(ary) ? RARRAY_EMBED_LEN_MAX : \
00167 ARY_SHARED_ROOT_P(ary) ? RARRAY_LEN(ary) : RARRAY(ary)->as.heap.aux.capa)
00168 #define ARY_SET_CAPA(ary, n) do { \
00169 assert(!ARY_EMBED_P(ary)); \
00170 assert(!ARY_SHARED_P(ary)); \
00171 assert(!OBJ_FROZEN(ary)); \
00172 RARRAY(ary)->as.heap.aux.capa = (n); \
00173 } while (0)
00174
00175 #define ARY_SHARED(ary) (assert(ARY_SHARED_P(ary)), RARRAY(ary)->as.heap.aux.shared)
00176 #define ARY_SET_SHARED(ary, value) do { \
00177 const VALUE _ary_ = (ary); \
00178 const VALUE _value_ = (value); \
00179 assert(!ARY_EMBED_P(_ary_)); \
00180 assert(ARY_SHARED_P(_ary_)); \
00181 assert(ARY_SHARED_ROOT_P(_value_)); \
00182 RB_OBJ_WRITE(_ary_, &RARRAY(_ary_)->as.heap.aux.shared, _value_); \
00183 } while (0)
00184 #define RARRAY_SHARED_ROOT_FLAG FL_USER5
00185 #define ARY_SHARED_ROOT_P(ary) (FL_TEST((ary), RARRAY_SHARED_ROOT_FLAG))
00186 #define ARY_SHARED_NUM(ary) \
00187 (assert(ARY_SHARED_ROOT_P(ary)), RARRAY(ary)->as.heap.aux.capa)
00188 #define ARY_SHARED_OCCUPIED(ary) (ARY_SHARED_NUM(ary) == 1)
00189 #define ARY_SET_SHARED_NUM(ary, value) do { \
00190 assert(ARY_SHARED_ROOT_P(ary)); \
00191 RARRAY(ary)->as.heap.aux.capa = (value); \
00192 } while (0)
00193 #define FL_SET_SHARED_ROOT(ary) do { \
00194 assert(!ARY_EMBED_P(ary)); \
00195 FL_SET((ary), RARRAY_SHARED_ROOT_FLAG); \
00196 } while (0)
00197
00198 static void
00199 ary_resize_capa(VALUE ary, long capacity)
00200 {
00201 assert(RARRAY_LEN(ary) <= capacity);
00202 assert(!OBJ_FROZEN(ary));
00203 assert(!ARY_SHARED_P(ary));
00204 if (capacity > RARRAY_EMBED_LEN_MAX) {
00205 if (ARY_EMBED_P(ary)) {
00206 long len = ARY_EMBED_LEN(ary);
00207 VALUE *ptr = ALLOC_N(VALUE, (capacity));
00208 MEMCPY(ptr, ARY_EMBED_PTR(ary), VALUE, len);
00209 FL_UNSET_EMBED(ary);
00210 ARY_SET_PTR(ary, ptr);
00211 ARY_SET_HEAP_LEN(ary, len);
00212 }
00213 else {
00214 SIZED_REALLOC_N(RARRAY(ary)->as.heap.ptr, VALUE, capacity, RARRAY(ary)->as.heap.aux.capa);
00215 }
00216 ARY_SET_CAPA(ary, (capacity));
00217 }
00218 else {
00219 if (!ARY_EMBED_P(ary)) {
00220 long len = RARRAY_LEN(ary);
00221 const VALUE *ptr = RARRAY_CONST_PTR(ary);
00222
00223 if (len > capacity) len = capacity;
00224 MEMCPY((VALUE *)RARRAY(ary)->as.ary, ptr, VALUE, len);
00225 FL_SET_EMBED(ary);
00226 ARY_SET_LEN(ary, len);
00227 ruby_xfree((VALUE *)ptr);
00228 }
00229 }
00230 }
00231
00232 static inline void
00233 ary_shrink_capa(VALUE ary)
00234 {
00235 long capacity = ARY_HEAP_LEN(ary);
00236 long old_capa = RARRAY(ary)->as.heap.aux.capa;
00237 assert(!ARY_SHARED_P(ary));
00238 assert(old_capa >= capacity);
00239 if (old_capa > capacity)
00240 REALLOC_N(RARRAY(ary)->as.heap.ptr, VALUE, capacity);
00241 }
00242
00243 static void
00244 ary_double_capa(VALUE ary, long min)
00245 {
00246 long new_capa = ARY_CAPA(ary) / 2;
00247
00248 if (new_capa < ARY_DEFAULT_SIZE) {
00249 new_capa = ARY_DEFAULT_SIZE;
00250 }
00251 if (new_capa >= ARY_MAX_SIZE - min) {
00252 new_capa = (ARY_MAX_SIZE - min) / 2;
00253 }
00254 new_capa += min;
00255 ary_resize_capa(ary, new_capa);
00256 }
00257
00258 static void
00259 rb_ary_decrement_share(VALUE shared)
00260 {
00261 if (shared) {
00262 long num = ARY_SHARED_NUM(shared) - 1;
00263 if (num == 0) {
00264 rb_ary_free(shared);
00265 rb_gc_force_recycle(shared);
00266 }
00267 else if (num > 0) {
00268 ARY_SET_SHARED_NUM(shared, num);
00269 }
00270 }
00271 }
00272
00273 static void
00274 rb_ary_unshare(VALUE ary)
00275 {
00276 VALUE shared = RARRAY(ary)->as.heap.aux.shared;
00277 rb_ary_decrement_share(shared);
00278 FL_UNSET_SHARED(ary);
00279 }
00280
00281 static inline void
00282 rb_ary_unshare_safe(VALUE ary)
00283 {
00284 if (ARY_SHARED_P(ary) && !ARY_EMBED_P(ary)) {
00285 rb_ary_unshare(ary);
00286 }
00287 }
00288
00289 static VALUE
00290 rb_ary_increment_share(VALUE shared)
00291 {
00292 long num = ARY_SHARED_NUM(shared);
00293 if (num >= 0) {
00294 ARY_SET_SHARED_NUM(shared, num + 1);
00295 }
00296 return shared;
00297 }
00298
00299 static void
00300 rb_ary_set_shared(VALUE ary, VALUE shared)
00301 {
00302 rb_ary_increment_share(shared);
00303 FL_SET_SHARED(ary);
00304 ARY_SET_SHARED(ary, shared);
00305 }
00306
00307 static inline void
00308 rb_ary_modify_check(VALUE ary)
00309 {
00310 rb_check_frozen(ary);
00311 }
00312
00313 void
00314 rb_ary_modify(VALUE ary)
00315 {
00316 rb_ary_modify_check(ary);
00317 if (ARY_SHARED_P(ary)) {
00318 long shared_len, len = RARRAY_LEN(ary);
00319 VALUE shared = ARY_SHARED(ary);
00320 if (len <= RARRAY_EMBED_LEN_MAX) {
00321 const VALUE *ptr = ARY_HEAP_PTR(ary);
00322 FL_UNSET_SHARED(ary);
00323 FL_SET_EMBED(ary);
00324 MEMCPY((VALUE *)ARY_EMBED_PTR(ary), ptr, VALUE, len);
00325 rb_ary_decrement_share(shared);
00326 ARY_SET_EMBED_LEN(ary, len);
00327 }
00328 else if (ARY_SHARED_OCCUPIED(shared) && len > ((shared_len = RARRAY_LEN(shared))>>1)) {
00329 long shift = RARRAY_CONST_PTR(ary) - RARRAY_CONST_PTR(shared);
00330 FL_UNSET_SHARED(ary);
00331 ARY_SET_PTR(ary, RARRAY_CONST_PTR(shared));
00332 ARY_SET_CAPA(ary, shared_len);
00333 RARRAY_PTR_USE(ary, ptr, {
00334 MEMMOVE(ptr, ptr+shift, VALUE, len);
00335 });
00336 FL_SET_EMBED(shared);
00337 rb_ary_decrement_share(shared);
00338 }
00339 else {
00340 VALUE *ptr = ALLOC_N(VALUE, len);
00341 MEMCPY(ptr, RARRAY_CONST_PTR(ary), VALUE, len);
00342 rb_ary_unshare(ary);
00343 ARY_SET_CAPA(ary, len);
00344 ARY_SET_PTR(ary, ptr);
00345 }
00346
00347
00348 if (OBJ_PROMOTED(ary) && !OBJ_PROMOTED(shared)) {
00349 rb_gc_writebarrier_remember_promoted(ary);
00350 }
00351 }
00352 }
00353
00354 static void
00355 ary_ensure_room_for_push(VALUE ary, long add_len)
00356 {
00357 long old_len = RARRAY_LEN(ary);
00358 long new_len = old_len + add_len;
00359 long capa;
00360
00361 if (old_len > ARY_MAX_SIZE - add_len) {
00362 rb_raise(rb_eIndexError, "index %ld too big", new_len);
00363 }
00364 if (ARY_SHARED_P(ary)) {
00365 if (new_len > RARRAY_EMBED_LEN_MAX) {
00366 VALUE shared = ARY_SHARED(ary);
00367 if (ARY_SHARED_OCCUPIED(shared)) {
00368 if (RARRAY_CONST_PTR(ary) - RARRAY_CONST_PTR(shared) + new_len <= RARRAY_LEN(shared)) {
00369 rb_ary_modify_check(ary);
00370 }
00371 else {
00372
00373 rb_ary_modify(ary);
00374 capa = ARY_CAPA(ary);
00375 if (new_len > capa - (capa >> 6)) {
00376 ary_double_capa(ary, new_len);
00377 }
00378 }
00379 return;
00380 }
00381 }
00382 }
00383 rb_ary_modify(ary);
00384 capa = ARY_CAPA(ary);
00385 if (new_len > capa) {
00386 ary_double_capa(ary, new_len);
00387 }
00388 }
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400 VALUE
00401 rb_ary_freeze(VALUE ary)
00402 {
00403 return rb_obj_freeze(ary);
00404 }
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414 static VALUE
00415 rb_ary_frozen_p(VALUE ary)
00416 {
00417 if (OBJ_FROZEN(ary)) return Qtrue;
00418 return Qfalse;
00419 }
00420
00421
00422
00423
00424
00425
00426
00427
00428 VALUE
00429 rb_ary_shared_with_p(VALUE ary1, VALUE ary2)
00430 {
00431 if (!ARY_EMBED_P(ary1) && ARY_SHARED_P(ary1) &&
00432 !ARY_EMBED_P(ary2) && ARY_SHARED_P(ary2) &&
00433 RARRAY(ary1)->as.heap.aux.shared == RARRAY(ary2)->as.heap.aux.shared &&
00434 RARRAY(ary1)->as.heap.len == RARRAY(ary2)->as.heap.len) {
00435 return Qtrue;
00436 }
00437 return Qfalse;
00438 }
00439
00440 static VALUE
00441 ary_alloc(VALUE klass)
00442 {
00443 NEWOBJ_OF(ary, struct RArray, klass, T_ARRAY | RARRAY_EMBED_FLAG | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0));
00444
00445
00446
00447
00448 return (VALUE)ary;
00449 }
00450
00451 static VALUE
00452 empty_ary_alloc(VALUE klass)
00453 {
00454 if (RUBY_DTRACE_ARRAY_CREATE_ENABLED()) {
00455 RUBY_DTRACE_ARRAY_CREATE(0, rb_sourcefile(), rb_sourceline());
00456 }
00457
00458 return ary_alloc(klass);
00459 }
00460
00461 static VALUE
00462 ary_new(VALUE klass, long capa)
00463 {
00464 VALUE ary,*ptr;
00465
00466 if (capa < 0) {
00467 rb_raise(rb_eArgError, "negative array size (or size too big)");
00468 }
00469 if (capa > ARY_MAX_SIZE) {
00470 rb_raise(rb_eArgError, "array size too big");
00471 }
00472
00473 if (RUBY_DTRACE_ARRAY_CREATE_ENABLED()) {
00474 RUBY_DTRACE_ARRAY_CREATE(capa, rb_sourcefile(), rb_sourceline());
00475 }
00476
00477 if (capa > RARRAY_EMBED_LEN_MAX) {
00478 ptr = ALLOC_N(VALUE, capa);
00479 ary = ary_alloc(klass);
00480 FL_UNSET_EMBED(ary);
00481 ARY_SET_PTR(ary, ptr);
00482 ARY_SET_CAPA(ary, capa);
00483 ARY_SET_HEAP_LEN(ary, 0);
00484 }
00485 else {
00486 ary = ary_alloc(klass);
00487 }
00488
00489 return ary;
00490 }
00491
00492 VALUE
00493 rb_ary_new_capa(long capa)
00494 {
00495 return ary_new(rb_cArray, capa);
00496 }
00497
00498 VALUE
00499 rb_ary_new(void)
00500 {
00501 return rb_ary_new2(RARRAY_EMBED_LEN_MAX);
00502 }
00503
00504 VALUE
00505 rb_ary_new_from_args(long n, ...)
00506 {
00507 va_list ar;
00508 VALUE ary;
00509 long i;
00510
00511 ary = rb_ary_new2(n);
00512
00513 va_start(ar, n);
00514 for (i=0; i<n; i++) {
00515 RARRAY_ASET(ary, i, va_arg(ar, VALUE));
00516 }
00517 va_end(ar);
00518
00519 ARY_SET_LEN(ary, n);
00520 return ary;
00521 }
00522
00523 VALUE
00524 rb_ary_new_from_values(long n, const VALUE *elts)
00525 {
00526 VALUE ary;
00527
00528 ary = rb_ary_new2(n);
00529 if (n > 0 && elts) {
00530 ary_memcpy(ary, 0, n, elts);
00531 ARY_SET_LEN(ary, n);
00532 }
00533
00534 return ary;
00535 }
00536
00537 VALUE
00538 rb_ary_tmp_new(long capa)
00539 {
00540 return ary_new(0, capa);
00541 }
00542
00543 void
00544 rb_ary_free(VALUE ary)
00545 {
00546 if (ARY_OWNS_HEAP_P(ary)) {
00547 ruby_sized_xfree((void *)ARY_HEAP_PTR(ary), ARY_HEAP_SIZE(ary));
00548 }
00549 }
00550
00551 RUBY_FUNC_EXPORTED size_t
00552 rb_ary_memsize(VALUE ary)
00553 {
00554 if (ARY_OWNS_HEAP_P(ary)) {
00555 return RARRAY(ary)->as.heap.aux.capa * sizeof(VALUE);
00556 }
00557 else {
00558 return 0;
00559 }
00560 }
00561
00562 static inline void
00563 ary_discard(VALUE ary)
00564 {
00565 rb_ary_free(ary);
00566 RBASIC(ary)->flags |= RARRAY_EMBED_FLAG;
00567 RBASIC(ary)->flags &= ~RARRAY_EMBED_LEN_MASK;
00568 }
00569
00570 static VALUE
00571 ary_make_shared(VALUE ary)
00572 {
00573 assert(!ARY_EMBED_P(ary));
00574 if (ARY_SHARED_P(ary)) {
00575 return ARY_SHARED(ary);
00576 }
00577 else if (ARY_SHARED_ROOT_P(ary)) {
00578 return ary;
00579 }
00580 else if (OBJ_FROZEN(ary)) {
00581 ary_shrink_capa(ary);
00582 FL_SET_SHARED_ROOT(ary);
00583 ARY_SET_SHARED_NUM(ary, 1);
00584 return ary;
00585 }
00586 else {
00587 long capa = ARY_CAPA(ary), len = RARRAY_LEN(ary);
00588 NEWOBJ_OF(shared, struct RArray, 0, T_ARRAY);
00589 FL_UNSET_EMBED(shared);
00590
00591 ARY_SET_LEN((VALUE)shared, capa);
00592 ARY_SET_PTR((VALUE)shared, RARRAY_CONST_PTR(ary));
00593 ary_mem_clear((VALUE)shared, len, capa - len);
00594 FL_SET_SHARED_ROOT(shared);
00595 ARY_SET_SHARED_NUM((VALUE)shared, 1);
00596 FL_SET_SHARED(ary);
00597 ARY_SET_SHARED(ary, (VALUE)shared);
00598 OBJ_FREEZE(shared);
00599 return (VALUE)shared;
00600 }
00601 }
00602
00603 static VALUE
00604 ary_make_substitution(VALUE ary)
00605 {
00606 long len = RARRAY_LEN(ary);
00607
00608 if (len <= RARRAY_EMBED_LEN_MAX) {
00609 VALUE subst = rb_ary_new2(len);
00610 ary_memcpy(subst, 0, len, RARRAY_CONST_PTR(ary));
00611 ARY_SET_EMBED_LEN(subst, len);
00612 return subst;
00613 }
00614 else {
00615 return rb_ary_increment_share(ary_make_shared(ary));
00616 }
00617 }
00618
00619 VALUE
00620 rb_assoc_new(VALUE car, VALUE cdr)
00621 {
00622 return rb_ary_new3(2, car, cdr);
00623 }
00624
00625 static VALUE
00626 to_ary(VALUE ary)
00627 {
00628 return rb_convert_type(ary, T_ARRAY, "Array", "to_ary");
00629 }
00630
00631 VALUE
00632 rb_check_array_type(VALUE ary)
00633 {
00634 return rb_check_convert_type(ary, T_ARRAY, "Array", "to_ary");
00635 }
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656 static VALUE
00657 rb_ary_s_try_convert(VALUE dummy, VALUE ary)
00658 {
00659 return rb_check_array_type(ary);
00660 }
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718 static VALUE
00719 rb_ary_initialize(int argc, VALUE *argv, VALUE ary)
00720 {
00721 long len;
00722 VALUE size, val;
00723
00724 rb_ary_modify(ary);
00725 if (argc == 0) {
00726 if (ARY_OWNS_HEAP_P(ary) && RARRAY_CONST_PTR(ary) != 0) {
00727 ruby_sized_xfree((void *)RARRAY_CONST_PTR(ary), ARY_HEAP_SIZE(ary));
00728 }
00729 rb_ary_unshare_safe(ary);
00730 FL_SET_EMBED(ary);
00731 ARY_SET_EMBED_LEN(ary, 0);
00732 if (rb_block_given_p()) {
00733 rb_warning("given block not used");
00734 }
00735 return ary;
00736 }
00737 rb_scan_args(argc, argv, "02", &size, &val);
00738 if (argc == 1 && !FIXNUM_P(size)) {
00739 val = rb_check_array_type(size);
00740 if (!NIL_P(val)) {
00741 rb_ary_replace(ary, val);
00742 return ary;
00743 }
00744 }
00745
00746 len = NUM2LONG(size);
00747 if (len < 0) {
00748 rb_raise(rb_eArgError, "negative array size");
00749 }
00750 if (len > ARY_MAX_SIZE) {
00751 rb_raise(rb_eArgError, "array size too big");
00752 }
00753 rb_ary_modify(ary);
00754 ary_resize_capa(ary, len);
00755 if (rb_block_given_p()) {
00756 long i;
00757
00758 if (argc == 2) {
00759 rb_warn("block supersedes default value argument");
00760 }
00761 for (i=0; i<len; i++) {
00762 rb_ary_store(ary, i, rb_yield(LONG2NUM(i)));
00763 ARY_SET_LEN(ary, i + 1);
00764 }
00765 }
00766 else {
00767 ary_memfill(ary, 0, len, val);
00768 ARY_SET_LEN(ary, len);
00769 }
00770 return ary;
00771 }
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781 static VALUE
00782 rb_ary_s_create(int argc, VALUE *argv, VALUE klass)
00783 {
00784 VALUE ary = ary_new(klass, argc);
00785 if (argc > 0 && argv) {
00786 ary_memcpy(ary, 0, argc, argv);
00787 ARY_SET_LEN(ary, argc);
00788 }
00789
00790 return ary;
00791 }
00792
00793 void
00794 rb_ary_store(VALUE ary, long idx, VALUE val)
00795 {
00796 long len = RARRAY_LEN(ary);
00797
00798 if (idx < 0) {
00799 idx += len;
00800 if (idx < 0) {
00801 rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
00802 idx - len, -len);
00803 }
00804 }
00805 else if (idx >= ARY_MAX_SIZE) {
00806 rb_raise(rb_eIndexError, "index %ld too big", idx);
00807 }
00808
00809 rb_ary_modify(ary);
00810 if (idx >= ARY_CAPA(ary)) {
00811 ary_double_capa(ary, idx);
00812 }
00813 if (idx > len) {
00814 ary_mem_clear(ary, len, idx - len + 1);
00815 }
00816
00817 if (idx >= len) {
00818 ARY_SET_LEN(ary, idx + 1);
00819 }
00820 RARRAY_ASET(ary, idx, val);
00821 }
00822
00823 static VALUE
00824 ary_make_partial(VALUE ary, VALUE klass, long offset, long len)
00825 {
00826 assert(offset >= 0);
00827 assert(len >= 0);
00828 assert(offset+len <= RARRAY_LEN(ary));
00829
00830 if (len <= RARRAY_EMBED_LEN_MAX) {
00831 VALUE result = ary_alloc(klass);
00832 ary_memcpy(result, 0, len, RARRAY_CONST_PTR(ary) + offset);
00833 ARY_SET_EMBED_LEN(result, len);
00834 return result;
00835 }
00836 else {
00837 VALUE shared, result = ary_alloc(klass);
00838 FL_UNSET_EMBED(result);
00839
00840 shared = ary_make_shared(ary);
00841 ARY_SET_PTR(result, RARRAY_CONST_PTR(ary));
00842 ARY_SET_LEN(result, RARRAY_LEN(ary));
00843 rb_ary_set_shared(result, shared);
00844
00845 ARY_INCREASE_PTR(result, offset);
00846 ARY_SET_LEN(result, len);
00847 return result;
00848 }
00849 }
00850
00851 static VALUE
00852 ary_make_shared_copy(VALUE ary)
00853 {
00854 return ary_make_partial(ary, rb_obj_class(ary), 0, RARRAY_LEN(ary));
00855 }
00856
00857 enum ary_take_pos_flags
00858 {
00859 ARY_TAKE_FIRST = 0,
00860 ARY_TAKE_LAST = 1
00861 };
00862
00863 static VALUE
00864 ary_take_first_or_last(int argc, VALUE *argv, VALUE ary, enum ary_take_pos_flags last)
00865 {
00866 VALUE nv;
00867 long n;
00868 long len;
00869 long offset = 0;
00870
00871 rb_scan_args(argc, argv, "1", &nv);
00872 n = NUM2LONG(nv);
00873 len = RARRAY_LEN(ary);
00874 if (n > len) {
00875 n = len;
00876 }
00877 else if (n < 0) {
00878 rb_raise(rb_eArgError, "negative array size");
00879 }
00880 if (last) {
00881 offset = len - n;
00882 }
00883 return ary_make_partial(ary, rb_cArray, offset, n);
00884 }
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899 VALUE
00900 rb_ary_push(VALUE ary, VALUE item)
00901 {
00902 long idx = RARRAY_LEN(ary);
00903
00904 ary_ensure_room_for_push(ary, 1);
00905 RARRAY_ASET(ary, idx, item);
00906 ARY_SET_LEN(ary, idx + 1);
00907 return ary;
00908 }
00909
00910 VALUE
00911 rb_ary_cat(VALUE ary, const VALUE *ptr, long len)
00912 {
00913 long oldlen = RARRAY_LEN(ary);
00914
00915 ary_ensure_room_for_push(ary, len);
00916 ary_memcpy(ary, oldlen, len, ptr);
00917 ARY_SET_LEN(ary, oldlen + len);
00918 return ary;
00919 }
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937 static VALUE
00938 rb_ary_push_m(int argc, VALUE *argv, VALUE ary)
00939 {
00940 return rb_ary_cat(ary, argv, argc);
00941 }
00942
00943 VALUE
00944 rb_ary_pop(VALUE ary)
00945 {
00946 long n;
00947 rb_ary_modify_check(ary);
00948 n = RARRAY_LEN(ary);
00949 if (n == 0) return Qnil;
00950 if (ARY_OWNS_HEAP_P(ary) &&
00951 n * 3 < ARY_CAPA(ary) &&
00952 ARY_CAPA(ary) > ARY_DEFAULT_SIZE)
00953 {
00954 ary_resize_capa(ary, n * 2);
00955 }
00956 --n;
00957 ARY_SET_LEN(ary, n);
00958 return RARRAY_AREF(ary, n);
00959 }
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979 static VALUE
00980 rb_ary_pop_m(int argc, VALUE *argv, VALUE ary)
00981 {
00982 VALUE result;
00983
00984 if (argc == 0) {
00985 return rb_ary_pop(ary);
00986 }
00987
00988 rb_ary_modify_check(ary);
00989 result = ary_take_first_or_last(argc, argv, ary, ARY_TAKE_LAST);
00990 ARY_INCREASE_LEN(ary, -RARRAY_LEN(result));
00991 return result;
00992 }
00993
00994 VALUE
00995 rb_ary_shift(VALUE ary)
00996 {
00997 VALUE top;
00998 long len = RARRAY_LEN(ary);
00999
01000 rb_ary_modify_check(ary);
01001 if (len == 0) return Qnil;
01002 top = RARRAY_AREF(ary, 0);
01003 if (!ARY_SHARED_P(ary)) {
01004 if (len < ARY_DEFAULT_SIZE) {
01005 RARRAY_PTR_USE(ary, ptr, {
01006 MEMMOVE(ptr, ptr+1, VALUE, len-1);
01007 });
01008 ARY_INCREASE_LEN(ary, -1);
01009 return top;
01010 }
01011 assert(!ARY_EMBED_P(ary));
01012
01013 RARRAY_ASET(ary, 0, Qnil);
01014 ary_make_shared(ary);
01015 }
01016 else if (ARY_SHARED_OCCUPIED(ARY_SHARED(ary))) {
01017 RARRAY_ASET(ary, 0, Qnil);
01018 }
01019 ARY_INCREASE_PTR(ary, 1);
01020 ARY_INCREASE_LEN(ary, -1);
01021
01022 return top;
01023 }
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048 static VALUE
01049 rb_ary_shift_m(int argc, VALUE *argv, VALUE ary)
01050 {
01051 VALUE result;
01052 long n;
01053
01054 if (argc == 0) {
01055 return rb_ary_shift(ary);
01056 }
01057
01058 rb_ary_modify_check(ary);
01059 result = ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST);
01060 n = RARRAY_LEN(result);
01061 if (ARY_SHARED_P(ary)) {
01062 if (ARY_SHARED_OCCUPIED(ARY_SHARED(ary))) {
01063 ary_mem_clear(ary, 0, n);
01064 }
01065 ARY_INCREASE_PTR(ary, n);
01066 }
01067 else {
01068 RARRAY_PTR_USE(ary, ptr, {
01069 MEMMOVE(ptr, ptr + n, VALUE, RARRAY_LEN(ary)-n);
01070 });
01071 }
01072 ARY_INCREASE_LEN(ary, -n);
01073
01074 return result;
01075 }
01076
01077 static void
01078 ary_ensure_room_for_unshift(VALUE ary, int argc)
01079 {
01080 long len = RARRAY_LEN(ary);
01081 long new_len = len + argc;
01082 long capa;
01083 const VALUE *head, *sharedp;
01084
01085 if (len > ARY_MAX_SIZE - argc) {
01086 rb_raise(rb_eIndexError, "index %ld too big", new_len);
01087 }
01088
01089 if (ARY_SHARED_P(ary)) {
01090 VALUE shared = ARY_SHARED(ary);
01091 capa = RARRAY_LEN(shared);
01092 if (ARY_SHARED_OCCUPIED(shared) && capa > new_len) {
01093 head = RARRAY_CONST_PTR(ary);
01094 sharedp = RARRAY_CONST_PTR(shared);
01095 goto makeroom_if_need;
01096 }
01097 }
01098
01099 rb_ary_modify(ary);
01100 capa = ARY_CAPA(ary);
01101 if (capa - (capa >> 6) <= new_len) {
01102 ary_double_capa(ary, new_len);
01103 }
01104
01105
01106 if (new_len > ARY_DEFAULT_SIZE * 4) {
01107
01108 capa = ARY_CAPA(ary);
01109 ary_make_shared(ary);
01110
01111 head = sharedp = RARRAY_CONST_PTR(ary);
01112 goto makeroom;
01113 makeroom_if_need:
01114 if (head - sharedp < argc) {
01115 long room;
01116 makeroom:
01117 room = capa - new_len;
01118 room -= room >> 4;
01119 MEMMOVE((VALUE *)sharedp + argc + room, head, VALUE, len);
01120 head = sharedp + argc + room;
01121 }
01122 ARY_SET_PTR(ary, head - argc);
01123 }
01124 else {
01125
01126 RARRAY_PTR_USE(ary, ptr, {
01127 MEMMOVE(ptr + argc, ptr, VALUE, len);
01128 });
01129 }
01130 }
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144 static VALUE
01145 rb_ary_unshift_m(int argc, VALUE *argv, VALUE ary)
01146 {
01147 long len = RARRAY_LEN(ary);
01148
01149 if (argc == 0) {
01150 rb_ary_modify_check(ary);
01151 return ary;
01152 }
01153
01154 ary_ensure_room_for_unshift(ary, argc);
01155 ary_memcpy(ary, 0, argc, argv);
01156 ARY_SET_LEN(ary, len + argc);
01157 return ary;
01158 }
01159
01160 VALUE
01161 rb_ary_unshift(VALUE ary, VALUE item)
01162 {
01163 return rb_ary_unshift_m(1,&item,ary);
01164 }
01165
01166
01167 static inline VALUE
01168 rb_ary_elt(VALUE ary, long offset)
01169 {
01170 long len = RARRAY_LEN(ary);
01171 if (len == 0) return Qnil;
01172 if (offset < 0 || len <= offset) {
01173 return Qnil;
01174 }
01175 return RARRAY_AREF(ary, offset);
01176 }
01177
01178 VALUE
01179 rb_ary_entry(VALUE ary, long offset)
01180 {
01181 if (offset < 0) {
01182 offset += RARRAY_LEN(ary);
01183 }
01184 return rb_ary_elt(ary, offset);
01185 }
01186
01187 VALUE
01188 rb_ary_subseq(VALUE ary, long beg, long len)
01189 {
01190 VALUE klass;
01191 long alen = RARRAY_LEN(ary);
01192
01193 if (beg > alen) return Qnil;
01194 if (beg < 0 || len < 0) return Qnil;
01195
01196 if (alen < len || alen < beg + len) {
01197 len = alen - beg;
01198 }
01199 klass = rb_obj_class(ary);
01200 if (len == 0) return ary_new(klass, 0);
01201
01202 return ary_make_partial(ary, klass, beg, len);
01203 }
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241 VALUE
01242 rb_ary_aref(int argc, VALUE *argv, VALUE ary)
01243 {
01244 VALUE arg;
01245 long beg, len;
01246
01247 if (argc == 2) {
01248 beg = NUM2LONG(argv[0]);
01249 len = NUM2LONG(argv[1]);
01250 if (beg < 0) {
01251 beg += RARRAY_LEN(ary);
01252 }
01253 return rb_ary_subseq(ary, beg, len);
01254 }
01255 if (argc != 1) {
01256 rb_scan_args(argc, argv, "11", NULL, NULL);
01257 }
01258 arg = argv[0];
01259
01260 if (FIXNUM_P(arg)) {
01261 return rb_ary_entry(ary, FIX2LONG(arg));
01262 }
01263
01264 switch (rb_range_beg_len(arg, &beg, &len, RARRAY_LEN(ary), 0)) {
01265 case Qfalse:
01266 break;
01267 case Qnil:
01268 return Qnil;
01269 default:
01270 return rb_ary_subseq(ary, beg, len);
01271 }
01272 return rb_ary_entry(ary, NUM2LONG(arg));
01273 }
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288 static VALUE
01289 rb_ary_at(VALUE ary, VALUE pos)
01290 {
01291 return rb_ary_entry(ary, NUM2LONG(pos));
01292 }
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309 static VALUE
01310 rb_ary_first(int argc, VALUE *argv, VALUE ary)
01311 {
01312 if (argc == 0) {
01313 if (RARRAY_LEN(ary) == 0) return Qnil;
01314 return RARRAY_AREF(ary, 0);
01315 }
01316 else {
01317 return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST);
01318 }
01319 }
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335
01336 VALUE
01337 rb_ary_last(int argc, VALUE *argv, VALUE ary)
01338 {
01339 if (argc == 0) {
01340 long len = RARRAY_LEN(ary);
01341 if (len == 0) return Qnil;
01342 return RARRAY_AREF(ary, len-1);
01343 }
01344 else {
01345 return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_LAST);
01346 }
01347 }
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372 static VALUE
01373 rb_ary_fetch(int argc, VALUE *argv, VALUE ary)
01374 {
01375 VALUE pos, ifnone;
01376 long block_given;
01377 long idx;
01378
01379 rb_scan_args(argc, argv, "11", &pos, &ifnone);
01380 block_given = rb_block_given_p();
01381 if (block_given && argc == 2) {
01382 rb_warn("block supersedes default value argument");
01383 }
01384 idx = NUM2LONG(pos);
01385
01386 if (idx < 0) {
01387 idx += RARRAY_LEN(ary);
01388 }
01389 if (idx < 0 || RARRAY_LEN(ary) <= idx) {
01390 if (block_given) return rb_yield(pos);
01391 if (argc == 1) {
01392 rb_raise(rb_eIndexError, "index %ld outside of array bounds: %ld...%ld",
01393 idx - (idx < 0 ? RARRAY_LEN(ary) : 0), -RARRAY_LEN(ary), RARRAY_LEN(ary));
01394 }
01395 return ifnone;
01396 }
01397 return RARRAY_AREF(ary, idx);
01398 }
01399
01400
01401
01402
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420
01421
01422
01423
01424
01425
01426 static VALUE
01427 rb_ary_index(int argc, VALUE *argv, VALUE ary)
01428 {
01429 const VALUE *ptr;
01430 VALUE val;
01431 long i, len;
01432
01433 if (argc == 0) {
01434 RETURN_ENUMERATOR(ary, 0, 0);
01435 for (i=0; i<RARRAY_LEN(ary); i++) {
01436 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) {
01437 return LONG2NUM(i);
01438 }
01439 }
01440 return Qnil;
01441 }
01442 rb_check_arity(argc, 0, 1);
01443 val = argv[0];
01444 if (rb_block_given_p())
01445 rb_warn("given block not used");
01446 len = RARRAY_LEN(ary);
01447 ptr = RARRAY_CONST_PTR(ary);
01448 for (i=0; i<len; i++) {
01449 VALUE e = ptr[i];
01450 switch (rb_equal_opt(e, val)) {
01451 case Qundef:
01452 if (!rb_equal(e, val)) break;
01453 case Qtrue:
01454 return LONG2NUM(i);
01455 case Qfalse:
01456 continue;
01457 }
01458 len = RARRAY_LEN(ary);
01459 ptr = RARRAY_CONST_PTR(ary);
01460 }
01461 return Qnil;
01462 }
01463
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486
01487
01488 static VALUE
01489 rb_ary_rindex(int argc, VALUE *argv, VALUE ary)
01490 {
01491 const VALUE *ptr;
01492 VALUE val;
01493 long i = RARRAY_LEN(ary), len;
01494
01495 if (argc == 0) {
01496 RETURN_ENUMERATOR(ary, 0, 0);
01497 while (i--) {
01498 if (RTEST(rb_yield(RARRAY_AREF(ary, i))))
01499 return LONG2NUM(i);
01500 if (i > (len = RARRAY_LEN(ary))) {
01501 i = len;
01502 }
01503 }
01504 return Qnil;
01505 }
01506 rb_check_arity(argc, 0, 1);
01507 val = argv[0];
01508 if (rb_block_given_p())
01509 rb_warn("given block not used");
01510 ptr = RARRAY_CONST_PTR(ary);
01511 while (i--) {
01512 VALUE e = ptr[i];
01513 switch (rb_equal_opt(e, val)) {
01514 case Qundef:
01515 if (!rb_equal(e, val)) break;
01516 case Qtrue:
01517 return LONG2NUM(i);
01518 case Qfalse:
01519 continue;
01520 }
01521 if (i > (len = RARRAY_LEN(ary))) {
01522 i = len;
01523 }
01524 ptr = RARRAY_CONST_PTR(ary);
01525 }
01526 return Qnil;
01527 }
01528
01529 VALUE
01530 rb_ary_to_ary(VALUE obj)
01531 {
01532 VALUE tmp = rb_check_array_type(obj);
01533
01534 if (!NIL_P(tmp)) return tmp;
01535 return rb_ary_new3(1, obj);
01536 }
01537
01538 static void
01539 rb_ary_splice(VALUE ary, long beg, long len, VALUE rpl)
01540 {
01541 long rlen;
01542 long olen;
01543
01544 if (len < 0) rb_raise(rb_eIndexError, "negative length (%ld)", len);
01545 olen = RARRAY_LEN(ary);
01546 if (beg < 0) {
01547 beg += olen;
01548 if (beg < 0) {
01549 rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
01550 beg - olen, -olen);
01551 }
01552 }
01553 if (olen < len || olen < beg + len) {
01554 len = olen - beg;
01555 }
01556
01557 if (rpl == Qundef) {
01558 rlen = 0;
01559 }
01560 else {
01561 rpl = rb_ary_to_ary(rpl);
01562 rlen = RARRAY_LEN(rpl);
01563 olen = RARRAY_LEN(ary);
01564 }
01565 if (beg >= olen) {
01566 if (beg > ARY_MAX_SIZE - rlen) {
01567 rb_raise(rb_eIndexError, "index %ld too big", beg);
01568 }
01569 ary_ensure_room_for_push(ary, rlen-len);
01570 len = beg + rlen;
01571 ary_mem_clear(ary, olen, beg - olen);
01572 if (rlen > 0) {
01573 ary_memcpy(ary, beg, rlen, RARRAY_CONST_PTR(rpl));
01574 }
01575 ARY_SET_LEN(ary, len);
01576 }
01577 else {
01578 long alen;
01579
01580 if (olen - len > ARY_MAX_SIZE - rlen) {
01581 rb_raise(rb_eIndexError, "index %ld too big", olen + rlen - len);
01582 }
01583 rb_ary_modify(ary);
01584 alen = olen + rlen - len;
01585 if (alen >= ARY_CAPA(ary)) {
01586 ary_double_capa(ary, alen);
01587 }
01588
01589 if (len != rlen) {
01590 RARRAY_PTR_USE(ary, ptr,
01591 MEMMOVE(ptr + beg + rlen, ptr + beg + len,
01592 VALUE, olen - (beg + len)));
01593 ARY_SET_LEN(ary, alen);
01594 }
01595 if (rlen > 0) {
01596 MEMMOVE(RARRAY_PTR(ary) + beg, RARRAY_CONST_PTR(rpl), VALUE, rlen);
01597 }
01598 }
01599 RB_GC_GUARD(rpl);
01600 }
01601
01602 void
01603 rb_ary_set_len(VALUE ary, long len)
01604 {
01605 long capa;
01606
01607 rb_ary_modify_check(ary);
01608 if (ARY_SHARED_P(ary)) {
01609 rb_raise(rb_eRuntimeError, "can't set length of shared ");
01610 }
01611 if (len > (capa = (long)ARY_CAPA(ary))) {
01612 rb_bug("probable buffer overflow: %ld for %ld", len, capa);
01613 }
01614 ARY_SET_LEN(ary, len);
01615 }
01616
01625 VALUE
01626 rb_ary_resize(VALUE ary, long len)
01627 {
01628 long olen;
01629
01630 rb_ary_modify(ary);
01631 olen = RARRAY_LEN(ary);
01632 if (len == olen) return ary;
01633 if (len > ARY_MAX_SIZE) {
01634 rb_raise(rb_eIndexError, "index %ld too big", len);
01635 }
01636 if (len > olen) {
01637 if (len >= ARY_CAPA(ary)) {
01638 ary_double_capa(ary, len);
01639 }
01640 ary_mem_clear(ary, olen, len - olen);
01641 ARY_SET_LEN(ary, len);
01642 }
01643 else if (ARY_EMBED_P(ary)) {
01644 ARY_SET_EMBED_LEN(ary, len);
01645 }
01646 else if (len <= RARRAY_EMBED_LEN_MAX) {
01647 VALUE tmp[RARRAY_EMBED_LEN_MAX];
01648 MEMCPY(tmp, ARY_HEAP_PTR(ary), VALUE, len);
01649 ary_discard(ary);
01650 MEMCPY((VALUE *)ARY_EMBED_PTR(ary), tmp, VALUE, len);
01651 ARY_SET_EMBED_LEN(ary, len);
01652 }
01653 else {
01654 if (olen > len + ARY_DEFAULT_SIZE) {
01655 SIZED_REALLOC_N(RARRAY(ary)->as.heap.ptr, VALUE, len, RARRAY(ary)->as.heap.aux.capa);
01656 ARY_SET_CAPA(ary, len);
01657 }
01658 ARY_SET_HEAP_LEN(ary, len);
01659 }
01660 return ary;
01661 }
01662
01663
01664
01665
01666
01667
01668
01669
01670
01671
01672
01673
01674
01675
01676
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686
01687
01688
01689
01690
01691
01692
01693
01694
01695
01696
01697
01698 static VALUE
01699 rb_ary_aset(int argc, VALUE *argv, VALUE ary)
01700 {
01701 long offset, beg, len;
01702
01703 if (argc == 3) {
01704 rb_ary_modify_check(ary);
01705 beg = NUM2LONG(argv[0]);
01706 len = NUM2LONG(argv[1]);
01707 rb_ary_splice(ary, beg, len, argv[2]);
01708 return argv[2];
01709 }
01710 rb_check_arity(argc, 2, 2);
01711 rb_ary_modify_check(ary);
01712 if (FIXNUM_P(argv[0])) {
01713 offset = FIX2LONG(argv[0]);
01714 goto fixnum;
01715 }
01716 if (rb_range_beg_len(argv[0], &beg, &len, RARRAY_LEN(ary), 1)) {
01717
01718 rb_ary_splice(ary, beg, len, argv[1]);
01719 return argv[1];
01720 }
01721
01722 offset = NUM2LONG(argv[0]);
01723 fixnum:
01724 rb_ary_store(ary, offset, argv[1]);
01725 return argv[1];
01726 }
01727
01728
01729
01730
01731
01732
01733
01734
01735
01736
01737
01738
01739
01740
01741
01742 static VALUE
01743 rb_ary_insert(int argc, VALUE *argv, VALUE ary)
01744 {
01745 long pos;
01746
01747 rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
01748 rb_ary_modify_check(ary);
01749 if (argc == 1) return ary;
01750 pos = NUM2LONG(argv[0]);
01751 if (pos == -1) {
01752 pos = RARRAY_LEN(ary);
01753 }
01754 if (pos < 0) {
01755 pos++;
01756 }
01757 rb_ary_splice(ary, pos, 0, rb_ary_new4(argc - 1, argv + 1));
01758 return ary;
01759 }
01760
01761 static VALUE
01762 rb_ary_length(VALUE ary);
01763
01764 static VALUE
01765 ary_enum_length(VALUE ary, VALUE args, VALUE eobj)
01766 {
01767 return rb_ary_length(ary);
01768 }
01769
01770
01771
01772
01773
01774
01775
01776
01777
01778
01779
01780
01781
01782
01783
01784
01785
01786
01787
01788 VALUE
01789 rb_ary_each(VALUE array)
01790 {
01791 long i;
01792 volatile VALUE ary = array;
01793
01794 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
01795 for (i=0; i<RARRAY_LEN(ary); i++) {
01796 rb_yield(RARRAY_AREF(ary, i));
01797 }
01798 return ary;
01799 }
01800
01801
01802
01803
01804
01805
01806
01807
01808
01809
01810
01811
01812
01813
01814
01815
01816
01817
01818
01819 static VALUE
01820 rb_ary_each_index(VALUE ary)
01821 {
01822 long i;
01823 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
01824
01825 for (i=0; i<RARRAY_LEN(ary); i++) {
01826 rb_yield(LONG2NUM(i));
01827 }
01828 return ary;
01829 }
01830
01831
01832
01833
01834
01835
01836
01837
01838
01839
01840
01841
01842
01843
01844
01845
01846 static VALUE
01847 rb_ary_reverse_each(VALUE ary)
01848 {
01849 long len;
01850
01851 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
01852 len = RARRAY_LEN(ary);
01853 while (len--) {
01854 long nlen;
01855 rb_yield(RARRAY_AREF(ary, len));
01856 nlen = RARRAY_LEN(ary);
01857 if (nlen < len) {
01858 len = nlen;
01859 }
01860 }
01861 return ary;
01862 }
01863
01864
01865
01866
01867
01868
01869
01870
01871
01872
01873
01874 static VALUE
01875 rb_ary_length(VALUE ary)
01876 {
01877 long len = RARRAY_LEN(ary);
01878 return LONG2NUM(len);
01879 }
01880
01881
01882
01883
01884
01885
01886
01887
01888
01889
01890 static VALUE
01891 rb_ary_empty_p(VALUE ary)
01892 {
01893 if (RARRAY_LEN(ary) == 0)
01894 return Qtrue;
01895 return Qfalse;
01896 }
01897
01898 VALUE
01899 rb_ary_dup(VALUE ary)
01900 {
01901 long len = RARRAY_LEN(ary);
01902 VALUE dup = rb_ary_new2(len);
01903 ary_memcpy(dup, 0, len, RARRAY_CONST_PTR(ary));
01904 ARY_SET_LEN(dup, len);
01905 return dup;
01906 }
01907
01908 VALUE
01909 rb_ary_resurrect(VALUE ary)
01910 {
01911 return rb_ary_new4(RARRAY_LEN(ary), RARRAY_CONST_PTR(ary));
01912 }
01913
01914 extern VALUE rb_output_fs;
01915
01916 static void ary_join_1(VALUE obj, VALUE ary, VALUE sep, long i, VALUE result, int *first);
01917
01918 static VALUE
01919 recursive_join(VALUE obj, VALUE argp, int recur)
01920 {
01921 VALUE *arg = (VALUE *)argp;
01922 VALUE ary = arg[0];
01923 VALUE sep = arg[1];
01924 VALUE result = arg[2];
01925 int *first = (int *)arg[3];
01926
01927 if (recur) {
01928 rb_raise(rb_eArgError, "recursive array join");
01929 }
01930 else {
01931 ary_join_1(obj, ary, sep, 0, result, first);
01932 }
01933 return Qnil;
01934 }
01935
01936 static void
01937 ary_join_0(VALUE ary, VALUE sep, long max, VALUE result)
01938 {
01939 long i;
01940 VALUE val;
01941
01942 if (max > 0) rb_enc_copy(result, RARRAY_AREF(ary, 0));
01943 for (i=0; i<max; i++) {
01944 val = RARRAY_AREF(ary, i);
01945 if (i > 0 && !NIL_P(sep))
01946 rb_str_buf_append(result, sep);
01947 rb_str_buf_append(result, val);
01948 if (OBJ_TAINTED(val)) OBJ_TAINT(result);
01949 }
01950 }
01951
01952 static void
01953 ary_join_1(VALUE obj, VALUE ary, VALUE sep, long i, VALUE result, int *first)
01954 {
01955 VALUE val, tmp;
01956
01957 for (; i<RARRAY_LEN(ary); i++) {
01958 if (i > 0 && !NIL_P(sep))
01959 rb_str_buf_append(result, sep);
01960
01961 val = RARRAY_AREF(ary, i);
01962 if (RB_TYPE_P(val, T_STRING)) {
01963 str_join:
01964 rb_str_buf_append(result, val);
01965 *first = FALSE;
01966 }
01967 else if (RB_TYPE_P(val, T_ARRAY)) {
01968 obj = val;
01969 ary_join:
01970 if (val == ary) {
01971 rb_raise(rb_eArgError, "recursive array join");
01972 }
01973 else {
01974 VALUE args[4];
01975
01976 args[0] = val;
01977 args[1] = sep;
01978 args[2] = result;
01979 args[3] = (VALUE)first;
01980 rb_exec_recursive(recursive_join, obj, (VALUE)args);
01981 }
01982 }
01983 else {
01984 tmp = rb_check_string_type(val);
01985 if (!NIL_P(tmp)) {
01986 val = tmp;
01987 goto str_join;
01988 }
01989 tmp = rb_check_convert_type(val, T_ARRAY, "Array", "to_ary");
01990 if (!NIL_P(tmp)) {
01991 obj = val;
01992 val = tmp;
01993 goto ary_join;
01994 }
01995 val = rb_obj_as_string(val);
01996 if (*first) {
01997 rb_enc_copy(result, val);
01998 *first = FALSE;
01999 }
02000 goto str_join;
02001 }
02002 }
02003 }
02004
02005 VALUE
02006 rb_ary_join(VALUE ary, VALUE sep)
02007 {
02008 long len = 1, i;
02009 int taint = FALSE;
02010 VALUE val, tmp, result;
02011
02012 if (RARRAY_LEN(ary) == 0) return rb_usascii_str_new(0, 0);
02013 if (OBJ_TAINTED(ary)) taint = TRUE;
02014
02015 if (!NIL_P(sep)) {
02016 StringValue(sep);
02017 len += RSTRING_LEN(sep) * (RARRAY_LEN(ary) - 1);
02018 }
02019 for (i=0; i<RARRAY_LEN(ary); i++) {
02020 val = RARRAY_AREF(ary, i);
02021 tmp = rb_check_string_type(val);
02022
02023 if (NIL_P(tmp) || tmp != val) {
02024 int first;
02025 result = rb_str_buf_new(len + (RARRAY_LEN(ary)-i)*10);
02026 rb_enc_associate(result, rb_usascii_encoding());
02027 if (taint) OBJ_TAINT(result);
02028 ary_join_0(ary, sep, i, result);
02029 first = i == 0;
02030 ary_join_1(ary, ary, sep, i, result, &first);
02031 return result;
02032 }
02033
02034 len += RSTRING_LEN(tmp);
02035 }
02036
02037 result = rb_str_buf_new(len);
02038 if (taint) OBJ_TAINT(result);
02039 ary_join_0(ary, sep, RARRAY_LEN(ary), result);
02040
02041 return result;
02042 }
02043
02044
02045
02046
02047
02048
02049
02050
02051
02052
02053
02054
02055
02056
02057 static VALUE
02058 rb_ary_join_m(int argc, VALUE *argv, VALUE ary)
02059 {
02060 VALUE sep;
02061
02062 rb_scan_args(argc, argv, "01", &sep);
02063 if (NIL_P(sep)) sep = rb_output_fs;
02064
02065 return rb_ary_join(ary, sep);
02066 }
02067
02068 static VALUE
02069 inspect_ary(VALUE ary, VALUE dummy, int recur)
02070 {
02071 int tainted = OBJ_TAINTED(ary);
02072 long i;
02073 VALUE s, str;
02074
02075 if (recur) return rb_usascii_str_new_cstr("[...]");
02076 str = rb_str_buf_new2("[");
02077 for (i=0; i<RARRAY_LEN(ary); i++) {
02078 s = rb_inspect(RARRAY_AREF(ary, i));
02079 if (OBJ_TAINTED(s)) tainted = TRUE;
02080 if (i > 0) rb_str_buf_cat2(str, ", ");
02081 else rb_enc_copy(str, s);
02082 rb_str_buf_append(str, s);
02083 }
02084 rb_str_buf_cat2(str, "]");
02085 if (tainted) OBJ_TAINT(str);
02086 return str;
02087 }
02088
02089
02090
02091
02092
02093
02094
02095
02096
02097
02098
02099 static VALUE
02100 rb_ary_inspect(VALUE ary)
02101 {
02102 if (RARRAY_LEN(ary) == 0) return rb_usascii_str_new2("[]");
02103 return rb_exec_recursive(inspect_ary, ary, 0);
02104 }
02105
02106 VALUE
02107 rb_ary_to_s(VALUE ary)
02108 {
02109 return rb_ary_inspect(ary);
02110 }
02111
02112
02113
02114
02115
02116
02117
02118
02119
02120
02121 static VALUE
02122 rb_ary_to_a(VALUE ary)
02123 {
02124 if (rb_obj_class(ary) != rb_cArray) {
02125 VALUE dup = rb_ary_new2(RARRAY_LEN(ary));
02126 rb_ary_replace(dup, ary);
02127 return dup;
02128 }
02129 return ary;
02130 }
02131
02132
02133
02134
02135
02136
02137
02138
02139
02140
02141
02142
02143 static VALUE
02144 rb_ary_to_h(VALUE ary)
02145 {
02146 long i;
02147 VALUE hash = rb_hash_new();
02148 for (i=0; i<RARRAY_LEN(ary); i++) {
02149 VALUE key_value_pair = rb_check_array_type(rb_ary_elt(ary, i));
02150 if (NIL_P(key_value_pair)) {
02151 rb_raise(rb_eTypeError, "wrong element type %s at %ld (expected array)",
02152 rb_builtin_class_name(rb_ary_elt(ary, i)), i);
02153 }
02154 if (RARRAY_LEN(key_value_pair) != 2) {
02155 rb_raise(rb_eArgError, "wrong array length at %ld (expected 2, was %ld)",
02156 i, RARRAY_LEN(key_value_pair));
02157 }
02158 rb_hash_aset(hash, RARRAY_AREF(key_value_pair, 0), RARRAY_AREF(key_value_pair, 1));
02159 }
02160 return hash;
02161 }
02162
02163
02164
02165
02166
02167
02168
02169
02170 static VALUE
02171 rb_ary_to_ary_m(VALUE ary)
02172 {
02173 return ary;
02174 }
02175
02176 static void
02177 ary_reverse(VALUE *p1, VALUE *p2)
02178 {
02179 while (p1 < p2) {
02180 VALUE tmp = *p1;
02181 *p1++ = *p2;
02182 *p2-- = tmp;
02183 }
02184 }
02185
02186 VALUE
02187 rb_ary_reverse(VALUE ary)
02188 {
02189 VALUE *p2;
02190 long len = RARRAY_LEN(ary);
02191
02192 rb_ary_modify(ary);
02193 if (len > 1) {
02194 RARRAY_PTR_USE(ary, p1, {
02195 p2 = p1 + len - 1;
02196 ary_reverse(p1, p2);
02197 });
02198 }
02199 return ary;
02200 }
02201
02202
02203
02204
02205
02206
02207
02208
02209
02210
02211
02212
02213 static VALUE
02214 rb_ary_reverse_bang(VALUE ary)
02215 {
02216 return rb_ary_reverse(ary);
02217 }
02218
02219
02220
02221
02222
02223
02224
02225
02226
02227
02228
02229 static VALUE
02230 rb_ary_reverse_m(VALUE ary)
02231 {
02232 long len = RARRAY_LEN(ary);
02233 VALUE dup = rb_ary_new2(len);
02234
02235 if (len > 0) {
02236 const VALUE *p1 = RARRAY_CONST_PTR(ary);
02237 VALUE *p2 = (VALUE *)RARRAY_CONST_PTR(dup) + len - 1;
02238 do *p2-- = *p1++; while (--len > 0);
02239 }
02240 ARY_SET_LEN(dup, RARRAY_LEN(ary));
02241 return dup;
02242 }
02243
02244 static inline long
02245 rotate_count(long cnt, long len)
02246 {
02247 return (cnt < 0) ? (len - (~cnt % len) - 1) : (cnt % len);
02248 }
02249
02250 VALUE
02251 rb_ary_rotate(VALUE ary, long cnt)
02252 {
02253 rb_ary_modify(ary);
02254
02255 if (cnt != 0) {
02256 VALUE *ptr = RARRAY_PTR(ary);
02257 long len = RARRAY_LEN(ary);
02258
02259 if (len > 0 && (cnt = rotate_count(cnt, len)) > 0) {
02260 --len;
02261 if (cnt < len) ary_reverse(ptr + cnt, ptr + len);
02262 if (--cnt > 0) ary_reverse(ptr, ptr + cnt);
02263 if (len > 0) ary_reverse(ptr, ptr + len);
02264 return ary;
02265 }
02266 }
02267
02268 return Qnil;
02269 }
02270
02271
02272
02273
02274
02275
02276
02277
02278
02279
02280
02281
02282
02283
02284
02285
02286
02287
02288 static VALUE
02289 rb_ary_rotate_bang(int argc, VALUE *argv, VALUE ary)
02290 {
02291 long n = 1;
02292
02293 switch (argc) {
02294 case 1: n = NUM2LONG(argv[0]);
02295 case 0: break;
02296 default: rb_scan_args(argc, argv, "01", NULL);
02297 }
02298 rb_ary_rotate(ary, n);
02299 return ary;
02300 }
02301
02302
02303
02304
02305
02306
02307
02308
02309
02310
02311
02312
02313
02314
02315
02316
02317
02318
02319 static VALUE
02320 rb_ary_rotate_m(int argc, VALUE *argv, VALUE ary)
02321 {
02322 VALUE rotated;
02323 const VALUE *ptr;
02324 long len, cnt = 1;
02325
02326 switch (argc) {
02327 case 1: cnt = NUM2LONG(argv[0]);
02328 case 0: break;
02329 default: rb_scan_args(argc, argv, "01", NULL);
02330 }
02331
02332 len = RARRAY_LEN(ary);
02333 rotated = rb_ary_new2(len);
02334 if (len > 0) {
02335 cnt = rotate_count(cnt, len);
02336 ptr = RARRAY_CONST_PTR(ary);
02337 len -= cnt;
02338 ary_memcpy(rotated, 0, len, ptr + cnt);
02339 ary_memcpy(rotated, len, cnt, ptr);
02340 }
02341 ARY_SET_LEN(rotated, RARRAY_LEN(ary));
02342 return rotated;
02343 }
02344
02345 struct ary_sort_data {
02346 VALUE ary;
02347 int opt_methods;
02348 int opt_inited;
02349 };
02350
02351 enum {
02352 sort_opt_Fixnum,
02353 sort_opt_String,
02354 sort_optimizable_count
02355 };
02356
02357 #define STRING_P(s) (RB_TYPE_P((s), T_STRING) && CLASS_OF(s) == rb_cString)
02358
02359 #define SORT_OPTIMIZABLE_BIT(type) (1U << TOKEN_PASTE(sort_opt_,type))
02360 #define SORT_OPTIMIZABLE(data, type) \
02361 (((data)->opt_inited & SORT_OPTIMIZABLE_BIT(type)) ? \
02362 ((data)->opt_methods & SORT_OPTIMIZABLE_BIT(type)) : \
02363 (((data)->opt_inited |= SORT_OPTIMIZABLE_BIT(type)), \
02364 rb_method_basic_definition_p(TOKEN_PASTE(rb_c,type), id_cmp) && \
02365 ((data)->opt_methods |= SORT_OPTIMIZABLE_BIT(type))))
02366
02367 static VALUE
02368 sort_reentered(VALUE ary)
02369 {
02370 if (RBASIC(ary)->klass) {
02371 rb_raise(rb_eRuntimeError, "sort reentered");
02372 }
02373 return Qnil;
02374 }
02375
02376 static int
02377 sort_1(const void *ap, const void *bp, void *dummy)
02378 {
02379 struct ary_sort_data *data = dummy;
02380 VALUE retval = sort_reentered(data->ary);
02381 VALUE a = *(const VALUE *)ap, b = *(const VALUE *)bp;
02382 int n;
02383
02384 retval = rb_yield_values(2, a, b);
02385 n = rb_cmpint(retval, a, b);
02386 sort_reentered(data->ary);
02387 return n;
02388 }
02389
02390 static int
02391 sort_2(const void *ap, const void *bp, void *dummy)
02392 {
02393 struct ary_sort_data *data = dummy;
02394 VALUE retval = sort_reentered(data->ary);
02395 VALUE a = *(const VALUE *)ap, b = *(const VALUE *)bp;
02396 int n;
02397
02398 if (FIXNUM_P(a) && FIXNUM_P(b) && SORT_OPTIMIZABLE(data, Fixnum)) {
02399 if ((long)a > (long)b) return 1;
02400 if ((long)a < (long)b) return -1;
02401 return 0;
02402 }
02403 if (STRING_P(a) && STRING_P(b) && SORT_OPTIMIZABLE(data, String)) {
02404 return rb_str_cmp(a, b);
02405 }
02406
02407 retval = rb_funcallv(a, id_cmp, 1, &b);
02408 n = rb_cmpint(retval, a, b);
02409 sort_reentered(data->ary);
02410
02411 return n;
02412 }
02413
02414
02415
02416
02417
02418
02419
02420
02421
02422
02423
02424
02425
02426
02427
02428
02429
02430
02431
02432
02433
02434
02435 VALUE
02436 rb_ary_sort_bang(VALUE ary)
02437 {
02438 rb_ary_modify(ary);
02439 assert(!ARY_SHARED_P(ary));
02440 if (RARRAY_LEN(ary) > 1) {
02441 VALUE tmp = ary_make_substitution(ary);
02442 struct ary_sort_data data;
02443 long len = RARRAY_LEN(ary);
02444
02445 RBASIC_CLEAR_CLASS(tmp);
02446 data.ary = tmp;
02447 data.opt_methods = 0;
02448 data.opt_inited = 0;
02449 RARRAY_PTR_USE(tmp, ptr, {
02450 ruby_qsort(ptr, len, sizeof(VALUE),
02451 rb_block_given_p()?sort_1:sort_2, &data);
02452 });
02453 rb_ary_modify(ary);
02454 if (ARY_EMBED_P(tmp)) {
02455 if (ARY_SHARED_P(ary)) {
02456 rb_ary_unshare(ary);
02457 }
02458 FL_SET_EMBED(ary);
02459 ary_memcpy(ary, 0, ARY_EMBED_LEN(tmp), ARY_EMBED_PTR(tmp));
02460 ARY_SET_LEN(ary, ARY_EMBED_LEN(tmp));
02461 }
02462 else {
02463 if (!ARY_EMBED_P(ary) && ARY_HEAP_PTR(ary) == ARY_HEAP_PTR(tmp)) {
02464 FL_UNSET_SHARED(ary);
02465 ARY_SET_CAPA(ary, RARRAY_LEN(tmp));
02466 }
02467 else {
02468 assert(!ARY_SHARED_P(tmp));
02469 if (ARY_EMBED_P(ary)) {
02470 FL_UNSET_EMBED(ary);
02471 }
02472 else if (ARY_SHARED_P(ary)) {
02473
02474 rb_ary_unshare(ary);
02475 }
02476 else {
02477 ruby_sized_xfree((void *)ARY_HEAP_PTR(ary), ARY_HEAP_SIZE(ary));
02478 }
02479 ARY_SET_PTR(ary, RARRAY_CONST_PTR(tmp));
02480 ARY_SET_HEAP_LEN(ary, len);
02481 ARY_SET_CAPA(ary, RARRAY_LEN(tmp));
02482 }
02483
02484 FL_UNSET(tmp, FL_FREEZE);
02485 FL_SET_EMBED(tmp);
02486 ARY_SET_EMBED_LEN(tmp, 0);
02487 FL_SET(tmp, FL_FREEZE);
02488 }
02489
02490 RBASIC_SET_CLASS_RAW(tmp, rb_cArray);
02491 }
02492 return ary;
02493 }
02494
02495
02496
02497
02498
02499
02500
02501
02502
02503
02504
02505
02506
02507
02508
02509
02510
02511
02512
02513
02514
02515
02516
02517 VALUE
02518 rb_ary_sort(VALUE ary)
02519 {
02520 ary = rb_ary_dup(ary);
02521 rb_ary_sort_bang(ary);
02522 return ary;
02523 }
02524
02525
02526
02527
02528
02529
02530
02531
02532
02533
02534
02535
02536
02537
02538
02539
02540
02541
02542
02543
02544
02545
02546
02547
02548
02549
02550
02551
02552
02553
02554
02555
02556
02557
02558
02559
02560
02561
02562
02563
02564
02565
02566
02567
02568
02569
02570
02571
02572
02573
02574
02575
02576
02577
02578 static VALUE
02579 rb_ary_bsearch(VALUE ary)
02580 {
02581 long low = 0, high = RARRAY_LEN(ary), mid;
02582 int smaller = 0, satisfied = 0;
02583 VALUE v, val;
02584
02585 RETURN_ENUMERATOR(ary, 0, 0);
02586 while (low < high) {
02587 mid = low + ((high - low) / 2);
02588 val = rb_ary_entry(ary, mid);
02589 v = rb_yield(val);
02590 if (FIXNUM_P(v)) {
02591 if (FIX2INT(v) == 0) return val;
02592 smaller = FIX2INT(v) < 0;
02593 }
02594 else if (v == Qtrue) {
02595 satisfied = 1;
02596 smaller = 1;
02597 }
02598 else if (v == Qfalse || v == Qnil) {
02599 smaller = 0;
02600 }
02601 else if (rb_obj_is_kind_of(v, rb_cNumeric)) {
02602 const VALUE zero = INT2FIX(0);
02603 switch (rb_cmpint(rb_funcallv(v, id_cmp, 1, &zero), v, INT2FIX(0))) {
02604 case 0: return val;
02605 case 1: smaller = 1; break;
02606 case -1: smaller = 0;
02607 }
02608 }
02609 else {
02610 rb_raise(rb_eTypeError, "wrong argument type %s"
02611 " (must be numeric, true, false or nil)",
02612 rb_obj_classname(v));
02613 }
02614 if (smaller) {
02615 high = mid;
02616 }
02617 else {
02618 low = mid + 1;
02619 }
02620 }
02621 if (low == RARRAY_LEN(ary)) return Qnil;
02622 if (!satisfied) return Qnil;
02623 return rb_ary_entry(ary, low);
02624 }
02625
02626
02627 static VALUE
02628 sort_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, dummy))
02629 {
02630 return rb_yield(i);
02631 }
02632
02633
02634
02635
02636
02637
02638
02639
02640
02641
02642
02643
02644
02645 static VALUE
02646 rb_ary_sort_by_bang(VALUE ary)
02647 {
02648 VALUE sorted;
02649
02650 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
02651 rb_ary_modify(ary);
02652 sorted = rb_block_call(ary, rb_intern("sort_by"), 0, 0, sort_by_i, 0);
02653 rb_ary_replace(ary, sorted);
02654 return ary;
02655 }
02656
02657
02658
02659
02660
02661
02662
02663
02664
02665
02666
02667
02668
02669
02670
02671
02672
02673
02674
02675
02676
02677
02678
02679 static VALUE
02680 rb_ary_collect(VALUE ary)
02681 {
02682 long i;
02683 VALUE collect;
02684
02685 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
02686 collect = rb_ary_new2(RARRAY_LEN(ary));
02687 for (i = 0; i < RARRAY_LEN(ary); i++) {
02688 rb_ary_push(collect, rb_yield(RARRAY_AREF(ary, i)));
02689 }
02690 return collect;
02691 }
02692
02693
02694
02695
02696
02697
02698
02699
02700
02701
02702
02703
02704
02705
02706
02707
02708
02709
02710
02711
02712
02713
02714
02715 static VALUE
02716 rb_ary_collect_bang(VALUE ary)
02717 {
02718 long i;
02719
02720 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
02721 rb_ary_modify(ary);
02722 for (i = 0; i < RARRAY_LEN(ary); i++) {
02723 rb_ary_store(ary, i, rb_yield(RARRAY_AREF(ary, i)));
02724 }
02725 return ary;
02726 }
02727
02728 VALUE
02729 rb_get_values_at(VALUE obj, long olen, int argc, VALUE *argv, VALUE (*func) (VALUE, long))
02730 {
02731 VALUE result = rb_ary_new2(argc);
02732 long beg, len, i, j;
02733
02734 for (i=0; i<argc; i++) {
02735 if (FIXNUM_P(argv[i])) {
02736 rb_ary_push(result, (*func)(obj, FIX2LONG(argv[i])));
02737 continue;
02738 }
02739
02740 if (rb_range_beg_len(argv[i], &beg, &len, olen, 1)) {
02741 long end = olen < beg+len ? olen : beg+len;
02742 for (j = beg; j < end; j++) {
02743 rb_ary_push(result, (*func)(obj, j));
02744 }
02745 if (beg + len > j)
02746 rb_ary_resize(result, RARRAY_LEN(result) + (beg + len) - j);
02747 continue;
02748 }
02749 rb_ary_push(result, (*func)(obj, NUM2LONG(argv[i])));
02750 }
02751 return result;
02752 }
02753
02754
02755
02756
02757
02758
02759
02760
02761
02762
02763
02764
02765
02766
02767
02768
02769
02770
02771
02772 static VALUE
02773 rb_ary_values_at(int argc, VALUE *argv, VALUE ary)
02774 {
02775 return rb_get_values_at(ary, RARRAY_LEN(ary), argc, argv, rb_ary_entry);
02776 }
02777
02778
02779
02780
02781
02782
02783
02784
02785
02786
02787
02788
02789
02790
02791
02792
02793
02794
02795
02796
02797 static VALUE
02798 rb_ary_select(VALUE ary)
02799 {
02800 VALUE result;
02801 long i;
02802
02803 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
02804 result = rb_ary_new2(RARRAY_LEN(ary));
02805 for (i = 0; i < RARRAY_LEN(ary); i++) {
02806 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) {
02807 rb_ary_push(result, rb_ary_elt(ary, i));
02808 }
02809 }
02810 return result;
02811 }
02812
02813
02814
02815
02816
02817
02818
02819
02820
02821
02822
02823
02824
02825
02826
02827
02828
02829 static VALUE
02830 rb_ary_select_bang(VALUE ary)
02831 {
02832 long i1, i2;
02833
02834 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
02835 rb_ary_modify(ary);
02836 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
02837 VALUE v = RARRAY_AREF(ary, i1);
02838 if (!RTEST(rb_yield(v))) continue;
02839 if (i1 != i2) {
02840 rb_ary_store(ary, i2, v);
02841 }
02842 i2++;
02843 }
02844
02845 if (i1 == i2) return Qnil;
02846 if (i2 < i1)
02847 ARY_SET_LEN(ary, i2);
02848 return ary;
02849 }
02850
02851
02852
02853
02854
02855
02856
02857
02858
02859
02860
02861
02862
02863
02864
02865
02866
02867 static VALUE
02868 rb_ary_keep_if(VALUE ary)
02869 {
02870 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
02871 rb_ary_select_bang(ary);
02872 return ary;
02873 }
02874
02875 static void
02876 ary_resize_smaller(VALUE ary, long len)
02877 {
02878 rb_ary_modify(ary);
02879 if (RARRAY_LEN(ary) > len) {
02880 ARY_SET_LEN(ary, len);
02881 if (len * 2 < ARY_CAPA(ary) &&
02882 ARY_CAPA(ary) > ARY_DEFAULT_SIZE) {
02883 ary_resize_capa(ary, len * 2);
02884 }
02885 }
02886 }
02887
02888
02889
02890
02891
02892
02893
02894
02895
02896
02897
02898
02899
02900
02901
02902
02903
02904
02905
02906
02907
02908 VALUE
02909 rb_ary_delete(VALUE ary, VALUE item)
02910 {
02911 VALUE v = item;
02912 long i1, i2;
02913
02914 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
02915 VALUE e = RARRAY_AREF(ary, i1);
02916
02917 if (rb_equal(e, item)) {
02918 v = e;
02919 continue;
02920 }
02921 if (i1 != i2) {
02922 rb_ary_store(ary, i2, e);
02923 }
02924 i2++;
02925 }
02926 if (RARRAY_LEN(ary) == i2) {
02927 if (rb_block_given_p()) {
02928 return rb_yield(item);
02929 }
02930 return Qnil;
02931 }
02932
02933 ary_resize_smaller(ary, i2);
02934
02935 return v;
02936 }
02937
02938 void
02939 rb_ary_delete_same(VALUE ary, VALUE item)
02940 {
02941 long i1, i2;
02942
02943 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
02944 VALUE e = RARRAY_AREF(ary, i1);
02945
02946 if (e == item) {
02947 continue;
02948 }
02949 if (i1 != i2) {
02950 rb_ary_store(ary, i2, e);
02951 }
02952 i2++;
02953 }
02954 if (RARRAY_LEN(ary) == i2) {
02955 return;
02956 }
02957
02958 ary_resize_smaller(ary, i2);
02959 }
02960
02961 VALUE
02962 rb_ary_delete_at(VALUE ary, long pos)
02963 {
02964 long len = RARRAY_LEN(ary);
02965 VALUE del;
02966
02967 if (pos >= len) return Qnil;
02968 if (pos < 0) {
02969 pos += len;
02970 if (pos < 0) return Qnil;
02971 }
02972
02973 rb_ary_modify(ary);
02974 del = RARRAY_AREF(ary, pos);
02975 RARRAY_PTR_USE(ary, ptr, {
02976 MEMMOVE(ptr+pos, ptr+pos+1, VALUE, len-pos-1);
02977 });
02978 ARY_INCREASE_LEN(ary, -1);
02979
02980 return del;
02981 }
02982
02983
02984
02985
02986
02987
02988
02989
02990
02991
02992
02993
02994
02995
02996
02997
02998 static VALUE
02999 rb_ary_delete_at_m(VALUE ary, VALUE pos)
03000 {
03001 return rb_ary_delete_at(ary, NUM2LONG(pos));
03002 }
03003
03004
03005
03006
03007
03008
03009
03010
03011
03012
03013
03014
03015
03016
03017
03018
03019
03020
03021
03022
03023
03024
03025 static VALUE
03026 rb_ary_slice_bang(int argc, VALUE *argv, VALUE ary)
03027 {
03028 VALUE arg1, arg2;
03029 long pos, len, orig_len;
03030
03031 rb_ary_modify_check(ary);
03032 if (argc == 2) {
03033 pos = NUM2LONG(argv[0]);
03034 len = NUM2LONG(argv[1]);
03035 delete_pos_len:
03036 if (len < 0) return Qnil;
03037 orig_len = RARRAY_LEN(ary);
03038 if (pos < 0) {
03039 pos += orig_len;
03040 if (pos < 0) return Qnil;
03041 }
03042 else if (orig_len < pos) return Qnil;
03043 if (orig_len < pos + len) {
03044 len = orig_len - pos;
03045 }
03046 if (len == 0) return rb_ary_new2(0);
03047 arg2 = rb_ary_new4(len, RARRAY_CONST_PTR(ary)+pos);
03048 RBASIC_SET_CLASS(arg2, rb_obj_class(ary));
03049 rb_ary_splice(ary, pos, len, Qundef);
03050 return arg2;
03051 }
03052
03053 if (argc != 1) {
03054
03055 rb_scan_args(argc, argv, "11", NULL, NULL);
03056 }
03057 arg1 = argv[0];
03058
03059 if (!FIXNUM_P(arg1)) {
03060 switch (rb_range_beg_len(arg1, &pos, &len, RARRAY_LEN(ary), 0)) {
03061 case Qtrue:
03062
03063 goto delete_pos_len;
03064 case Qnil:
03065
03066 return Qnil;
03067 default:
03068
03069 break;
03070 }
03071 }
03072
03073 return rb_ary_delete_at(ary, NUM2LONG(arg1));
03074 }
03075
03076 static VALUE
03077 ary_reject(VALUE orig, VALUE result)
03078 {
03079 long i;
03080
03081 for (i = 0; i < RARRAY_LEN(orig); i++) {
03082 VALUE v = RARRAY_AREF(orig, i);
03083 if (!RTEST(rb_yield(v))) {
03084 rb_ary_push(result, v);
03085 }
03086 }
03087 return result;
03088 }
03089
03090 static VALUE
03091 ary_reject_bang(VALUE ary)
03092 {
03093 long i;
03094 VALUE result = Qnil;
03095
03096 rb_ary_modify_check(ary);
03097 for (i = 0; i < RARRAY_LEN(ary); ) {
03098 VALUE v = RARRAY_AREF(ary, i);
03099 if (RTEST(rb_yield(v))) {
03100 rb_ary_delete_at(ary, i);
03101 result = ary;
03102 }
03103 else {
03104 i++;
03105 }
03106 }
03107 return result;
03108 }
03109
03110
03111
03112
03113
03114
03115
03116
03117
03118
03119
03120
03121
03122
03123
03124
03125
03126 static VALUE
03127 rb_ary_reject_bang(VALUE ary)
03128 {
03129 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
03130 return ary_reject_bang(ary);
03131 }
03132
03133
03134
03135
03136
03137
03138
03139
03140
03141
03142
03143
03144
03145
03146 static VALUE
03147 rb_ary_reject(VALUE ary)
03148 {
03149 VALUE rejected_ary;
03150
03151 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
03152 rejected_ary = rb_ary_new();
03153 ary_reject(ary, rejected_ary);
03154 return rejected_ary;
03155 }
03156
03157
03158
03159
03160
03161
03162
03163
03164
03165
03166
03167
03168
03169
03170
03171
03172
03173
03174
03175 static VALUE
03176 rb_ary_delete_if(VALUE ary)
03177 {
03178 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
03179 ary_reject_bang(ary);
03180 return ary;
03181 }
03182
03183 static VALUE
03184 take_i(RB_BLOCK_CALL_FUNC_ARGLIST(val, cbarg))
03185 {
03186 VALUE *args = (VALUE *)cbarg;
03187 if (args[1]-- == 0) rb_iter_break();
03188 if (argc > 1) val = rb_ary_new4(argc, argv);
03189 rb_ary_push(args[0], val);
03190 return Qnil;
03191 }
03192
03193 static VALUE
03194 take_items(VALUE obj, long n)
03195 {
03196 VALUE result = rb_check_array_type(obj);
03197 VALUE args[2];
03198
03199 if (!NIL_P(result)) return rb_ary_subseq(result, 0, n);
03200 result = rb_ary_new2(n);
03201 args[0] = result; args[1] = (VALUE)n;
03202 if (rb_check_block_call(obj, idEach, 0, 0, take_i, (VALUE)args) == Qundef)
03203 rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (must respond to :each)",
03204 rb_obj_class(obj));
03205 return result;
03206 }
03207
03208
03209
03210
03211
03212
03213
03214
03215
03216
03217
03218
03219
03220
03221
03222
03223
03224
03225
03226
03227
03228
03229
03230
03231
03232
03233 static VALUE
03234 rb_ary_zip(int argc, VALUE *argv, VALUE ary)
03235 {
03236 int i, j;
03237 long len = RARRAY_LEN(ary);
03238 VALUE result = Qnil;
03239
03240 for (i=0; i<argc; i++) {
03241 argv[i] = take_items(argv[i], len);
03242 }
03243
03244 if (rb_block_given_p()) {
03245 int arity = rb_block_arity();
03246
03247 if (arity > 1 && argc+1 < 0x100) {
03248 VALUE *tmp = ALLOCA_N(VALUE, argc+1);
03249
03250 for (i=0; i<RARRAY_LEN(ary); i++) {
03251 tmp[0] = RARRAY_AREF(ary, i);
03252 for (j=0; j<argc; j++) {
03253 tmp[j+1] = rb_ary_elt(argv[j], i);
03254 }
03255 rb_yield_values2(argc+1, tmp);
03256 }
03257 }
03258 else {
03259 for (i=0; i<RARRAY_LEN(ary); i++) {
03260 VALUE tmp = rb_ary_new2(argc+1);
03261
03262 rb_ary_push(tmp, RARRAY_AREF(ary, i));
03263 for (j=0; j<argc; j++) {
03264 rb_ary_push(tmp, rb_ary_elt(argv[j], i));
03265 }
03266 rb_yield(tmp);
03267 }
03268 }
03269 }
03270 else {
03271 result = rb_ary_new_capa(len);
03272
03273 for (i=0; i<len; i++) {
03274 VALUE tmp = rb_ary_new_capa(argc+1);
03275
03276 rb_ary_push(tmp, RARRAY_AREF(ary, i));
03277 for (j=0; j<argc; j++) {
03278 rb_ary_push(tmp, rb_ary_elt(argv[j], i));
03279 }
03280 rb_ary_push(result, tmp);
03281 }
03282 }
03283
03284 return result;
03285 }
03286
03287
03288
03289
03290
03291
03292
03293
03294
03295
03296
03297
03298
03299
03300 static VALUE
03301 rb_ary_transpose(VALUE ary)
03302 {
03303 long elen = -1, alen, i, j;
03304 VALUE tmp, result = 0;
03305
03306 alen = RARRAY_LEN(ary);
03307 if (alen == 0) return rb_ary_dup(ary);
03308 for (i=0; i<alen; i++) {
03309 tmp = to_ary(rb_ary_elt(ary, i));
03310 if (elen < 0) {
03311 elen = RARRAY_LEN(tmp);
03312 result = rb_ary_new2(elen);
03313 for (j=0; j<elen; j++) {
03314 rb_ary_store(result, j, rb_ary_new2(alen));
03315 }
03316 }
03317 else if (elen != RARRAY_LEN(tmp)) {
03318 rb_raise(rb_eIndexError, "element size differs (%ld should be %ld)",
03319 RARRAY_LEN(tmp), elen);
03320 }
03321 for (j=0; j<elen; j++) {
03322 rb_ary_store(rb_ary_elt(result, j), i, rb_ary_elt(tmp, j));
03323 }
03324 }
03325 return result;
03326 }
03327
03328
03329
03330
03331
03332
03333
03334
03335
03336
03337
03338
03339
03340
03341 VALUE
03342 rb_ary_replace(VALUE copy, VALUE orig)
03343 {
03344 rb_ary_modify_check(copy);
03345 orig = to_ary(orig);
03346 if (copy == orig) return copy;
03347
03348 if (RARRAY_LEN(orig) <= RARRAY_EMBED_LEN_MAX) {
03349 VALUE shared = 0;
03350
03351 if (ARY_OWNS_HEAP_P(copy)) {
03352 RARRAY_PTR_USE(copy, ptr, ruby_sized_xfree(ptr, ARY_HEAP_SIZE(copy)));
03353 }
03354 else if (ARY_SHARED_P(copy)) {
03355 shared = ARY_SHARED(copy);
03356 FL_UNSET_SHARED(copy);
03357 }
03358 FL_SET_EMBED(copy);
03359 ary_memcpy(copy, 0, RARRAY_LEN(orig), RARRAY_CONST_PTR(orig));
03360 if (shared) {
03361 rb_ary_decrement_share(shared);
03362 }
03363 ARY_SET_LEN(copy, RARRAY_LEN(orig));
03364 }
03365 else {
03366 VALUE shared = ary_make_shared(orig);
03367 if (ARY_OWNS_HEAP_P(copy)) {
03368 RARRAY_PTR_USE(copy, ptr, ruby_sized_xfree(ptr, ARY_HEAP_SIZE(copy)));
03369 }
03370 else {
03371 rb_ary_unshare_safe(copy);
03372 }
03373 FL_UNSET_EMBED(copy);
03374 ARY_SET_PTR(copy, RARRAY_CONST_PTR(orig));
03375 ARY_SET_LEN(copy, RARRAY_LEN(orig));
03376 rb_ary_set_shared(copy, shared);
03377 }
03378 return copy;
03379 }
03380
03381
03382
03383
03384
03385
03386
03387
03388
03389
03390
03391 VALUE
03392 rb_ary_clear(VALUE ary)
03393 {
03394 rb_ary_modify_check(ary);
03395 ARY_SET_LEN(ary, 0);
03396 if (ARY_SHARED_P(ary)) {
03397 if (!ARY_EMBED_P(ary)) {
03398 rb_ary_unshare(ary);
03399 FL_SET_EMBED(ary);
03400 }
03401 }
03402 else if (ARY_DEFAULT_SIZE * 2 < ARY_CAPA(ary)) {
03403 ary_resize_capa(ary, ARY_DEFAULT_SIZE * 2);
03404 }
03405 return ary;
03406 }
03407
03408
03409
03410
03411
03412
03413
03414
03415
03416
03417
03418
03419
03420
03421
03422
03423
03424
03425
03426
03427
03428
03429
03430
03431
03432
03433
03434
03435
03436
03437
03438 static VALUE
03439 rb_ary_fill(int argc, VALUE *argv, VALUE ary)
03440 {
03441 VALUE item, arg1, arg2;
03442 long beg = 0, end = 0, len = 0;
03443 int block_p = FALSE;
03444
03445 if (rb_block_given_p()) {
03446 block_p = TRUE;
03447 rb_scan_args(argc, argv, "02", &arg1, &arg2);
03448 argc += 1;
03449 }
03450 else {
03451 rb_scan_args(argc, argv, "12", &item, &arg1, &arg2);
03452 }
03453 switch (argc) {
03454 case 1:
03455 beg = 0;
03456 len = RARRAY_LEN(ary);
03457 break;
03458 case 2:
03459 if (rb_range_beg_len(arg1, &beg, &len, RARRAY_LEN(ary), 1)) {
03460 break;
03461 }
03462
03463 case 3:
03464 beg = NIL_P(arg1) ? 0 : NUM2LONG(arg1);
03465 if (beg < 0) {
03466 beg = RARRAY_LEN(ary) + beg;
03467 if (beg < 0) beg = 0;
03468 }
03469 len = NIL_P(arg2) ? RARRAY_LEN(ary) - beg : NUM2LONG(arg2);
03470 break;
03471 }
03472 rb_ary_modify(ary);
03473 if (len < 0) {
03474 return ary;
03475 }
03476 if (beg >= ARY_MAX_SIZE || len > ARY_MAX_SIZE - beg) {
03477 rb_raise(rb_eArgError, "argument too big");
03478 }
03479 end = beg + len;
03480 if (RARRAY_LEN(ary) < end) {
03481 if (end >= ARY_CAPA(ary)) {
03482 ary_resize_capa(ary, end);
03483 }
03484 ary_mem_clear(ary, RARRAY_LEN(ary), end - RARRAY_LEN(ary));
03485 ARY_SET_LEN(ary, end);
03486 }
03487
03488 if (block_p) {
03489 VALUE v;
03490 long i;
03491
03492 for (i=beg; i<end; i++) {
03493 v = rb_yield(LONG2NUM(i));
03494 if (i>=RARRAY_LEN(ary)) break;
03495 RARRAY_ASET(ary, i, v);
03496 }
03497 }
03498 else {
03499 ary_memfill(ary, beg, len, item);
03500 }
03501 return ary;
03502 }
03503
03504
03505
03506
03507
03508
03509
03510
03511
03512
03513
03514
03515
03516
03517
03518
03519
03520 VALUE
03521 rb_ary_plus(VALUE x, VALUE y)
03522 {
03523 VALUE z;
03524 long len, xlen, ylen;
03525
03526 y = to_ary(y);
03527 xlen = RARRAY_LEN(x);
03528 ylen = RARRAY_LEN(y);
03529 len = xlen + ylen;
03530 z = rb_ary_new2(len);
03531
03532 ary_memcpy(z, 0, xlen, RARRAY_CONST_PTR(x));
03533 ary_memcpy(z, xlen, ylen, RARRAY_CONST_PTR(y));
03534 ARY_SET_LEN(z, len);
03535 return z;
03536 }
03537
03538
03539
03540
03541
03542
03543
03544
03545
03546
03547
03548
03549
03550
03551
03552 VALUE
03553 rb_ary_concat(VALUE x, VALUE y)
03554 {
03555 rb_ary_modify_check(x);
03556 y = to_ary(y);
03557 if (RARRAY_LEN(y) > 0) {
03558 rb_ary_splice(x, RARRAY_LEN(x), 0, y);
03559 }
03560 return x;
03561 }
03562
03563
03564
03565
03566
03567
03568
03569
03570
03571
03572
03573
03574
03575
03576
03577
03578
03579
03580
03581 static VALUE
03582 rb_ary_times(VALUE ary, VALUE times)
03583 {
03584 VALUE ary2, tmp;
03585 const VALUE *ptr;
03586 long t, len;
03587
03588 tmp = rb_check_string_type(times);
03589 if (!NIL_P(tmp)) {
03590 return rb_ary_join(ary, tmp);
03591 }
03592
03593 len = NUM2LONG(times);
03594 if (len == 0) {
03595 ary2 = ary_new(rb_obj_class(ary), 0);
03596 goto out;
03597 }
03598 if (len < 0) {
03599 rb_raise(rb_eArgError, "negative argument");
03600 }
03601 if (ARY_MAX_SIZE/len < RARRAY_LEN(ary)) {
03602 rb_raise(rb_eArgError, "argument too big");
03603 }
03604 len *= RARRAY_LEN(ary);
03605
03606 ary2 = ary_new(rb_obj_class(ary), len);
03607 ARY_SET_LEN(ary2, len);
03608
03609 ptr = RARRAY_CONST_PTR(ary);
03610 t = RARRAY_LEN(ary);
03611 if (0 < t) {
03612 ary_memcpy(ary2, 0, t, ptr);
03613 while (t <= len/2) {
03614 ary_memcpy(ary2, t, t, RARRAY_CONST_PTR(ary2));
03615 t *= 2;
03616 }
03617 if (t < len) {
03618 ary_memcpy(ary2, t, len-t, RARRAY_CONST_PTR(ary2));
03619 }
03620 }
03621 out:
03622 OBJ_INFECT(ary2, ary);
03623
03624 return ary2;
03625 }
03626
03627
03628
03629
03630
03631
03632
03633
03634
03635
03636
03637
03638
03639
03640
03641
03642
03643
03644
03645
03646
03647 VALUE
03648 rb_ary_assoc(VALUE ary, VALUE key)
03649 {
03650 long i;
03651 VALUE v;
03652
03653 for (i = 0; i < RARRAY_LEN(ary); ++i) {
03654 v = rb_check_array_type(RARRAY_AREF(ary, i));
03655 if (!NIL_P(v) && RARRAY_LEN(v) > 0 &&
03656 rb_equal(RARRAY_AREF(v, 0), key))
03657 return v;
03658 }
03659 return Qnil;
03660 }
03661
03662
03663
03664
03665
03666
03667
03668
03669
03670
03671
03672
03673
03674
03675
03676
03677
03678
03679
03680 VALUE
03681 rb_ary_rassoc(VALUE ary, VALUE value)
03682 {
03683 long i;
03684 VALUE v;
03685
03686 for (i = 0; i < RARRAY_LEN(ary); ++i) {
03687 v = RARRAY_AREF(ary, i);
03688 if (RB_TYPE_P(v, T_ARRAY) &&
03689 RARRAY_LEN(v) > 1 &&
03690 rb_equal(RARRAY_AREF(v, 1), value))
03691 return v;
03692 }
03693 return Qnil;
03694 }
03695
03696 static VALUE
03697 recursive_equal(VALUE ary1, VALUE ary2, int recur)
03698 {
03699 long i, len1;
03700 const VALUE *p1, *p2;
03701
03702 if (recur) return Qtrue;
03703
03704 p1 = RARRAY_CONST_PTR(ary1);
03705 p2 = RARRAY_CONST_PTR(ary2);
03706 len1 = RARRAY_LEN(ary1);
03707
03708 for (i = 0; i < len1; i++) {
03709 if (*p1 != *p2) {
03710 if (rb_equal(*p1, *p2)) {
03711 len1 = RARRAY_LEN(ary1);
03712 if (len1 != RARRAY_LEN(ary2))
03713 return Qfalse;
03714 if (len1 < i)
03715 return Qtrue;
03716 p1 = RARRAY_CONST_PTR(ary1) + i;
03717 p2 = RARRAY_CONST_PTR(ary2) + i;
03718 }
03719 else {
03720 return Qfalse;
03721 }
03722 }
03723 p1++;
03724 p2++;
03725 }
03726 return Qtrue;
03727 }
03728
03729
03730
03731
03732
03733
03734
03735
03736
03737
03738
03739
03740
03741
03742
03743 static VALUE
03744 rb_ary_equal(VALUE ary1, VALUE ary2)
03745 {
03746 if (ary1 == ary2) return Qtrue;
03747 if (!RB_TYPE_P(ary2, T_ARRAY)) {
03748 if (!rb_respond_to(ary2, rb_intern("to_ary"))) {
03749 return Qfalse;
03750 }
03751 return rb_equal(ary2, ary1);
03752 }
03753 if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return Qfalse;
03754 if (RARRAY_CONST_PTR(ary1) == RARRAY_CONST_PTR(ary2)) return Qtrue;
03755 return rb_exec_recursive_paired(recursive_equal, ary1, ary2, ary2);
03756 }
03757
03758 static VALUE
03759 recursive_eql(VALUE ary1, VALUE ary2, int recur)
03760 {
03761 long i;
03762
03763 if (recur) return Qtrue;
03764 for (i=0; i<RARRAY_LEN(ary1); i++) {
03765 if (!rb_eql(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i)))
03766 return Qfalse;
03767 }
03768 return Qtrue;
03769 }
03770
03771
03772
03773
03774
03775
03776
03777
03778
03779 static VALUE
03780 rb_ary_eql(VALUE ary1, VALUE ary2)
03781 {
03782 if (ary1 == ary2) return Qtrue;
03783 if (!RB_TYPE_P(ary2, T_ARRAY)) return Qfalse;
03784 if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return Qfalse;
03785 if (RARRAY_CONST_PTR(ary1) == RARRAY_CONST_PTR(ary2)) return Qtrue;
03786 return rb_exec_recursive_paired(recursive_eql, ary1, ary2, ary2);
03787 }
03788
03789
03790
03791
03792
03793
03794
03795
03796
03797
03798
03799 static VALUE
03800 rb_ary_hash(VALUE ary)
03801 {
03802 long i;
03803 st_index_t h;
03804 VALUE n;
03805
03806 h = rb_hash_start(RARRAY_LEN(ary));
03807 h = rb_hash_uint(h, (st_index_t)rb_ary_hash);
03808 for (i=0; i<RARRAY_LEN(ary); i++) {
03809 n = rb_hash(RARRAY_AREF(ary, i));
03810 h = rb_hash_uint(h, NUM2LONG(n));
03811 }
03812 h = rb_hash_end(h);
03813 return LONG2FIX(h);
03814 }
03815
03816
03817
03818
03819
03820
03821
03822
03823
03824
03825
03826
03827
03828 VALUE
03829 rb_ary_includes(VALUE ary, VALUE item)
03830 {
03831 long i;
03832
03833 for (i=0; i<RARRAY_LEN(ary); i++) {
03834 if (rb_equal(RARRAY_AREF(ary, i), item)) {
03835 return Qtrue;
03836 }
03837 }
03838 return Qfalse;
03839 }
03840
03841
03842 static VALUE
03843 recursive_cmp(VALUE ary1, VALUE ary2, int recur)
03844 {
03845 long i, len;
03846
03847 if (recur) return Qundef;
03848 len = RARRAY_LEN(ary1);
03849 if (len > RARRAY_LEN(ary2)) {
03850 len = RARRAY_LEN(ary2);
03851 }
03852 for (i=0; i<len; i++) {
03853 VALUE e1 = rb_ary_elt(ary1, i), e2 = rb_ary_elt(ary2, i);
03854 VALUE v = rb_funcallv(e1, id_cmp, 1, &e2);
03855 if (v != INT2FIX(0)) {
03856 return v;
03857 }
03858 }
03859 return Qundef;
03860 }
03861
03862
03863
03864
03865
03866
03867
03868
03869
03870
03871
03872
03873
03874
03875
03876
03877
03878
03879
03880
03881
03882
03883
03884
03885
03886
03887 VALUE
03888 rb_ary_cmp(VALUE ary1, VALUE ary2)
03889 {
03890 long len;
03891 VALUE v;
03892
03893 ary2 = rb_check_array_type(ary2);
03894 if (NIL_P(ary2)) return Qnil;
03895 if (ary1 == ary2) return INT2FIX(0);
03896 v = rb_exec_recursive_paired(recursive_cmp, ary1, ary2, ary2);
03897 if (v != Qundef) return v;
03898 len = RARRAY_LEN(ary1) - RARRAY_LEN(ary2);
03899 if (len == 0) return INT2FIX(0);
03900 if (len > 0) return INT2FIX(1);
03901 return INT2FIX(-1);
03902 }
03903
03904 static VALUE
03905 ary_add_hash(VALUE hash, VALUE ary)
03906 {
03907 long i;
03908
03909 for (i=0; i<RARRAY_LEN(ary); i++) {
03910 VALUE elt = RARRAY_AREF(ary, i);
03911 if (rb_hash_lookup2(hash, elt, Qundef) == Qundef) {
03912 rb_hash_aset(hash, elt, elt);
03913 }
03914 }
03915 return hash;
03916 }
03917
03918 static inline VALUE
03919 ary_tmp_hash_new(void)
03920 {
03921 VALUE hash = rb_hash_new();
03922
03923 RBASIC_CLEAR_CLASS(hash);
03924 return hash;
03925 }
03926
03927 static VALUE
03928 ary_make_hash(VALUE ary)
03929 {
03930 VALUE hash = ary_tmp_hash_new();
03931 return ary_add_hash(hash, ary);
03932 }
03933
03934 static VALUE
03935 ary_add_hash_by(VALUE hash, VALUE ary)
03936 {
03937 long i;
03938
03939 for (i = 0; i < RARRAY_LEN(ary); ++i) {
03940 VALUE v = rb_ary_elt(ary, i), k = rb_yield(v);
03941 if (rb_hash_lookup2(hash, k, Qundef) == Qundef) {
03942 rb_hash_aset(hash, k, v);
03943 }
03944 }
03945 return hash;
03946 }
03947
03948 static VALUE
03949 ary_make_hash_by(VALUE ary)
03950 {
03951 VALUE hash = ary_tmp_hash_new();
03952 return ary_add_hash_by(hash, ary);
03953 }
03954
03955 static inline void
03956 ary_recycle_hash(VALUE hash)
03957 {
03958 if (RHASH(hash)->ntbl) {
03959 st_table *tbl = RHASH(hash)->ntbl;
03960 RHASH(hash)->ntbl = 0;
03961 st_free_table(tbl);
03962 }
03963 RB_GC_GUARD(hash);
03964 }
03965
03966
03967
03968
03969
03970
03971
03972
03973
03974
03975
03976
03977
03978
03979
03980
03981
03982
03983 static VALUE
03984 rb_ary_diff(VALUE ary1, VALUE ary2)
03985 {
03986 VALUE ary3;
03987 VALUE hash;
03988 long i;
03989
03990 hash = ary_make_hash(to_ary(ary2));
03991 ary3 = rb_ary_new();
03992
03993 for (i=0; i<RARRAY_LEN(ary1); i++) {
03994 if (st_lookup(rb_hash_tbl_raw(hash), RARRAY_AREF(ary1, i), 0)) continue;
03995 rb_ary_push(ary3, rb_ary_elt(ary1, i));
03996 }
03997 ary_recycle_hash(hash);
03998 return ary3;
03999 }
04000
04001
04002
04003
04004
04005
04006
04007
04008
04009
04010
04011
04012
04013
04014
04015
04016
04017
04018 static VALUE
04019 rb_ary_and(VALUE ary1, VALUE ary2)
04020 {
04021 VALUE hash, ary3, v;
04022 st_table *table;
04023 st_data_t vv;
04024 long i;
04025
04026 ary2 = to_ary(ary2);
04027 ary3 = rb_ary_new();
04028 if (RARRAY_LEN(ary2) == 0) return ary3;
04029 hash = ary_make_hash(ary2);
04030 table = rb_hash_tbl_raw(hash);
04031
04032 for (i=0; i<RARRAY_LEN(ary1); i++) {
04033 v = RARRAY_AREF(ary1, i);
04034 vv = (st_data_t)v;
04035 if (st_delete(table, &vv, 0)) {
04036 rb_ary_push(ary3, v);
04037 }
04038 }
04039 ary_recycle_hash(hash);
04040
04041 return ary3;
04042 }
04043
04044 static int
04045 ary_hash_orset(st_data_t *key, st_data_t *value, st_data_t arg, int existing)
04046 {
04047 if (existing) return ST_STOP;
04048 *key = *value = (VALUE)arg;
04049 return ST_CONTINUE;
04050 }
04051
04052
04053
04054
04055
04056
04057
04058
04059
04060
04061
04062
04063
04064
04065
04066 static VALUE
04067 rb_ary_or(VALUE ary1, VALUE ary2)
04068 {
04069 VALUE hash, ary3;
04070 long i;
04071
04072 ary2 = to_ary(ary2);
04073 hash = ary_make_hash(ary1);
04074
04075 for (i=0; i<RARRAY_LEN(ary2); i++) {
04076 VALUE elt = RARRAY_AREF(ary2, i);
04077 if (!st_update(RHASH_TBL_RAW(hash), (st_data_t)elt, ary_hash_orset, (st_data_t)elt)) {
04078 RB_OBJ_WRITTEN(hash, Qundef, elt);
04079 }
04080 }
04081 ary3 = rb_hash_values(hash);
04082 ary_recycle_hash(hash);
04083 return ary3;
04084 }
04085
04086 static int
04087 push_value(st_data_t key, st_data_t val, st_data_t ary)
04088 {
04089 rb_ary_push((VALUE)ary, (VALUE)val);
04090 return ST_CONTINUE;
04091 }
04092
04093
04094
04095
04096
04097
04098
04099
04100
04101
04102
04103
04104
04105
04106
04107
04108
04109
04110
04111
04112
04113
04114
04115
04116
04117
04118 static VALUE
04119 rb_ary_uniq_bang(VALUE ary)
04120 {
04121 VALUE hash;
04122 long hash_size;
04123
04124 rb_ary_modify_check(ary);
04125 if (RARRAY_LEN(ary) <= 1)
04126 return Qnil;
04127 if (rb_block_given_p())
04128 hash = ary_make_hash_by(ary);
04129 else
04130 hash = ary_make_hash(ary);
04131
04132 hash_size = RHASH_SIZE(hash);
04133 if (RARRAY_LEN(ary) == hash_size) {
04134 return Qnil;
04135 }
04136 rb_ary_modify_check(ary);
04137 ARY_SET_LEN(ary, 0);
04138 if (ARY_SHARED_P(ary) && !ARY_EMBED_P(ary)) {
04139 rb_ary_unshare(ary);
04140 FL_SET_EMBED(ary);
04141 }
04142 ary_resize_capa(ary, hash_size);
04143 st_foreach(rb_hash_tbl_raw(hash), push_value, ary);
04144 ary_recycle_hash(hash);
04145
04146 return ary;
04147 }
04148
04149
04150
04151
04152
04153
04154
04155
04156
04157
04158
04159
04160
04161
04162
04163
04164
04165
04166
04167
04168 static VALUE
04169 rb_ary_uniq(VALUE ary)
04170 {
04171 VALUE hash, uniq;
04172
04173 if (RARRAY_LEN(ary) <= 1)
04174 return rb_ary_dup(ary);
04175 if (rb_block_given_p()) {
04176 hash = ary_make_hash_by(ary);
04177 uniq = rb_hash_values(hash);
04178 }
04179 else {
04180 hash = ary_make_hash(ary);
04181 uniq = rb_hash_values(hash);
04182 }
04183 RBASIC_SET_CLASS(uniq, rb_obj_class(ary));
04184 ary_recycle_hash(hash);
04185
04186 return uniq;
04187 }
04188
04189
04190
04191
04192
04193
04194
04195
04196
04197
04198
04199
04200
04201 static VALUE
04202 rb_ary_compact_bang(VALUE ary)
04203 {
04204 VALUE *p, *t, *end;
04205 long n;
04206
04207 rb_ary_modify(ary);
04208 p = t = (VALUE *)RARRAY_CONST_PTR(ary);
04209 end = p + RARRAY_LEN(ary);
04210
04211 while (t < end) {
04212 if (NIL_P(*t)) t++;
04213 else *p++ = *t++;
04214 }
04215 n = p - RARRAY_CONST_PTR(ary);
04216 if (RARRAY_LEN(ary) == n) {
04217 return Qnil;
04218 }
04219 ary_resize_smaller(ary, n);
04220
04221 return ary;
04222 }
04223
04224
04225
04226
04227
04228
04229
04230
04231
04232
04233
04234 static VALUE
04235 rb_ary_compact(VALUE ary)
04236 {
04237 ary = rb_ary_dup(ary);
04238 rb_ary_compact_bang(ary);
04239 return ary;
04240 }
04241
04242
04243
04244
04245
04246
04247
04248
04249
04250
04251
04252
04253
04254
04255
04256
04257
04258
04259
04260
04261
04262
04263 static VALUE
04264 rb_ary_count(int argc, VALUE *argv, VALUE ary)
04265 {
04266 long i, n = 0;
04267
04268 if (argc == 0) {
04269 VALUE v;
04270
04271 if (!rb_block_given_p())
04272 return LONG2NUM(RARRAY_LEN(ary));
04273
04274 for (i = 0; i < RARRAY_LEN(ary); i++) {
04275 v = RARRAY_AREF(ary, i);
04276 if (RTEST(rb_yield(v))) n++;
04277 }
04278 }
04279 else {
04280 VALUE obj;
04281
04282 rb_scan_args(argc, argv, "1", &obj);
04283 if (rb_block_given_p()) {
04284 rb_warn("given block not used");
04285 }
04286 for (i = 0; i < RARRAY_LEN(ary); i++) {
04287 if (rb_equal(RARRAY_AREF(ary, i), obj)) n++;
04288 }
04289 }
04290
04291 return LONG2NUM(n);
04292 }
04293
04294 static VALUE
04295 flatten(VALUE ary, int level, int *modified)
04296 {
04297 long i = 0;
04298 VALUE stack, result, tmp, elt;
04299 st_table *memo;
04300 st_data_t id;
04301
04302 stack = ary_new(0, ARY_DEFAULT_SIZE);
04303 result = ary_new(0, RARRAY_LEN(ary));
04304 memo = st_init_numtable();
04305 st_insert(memo, (st_data_t)ary, (st_data_t)Qtrue);
04306 *modified = 0;
04307
04308 while (1) {
04309 while (i < RARRAY_LEN(ary)) {
04310 elt = RARRAY_AREF(ary, i++);
04311 tmp = rb_check_array_type(elt);
04312 if (RBASIC(result)->klass) {
04313 rb_raise(rb_eRuntimeError, "flatten reentered");
04314 }
04315 if (NIL_P(tmp) || (level >= 0 && RARRAY_LEN(stack) / 2 >= level)) {
04316 rb_ary_push(result, elt);
04317 }
04318 else {
04319 *modified = 1;
04320 id = (st_data_t)tmp;
04321 if (st_lookup(memo, id, 0)) {
04322 st_free_table(memo);
04323 rb_raise(rb_eArgError, "tried to flatten recursive array");
04324 }
04325 st_insert(memo, id, (st_data_t)Qtrue);
04326 rb_ary_push(stack, ary);
04327 rb_ary_push(stack, LONG2NUM(i));
04328 ary = tmp;
04329 i = 0;
04330 }
04331 }
04332 if (RARRAY_LEN(stack) == 0) {
04333 break;
04334 }
04335 id = (st_data_t)ary;
04336 st_delete(memo, &id, 0);
04337 tmp = rb_ary_pop(stack);
04338 i = NUM2LONG(tmp);
04339 ary = rb_ary_pop(stack);
04340 }
04341
04342 st_free_table(memo);
04343
04344 RBASIC_SET_CLASS(result, rb_class_of(ary));
04345 return result;
04346 }
04347
04348
04349
04350
04351
04352
04353
04354
04355
04356
04357
04358
04359
04360
04361
04362
04363
04364
04365
04366
04367
04368 static VALUE
04369 rb_ary_flatten_bang(int argc, VALUE *argv, VALUE ary)
04370 {
04371 int mod = 0, level = -1;
04372 VALUE result, lv;
04373
04374 rb_scan_args(argc, argv, "01", &lv);
04375 rb_ary_modify_check(ary);
04376 if (!NIL_P(lv)) level = NUM2INT(lv);
04377 if (level == 0) return Qnil;
04378
04379 result = flatten(ary, level, &mod);
04380 if (mod == 0) {
04381 ary_discard(result);
04382 return Qnil;
04383 }
04384 if (!(mod = ARY_EMBED_P(result))) rb_obj_freeze(result);
04385 rb_ary_replace(ary, result);
04386 if (mod) ARY_SET_EMBED_LEN(result, 0);
04387
04388 return ary;
04389 }
04390
04391
04392
04393
04394
04395
04396
04397
04398
04399
04400
04401
04402
04403
04404
04405
04406
04407
04408
04409
04410
04411
04412
04413 static VALUE
04414 rb_ary_flatten(int argc, VALUE *argv, VALUE ary)
04415 {
04416 int mod = 0, level = -1;
04417 VALUE result, lv;
04418
04419 rb_scan_args(argc, argv, "01", &lv);
04420 if (!NIL_P(lv)) level = NUM2INT(lv);
04421 if (level == 0) return ary_make_shared_copy(ary);
04422
04423 result = flatten(ary, level, &mod);
04424 OBJ_INFECT(result, ary);
04425
04426 return result;
04427 }
04428
04429 #define OPTHASH_GIVEN_P(opts) \
04430 (argc > 0 && !NIL_P((opts) = rb_check_hash_type(argv[argc-1])) && (--argc, 1))
04431 static ID id_random;
04432
04433 #define RAND_UPTO(max) (long)rb_random_ulong_limited((randgen), (max)-1)
04434
04435
04436
04437
04438
04439
04440
04441
04442
04443
04444
04445 static VALUE
04446 rb_ary_shuffle_bang(int argc, VALUE *argv, VALUE ary)
04447 {
04448 VALUE opts, randgen = rb_cRandom;
04449 long i, len;
04450
04451 if (OPTHASH_GIVEN_P(opts)) {
04452 VALUE rnd;
04453 ID keyword_ids[1];
04454
04455 keyword_ids[0] = id_random;
04456 rb_get_kwargs(opts, keyword_ids, 0, 1, &rnd);
04457 if (rnd != Qundef) {
04458 randgen = rnd;
04459 }
04460 }
04461 rb_check_arity(argc, 0, 0);
04462 rb_ary_modify(ary);
04463 i = len = RARRAY_LEN(ary);
04464 RARRAY_PTR_USE(ary, ptr, {
04465 while (i) {
04466 long j = RAND_UPTO(i);
04467 VALUE tmp;
04468 if (len != RARRAY_LEN(ary) || ptr != RARRAY_CONST_PTR(ary)) {
04469 rb_raise(rb_eRuntimeError, "modified during shuffle");
04470 }
04471 tmp = ptr[--i];
04472 ptr[i] = ptr[j];
04473 ptr[j] = tmp;
04474 }
04475 });
04476 return ary;
04477 }
04478
04479
04480
04481
04482
04483
04484
04485
04486
04487
04488
04489
04490
04491
04492
04493
04494
04495 static VALUE
04496 rb_ary_shuffle(int argc, VALUE *argv, VALUE ary)
04497 {
04498 ary = rb_ary_dup(ary);
04499 rb_ary_shuffle_bang(argc, argv, ary);
04500 return ary;
04501 }
04502
04503
04504
04505
04506
04507
04508
04509
04510
04511
04512
04513
04514
04515
04516
04517
04518
04519
04520
04521
04522
04523
04524
04525
04526
04527
04528 static VALUE
04529 rb_ary_sample(int argc, VALUE *argv, VALUE ary)
04530 {
04531 VALUE nv, result;
04532 VALUE opts, randgen = rb_cRandom;
04533 long n, len, i, j, k, idx[10];
04534 long rnds[numberof(idx)];
04535
04536 if (OPTHASH_GIVEN_P(opts)) {
04537 VALUE rnd;
04538 ID keyword_ids[1];
04539
04540 keyword_ids[0] = id_random;
04541 rb_get_kwargs(opts, keyword_ids, 0, 1, &rnd);
04542 if (rnd != Qundef) {
04543 randgen = rnd;
04544 }
04545 }
04546 len = RARRAY_LEN(ary);
04547 if (argc == 0) {
04548 if (len < 2)
04549 i = 0;
04550 else
04551 i = RAND_UPTO(len);
04552
04553 return rb_ary_elt(ary, i);
04554 }
04555 rb_scan_args(argc, argv, "1", &nv);
04556 n = NUM2LONG(nv);
04557 if (n < 0) rb_raise(rb_eArgError, "negative sample number");
04558 if (n > len) n = len;
04559 if (n <= numberof(idx)) {
04560 for (i = 0; i < n; ++i) {
04561 rnds[i] = RAND_UPTO(len - i);
04562 }
04563 }
04564 k = len;
04565 len = RARRAY_LEN(ary);
04566 if (len < k && n <= numberof(idx)) {
04567 for (i = 0; i < n; ++i) {
04568 if (rnds[i] >= len) return rb_ary_new_capa(0);
04569 }
04570 }
04571 if (n > len) n = len;
04572 switch (n) {
04573 case 0:
04574 return rb_ary_new_capa(0);
04575 case 1:
04576 i = rnds[0];
04577 return rb_ary_new_from_values(1, &RARRAY_AREF(ary, i));
04578 case 2:
04579 i = rnds[0];
04580 j = rnds[1];
04581 if (j >= i) j++;
04582 return rb_ary_new_from_args(2, RARRAY_AREF(ary, i), RARRAY_AREF(ary, j));
04583 case 3:
04584 i = rnds[0];
04585 j = rnds[1];
04586 k = rnds[2];
04587 {
04588 long l = j, g = i;
04589 if (j >= i) l = i, g = ++j;
04590 if (k >= l && (++k >= g)) ++k;
04591 }
04592 return rb_ary_new_from_args(3, RARRAY_AREF(ary, i), RARRAY_AREF(ary, j), RARRAY_AREF(ary, k));
04593 }
04594 if (n <= numberof(idx)) {
04595 long sorted[numberof(idx)];
04596 sorted[0] = idx[0] = rnds[0];
04597 for (i=1; i<n; i++) {
04598 k = rnds[i];
04599 for (j = 0; j < i; ++j) {
04600 if (k < sorted[j]) break;
04601 ++k;
04602 }
04603 memmove(&sorted[j+1], &sorted[j], sizeof(sorted[0])*(i-j));
04604 sorted[j] = idx[i] = k;
04605 }
04606 result = rb_ary_new_capa(n);
04607 RARRAY_PTR_USE(result, ptr_result, {
04608 for (i=0; i<n; i++) {
04609 ptr_result[i] = RARRAY_AREF(ary, idx[i]);
04610 }
04611 });
04612 }
04613 else {
04614 result = rb_ary_dup(ary);
04615 RBASIC_CLEAR_CLASS(result);
04616 RB_GC_GUARD(ary);
04617 RARRAY_PTR_USE(result, ptr_result, {
04618 for (i=0; i<n; i++) {
04619 j = RAND_UPTO(len-i) + i;
04620 nv = ptr_result[j];
04621 ptr_result[j] = ptr_result[i];
04622 ptr_result[i] = nv;
04623 }
04624 });
04625 RBASIC_SET_CLASS_RAW(result, rb_cArray);
04626 }
04627 ARY_SET_LEN(result, n);
04628
04629 return result;
04630 }
04631
04632 static VALUE
04633 rb_ary_cycle_size(VALUE self, VALUE args, VALUE eobj)
04634 {
04635 long mul;
04636 VALUE n = Qnil;
04637 if (args && (RARRAY_LEN(args) > 0)) {
04638 n = RARRAY_AREF(args, 0);
04639 }
04640 if (RARRAY_LEN(self) == 0) return INT2FIX(0);
04641 if (n == Qnil) return DBL2NUM(INFINITY);
04642 mul = NUM2LONG(n);
04643 if (mul <= 0) return INT2FIX(0);
04644 n = LONG2FIX(mul);
04645 return rb_funcallv(rb_ary_length(self), '*', 1, &n);
04646 }
04647
04648
04649
04650
04651
04652
04653
04654
04655
04656
04657
04658
04659
04660
04661
04662
04663
04664
04665
04666
04667
04668 static VALUE
04669 rb_ary_cycle(int argc, VALUE *argv, VALUE ary)
04670 {
04671 long n, i;
04672 VALUE nv = Qnil;
04673
04674 rb_scan_args(argc, argv, "01", &nv);
04675
04676 RETURN_SIZED_ENUMERATOR(ary, argc, argv, rb_ary_cycle_size);
04677 if (NIL_P(nv)) {
04678 n = -1;
04679 }
04680 else {
04681 n = NUM2LONG(nv);
04682 if (n <= 0) return Qnil;
04683 }
04684
04685 while (RARRAY_LEN(ary) > 0 && (n < 0 || 0 < n--)) {
04686 for (i=0; i<RARRAY_LEN(ary); i++) {
04687 rb_yield(RARRAY_AREF(ary, i));
04688 }
04689 }
04690 return Qnil;
04691 }
04692
04693 #define tmpbuf(n, size) rb_str_tmp_new((n)*(size))
04694 #define tmpbuf_discard(s) (rb_str_resize((s), 0L), RBASIC_SET_CLASS_RAW(s, rb_cString))
04695 #define tmpary(n) rb_ary_tmp_new(n)
04696 #define tmpary_discard(a) (ary_discard(a), RBASIC_SET_CLASS_RAW(a, rb_cArray))
04697
04698
04699
04700
04701
04702
04703 static int
04704 yield_indexed_values(const VALUE values, const long r, const long *const p)
04705 {
04706 const VALUE result = rb_ary_new2(r);
04707 VALUE *const result_array = RARRAY_PTR(result);
04708 const VALUE *const values_array = RARRAY_CONST_PTR(values);
04709 long i;
04710
04711 for (i = 0; i < r; i++) result_array[i] = values_array[p[i]];
04712 ARY_SET_LEN(result, r);
04713 rb_yield(result);
04714 return !RBASIC(values)->klass;
04715 }
04716
04717
04718
04719
04720
04721
04722
04723
04724
04725
04726
04727
04728
04729
04730
04731 static void
04732 permute0(long n, long r, long *p, long index, char *used, VALUE values)
04733 {
04734 long i;
04735 for (i = 0; i < n; i++) {
04736 if (used[i] == 0) {
04737 p[index] = i;
04738 if (index < r-1) {
04739 used[i] = 1;
04740 permute0(n, r, p, index+1,
04741 used, values);
04742 used[i] = 0;
04743 }
04744 else {
04745 if (!yield_indexed_values(values, r, p)) {
04746 rb_raise(rb_eRuntimeError, "permute reentered");
04747 }
04748 }
04749 }
04750 }
04751 }
04752
04753
04754
04755
04756
04757 static VALUE
04758 descending_factorial(long from, long how_many)
04759 {
04760 VALUE cnt = LONG2FIX(how_many >= 0);
04761 while (how_many-- > 0) {
04762 VALUE v = LONG2FIX(from--);
04763 cnt = rb_funcallv(cnt, '*', 1, &v);
04764 }
04765 return cnt;
04766 }
04767
04768 static VALUE
04769 binomial_coefficient(long comb, long size)
04770 {
04771 VALUE r, v;
04772 if (comb > size-comb) {
04773 comb = size-comb;
04774 }
04775 if (comb < 0) {
04776 return LONG2FIX(0);
04777 }
04778 r = descending_factorial(size, comb);
04779 v = descending_factorial(comb, comb);
04780 return rb_funcallv(r, id_div, 1, &v);
04781 }
04782
04783 static VALUE
04784 rb_ary_permutation_size(VALUE ary, VALUE args, VALUE eobj)
04785 {
04786 long n = RARRAY_LEN(ary);
04787 long k = (args && (RARRAY_LEN(args) > 0)) ? NUM2LONG(RARRAY_AREF(args, 0)) : n;
04788
04789 return descending_factorial(n, k);
04790 }
04791
04792
04793
04794
04795
04796
04797
04798
04799
04800
04801
04802
04803
04804
04805
04806
04807
04808
04809
04810
04811
04812
04813
04814
04815
04816
04817
04818
04819
04820 static VALUE
04821 rb_ary_permutation(int argc, VALUE *argv, VALUE ary)
04822 {
04823 VALUE num;
04824 long r, n, i;
04825
04826 n = RARRAY_LEN(ary);
04827 RETURN_SIZED_ENUMERATOR(ary, argc, argv, rb_ary_permutation_size);
04828 rb_scan_args(argc, argv, "01", &num);
04829 r = NIL_P(num) ? n : NUM2LONG(num);
04830
04831 if (r < 0 || n < r) {
04832
04833 }
04834 else if (r == 0) {
04835 rb_yield(rb_ary_new2(0));
04836 }
04837 else if (r == 1) {
04838 for (i = 0; i < RARRAY_LEN(ary); i++) {
04839 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
04840 }
04841 }
04842 else {
04843 volatile VALUE t0 = tmpbuf(r,sizeof(long));
04844 long *p = (long*)RSTRING_PTR(t0);
04845 volatile VALUE t1 = tmpbuf(n,sizeof(char));
04846 char *used = (char*)RSTRING_PTR(t1);
04847 VALUE ary0 = ary_make_shared_copy(ary);
04848 RBASIC_CLEAR_CLASS(ary0);
04849
04850 MEMZERO(used, char, n);
04851
04852 permute0(n, r, p, 0, used, ary0);
04853 tmpbuf_discard(t0);
04854 tmpbuf_discard(t1);
04855 RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
04856 }
04857 return ary;
04858 }
04859
04860 static VALUE
04861 rb_ary_combination_size(VALUE ary, VALUE args, VALUE eobj)
04862 {
04863 long n = RARRAY_LEN(ary);
04864 long k = NUM2LONG(RARRAY_AREF(args, 0));
04865
04866 return binomial_coefficient(k, n);
04867 }
04868
04869
04870
04871
04872
04873
04874
04875
04876
04877
04878
04879
04880
04881
04882
04883
04884
04885
04886
04887
04888
04889
04890
04891
04892
04893
04894 static VALUE
04895 rb_ary_combination(VALUE ary, VALUE num)
04896 {
04897 long n, i, len;
04898
04899 n = NUM2LONG(num);
04900 RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_combination_size);
04901 len = RARRAY_LEN(ary);
04902 if (n < 0 || len < n) {
04903
04904 }
04905 else if (n == 0) {
04906 rb_yield(rb_ary_new2(0));
04907 }
04908 else if (n == 1) {
04909 for (i = 0; i < len; i++) {
04910 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
04911 }
04912 }
04913 else {
04914 VALUE ary0 = ary_make_shared_copy(ary);
04915 volatile VALUE t0;
04916 long *stack = ALLOCV_N(long, t0, n+1);
04917 long lev = 0;
04918
04919 RBASIC_CLEAR_CLASS(ary0);
04920 MEMZERO(stack+1, long, n);
04921 stack[0] = -1;
04922 for (;;) {
04923 for (lev++; lev < n; lev++) {
04924 stack[lev+1] = stack[lev]+1;
04925 }
04926 if (!yield_indexed_values(ary0, n, stack+1)) {
04927 rb_raise(rb_eRuntimeError, "combination reentered");
04928 }
04929 do {
04930 if (lev == 0) goto done;
04931 stack[lev--]++;
04932 } while (stack[lev+1]+n == len+lev+1);
04933 }
04934 done:
04935 ALLOCV_END(t0);
04936 RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
04937 }
04938 return ary;
04939 }
04940
04941
04942
04943
04944
04945
04946
04947
04948
04949
04950
04951
04952
04953
04954 static void
04955 rpermute0(long n, long r, long *p, long index, VALUE values)
04956 {
04957 long i;
04958 for (i = 0; i < n; i++) {
04959 p[index] = i;
04960 if (index < r-1) {
04961 rpermute0(n, r, p, index+1, values);
04962 }
04963 else {
04964 if (!yield_indexed_values(values, r, p)) {
04965 rb_raise(rb_eRuntimeError, "repeated permute reentered");
04966 }
04967 }
04968 }
04969 }
04970
04971 static VALUE
04972 rb_ary_repeated_permutation_size(VALUE ary, VALUE args, VALUE eobj)
04973 {
04974 long n = RARRAY_LEN(ary);
04975 long k = NUM2LONG(RARRAY_AREF(args, 0));
04976 VALUE v;
04977
04978 if (k < 0) {
04979 return LONG2FIX(0);
04980 }
04981
04982 v = LONG2NUM(k);
04983 return rb_funcallv(LONG2NUM(n), id_power, 1, &v);
04984 }
04985
04986
04987
04988
04989
04990
04991
04992
04993
04994
04995
04996
04997
04998
04999
05000
05001
05002
05003
05004
05005
05006
05007
05008
05009 static VALUE
05010 rb_ary_repeated_permutation(VALUE ary, VALUE num)
05011 {
05012 long r, n, i;
05013
05014 n = RARRAY_LEN(ary);
05015 RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_repeated_permutation_size);
05016 r = NUM2LONG(num);
05017
05018 if (r < 0) {
05019
05020 }
05021 else if (r == 0) {
05022 rb_yield(rb_ary_new2(0));
05023 }
05024 else if (r == 1) {
05025 for (i = 0; i < RARRAY_LEN(ary); i++) {
05026 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
05027 }
05028 }
05029 else {
05030 volatile VALUE t0 = tmpbuf(r, sizeof(long));
05031 long *p = (long*)RSTRING_PTR(t0);
05032 VALUE ary0 = ary_make_shared_copy(ary);
05033 RBASIC_CLEAR_CLASS(ary0);
05034
05035 rpermute0(n, r, p, 0, ary0);
05036 tmpbuf_discard(t0);
05037 RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
05038 }
05039 return ary;
05040 }
05041
05042 static void
05043 rcombinate0(long n, long r, long *p, long index, long rest, VALUE values)
05044 {
05045 if (rest > 0) {
05046 for (; index < n; ++index) {
05047 p[r-rest] = index;
05048 rcombinate0(n, r, p, index, rest-1, values);
05049 }
05050 }
05051 else {
05052 if (!yield_indexed_values(values, r, p)) {
05053 rb_raise(rb_eRuntimeError, "repeated combination reentered");
05054 }
05055 }
05056 }
05057
05058 static VALUE
05059 rb_ary_repeated_combination_size(VALUE ary, VALUE args, VALUE eobj)
05060 {
05061 long n = RARRAY_LEN(ary);
05062 long k = NUM2LONG(RARRAY_AREF(args, 0));
05063 if (k == 0) {
05064 return LONG2FIX(1);
05065 }
05066 return binomial_coefficient(k, n + k - 1);
05067 }
05068
05069
05070
05071
05072
05073
05074
05075
05076
05077
05078
05079
05080
05081
05082
05083
05084
05085
05086
05087
05088
05089
05090
05091
05092
05093
05094
05095
05096 static VALUE
05097 rb_ary_repeated_combination(VALUE ary, VALUE num)
05098 {
05099 long n, i, len;
05100
05101 n = NUM2LONG(num);
05102 RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_repeated_combination_size);
05103 len = RARRAY_LEN(ary);
05104 if (n < 0) {
05105
05106 }
05107 else if (n == 0) {
05108 rb_yield(rb_ary_new2(0));
05109 }
05110 else if (n == 1) {
05111 for (i = 0; i < len; i++) {
05112 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
05113 }
05114 }
05115 else if (len == 0) {
05116
05117 }
05118 else {
05119 volatile VALUE t0 = tmpbuf(n, sizeof(long));
05120 long *p = (long*)RSTRING_PTR(t0);
05121 VALUE ary0 = ary_make_shared_copy(ary);
05122 RBASIC_CLEAR_CLASS(ary0);
05123
05124 rcombinate0(len, n, p, 0, n, ary0);
05125 tmpbuf_discard(t0);
05126 RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
05127 }
05128 return ary;
05129 }
05130
05131
05132
05133
05134
05135
05136
05137
05138
05139
05140
05141
05142
05143
05144
05145
05146
05147
05148
05149
05150
05151
05152 static VALUE
05153 rb_ary_product(int argc, VALUE *argv, VALUE ary)
05154 {
05155 int n = argc+1;
05156 volatile VALUE t0 = tmpary(n);
05157 volatile VALUE t1 = tmpbuf(n, sizeof(int));
05158 VALUE *arrays = RARRAY_PTR(t0);
05159 int *counters = (int*)RSTRING_PTR(t1);
05160 VALUE result = Qnil;
05161 long i,j;
05162 long resultlen = 1;
05163
05164 RBASIC_CLEAR_CLASS(t0);
05165 RBASIC_CLEAR_CLASS(t1);
05166
05167
05168 ARY_SET_LEN(t0, n);
05169 arrays[0] = ary;
05170 for (i = 1; i < n; i++) arrays[i] = Qnil;
05171 for (i = 1; i < n; i++) arrays[i] = to_ary(argv[i-1]);
05172
05173
05174 for (i = 0; i < n; i++) counters[i] = 0;
05175
05176
05177 if (rb_block_given_p()) {
05178
05179 for (i = 0; i < n; i++) {
05180 if (RARRAY_LEN(arrays[i]) == 0) goto done;
05181 arrays[i] = ary_make_shared_copy(arrays[i]);
05182 }
05183 }
05184 else {
05185
05186 for (i = 0; i < n; i++) {
05187 long k = RARRAY_LEN(arrays[i]);
05188 if (k == 0) {
05189 result = rb_ary_new2(0);
05190 goto done;
05191 }
05192 if (MUL_OVERFLOW_LONG_P(resultlen, k))
05193 rb_raise(rb_eRangeError, "too big to product");
05194 resultlen *= k;
05195 }
05196 result = rb_ary_new2(resultlen);
05197 }
05198 for (;;) {
05199 int m;
05200
05201 VALUE subarray = rb_ary_new2(n);
05202 for (j = 0; j < n; j++) {
05203 rb_ary_push(subarray, rb_ary_entry(arrays[j], counters[j]));
05204 }
05205
05206
05207 if (NIL_P(result)) {
05208 FL_SET(t0, FL_USER5);
05209 rb_yield(subarray);
05210 if (! FL_TEST(t0, FL_USER5)) {
05211 rb_raise(rb_eRuntimeError, "product reentered");
05212 }
05213 else {
05214 FL_UNSET(t0, FL_USER5);
05215 }
05216 }
05217 else {
05218 rb_ary_push(result, subarray);
05219 }
05220
05221
05222
05223
05224
05225 m = n-1;
05226 counters[m]++;
05227 while (counters[m] == RARRAY_LEN(arrays[m])) {
05228 counters[m] = 0;
05229
05230 if (--m < 0) goto done;
05231 counters[m]++;
05232 }
05233 }
05234 done:
05235 tmpary_discard(t0);
05236 tmpbuf_discard(t1);
05237
05238 return NIL_P(result) ? ary : result;
05239 }
05240
05241
05242
05243
05244
05245
05246
05247
05248
05249
05250
05251
05252
05253
05254
05255
05256 static VALUE
05257 rb_ary_take(VALUE obj, VALUE n)
05258 {
05259 long len = NUM2LONG(n);
05260 if (len < 0) {
05261 rb_raise(rb_eArgError, "attempt to take negative size");
05262 }
05263 return rb_ary_subseq(obj, 0, len);
05264 }
05265
05266
05267
05268
05269
05270
05271
05272
05273
05274
05275
05276
05277
05278
05279
05280
05281
05282
05283 static VALUE
05284 rb_ary_take_while(VALUE ary)
05285 {
05286 long i;
05287
05288 RETURN_ENUMERATOR(ary, 0, 0);
05289 for (i = 0; i < RARRAY_LEN(ary); i++) {
05290 if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) break;
05291 }
05292 return rb_ary_take(ary, LONG2FIX(i));
05293 }
05294
05295
05296
05297
05298
05299
05300
05301
05302
05303
05304
05305
05306
05307
05308
05309
05310
05311 static VALUE
05312 rb_ary_drop(VALUE ary, VALUE n)
05313 {
05314 VALUE result;
05315 long pos = NUM2LONG(n);
05316 if (pos < 0) {
05317 rb_raise(rb_eArgError, "attempt to drop negative size");
05318 }
05319
05320 result = rb_ary_subseq(ary, pos, RARRAY_LEN(ary));
05321 if (result == Qnil) result = rb_ary_new();
05322 return result;
05323 }
05324
05325
05326
05327
05328
05329
05330
05331
05332
05333
05334
05335
05336
05337
05338
05339
05340
05341
05342
05343 static VALUE
05344 rb_ary_drop_while(VALUE ary)
05345 {
05346 long i;
05347
05348 RETURN_ENUMERATOR(ary, 0, 0);
05349 for (i = 0; i < RARRAY_LEN(ary); i++) {
05350 if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) break;
05351 }
05352 return rb_ary_drop(ary, LONG2FIX(i));
05353 }
05354
05355
05356
05357
05358
05359
05360
05361
05362
05363
05364
05365
05366
05367
05368
05369
05370
05371
05372
05373
05374
05375
05376
05377
05378
05379
05380
05381
05382
05383
05384
05385
05386
05387
05388
05389
05390
05391
05392
05393
05394
05395
05396
05397
05398
05399
05400
05401
05402
05403
05404
05405
05406
05407
05408
05409
05410
05411
05412
05413
05414
05415
05416
05417
05418
05419
05420
05421
05422
05423
05424
05425
05426
05427
05428
05429
05430
05431
05432
05433
05434
05435
05436
05437
05438
05439
05440
05441
05442
05443
05444
05445
05446
05447
05448
05449
05450
05451
05452
05453
05454
05455
05456
05457
05458
05459
05460
05461
05462
05463
05464
05465
05466
05467
05468
05469
05470
05471
05472
05473
05474
05475
05476
05477
05478
05479
05480
05481
05482
05483
05484
05485
05486
05487
05488
05489
05490
05491
05492
05493
05494
05495
05496
05497
05498
05499
05500
05501
05502
05503
05504
05505
05506
05507
05508
05509
05510
05511
05512
05513
05514
05515
05516
05517
05518
05519
05520
05521
05522
05523
05524
05525
05526
05527
05528
05529
05530
05531
05532
05533
05534
05535
05536
05537
05538
05539
05540
05541
05542
05543
05544
05545
05546
05547
05548
05549
05550
05551
05552
05553
05554
05555
05556
05557
05558
05559
05560
05561
05562
05563
05564
05565
05566
05567
05568
05569
05570
05571
05572
05573
05574
05575
05576
05577
05578
05579
05580
05581
05582
05583
05584
05585
05586
05587
05588
05589
05590
05591
05592 void
05593 Init_Array(void)
05594 {
05595 #undef rb_intern
05596 #define rb_intern(str) rb_intern_const(str)
05597
05598 rb_cArray = rb_define_class("Array", rb_cObject);
05599 rb_include_module(rb_cArray, rb_mEnumerable);
05600
05601 rb_define_alloc_func(rb_cArray, empty_ary_alloc);
05602 rb_define_singleton_method(rb_cArray, "[]", rb_ary_s_create, -1);
05603 rb_define_singleton_method(rb_cArray, "try_convert", rb_ary_s_try_convert, 1);
05604 rb_define_method(rb_cArray, "initialize", rb_ary_initialize, -1);
05605 rb_define_method(rb_cArray, "initialize_copy", rb_ary_replace, 1);
05606
05607 rb_define_method(rb_cArray, "inspect", rb_ary_inspect, 0);
05608 rb_define_alias(rb_cArray, "to_s", "inspect");
05609 rb_define_method(rb_cArray, "to_a", rb_ary_to_a, 0);
05610 rb_define_method(rb_cArray, "to_h", rb_ary_to_h, 0);
05611 rb_define_method(rb_cArray, "to_ary", rb_ary_to_ary_m, 0);
05612 rb_define_method(rb_cArray, "frozen?", rb_ary_frozen_p, 0);
05613
05614 rb_define_method(rb_cArray, "==", rb_ary_equal, 1);
05615 rb_define_method(rb_cArray, "eql?", rb_ary_eql, 1);
05616 rb_define_method(rb_cArray, "hash", rb_ary_hash, 0);
05617
05618 rb_define_method(rb_cArray, "[]", rb_ary_aref, -1);
05619 rb_define_method(rb_cArray, "[]=", rb_ary_aset, -1);
05620 rb_define_method(rb_cArray, "at", rb_ary_at, 1);
05621 rb_define_method(rb_cArray, "fetch", rb_ary_fetch, -1);
05622 rb_define_method(rb_cArray, "first", rb_ary_first, -1);
05623 rb_define_method(rb_cArray, "last", rb_ary_last, -1);
05624 rb_define_method(rb_cArray, "concat", rb_ary_concat, 1);
05625 rb_define_method(rb_cArray, "<<", rb_ary_push, 1);
05626 rb_define_method(rb_cArray, "push", rb_ary_push_m, -1);
05627 rb_define_method(rb_cArray, "pop", rb_ary_pop_m, -1);
05628 rb_define_method(rb_cArray, "shift", rb_ary_shift_m, -1);
05629 rb_define_method(rb_cArray, "unshift", rb_ary_unshift_m, -1);
05630 rb_define_method(rb_cArray, "insert", rb_ary_insert, -1);
05631 rb_define_method(rb_cArray, "each", rb_ary_each, 0);
05632 rb_define_method(rb_cArray, "each_index", rb_ary_each_index, 0);
05633 rb_define_method(rb_cArray, "reverse_each", rb_ary_reverse_each, 0);
05634 rb_define_method(rb_cArray, "length", rb_ary_length, 0);
05635 rb_define_alias(rb_cArray, "size", "length");
05636 rb_define_method(rb_cArray, "empty?", rb_ary_empty_p, 0);
05637 rb_define_method(rb_cArray, "find_index", rb_ary_index, -1);
05638 rb_define_method(rb_cArray, "index", rb_ary_index, -1);
05639 rb_define_method(rb_cArray, "rindex", rb_ary_rindex, -1);
05640 rb_define_method(rb_cArray, "join", rb_ary_join_m, -1);
05641 rb_define_method(rb_cArray, "reverse", rb_ary_reverse_m, 0);
05642 rb_define_method(rb_cArray, "reverse!", rb_ary_reverse_bang, 0);
05643 rb_define_method(rb_cArray, "rotate", rb_ary_rotate_m, -1);
05644 rb_define_method(rb_cArray, "rotate!", rb_ary_rotate_bang, -1);
05645 rb_define_method(rb_cArray, "sort", rb_ary_sort, 0);
05646 rb_define_method(rb_cArray, "sort!", rb_ary_sort_bang, 0);
05647 rb_define_method(rb_cArray, "sort_by!", rb_ary_sort_by_bang, 0);
05648 rb_define_method(rb_cArray, "collect", rb_ary_collect, 0);
05649 rb_define_method(rb_cArray, "collect!", rb_ary_collect_bang, 0);
05650 rb_define_method(rb_cArray, "map", rb_ary_collect, 0);
05651 rb_define_method(rb_cArray, "map!", rb_ary_collect_bang, 0);
05652 rb_define_method(rb_cArray, "select", rb_ary_select, 0);
05653 rb_define_method(rb_cArray, "select!", rb_ary_select_bang, 0);
05654 rb_define_method(rb_cArray, "keep_if", rb_ary_keep_if, 0);
05655 rb_define_method(rb_cArray, "values_at", rb_ary_values_at, -1);
05656 rb_define_method(rb_cArray, "delete", rb_ary_delete, 1);
05657 rb_define_method(rb_cArray, "delete_at", rb_ary_delete_at_m, 1);
05658 rb_define_method(rb_cArray, "delete_if", rb_ary_delete_if, 0);
05659 rb_define_method(rb_cArray, "reject", rb_ary_reject, 0);
05660 rb_define_method(rb_cArray, "reject!", rb_ary_reject_bang, 0);
05661 rb_define_method(rb_cArray, "zip", rb_ary_zip, -1);
05662 rb_define_method(rb_cArray, "transpose", rb_ary_transpose, 0);
05663 rb_define_method(rb_cArray, "replace", rb_ary_replace, 1);
05664 rb_define_method(rb_cArray, "clear", rb_ary_clear, 0);
05665 rb_define_method(rb_cArray, "fill", rb_ary_fill, -1);
05666 rb_define_method(rb_cArray, "include?", rb_ary_includes, 1);
05667 rb_define_method(rb_cArray, "<=>", rb_ary_cmp, 1);
05668
05669 rb_define_method(rb_cArray, "slice", rb_ary_aref, -1);
05670 rb_define_method(rb_cArray, "slice!", rb_ary_slice_bang, -1);
05671
05672 rb_define_method(rb_cArray, "assoc", rb_ary_assoc, 1);
05673 rb_define_method(rb_cArray, "rassoc", rb_ary_rassoc, 1);
05674
05675 rb_define_method(rb_cArray, "+", rb_ary_plus, 1);
05676 rb_define_method(rb_cArray, "*", rb_ary_times, 1);
05677
05678 rb_define_method(rb_cArray, "-", rb_ary_diff, 1);
05679 rb_define_method(rb_cArray, "&", rb_ary_and, 1);
05680 rb_define_method(rb_cArray, "|", rb_ary_or, 1);
05681
05682 rb_define_method(rb_cArray, "uniq", rb_ary_uniq, 0);
05683 rb_define_method(rb_cArray, "uniq!", rb_ary_uniq_bang, 0);
05684 rb_define_method(rb_cArray, "compact", rb_ary_compact, 0);
05685 rb_define_method(rb_cArray, "compact!", rb_ary_compact_bang, 0);
05686 rb_define_method(rb_cArray, "flatten", rb_ary_flatten, -1);
05687 rb_define_method(rb_cArray, "flatten!", rb_ary_flatten_bang, -1);
05688 rb_define_method(rb_cArray, "count", rb_ary_count, -1);
05689 rb_define_method(rb_cArray, "shuffle!", rb_ary_shuffle_bang, -1);
05690 rb_define_method(rb_cArray, "shuffle", rb_ary_shuffle, -1);
05691 rb_define_method(rb_cArray, "sample", rb_ary_sample, -1);
05692 rb_define_method(rb_cArray, "cycle", rb_ary_cycle, -1);
05693 rb_define_method(rb_cArray, "permutation", rb_ary_permutation, -1);
05694 rb_define_method(rb_cArray, "combination", rb_ary_combination, 1);
05695 rb_define_method(rb_cArray, "repeated_permutation", rb_ary_repeated_permutation, 1);
05696 rb_define_method(rb_cArray, "repeated_combination", rb_ary_repeated_combination, 1);
05697 rb_define_method(rb_cArray, "product", rb_ary_product, -1);
05698
05699 rb_define_method(rb_cArray, "take", rb_ary_take, 1);
05700 rb_define_method(rb_cArray, "take_while", rb_ary_take_while, 0);
05701 rb_define_method(rb_cArray, "drop", rb_ary_drop, 1);
05702 rb_define_method(rb_cArray, "drop_while", rb_ary_drop_while, 0);
05703 rb_define_method(rb_cArray, "bsearch", rb_ary_bsearch, 0);
05704
05705 id_cmp = rb_intern("<=>");
05706 id_random = rb_intern("random");
05707 id_div = rb_intern("div");
05708 id_power = rb_intern("**");
05709 }
05710