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
00018 #ifndef ARRAY_DEBUG
00019 # define NDEBUG
00020 #endif
00021 #include <assert.h>
00022
00023 VALUE rb_cArray;
00024
00025 static ID id_cmp;
00026
00027 #define ARY_DEFAULT_SIZE 16
00028 #define ARY_MAX_SIZE (LONG_MAX / (int)sizeof(VALUE))
00029
00030 void
00031 rb_mem_clear(register VALUE *mem, register long size)
00032 {
00033 while (size--) {
00034 *mem++ = Qnil;
00035 }
00036 }
00037
00038 static inline void
00039 memfill(register VALUE *mem, register long size, register VALUE val)
00040 {
00041 while (size--) {
00042 *mem++ = val;
00043 }
00044 }
00045
00046 # define ARY_SHARED_P(ary) \
00047 (assert(!FL_TEST(ary, ELTS_SHARED) || !FL_TEST(ary, RARRAY_EMBED_FLAG)), \
00048 FL_TEST(ary,ELTS_SHARED)!=0)
00049 # define ARY_EMBED_P(ary) \
00050 (assert(!FL_TEST(ary, ELTS_SHARED) || !FL_TEST(ary, RARRAY_EMBED_FLAG)), \
00051 FL_TEST(ary, RARRAY_EMBED_FLAG)!=0)
00052
00053 #define ARY_HEAP_PTR(a) (assert(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.ptr)
00054 #define ARY_HEAP_LEN(a) (assert(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.len)
00055 #define ARY_EMBED_PTR(a) (assert(ARY_EMBED_P(a)), RARRAY(a)->as.ary)
00056 #define ARY_EMBED_LEN(a) \
00057 (assert(ARY_EMBED_P(a)), \
00058 (long)((RBASIC(a)->flags >> RARRAY_EMBED_LEN_SHIFT) & \
00059 (RARRAY_EMBED_LEN_MASK >> RARRAY_EMBED_LEN_SHIFT)))
00060
00061 #define ARY_OWNS_HEAP_P(a) (!FL_TEST(a, ELTS_SHARED|RARRAY_EMBED_FLAG))
00062 #define FL_SET_EMBED(a) do { \
00063 assert(!ARY_SHARED_P(a)); \
00064 assert(!OBJ_FROZEN(a)); \
00065 FL_SET(a, RARRAY_EMBED_FLAG); \
00066 } while (0)
00067 #define FL_UNSET_EMBED(ary) FL_UNSET(ary, RARRAY_EMBED_FLAG|RARRAY_EMBED_LEN_MASK)
00068 #define FL_SET_SHARED(ary) do { \
00069 assert(!ARY_EMBED_P(ary)); \
00070 FL_SET(ary, ELTS_SHARED); \
00071 } while (0)
00072 #define FL_UNSET_SHARED(ary) FL_UNSET(ary, ELTS_SHARED)
00073
00074 #define ARY_SET_PTR(ary, p) do { \
00075 assert(!ARY_EMBED_P(ary)); \
00076 assert(!OBJ_FROZEN(ary)); \
00077 RARRAY(ary)->as.heap.ptr = (p); \
00078 } while (0)
00079 #define ARY_SET_EMBED_LEN(ary, n) do { \
00080 long tmp_n = n; \
00081 assert(ARY_EMBED_P(ary)); \
00082 assert(!OBJ_FROZEN(ary)); \
00083 RBASIC(ary)->flags &= ~RARRAY_EMBED_LEN_MASK; \
00084 RBASIC(ary)->flags |= (tmp_n) << RARRAY_EMBED_LEN_SHIFT; \
00085 } while (0)
00086 #define ARY_SET_HEAP_LEN(ary, n) do { \
00087 assert(!ARY_EMBED_P(ary)); \
00088 RARRAY(ary)->as.heap.len = n; \
00089 } while (0)
00090 #define ARY_SET_LEN(ary, n) do { \
00091 if (ARY_EMBED_P(ary)) { \
00092 ARY_SET_EMBED_LEN(ary, n); \
00093 } \
00094 else { \
00095 ARY_SET_HEAP_LEN(ary, n); \
00096 } \
00097 assert(RARRAY_LEN(ary) == n); \
00098 } while (0)
00099 #define ARY_INCREASE_PTR(ary, n) do { \
00100 assert(!ARY_EMBED_P(ary)); \
00101 assert(!OBJ_FROZEN(ary)); \
00102 RARRAY(ary)->as.heap.ptr += n; \
00103 } while (0)
00104 #define ARY_INCREASE_LEN(ary, n) do { \
00105 assert(!OBJ_FROZEN(ary)); \
00106 if (ARY_EMBED_P(ary)) { \
00107 ARY_SET_EMBED_LEN(ary, RARRAY_LEN(ary)+n); \
00108 } \
00109 else { \
00110 RARRAY(ary)->as.heap.len += n; \
00111 } \
00112 } while (0)
00113
00114 #define ARY_CAPA(ary) (ARY_EMBED_P(ary) ? RARRAY_EMBED_LEN_MAX : \
00115 ARY_SHARED_ROOT_P(ary) ? RARRAY_LEN(ary) : RARRAY(ary)->as.heap.aux.capa)
00116 #define ARY_SET_CAPA(ary, n) do { \
00117 assert(!ARY_EMBED_P(ary)); \
00118 assert(!ARY_SHARED_P(ary)); \
00119 assert(!OBJ_FROZEN(ary)); \
00120 RARRAY(ary)->as.heap.aux.capa = (n); \
00121 } while (0)
00122
00123 #define ARY_SHARED(ary) (assert(ARY_SHARED_P(ary)), RARRAY(ary)->as.heap.aux.shared)
00124 #define ARY_SET_SHARED(ary, value) do { \
00125 assert(!ARY_EMBED_P(ary)); \
00126 assert(ARY_SHARED_P(ary)); \
00127 assert(ARY_SHARED_ROOT_P(value)); \
00128 RARRAY(ary)->as.heap.aux.shared = (value); \
00129 } while (0)
00130 #define RARRAY_SHARED_ROOT_FLAG FL_USER5
00131 #define ARY_SHARED_ROOT_P(ary) (FL_TEST(ary, RARRAY_SHARED_ROOT_FLAG))
00132 #define ARY_SHARED_NUM(ary) \
00133 (assert(ARY_SHARED_ROOT_P(ary)), RARRAY(ary)->as.heap.aux.capa)
00134 #define ARY_SET_SHARED_NUM(ary, value) do { \
00135 assert(ARY_SHARED_ROOT_P(ary)); \
00136 RARRAY(ary)->as.heap.aux.capa = (value); \
00137 } while (0)
00138 #define FL_SET_SHARED_ROOT(ary) do { \
00139 assert(!ARY_EMBED_P(ary)); \
00140 FL_SET(ary, RARRAY_SHARED_ROOT_FLAG); \
00141 } while (0)
00142
00143 static void
00144 ary_resize_capa(VALUE ary, long capacity)
00145 {
00146 assert(RARRAY_LEN(ary) <= capacity);
00147 assert(!OBJ_FROZEN(ary));
00148 assert(!ARY_SHARED_P(ary));
00149 if (capacity > RARRAY_EMBED_LEN_MAX) {
00150 if (ARY_EMBED_P(ary)) {
00151 long len = ARY_EMBED_LEN(ary);
00152 VALUE *ptr = ALLOC_N(VALUE, (capacity));
00153 MEMCPY(ptr, ARY_EMBED_PTR(ary), VALUE, len);
00154 FL_UNSET_EMBED(ary);
00155 ARY_SET_PTR(ary, ptr);
00156 ARY_SET_HEAP_LEN(ary, len);
00157 }
00158 else {
00159 REALLOC_N(RARRAY(ary)->as.heap.ptr, VALUE, (capacity));
00160 }
00161 ARY_SET_CAPA(ary, (capacity));
00162 }
00163 else {
00164 if (!ARY_EMBED_P(ary)) {
00165 long len = RARRAY_LEN(ary);
00166 VALUE *ptr = RARRAY_PTR(ary);
00167 if (len > capacity) len = capacity;
00168 MEMCPY(RARRAY(ary)->as.ary, ptr, VALUE, len);
00169 FL_SET_EMBED(ary);
00170 ARY_SET_LEN(ary, len);
00171 xfree(ptr);
00172 }
00173 }
00174 }
00175
00176 static void
00177 ary_double_capa(VALUE ary, long min)
00178 {
00179 long new_capa = ARY_CAPA(ary) / 2;
00180
00181 if (new_capa < ARY_DEFAULT_SIZE) {
00182 new_capa = ARY_DEFAULT_SIZE;
00183 }
00184 if (new_capa >= ARY_MAX_SIZE - min) {
00185 new_capa = (ARY_MAX_SIZE - min) / 2;
00186 }
00187 new_capa += min;
00188 ary_resize_capa(ary, new_capa);
00189 }
00190
00191 static void
00192 rb_ary_decrement_share(VALUE shared)
00193 {
00194 if (shared) {
00195 long num = ARY_SHARED_NUM(shared) - 1;
00196 if (num == 0) {
00197 rb_ary_free(shared);
00198 rb_gc_force_recycle(shared);
00199 }
00200 else if (num > 0) {
00201 ARY_SET_SHARED_NUM(shared, num);
00202 }
00203 }
00204 }
00205
00206 static void
00207 rb_ary_unshare(VALUE ary)
00208 {
00209 VALUE shared = RARRAY(ary)->as.heap.aux.shared;
00210 rb_ary_decrement_share(shared);
00211 FL_UNSET_SHARED(ary);
00212 }
00213
00214 static inline void
00215 rb_ary_unshare_safe(VALUE ary)
00216 {
00217 if (ARY_SHARED_P(ary) && !ARY_EMBED_P(ary)) {
00218 rb_ary_unshare(ary);
00219 }
00220 }
00221
00222 static VALUE
00223 rb_ary_increment_share(VALUE shared)
00224 {
00225 long num = ARY_SHARED_NUM(shared);
00226 if (num >= 0) {
00227 ARY_SET_SHARED_NUM(shared, num + 1);
00228 }
00229 return shared;
00230 }
00231
00232 static void
00233 rb_ary_set_shared(VALUE ary, VALUE shared)
00234 {
00235 rb_ary_increment_share(shared);
00236 FL_SET_SHARED(ary);
00237 ARY_SET_SHARED(ary, shared);
00238 }
00239
00240 static inline void
00241 rb_ary_modify_check(VALUE ary)
00242 {
00243 if (OBJ_FROZEN(ary)) rb_error_frozen("array");
00244 if (!OBJ_UNTRUSTED(ary) && rb_safe_level() >= 4)
00245 rb_raise(rb_eSecurityError, "Insecure: can't modify array");
00246 }
00247
00248 static void
00249 rb_ary_modify(VALUE ary)
00250 {
00251 rb_ary_modify_check(ary);
00252 if (ARY_SHARED_P(ary)) {
00253 long len = RARRAY_LEN(ary);
00254 if (len <= RARRAY_EMBED_LEN_MAX) {
00255 VALUE *ptr = ARY_HEAP_PTR(ary);
00256 VALUE shared = ARY_SHARED(ary);
00257 FL_UNSET_SHARED(ary);
00258 FL_SET_EMBED(ary);
00259 MEMCPY(ARY_EMBED_PTR(ary), ptr, VALUE, len);
00260 rb_ary_decrement_share(shared);
00261 ARY_SET_EMBED_LEN(ary, len);
00262 }
00263 else {
00264 VALUE *ptr = ALLOC_N(VALUE, len);
00265 MEMCPY(ptr, RARRAY_PTR(ary), VALUE, len);
00266 rb_ary_unshare(ary);
00267 ARY_SET_CAPA(ary, len);
00268 ARY_SET_PTR(ary, ptr);
00269 }
00270 }
00271 }
00272
00273 VALUE
00274 rb_ary_freeze(VALUE ary)
00275 {
00276 return rb_obj_freeze(ary);
00277 }
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287 static VALUE
00288 rb_ary_frozen_p(VALUE ary)
00289 {
00290 if (OBJ_FROZEN(ary)) return Qtrue;
00291 return Qfalse;
00292 }
00293
00294 static VALUE
00295 ary_alloc(VALUE klass)
00296 {
00297 NEWOBJ(ary, struct RArray);
00298 OBJSETUP(ary, klass, T_ARRAY);
00299 FL_SET_EMBED((VALUE)ary);
00300 ARY_SET_EMBED_LEN((VALUE)ary, 0);
00301
00302 return (VALUE)ary;
00303 }
00304
00305 static VALUE
00306 ary_new(VALUE klass, long capa)
00307 {
00308 VALUE ary;
00309
00310 if (capa < 0) {
00311 rb_raise(rb_eArgError, "negative array size (or size too big)");
00312 }
00313 if (capa > ARY_MAX_SIZE) {
00314 rb_raise(rb_eArgError, "array size too big");
00315 }
00316 ary = ary_alloc(klass);
00317 if (capa > RARRAY_EMBED_LEN_MAX) {
00318 FL_UNSET_EMBED(ary);
00319 ARY_SET_PTR(ary, ALLOC_N(VALUE, capa));
00320 ARY_SET_CAPA(ary, capa);
00321 ARY_SET_HEAP_LEN(ary, 0);
00322 }
00323
00324 return ary;
00325 }
00326
00327 VALUE
00328 rb_ary_new2(long capa)
00329 {
00330 return ary_new(rb_cArray, capa);
00331 }
00332
00333
00334 VALUE
00335 rb_ary_new(void)
00336 {
00337 return rb_ary_new2(RARRAY_EMBED_LEN_MAX);
00338 }
00339
00340 #include <stdarg.h>
00341
00342 VALUE
00343 rb_ary_new3(long n, ...)
00344 {
00345 va_list ar;
00346 VALUE ary;
00347 long i;
00348
00349 ary = rb_ary_new2(n);
00350
00351 va_start(ar, n);
00352 for (i=0; i<n; i++) {
00353 RARRAY_PTR(ary)[i] = va_arg(ar, VALUE);
00354 }
00355 va_end(ar);
00356
00357 ARY_SET_LEN(ary, n);
00358 return ary;
00359 }
00360
00361 VALUE
00362 rb_ary_new4(long n, const VALUE *elts)
00363 {
00364 VALUE ary;
00365
00366 ary = rb_ary_new2(n);
00367 if (n > 0 && elts) {
00368 MEMCPY(RARRAY_PTR(ary), elts, VALUE, n);
00369 ARY_SET_LEN(ary, n);
00370 }
00371
00372 return ary;
00373 }
00374
00375 VALUE
00376 rb_ary_tmp_new(long capa)
00377 {
00378 return ary_new(0, capa);
00379 }
00380
00381 void
00382 rb_ary_free(VALUE ary)
00383 {
00384 if (ARY_OWNS_HEAP_P(ary)) {
00385 xfree(ARY_HEAP_PTR(ary));
00386 }
00387 }
00388
00389 size_t
00390 rb_ary_memsize(VALUE ary)
00391 {
00392 if (ARY_OWNS_HEAP_P(ary)) {
00393 return RARRAY(ary)->as.heap.aux.capa * sizeof(VALUE);
00394 }
00395 else {
00396 return 0;
00397 }
00398 }
00399
00400 static inline void
00401 ary_discard(VALUE ary)
00402 {
00403 rb_ary_free(ary);
00404 RBASIC(ary)->flags |= RARRAY_EMBED_FLAG;
00405 RBASIC(ary)->flags &= ~RARRAY_EMBED_LEN_MASK;
00406 }
00407
00408 static VALUE
00409 ary_make_shared(VALUE ary)
00410 {
00411 assert(!ARY_EMBED_P(ary));
00412 if (ARY_SHARED_P(ary)) {
00413 return ARY_SHARED(ary);
00414 }
00415 else if (ARY_SHARED_ROOT_P(ary)) {
00416 return ary;
00417 }
00418 else if (OBJ_FROZEN(ary)) {
00419 ary_resize_capa(ary, ARY_HEAP_LEN(ary));
00420 FL_SET_SHARED_ROOT(ary);
00421 ARY_SET_SHARED_NUM(ary, 1);
00422 return ary;
00423 }
00424 else {
00425 NEWOBJ(shared, struct RArray);
00426 OBJSETUP(shared, 0, T_ARRAY);
00427 FL_UNSET_EMBED(shared);
00428
00429 ARY_SET_LEN((VALUE)shared, RARRAY_LEN(ary));
00430 ARY_SET_PTR((VALUE)shared, RARRAY_PTR(ary));
00431 FL_SET_SHARED_ROOT(shared);
00432 ARY_SET_SHARED_NUM((VALUE)shared, 1);
00433 FL_SET_SHARED(ary);
00434 ARY_SET_SHARED(ary, (VALUE)shared);
00435 OBJ_FREEZE(shared);
00436 return (VALUE)shared;
00437 }
00438 }
00439
00440
00441 static VALUE
00442 ary_make_substitution(VALUE ary)
00443 {
00444 if (RARRAY_LEN(ary) <= RARRAY_EMBED_LEN_MAX) {
00445 VALUE subst = rb_ary_new2(RARRAY_LEN(ary));
00446 MEMCPY(ARY_EMBED_PTR(subst), RARRAY_PTR(ary), VALUE, RARRAY_LEN(ary));
00447 ARY_SET_EMBED_LEN(subst, RARRAY_LEN(ary));
00448 return subst;
00449 }
00450 else {
00451 return rb_ary_increment_share(ary_make_shared(ary));
00452 }
00453 }
00454
00455 VALUE
00456 rb_assoc_new(VALUE car, VALUE cdr)
00457 {
00458 return rb_ary_new3(2, car, cdr);
00459 }
00460
00461 static VALUE
00462 to_ary(VALUE ary)
00463 {
00464 return rb_convert_type(ary, T_ARRAY, "Array", "to_ary");
00465 }
00466
00467 VALUE
00468 rb_check_array_type(VALUE ary)
00469 {
00470 return rb_check_convert_type(ary, T_ARRAY, "Array", "to_ary");
00471 }
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493 static VALUE
00494 rb_ary_s_try_convert(VALUE dummy, VALUE ary)
00495 {
00496 return rb_check_array_type(ary);
00497 }
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537 static VALUE
00538 rb_ary_initialize(int argc, VALUE *argv, VALUE ary)
00539 {
00540 long len;
00541 VALUE size, val;
00542
00543 rb_ary_modify(ary);
00544 if (argc == 0) {
00545 if (ARY_OWNS_HEAP_P(ary) && RARRAY_PTR(ary)) {
00546 xfree(RARRAY_PTR(ary));
00547 }
00548 rb_ary_unshare_safe(ary);
00549 FL_SET_EMBED(ary);
00550 ARY_SET_EMBED_LEN(ary, 0);
00551 if (rb_block_given_p()) {
00552 rb_warning("given block not used");
00553 }
00554 return ary;
00555 }
00556 rb_scan_args(argc, argv, "02", &size, &val);
00557 if (argc == 1 && !FIXNUM_P(size)) {
00558 val = rb_check_array_type(size);
00559 if (!NIL_P(val)) {
00560 rb_ary_replace(ary, val);
00561 return ary;
00562 }
00563 }
00564
00565 len = NUM2LONG(size);
00566 if (len < 0) {
00567 rb_raise(rb_eArgError, "negative array size");
00568 }
00569 if (len > ARY_MAX_SIZE) {
00570 rb_raise(rb_eArgError, "array size too big");
00571 }
00572 rb_ary_modify(ary);
00573 ary_resize_capa(ary, len);
00574 if (rb_block_given_p()) {
00575 long i;
00576
00577 if (argc == 2) {
00578 rb_warn("block supersedes default value argument");
00579 }
00580 for (i=0; i<len; i++) {
00581 rb_ary_store(ary, i, rb_yield(LONG2NUM(i)));
00582 ARY_SET_LEN(ary, i + 1);
00583 }
00584 }
00585 else {
00586 memfill(RARRAY_PTR(ary), len, val);
00587 ARY_SET_LEN(ary, len);
00588 }
00589 return ary;
00590 }
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601 static VALUE
00602 rb_ary_s_create(int argc, VALUE *argv, VALUE klass)
00603 {
00604 VALUE ary = ary_new(klass, argc);
00605 if (argc > 0 && argv) {
00606 MEMCPY(RARRAY_PTR(ary), argv, VALUE, argc);
00607 ARY_SET_LEN(ary, argc);
00608 }
00609
00610 return ary;
00611 }
00612
00613 void
00614 rb_ary_store(VALUE ary, long idx, VALUE val)
00615 {
00616 if (idx < 0) {
00617 idx += RARRAY_LEN(ary);
00618 if (idx < 0) {
00619 rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
00620 idx - RARRAY_LEN(ary), -RARRAY_LEN(ary));
00621 }
00622 }
00623 else if (idx >= ARY_MAX_SIZE) {
00624 rb_raise(rb_eIndexError, "index %ld too big", idx);
00625 }
00626
00627 rb_ary_modify(ary);
00628 if (idx >= ARY_CAPA(ary)) {
00629 ary_double_capa(ary, idx);
00630 }
00631 if (idx > RARRAY_LEN(ary)) {
00632 rb_mem_clear(RARRAY_PTR(ary) + RARRAY_LEN(ary),
00633 idx-RARRAY_LEN(ary) + 1);
00634 }
00635
00636 if (idx >= RARRAY_LEN(ary)) {
00637 ARY_SET_LEN(ary, idx + 1);
00638 }
00639 RARRAY_PTR(ary)[idx] = val;
00640 }
00641
00642 static VALUE
00643 ary_make_partial(VALUE ary, VALUE klass, long offset, long len)
00644 {
00645 assert(offset >= 0);
00646 assert(len >= 0);
00647 assert(offset+len <= RARRAY_LEN(ary));
00648
00649 if (len <= RARRAY_EMBED_LEN_MAX) {
00650 VALUE result = ary_alloc(klass);
00651 MEMCPY(ARY_EMBED_PTR(result), RARRAY_PTR(ary) + offset, VALUE, len);
00652 ARY_SET_EMBED_LEN(result, len);
00653 return result;
00654 }
00655 else {
00656 VALUE shared, result = ary_alloc(klass);
00657 FL_UNSET_EMBED(result);
00658
00659 shared = ary_make_shared(ary);
00660 ARY_SET_PTR(result, RARRAY_PTR(ary));
00661 ARY_SET_LEN(result, RARRAY_LEN(ary));
00662 rb_ary_set_shared(result, shared);
00663
00664 ARY_INCREASE_PTR(result, offset);
00665 ARY_SET_LEN(result, len);
00666 return result;
00667 }
00668 }
00669
00670 static VALUE
00671 ary_make_shared_copy(VALUE ary)
00672 {
00673 return ary_make_partial(ary, rb_obj_class(ary), 0, RARRAY_LEN(ary));
00674 }
00675
00676 enum ary_take_pos_flags
00677 {
00678 ARY_TAKE_FIRST = 0,
00679 ARY_TAKE_LAST = 1
00680 };
00681
00682 static VALUE
00683 ary_take_first_or_last(int argc, VALUE *argv, VALUE ary, enum ary_take_pos_flags last)
00684 {
00685 VALUE nv;
00686 long n;
00687 long offset = 0;
00688
00689 rb_scan_args(argc, argv, "1", &nv);
00690 n = NUM2LONG(nv);
00691 if (n > RARRAY_LEN(ary)) {
00692 n = RARRAY_LEN(ary);
00693 }
00694 else if (n < 0) {
00695 rb_raise(rb_eArgError, "negative array size");
00696 }
00697 if (last) {
00698 offset = RARRAY_LEN(ary) - n;
00699 }
00700 return ary_make_partial(ary, rb_cArray, offset, n);
00701 }
00702
00703 static VALUE rb_ary_push_1(VALUE ary, VALUE item);
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718 VALUE
00719 rb_ary_push(VALUE ary, VALUE item)
00720 {
00721 rb_ary_modify(ary);
00722 return rb_ary_push_1(ary, item);
00723 }
00724
00725 static VALUE
00726 rb_ary_push_1(VALUE ary, VALUE item)
00727 {
00728 long idx = RARRAY_LEN(ary);
00729
00730 if (idx >= ARY_CAPA(ary)) {
00731 ary_double_capa(ary, idx);
00732 }
00733 RARRAY_PTR(ary)[idx] = item;
00734 ARY_SET_LEN(ary, idx + 1);
00735 return ary;
00736 }
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751 static VALUE
00752 rb_ary_push_m(int argc, VALUE *argv, VALUE ary)
00753 {
00754 rb_ary_modify(ary);
00755 while (argc--) {
00756 rb_ary_push_1(ary, *argv++);
00757 }
00758 return ary;
00759 }
00760
00761 VALUE
00762 rb_ary_pop(VALUE ary)
00763 {
00764 long n;
00765 rb_ary_modify_check(ary);
00766 if (RARRAY_LEN(ary) == 0) return Qnil;
00767 if (ARY_OWNS_HEAP_P(ary) &&
00768 RARRAY_LEN(ary) * 3 < ARY_CAPA(ary) &&
00769 ARY_CAPA(ary) > ARY_DEFAULT_SIZE)
00770 {
00771 ary_resize_capa(ary, RARRAY_LEN(ary) * 2);
00772 }
00773 n = RARRAY_LEN(ary)-1;
00774 ARY_SET_LEN(ary, n);
00775 return RARRAY_PTR(ary)[n];
00776 }
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795 static VALUE
00796 rb_ary_pop_m(int argc, VALUE *argv, VALUE ary)
00797 {
00798 VALUE result;
00799
00800 if (argc == 0) {
00801 return rb_ary_pop(ary);
00802 }
00803
00804 rb_ary_modify_check(ary);
00805 result = ary_take_first_or_last(argc, argv, ary, ARY_TAKE_LAST);
00806 ARY_INCREASE_LEN(ary, -RARRAY_LEN(result));
00807 return result;
00808 }
00809
00810 VALUE
00811 rb_ary_shift(VALUE ary)
00812 {
00813 VALUE top;
00814
00815 rb_ary_modify_check(ary);
00816 if (RARRAY_LEN(ary) == 0) return Qnil;
00817 top = RARRAY_PTR(ary)[0];
00818 if (!ARY_SHARED_P(ary)) {
00819 if (RARRAY_LEN(ary) < ARY_DEFAULT_SIZE) {
00820 MEMMOVE(RARRAY_PTR(ary), RARRAY_PTR(ary)+1, VALUE, RARRAY_LEN(ary)-1);
00821 ARY_INCREASE_LEN(ary, -1);
00822 return top;
00823 }
00824 assert(!ARY_EMBED_P(ary));
00825
00826 RARRAY_PTR(ary)[0] = Qnil;
00827 ary_make_shared(ary);
00828 }
00829 else if (ARY_SHARED_NUM(ARY_SHARED(ary)) == 1) {
00830 RARRAY_PTR(ary)[0] = Qnil;
00831 }
00832 ARY_INCREASE_PTR(ary, 1);
00833 ARY_INCREASE_LEN(ary, -1);
00834
00835 return top;
00836 }
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859 static VALUE
00860 rb_ary_shift_m(int argc, VALUE *argv, VALUE ary)
00861 {
00862 VALUE result;
00863 long n;
00864
00865 if (argc == 0) {
00866 return rb_ary_shift(ary);
00867 }
00868
00869 rb_ary_modify_check(ary);
00870 result = ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST);
00871 n = RARRAY_LEN(result);
00872 if (ARY_SHARED_P(ary)) {
00873 if (ARY_SHARED_NUM(ARY_SHARED(ary)) == 1) {
00874 rb_mem_clear(RARRAY_PTR(ary), n);
00875 }
00876 ARY_INCREASE_PTR(ary, n);
00877 }
00878 else {
00879 MEMMOVE(RARRAY_PTR(ary), RARRAY_PTR(ary)+n, VALUE, RARRAY_LEN(ary)-n);
00880 }
00881 ARY_INCREASE_LEN(ary, -n);
00882
00883 return result;
00884 }
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898 static VALUE
00899 rb_ary_unshift_m(int argc, VALUE *argv, VALUE ary)
00900 {
00901 long len;
00902
00903 rb_ary_modify(ary);
00904 if (argc == 0) return ary;
00905 if (ARY_CAPA(ary) <= (len = RARRAY_LEN(ary)) + argc) {
00906 ary_double_capa(ary, len + argc);
00907 }
00908
00909
00910 MEMMOVE(RARRAY_PTR(ary) + argc, RARRAY_PTR(ary), VALUE, len);
00911 MEMCPY(RARRAY_PTR(ary), argv, VALUE, argc);
00912 ARY_INCREASE_LEN(ary, argc);
00913
00914 return ary;
00915 }
00916
00917 VALUE
00918 rb_ary_unshift(VALUE ary, VALUE item)
00919 {
00920 return rb_ary_unshift_m(1,&item,ary);
00921 }
00922
00923
00924 static inline VALUE
00925 rb_ary_elt(VALUE ary, long offset)
00926 {
00927 if (RARRAY_LEN(ary) == 0) return Qnil;
00928 if (offset < 0 || RARRAY_LEN(ary) <= offset) {
00929 return Qnil;
00930 }
00931 return RARRAY_PTR(ary)[offset];
00932 }
00933
00934 VALUE
00935 rb_ary_entry(VALUE ary, long offset)
00936 {
00937 if (offset < 0) {
00938 offset += RARRAY_LEN(ary);
00939 }
00940 return rb_ary_elt(ary, offset);
00941 }
00942
00943 VALUE
00944 rb_ary_subseq(VALUE ary, long beg, long len)
00945 {
00946 VALUE klass;
00947
00948 if (beg > RARRAY_LEN(ary)) return Qnil;
00949 if (beg < 0 || len < 0) return Qnil;
00950
00951 if (RARRAY_LEN(ary) < len || RARRAY_LEN(ary) < beg + len) {
00952 len = RARRAY_LEN(ary) - beg;
00953 }
00954 klass = rb_obj_class(ary);
00955 if (len == 0) return ary_new(klass, 0);
00956
00957 return ary_make_partial(ary, klass, beg, len);
00958 }
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992 VALUE
00993 rb_ary_aref(int argc, VALUE *argv, VALUE ary)
00994 {
00995 VALUE arg;
00996 long beg, len;
00997
00998 if (argc == 2) {
00999 beg = NUM2LONG(argv[0]);
01000 len = NUM2LONG(argv[1]);
01001 if (beg < 0) {
01002 beg += RARRAY_LEN(ary);
01003 }
01004 return rb_ary_subseq(ary, beg, len);
01005 }
01006 if (argc != 1) {
01007 rb_scan_args(argc, argv, "11", 0, 0);
01008 }
01009 arg = argv[0];
01010
01011 if (FIXNUM_P(arg)) {
01012 return rb_ary_entry(ary, FIX2LONG(arg));
01013 }
01014
01015 switch (rb_range_beg_len(arg, &beg, &len, RARRAY_LEN(ary), 0)) {
01016 case Qfalse:
01017 break;
01018 case Qnil:
01019 return Qnil;
01020 default:
01021 return rb_ary_subseq(ary, beg, len);
01022 }
01023 return rb_ary_entry(ary, NUM2LONG(arg));
01024 }
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039 static VALUE
01040 rb_ary_at(VALUE ary, VALUE pos)
01041 {
01042 return rb_ary_entry(ary, NUM2LONG(pos));
01043 }
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059 static VALUE
01060 rb_ary_first(int argc, VALUE *argv, VALUE ary)
01061 {
01062 if (argc == 0) {
01063 if (RARRAY_LEN(ary) == 0) return Qnil;
01064 return RARRAY_PTR(ary)[0];
01065 }
01066 else {
01067 return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST);
01068 }
01069 }
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084 VALUE
01085 rb_ary_last(int argc, VALUE *argv, VALUE ary)
01086 {
01087 if (argc == 0) {
01088 if (RARRAY_LEN(ary) == 0) return Qnil;
01089 return RARRAY_PTR(ary)[RARRAY_LEN(ary)-1];
01090 }
01091 else {
01092 return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_LAST);
01093 }
01094 }
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116 static VALUE
01117 rb_ary_fetch(int argc, VALUE *argv, VALUE ary)
01118 {
01119 VALUE pos, ifnone;
01120 long block_given;
01121 long idx;
01122
01123 rb_scan_args(argc, argv, "11", &pos, &ifnone);
01124 block_given = rb_block_given_p();
01125 if (block_given && argc == 2) {
01126 rb_warn("block supersedes default value argument");
01127 }
01128 idx = NUM2LONG(pos);
01129
01130 if (idx < 0) {
01131 idx += RARRAY_LEN(ary);
01132 }
01133 if (idx < 0 || RARRAY_LEN(ary) <= idx) {
01134 if (block_given) return rb_yield(pos);
01135 if (argc == 1) {
01136 rb_raise(rb_eIndexError, "index %ld outside of array bounds: %ld...%ld",
01137 idx - (idx < 0 ? RARRAY_LEN(ary) : 0), -RARRAY_LEN(ary), RARRAY_LEN(ary));
01138 }
01139 return ifnone;
01140 }
01141 return RARRAY_PTR(ary)[idx];
01142 }
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166 static VALUE
01167 rb_ary_index(int argc, VALUE *argv, VALUE ary)
01168 {
01169 VALUE val;
01170 long i;
01171
01172 if (argc == 0) {
01173 RETURN_ENUMERATOR(ary, 0, 0);
01174 for (i=0; i<RARRAY_LEN(ary); i++) {
01175 if (RTEST(rb_yield(RARRAY_PTR(ary)[i]))) {
01176 return LONG2NUM(i);
01177 }
01178 }
01179 return Qnil;
01180 }
01181 rb_scan_args(argc, argv, "1", &val);
01182 if (rb_block_given_p())
01183 rb_warn("given block not used");
01184 for (i=0; i<RARRAY_LEN(ary); i++) {
01185 if (rb_equal(RARRAY_PTR(ary)[i], val))
01186 return LONG2NUM(i);
01187 }
01188 return Qnil;
01189 }
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212 static VALUE
01213 rb_ary_rindex(int argc, VALUE *argv, VALUE ary)
01214 {
01215 VALUE val;
01216 long i = RARRAY_LEN(ary);
01217
01218 if (argc == 0) {
01219 RETURN_ENUMERATOR(ary, 0, 0);
01220 while (i--) {
01221 if (RTEST(rb_yield(RARRAY_PTR(ary)[i])))
01222 return LONG2NUM(i);
01223 if (i > RARRAY_LEN(ary)) {
01224 i = RARRAY_LEN(ary);
01225 }
01226 }
01227 return Qnil;
01228 }
01229 rb_scan_args(argc, argv, "1", &val);
01230 if (rb_block_given_p())
01231 rb_warn("given block not used");
01232 while (i--) {
01233 if (rb_equal(RARRAY_PTR(ary)[i], val))
01234 return LONG2NUM(i);
01235 if (i > RARRAY_LEN(ary)) {
01236 i = RARRAY_LEN(ary);
01237 }
01238 }
01239 return Qnil;
01240 }
01241
01242 VALUE
01243 rb_ary_to_ary(VALUE obj)
01244 {
01245 VALUE tmp = rb_check_array_type(obj);
01246
01247 if (!NIL_P(tmp)) return tmp;
01248 return rb_ary_new3(1, obj);
01249 }
01250
01251 static void
01252 rb_ary_splice(VALUE ary, long beg, long len, VALUE rpl)
01253 {
01254 long rlen;
01255
01256 if (len < 0) rb_raise(rb_eIndexError, "negative length (%ld)", len);
01257 if (beg < 0) {
01258 beg += RARRAY_LEN(ary);
01259 if (beg < 0) {
01260 rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
01261 beg - RARRAY_LEN(ary), -RARRAY_LEN(ary));
01262 }
01263 }
01264 if (RARRAY_LEN(ary) < len || RARRAY_LEN(ary) < beg + len) {
01265 len = RARRAY_LEN(ary) - beg;
01266 }
01267
01268 if (rpl == Qundef) {
01269 rlen = 0;
01270 }
01271 else {
01272 rpl = rb_ary_to_ary(rpl);
01273 rlen = RARRAY_LEN(rpl);
01274 }
01275 rb_ary_modify(ary);
01276 if (beg >= RARRAY_LEN(ary)) {
01277 if (beg > ARY_MAX_SIZE - rlen) {
01278 rb_raise(rb_eIndexError, "index %ld too big", beg);
01279 }
01280 len = beg + rlen;
01281 if (len >= ARY_CAPA(ary)) {
01282 ary_double_capa(ary, len);
01283 }
01284 rb_mem_clear(RARRAY_PTR(ary) + RARRAY_LEN(ary), beg - RARRAY_LEN(ary));
01285 if (rlen > 0) {
01286 MEMCPY(RARRAY_PTR(ary) + beg, RARRAY_PTR(rpl), VALUE, rlen);
01287 }
01288 ARY_SET_LEN(ary, len);
01289 }
01290 else {
01291 long alen;
01292
01293 alen = RARRAY_LEN(ary) + rlen - len;
01294 if (alen >= ARY_CAPA(ary)) {
01295 ary_double_capa(ary, alen);
01296 }
01297
01298 if (len != rlen) {
01299 MEMMOVE(RARRAY_PTR(ary) + beg + rlen, RARRAY_PTR(ary) + beg + len,
01300 VALUE, RARRAY_LEN(ary) - (beg + len));
01301 ARY_SET_LEN(ary, alen);
01302 }
01303 if (rlen > 0) {
01304 MEMMOVE(RARRAY_PTR(ary) + beg, RARRAY_PTR(rpl), VALUE, rlen);
01305 }
01306 }
01307 }
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335
01336
01337 static VALUE
01338 rb_ary_aset(int argc, VALUE *argv, VALUE ary)
01339 {
01340 long offset, beg, len;
01341
01342 if (argc == 3) {
01343 rb_ary_modify_check(ary);
01344 beg = NUM2LONG(argv[0]);
01345 len = NUM2LONG(argv[1]);
01346 rb_ary_splice(ary, beg, len, argv[2]);
01347 return argv[2];
01348 }
01349 if (argc != 2) {
01350 rb_raise(rb_eArgError, "wrong number of arguments (%d for 2)", argc);
01351 }
01352 rb_ary_modify_check(ary);
01353 if (FIXNUM_P(argv[0])) {
01354 offset = FIX2LONG(argv[0]);
01355 goto fixnum;
01356 }
01357 if (rb_range_beg_len(argv[0], &beg, &len, RARRAY_LEN(ary), 1)) {
01358
01359 rb_ary_splice(ary, beg, len, argv[1]);
01360 return argv[1];
01361 }
01362
01363 offset = NUM2LONG(argv[0]);
01364 fixnum:
01365 rb_ary_store(ary, offset, argv[1]);
01366 return argv[1];
01367 }
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381 static VALUE
01382 rb_ary_insert(int argc, VALUE *argv, VALUE ary)
01383 {
01384 long pos;
01385
01386 if (argc < 1) {
01387 rb_raise(rb_eArgError, "wrong number of arguments (at least 1)");
01388 }
01389 rb_ary_modify_check(ary);
01390 if (argc == 1) return ary;
01391 pos = NUM2LONG(argv[0]);
01392 if (pos == -1) {
01393 pos = RARRAY_LEN(ary);
01394 }
01395 if (pos < 0) {
01396 pos++;
01397 }
01398 rb_ary_splice(ary, pos, 0, rb_ary_new4(argc - 1, argv + 1));
01399 return ary;
01400 }
01401
01402
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420 VALUE
01421 rb_ary_each(VALUE ary)
01422 {
01423 long i;
01424
01425 RETURN_ENUMERATOR(ary, 0, 0);
01426 for (i=0; i<RARRAY_LEN(ary); i++) {
01427 rb_yield(RARRAY_PTR(ary)[i]);
01428 }
01429 return ary;
01430 }
01431
01432
01433
01434
01435
01436
01437
01438
01439
01440
01441
01442
01443
01444
01445
01446
01447
01448
01449
01450
01451 static VALUE
01452 rb_ary_each_index(VALUE ary)
01453 {
01454 long i;
01455 RETURN_ENUMERATOR(ary, 0, 0);
01456
01457 for (i=0; i<RARRAY_LEN(ary); i++) {
01458 rb_yield(LONG2NUM(i));
01459 }
01460 return ary;
01461 }
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479 static VALUE
01480 rb_ary_reverse_each(VALUE ary)
01481 {
01482 long len;
01483
01484 RETURN_ENUMERATOR(ary, 0, 0);
01485 len = RARRAY_LEN(ary);
01486 while (len--) {
01487 rb_yield(RARRAY_PTR(ary)[len]);
01488 if (RARRAY_LEN(ary) < len) {
01489 len = RARRAY_LEN(ary);
01490 }
01491 }
01492 return ary;
01493 }
01494
01495
01496
01497
01498
01499
01500
01501
01502
01503
01504 static VALUE
01505 rb_ary_length(VALUE ary)
01506 {
01507 long len = RARRAY_LEN(ary);
01508 return LONG2NUM(len);
01509 }
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519
01520 static VALUE
01521 rb_ary_empty_p(VALUE ary)
01522 {
01523 if (RARRAY_LEN(ary) == 0)
01524 return Qtrue;
01525 return Qfalse;
01526 }
01527
01528 static VALUE
01529 rb_ary_dup_setup(VALUE ary)
01530 {
01531 VALUE dup = rb_ary_new2(RARRAY_LEN(ary));
01532 int is_embed = ARY_EMBED_P(dup);
01533 DUPSETUP(dup, ary);
01534 if (is_embed) FL_SET_EMBED(dup);
01535 ARY_SET_LEN(dup, RARRAY_LEN(ary));
01536 return dup;
01537 }
01538
01539 VALUE
01540 rb_ary_dup(VALUE ary)
01541 {
01542 VALUE dup = rb_ary_dup_setup(ary);
01543 MEMCPY(RARRAY_PTR(dup), RARRAY_PTR(ary), VALUE, RARRAY_LEN(ary));
01544 return dup;
01545 }
01546
01547 VALUE
01548 rb_ary_resurrect(VALUE ary)
01549 {
01550 return rb_ary_new4(RARRAY_LEN(ary), RARRAY_PTR(ary));
01551 }
01552
01553 extern VALUE rb_output_fs;
01554
01555 static void ary_join_1(VALUE obj, VALUE ary, VALUE sep, long i, VALUE result);
01556
01557 static VALUE
01558 recursive_join(VALUE obj, VALUE argp, int recur)
01559 {
01560 VALUE *arg = (VALUE *)argp;
01561 VALUE ary = arg[0];
01562 VALUE sep = arg[1];
01563 VALUE result = arg[2];
01564
01565 if (recur) {
01566 rb_raise(rb_eArgError, "recursive array join");
01567 }
01568 else {
01569 ary_join_1(obj, ary, sep, 0, result);
01570 }
01571 return Qnil;
01572 }
01573
01574 static void
01575 ary_join_0(VALUE ary, VALUE sep, long max, VALUE result)
01576 {
01577 long i;
01578 VALUE val;
01579
01580 for (i=0; i<max; i++) {
01581 val = RARRAY_PTR(ary)[i];
01582 if (i > 0 && !NIL_P(sep))
01583 rb_str_buf_append(result, sep);
01584 rb_str_buf_append(result, val);
01585 if (OBJ_TAINTED(val)) OBJ_TAINT(result);
01586 if (OBJ_UNTRUSTED(val)) OBJ_TAINT(result);
01587 }
01588 }
01589
01590 static void
01591 ary_join_1(VALUE obj, VALUE ary, VALUE sep, long i, VALUE result)
01592 {
01593 VALUE val, tmp;
01594
01595 for (; i<RARRAY_LEN(ary); i++) {
01596 if (i > 0 && !NIL_P(sep))
01597 rb_str_buf_append(result, sep);
01598
01599 val = RARRAY_PTR(ary)[i];
01600 switch (TYPE(val)) {
01601 case T_STRING:
01602 str_join:
01603 rb_str_buf_append(result, val);
01604 break;
01605 case T_ARRAY:
01606 obj = val;
01607 ary_join:
01608 if (val == ary) {
01609 rb_raise(rb_eArgError, "recursive array join");
01610 }
01611 else {
01612 VALUE args[3];
01613
01614 args[0] = val;
01615 args[1] = sep;
01616 args[2] = result;
01617 rb_exec_recursive(recursive_join, obj, (VALUE)args);
01618 }
01619 break;
01620 default:
01621 tmp = rb_check_string_type(val);
01622 if (!NIL_P(tmp)) {
01623 val = tmp;
01624 goto str_join;
01625 }
01626 tmp = rb_check_convert_type(val, T_ARRAY, "Array", "to_ary");
01627 if (!NIL_P(tmp)) {
01628 obj = val;
01629 val = tmp;
01630 goto ary_join;
01631 }
01632 val = rb_obj_as_string(val);
01633 goto str_join;
01634 }
01635 }
01636 }
01637
01638 VALUE
01639 rb_ary_join(VALUE ary, VALUE sep)
01640 {
01641 long len = 1, i;
01642 int taint = FALSE;
01643 int untrust = FALSE;
01644 VALUE val, tmp, result;
01645
01646 if (RARRAY_LEN(ary) == 0) return rb_usascii_str_new(0, 0);
01647 if (OBJ_TAINTED(ary) || OBJ_TAINTED(sep)) taint = TRUE;
01648 if (OBJ_UNTRUSTED(ary) || OBJ_UNTRUSTED(sep)) untrust = TRUE;
01649
01650 if (!NIL_P(sep)) {
01651 StringValue(sep);
01652 len += RSTRING_LEN(sep) * (RARRAY_LEN(ary) - 1);
01653 }
01654 for (i=0; i<RARRAY_LEN(ary); i++) {
01655 val = RARRAY_PTR(ary)[i];
01656 tmp = rb_check_string_type(val);
01657
01658 if (NIL_P(tmp) || tmp != val) {
01659 result = rb_str_buf_new(len + (RARRAY_LEN(ary)-i)*10);
01660 if (taint) OBJ_TAINT(result);
01661 if (untrust) OBJ_UNTRUST(result);
01662 ary_join_0(ary, sep, i, result);
01663 ary_join_1(ary, ary, sep, i, result);
01664 return result;
01665 }
01666
01667 len += RSTRING_LEN(tmp);
01668 }
01669
01670 result = rb_str_buf_new(len);
01671 if (taint) OBJ_TAINT(result);
01672 if (untrust) OBJ_UNTRUST(result);
01673 ary_join_0(ary, sep, RARRAY_LEN(ary), result);
01674
01675 return result;
01676 }
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686
01687
01688
01689 static VALUE
01690 rb_ary_join_m(int argc, VALUE *argv, VALUE ary)
01691 {
01692 VALUE sep;
01693
01694 rb_scan_args(argc, argv, "01", &sep);
01695 if (NIL_P(sep)) sep = rb_output_fs;
01696
01697 return rb_ary_join(ary, sep);
01698 }
01699
01700 static VALUE
01701 inspect_ary(VALUE ary, VALUE dummy, int recur)
01702 {
01703 int tainted = OBJ_TAINTED(ary);
01704 int untrust = OBJ_UNTRUSTED(ary);
01705 long i;
01706 VALUE s, str;
01707
01708 if (recur) return rb_tainted_str_new2("[...]");
01709 str = rb_str_buf_new2("[");
01710 for (i=0; i<RARRAY_LEN(ary); i++) {
01711 s = rb_inspect(RARRAY_PTR(ary)[i]);
01712 if (OBJ_TAINTED(s)) tainted = TRUE;
01713 if (OBJ_UNTRUSTED(s)) untrust = TRUE;
01714 if (i > 0) rb_str_buf_cat2(str, ", ");
01715 rb_str_buf_append(str, s);
01716 }
01717 rb_str_buf_cat2(str, "]");
01718 if (tainted) OBJ_TAINT(str);
01719 if (untrust) OBJ_UNTRUST(str);
01720 return str;
01721 }
01722
01723
01724
01725
01726
01727
01728
01729
01730
01731 static VALUE
01732 rb_ary_inspect(VALUE ary)
01733 {
01734 if (RARRAY_LEN(ary) == 0) return rb_usascii_str_new2("[]");
01735 return rb_exec_recursive(inspect_ary, ary, 0);
01736 }
01737
01738 VALUE
01739 rb_ary_to_s(VALUE ary)
01740 {
01741 return rb_ary_inspect(ary);
01742 }
01743
01744
01745
01746
01747
01748
01749
01750
01751
01752 static VALUE
01753 rb_ary_to_a(VALUE ary)
01754 {
01755 if (rb_obj_class(ary) != rb_cArray) {
01756 VALUE dup = rb_ary_new2(RARRAY_LEN(ary));
01757 rb_ary_replace(dup, ary);
01758 return dup;
01759 }
01760 return ary;
01761 }
01762
01763
01764
01765
01766
01767
01768
01769
01770 static VALUE
01771 rb_ary_to_ary_m(VALUE ary)
01772 {
01773 return ary;
01774 }
01775
01776 static void
01777 ary_reverse(p1, p2)
01778 VALUE *p1, *p2;
01779 {
01780 while (p1 < p2) {
01781 VALUE tmp = *p1;
01782 *p1++ = *p2;
01783 *p2-- = tmp;
01784 }
01785 }
01786
01787 VALUE
01788 rb_ary_reverse(VALUE ary)
01789 {
01790 VALUE *p1, *p2;
01791
01792 rb_ary_modify(ary);
01793 if (RARRAY_LEN(ary) > 1) {
01794 p1 = RARRAY_PTR(ary);
01795 p2 = p1 + RARRAY_LEN(ary) - 1;
01796 ary_reverse(p1, p2);
01797 }
01798 return ary;
01799 }
01800
01801
01802
01803
01804
01805
01806
01807
01808
01809
01810
01811
01812 static VALUE
01813 rb_ary_reverse_bang(VALUE ary)
01814 {
01815 return rb_ary_reverse(ary);
01816 }
01817
01818
01819
01820
01821
01822
01823
01824
01825
01826
01827
01828 static VALUE
01829 rb_ary_reverse_m(VALUE ary)
01830 {
01831 VALUE dup = rb_ary_dup_setup(ary);
01832 long len = RARRAY_LEN(ary);
01833
01834 if (len > 0) {
01835 VALUE *p1 = RARRAY_PTR(ary);
01836 VALUE *p2 = RARRAY_PTR(dup) + len - 1;
01837 do *p2-- = *p1++; while (--len > 0);
01838 }
01839 return dup;
01840 }
01841
01842 static inline long
01843 rotate_count(long cnt, long len)
01844 {
01845 return (cnt < 0) ? (len - (~cnt % len) - 1) : (cnt % len);
01846 }
01847
01848 VALUE
01849 rb_ary_rotate(VALUE ary, long cnt)
01850 {
01851 rb_ary_modify(ary);
01852
01853 if (cnt != 0) {
01854 VALUE *ptr = RARRAY_PTR(ary);
01855 long len = RARRAY_LEN(ary);
01856
01857 if (len > 0 && (cnt = rotate_count(cnt, len)) > 0) {
01858 --len;
01859 if (cnt < len) ary_reverse(ptr + cnt, ptr + len);
01860 if (--cnt > 0) ary_reverse(ptr, ptr + cnt);
01861 if (len > 0) ary_reverse(ptr, ptr + len);
01862 return ary;
01863 }
01864 }
01865
01866 return Qnil;
01867 }
01868
01869
01870
01871
01872
01873
01874
01875
01876
01877
01878
01879
01880
01881
01882
01883
01884 static VALUE
01885 rb_ary_rotate_bang(int argc, VALUE *argv, VALUE ary)
01886 {
01887 long n = 1;
01888
01889 switch (argc) {
01890 case 1: n = NUM2LONG(argv[0]);
01891 case 0: break;
01892 default: rb_scan_args(argc, argv, "01", NULL);
01893 }
01894 rb_ary_rotate(ary, n);
01895 return ary;
01896 }
01897
01898
01899
01900
01901
01902
01903
01904
01905
01906
01907
01908
01909
01910
01911
01912
01913 static VALUE
01914 rb_ary_rotate_m(int argc, VALUE *argv, VALUE ary)
01915 {
01916 VALUE rotated, *ptr, *ptr2;
01917 long len, cnt = 1;
01918
01919 switch (argc) {
01920 case 1: cnt = NUM2LONG(argv[0]);
01921 case 0: break;
01922 default: rb_scan_args(argc, argv, "01", NULL);
01923 }
01924
01925 len = RARRAY_LEN(ary);
01926 rotated = rb_ary_dup_setup(ary);
01927 if (len > 0) {
01928 cnt = rotate_count(cnt, len);
01929 ptr = RARRAY_PTR(ary);
01930 ptr2 = RARRAY_PTR(rotated);
01931 len -= cnt;
01932 MEMCPY(ptr2, ptr + cnt, VALUE, len);
01933 MEMCPY(ptr2 + len, ptr, VALUE, cnt);
01934 }
01935 return rotated;
01936 }
01937
01938 struct ary_sort_data {
01939 VALUE ary;
01940 int opt_methods;
01941 int opt_inited;
01942 };
01943
01944 enum {
01945 sort_opt_Fixnum,
01946 sort_opt_String,
01947 sort_optimizable_count
01948 };
01949
01950 #define STRING_P(s) (TYPE(s) == T_STRING && CLASS_OF(s) == rb_cString)
01951
01952 #define SORT_OPTIMIZABLE_BIT(type) (1U << TOKEN_PASTE(sort_opt_,type))
01953 #define SORT_OPTIMIZABLE(data, type) \
01954 ((data->opt_inited & SORT_OPTIMIZABLE_BIT(type)) ? \
01955 (data->opt_methods & SORT_OPTIMIZABLE_BIT(type)) : \
01956 ((data->opt_inited |= SORT_OPTIMIZABLE_BIT(type)), \
01957 rb_method_basic_definition_p(TOKEN_PASTE(rb_c,type), id_cmp) && \
01958 (data->opt_methods |= SORT_OPTIMIZABLE_BIT(type))))
01959
01960 static VALUE
01961 sort_reentered(VALUE ary)
01962 {
01963 if (RBASIC(ary)->klass) {
01964 rb_raise(rb_eRuntimeError, "sort reentered");
01965 }
01966 return Qnil;
01967 }
01968
01969 static int
01970 sort_1(const void *ap, const void *bp, void *dummy)
01971 {
01972 struct ary_sort_data *data = dummy;
01973 VALUE retval = sort_reentered(data->ary);
01974 VALUE a = *(const VALUE *)ap, b = *(const VALUE *)bp;
01975 int n;
01976
01977 retval = rb_yield_values(2, a, b);
01978 n = rb_cmpint(retval, a, b);
01979 sort_reentered(data->ary);
01980 return n;
01981 }
01982
01983 static int
01984 sort_2(const void *ap, const void *bp, void *dummy)
01985 {
01986 struct ary_sort_data *data = dummy;
01987 VALUE retval = sort_reentered(data->ary);
01988 VALUE a = *(const VALUE *)ap, b = *(const VALUE *)bp;
01989 int n;
01990
01991 if (FIXNUM_P(a) && FIXNUM_P(b) && SORT_OPTIMIZABLE(data, Fixnum)) {
01992 if ((long)a > (long)b) return 1;
01993 if ((long)a < (long)b) return -1;
01994 return 0;
01995 }
01996 if (STRING_P(a) && STRING_P(b) && SORT_OPTIMIZABLE(data, String)) {
01997 return rb_str_cmp(a, b);
01998 }
01999
02000 retval = rb_funcall(a, id_cmp, 1, b);
02001 n = rb_cmpint(retval, a, b);
02002 sort_reentered(data->ary);
02003
02004 return n;
02005 }
02006
02007
02008
02009
02010
02011
02012
02013
02014
02015
02016
02017
02018
02019
02020
02021
02022
02023 VALUE
02024 rb_ary_sort_bang(VALUE ary)
02025 {
02026 rb_ary_modify(ary);
02027 assert(!ARY_SHARED_P(ary));
02028 if (RARRAY_LEN(ary) > 1) {
02029 VALUE tmp = ary_make_substitution(ary);
02030 struct ary_sort_data data;
02031
02032 RBASIC(tmp)->klass = 0;
02033 data.ary = tmp;
02034 data.opt_methods = 0;
02035 data.opt_inited = 0;
02036 ruby_qsort(RARRAY_PTR(tmp), RARRAY_LEN(tmp), sizeof(VALUE),
02037 rb_block_given_p()?sort_1:sort_2, &data);
02038
02039 if (ARY_EMBED_P(tmp)) {
02040 assert(ARY_EMBED_P(tmp));
02041 if (ARY_SHARED_P(ary)) {
02042 rb_ary_unshare(ary);
02043 }
02044 FL_SET_EMBED(ary);
02045 MEMCPY(RARRAY_PTR(ary), ARY_EMBED_PTR(tmp), VALUE, ARY_EMBED_LEN(tmp));
02046 ARY_SET_LEN(ary, ARY_EMBED_LEN(tmp));
02047 }
02048 else {
02049 assert(!ARY_EMBED_P(tmp));
02050 if (ARY_HEAP_PTR(ary) == ARY_HEAP_PTR(tmp)) {
02051 assert(!ARY_EMBED_P(ary));
02052 FL_UNSET_SHARED(ary);
02053 ARY_SET_CAPA(ary, ARY_CAPA(tmp));
02054 }
02055 else {
02056 assert(!ARY_SHARED_P(tmp));
02057 if (ARY_EMBED_P(ary)) {
02058 FL_UNSET_EMBED(ary);
02059 }
02060 else if (ARY_SHARED_P(ary)) {
02061
02062 rb_ary_unshare(ary);
02063 }
02064 else {
02065 xfree(ARY_HEAP_PTR(ary));
02066 }
02067 ARY_SET_PTR(ary, RARRAY_PTR(tmp));
02068 ARY_SET_HEAP_LEN(ary, RARRAY_LEN(tmp));
02069 ARY_SET_CAPA(ary, ARY_CAPA(tmp));
02070 }
02071
02072 FL_UNSET(tmp, FL_FREEZE);
02073 FL_SET_EMBED(tmp);
02074 ARY_SET_EMBED_LEN(tmp, 0);
02075 FL_SET(tmp, FL_FREEZE);
02076 }
02077
02078 RBASIC(tmp)->klass = rb_cArray;
02079 }
02080 return ary;
02081 }
02082
02083
02084
02085
02086
02087
02088
02089
02090
02091
02092
02093
02094
02095
02096
02097
02098
02099 VALUE
02100 rb_ary_sort(VALUE ary)
02101 {
02102 ary = rb_ary_dup(ary);
02103 rb_ary_sort_bang(ary);
02104 return ary;
02105 }
02106
02107
02108 static VALUE
02109 sort_by_i(VALUE i)
02110 {
02111 return rb_yield(i);
02112 }
02113
02114
02115
02116
02117
02118
02119
02120
02121
02122
02123
02124
02125
02126 static VALUE
02127 rb_ary_sort_by_bang(VALUE ary)
02128 {
02129 VALUE sorted;
02130
02131 RETURN_ENUMERATOR(ary, 0, 0);
02132 rb_ary_modify(ary);
02133 sorted = rb_block_call(ary, rb_intern("sort_by"), 0, 0, sort_by_i, 0);
02134 rb_ary_replace(ary, sorted);
02135 return ary;
02136 }
02137
02138
02139
02140
02141
02142
02143
02144
02145
02146
02147
02148
02149
02150
02151
02152
02153
02154
02155
02156
02157 static VALUE
02158 rb_ary_collect(VALUE ary)
02159 {
02160 long i;
02161 VALUE collect;
02162
02163 RETURN_ENUMERATOR(ary, 0, 0);
02164 collect = rb_ary_new2(RARRAY_LEN(ary));
02165 for (i = 0; i < RARRAY_LEN(ary); i++) {
02166 rb_ary_push(collect, rb_yield(RARRAY_PTR(ary)[i]));
02167 }
02168 return collect;
02169 }
02170
02171
02172
02173
02174
02175
02176
02177
02178
02179
02180
02181
02182
02183
02184
02185
02186
02187
02188
02189
02190 static VALUE
02191 rb_ary_collect_bang(VALUE ary)
02192 {
02193 long i;
02194
02195 RETURN_ENUMERATOR(ary, 0, 0);
02196 rb_ary_modify(ary);
02197 for (i = 0; i < RARRAY_LEN(ary); i++) {
02198 rb_ary_store(ary, i, rb_yield(RARRAY_PTR(ary)[i]));
02199 }
02200 return ary;
02201 }
02202
02203 VALUE
02204 rb_get_values_at(VALUE obj, long olen, int argc, VALUE *argv, VALUE (*func) (VALUE, long))
02205 {
02206 VALUE result = rb_ary_new2(argc);
02207 long beg, len, i, j;
02208
02209 for (i=0; i<argc; i++) {
02210 if (FIXNUM_P(argv[i])) {
02211 rb_ary_push(result, (*func)(obj, FIX2LONG(argv[i])));
02212 continue;
02213 }
02214
02215 switch (rb_range_beg_len(argv[i], &beg, &len, olen, 0)) {
02216 case Qfalse:
02217 break;
02218 case Qnil:
02219 continue;
02220 default:
02221 for (j=0; j<len; j++) {
02222 rb_ary_push(result, (*func)(obj, j+beg));
02223 }
02224 continue;
02225 }
02226 rb_ary_push(result, (*func)(obj, NUM2LONG(argv[i])));
02227 }
02228 return result;
02229 }
02230
02231
02232
02233
02234
02235
02236
02237
02238
02239
02240
02241
02242
02243
02244
02245
02246
02247 static VALUE
02248 rb_ary_values_at(int argc, VALUE *argv, VALUE ary)
02249 {
02250 return rb_get_values_at(ary, RARRAY_LEN(ary), argc, argv, rb_ary_entry);
02251 }
02252
02253
02254
02255
02256
02257
02258
02259
02260
02261
02262
02263
02264
02265
02266
02267
02268
02269 static VALUE
02270 rb_ary_select(VALUE ary)
02271 {
02272 VALUE result;
02273 long i;
02274
02275 RETURN_ENUMERATOR(ary, 0, 0);
02276 result = rb_ary_new2(RARRAY_LEN(ary));
02277 for (i = 0; i < RARRAY_LEN(ary); i++) {
02278 if (RTEST(rb_yield(RARRAY_PTR(ary)[i]))) {
02279 rb_ary_push(result, rb_ary_elt(ary, i));
02280 }
02281 }
02282 return result;
02283 }
02284
02285
02286
02287
02288
02289
02290
02291
02292
02293
02294
02295
02296
02297
02298
02299
02300 static VALUE
02301 rb_ary_select_bang(VALUE ary)
02302 {
02303 long i1, i2;
02304
02305 RETURN_ENUMERATOR(ary, 0, 0);
02306 rb_ary_modify(ary);
02307 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
02308 VALUE v = RARRAY_PTR(ary)[i1];
02309 if (!RTEST(rb_yield(v))) continue;
02310 if (i1 != i2) {
02311 rb_ary_store(ary, i2, v);
02312 }
02313 i2++;
02314 }
02315
02316 if (RARRAY_LEN(ary) == i2) return Qnil;
02317 if (i2 < RARRAY_LEN(ary))
02318 ARY_SET_LEN(ary, i2);
02319 return ary;
02320 }
02321
02322
02323
02324
02325
02326
02327
02328
02329
02330
02331
02332
02333
02334
02335
02336
02337 static VALUE
02338 rb_ary_keep_if(VALUE ary)
02339 {
02340 RETURN_ENUMERATOR(ary, 0, 0);
02341 rb_ary_select_bang(ary);
02342 return ary;
02343 }
02344
02345
02346
02347
02348
02349
02350
02351
02352
02353
02354
02355
02356
02357
02358
02359
02360
02361
02362
02363
02364 VALUE
02365 rb_ary_delete(VALUE ary, VALUE item)
02366 {
02367 VALUE v = item;
02368 long i1, i2;
02369
02370 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
02371 VALUE e = RARRAY_PTR(ary)[i1];
02372
02373 if (rb_equal(e, item)) {
02374 v = e;
02375 continue;
02376 }
02377 if (i1 != i2) {
02378 rb_ary_store(ary, i2, e);
02379 }
02380 i2++;
02381 }
02382 if (RARRAY_LEN(ary) == i2) {
02383 if (rb_block_given_p()) {
02384 return rb_yield(item);
02385 }
02386 return Qnil;
02387 }
02388
02389 rb_ary_modify(ary);
02390 if (RARRAY_LEN(ary) > i2) {
02391 ARY_SET_LEN(ary, i2);
02392 if (i2 * 2 < ARY_CAPA(ary) &&
02393 ARY_CAPA(ary) > ARY_DEFAULT_SIZE) {
02394 ary_resize_capa(ary, i2*2);
02395 }
02396 }
02397
02398 return v;
02399 }
02400
02401 VALUE
02402 rb_ary_delete_at(VALUE ary, long pos)
02403 {
02404 long len = RARRAY_LEN(ary);
02405 VALUE del;
02406
02407 if (pos >= len) return Qnil;
02408 if (pos < 0) {
02409 pos += len;
02410 if (pos < 0) return Qnil;
02411 }
02412
02413 rb_ary_modify(ary);
02414 del = RARRAY_PTR(ary)[pos];
02415 MEMMOVE(RARRAY_PTR(ary)+pos, RARRAY_PTR(ary)+pos+1, VALUE,
02416 RARRAY_LEN(ary)-pos-1);
02417 ARY_INCREASE_LEN(ary, -1);
02418
02419 return del;
02420 }
02421
02422
02423
02424
02425
02426
02427
02428
02429
02430
02431
02432
02433
02434
02435
02436 static VALUE
02437 rb_ary_delete_at_m(VALUE ary, VALUE pos)
02438 {
02439 return rb_ary_delete_at(ary, NUM2LONG(pos));
02440 }
02441
02442
02443
02444
02445
02446
02447
02448
02449
02450
02451
02452
02453
02454
02455
02456
02457
02458
02459
02460
02461 static VALUE
02462 rb_ary_slice_bang(int argc, VALUE *argv, VALUE ary)
02463 {
02464 VALUE arg1, arg2;
02465 long pos, len, orig_len;
02466
02467 rb_ary_modify_check(ary);
02468 if (argc == 2) {
02469 pos = NUM2LONG(argv[0]);
02470 len = NUM2LONG(argv[1]);
02471 delete_pos_len:
02472 if (len < 0) return Qnil;
02473 orig_len = RARRAY_LEN(ary);
02474 if (pos < 0) {
02475 pos += orig_len;
02476 if (pos < 0) return Qnil;
02477 }
02478 else if (orig_len < pos) return Qnil;
02479 if (orig_len < pos + len) {
02480 len = orig_len - pos;
02481 }
02482 if (len == 0) return rb_ary_new2(0);
02483 arg2 = rb_ary_new4(len, RARRAY_PTR(ary)+pos);
02484 RBASIC(arg2)->klass = rb_obj_class(ary);
02485 rb_ary_splice(ary, pos, len, Qundef);
02486 return arg2;
02487 }
02488
02489 if (argc != 1) {
02490
02491 rb_scan_args(argc, argv, "11", NULL, NULL);
02492 }
02493 arg1 = argv[0];
02494
02495 if (!FIXNUM_P(arg1)) {
02496 switch (rb_range_beg_len(arg1, &pos, &len, RARRAY_LEN(ary), 0)) {
02497 case Qtrue:
02498
02499 goto delete_pos_len;
02500 case Qnil:
02501
02502 return Qnil;
02503 default:
02504
02505 break;
02506 }
02507 }
02508
02509 return rb_ary_delete_at(ary, NUM2LONG(arg1));
02510 }
02511
02512
02513
02514
02515
02516
02517
02518
02519
02520
02521
02522
02523
02524
02525
02526 static VALUE
02527 rb_ary_reject_bang(VALUE ary)
02528 {
02529 long i1, i2;
02530
02531 RETURN_ENUMERATOR(ary, 0, 0);
02532 rb_ary_modify(ary);
02533 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
02534 VALUE v = RARRAY_PTR(ary)[i1];
02535 if (RTEST(rb_yield(v))) continue;
02536 if (i1 != i2) {
02537 rb_ary_store(ary, i2, v);
02538 }
02539 i2++;
02540 }
02541
02542 if (RARRAY_LEN(ary) == i2) return Qnil;
02543 if (i2 < RARRAY_LEN(ary))
02544 ARY_SET_LEN(ary, i2);
02545 return ary;
02546 }
02547
02548
02549
02550
02551
02552
02553
02554
02555
02556
02557
02558
02559
02560
02561 static VALUE
02562 rb_ary_reject(VALUE ary)
02563 {
02564 RETURN_ENUMERATOR(ary, 0, 0);
02565 ary = rb_ary_dup(ary);
02566 rb_ary_reject_bang(ary);
02567 return ary;
02568 }
02569
02570
02571
02572
02573
02574
02575
02576
02577
02578
02579
02580
02581
02582
02583
02584
02585 static VALUE
02586 rb_ary_delete_if(VALUE ary)
02587 {
02588 RETURN_ENUMERATOR(ary, 0, 0);
02589 rb_ary_reject_bang(ary);
02590 return ary;
02591 }
02592
02593 static VALUE
02594 take_i(VALUE val, VALUE *args, int argc, VALUE *argv)
02595 {
02596 if (args[1]-- == 0) rb_iter_break();
02597 if (argc > 1) val = rb_ary_new4(argc, argv);
02598 rb_ary_push(args[0], val);
02599 return Qnil;
02600 }
02601
02602 static VALUE
02603 take_items(VALUE obj, long n)
02604 {
02605 VALUE result = rb_check_array_type(obj);
02606 VALUE args[2];
02607
02608 if (!NIL_P(result)) return rb_ary_subseq(result, 0, n);
02609 result = rb_ary_new2(n);
02610 args[0] = result; args[1] = (VALUE)n;
02611 rb_block_call(obj, rb_intern("each"), 0, 0, take_i, (VALUE)args);
02612 return result;
02613 }
02614
02615
02616
02617
02618
02619
02620
02621
02622
02623
02624
02625
02626
02627
02628
02629
02630
02631
02632
02633
02634
02635
02636
02637 static VALUE
02638 rb_ary_zip(int argc, VALUE *argv, VALUE ary)
02639 {
02640 int i, j;
02641 long len;
02642 VALUE result = Qnil;
02643
02644 len = RARRAY_LEN(ary);
02645 for (i=0; i<argc; i++) {
02646 argv[i] = take_items(argv[i], len);
02647 }
02648 if (!rb_block_given_p()) {
02649 result = rb_ary_new2(len);
02650 }
02651
02652 for (i=0; i<RARRAY_LEN(ary); i++) {
02653 VALUE tmp = rb_ary_new2(argc+1);
02654
02655 rb_ary_push(tmp, rb_ary_elt(ary, i));
02656 for (j=0; j<argc; j++) {
02657 rb_ary_push(tmp, rb_ary_elt(argv[j], i));
02658 }
02659 if (NIL_P(result)) {
02660 rb_yield(tmp);
02661 }
02662 else {
02663 rb_ary_push(result, tmp);
02664 }
02665 }
02666 return result;
02667 }
02668
02669
02670
02671
02672
02673
02674
02675
02676
02677
02678
02679
02680 static VALUE
02681 rb_ary_transpose(VALUE ary)
02682 {
02683 long elen = -1, alen, i, j;
02684 VALUE tmp, result = 0;
02685
02686 alen = RARRAY_LEN(ary);
02687 if (alen == 0) return rb_ary_dup(ary);
02688 for (i=0; i<alen; i++) {
02689 tmp = to_ary(rb_ary_elt(ary, i));
02690 if (elen < 0) {
02691 elen = RARRAY_LEN(tmp);
02692 result = rb_ary_new2(elen);
02693 for (j=0; j<elen; j++) {
02694 rb_ary_store(result, j, rb_ary_new2(alen));
02695 }
02696 }
02697 else if (elen != RARRAY_LEN(tmp)) {
02698 rb_raise(rb_eIndexError, "element size differs (%ld should be %ld)",
02699 RARRAY_LEN(tmp), elen);
02700 }
02701 for (j=0; j<elen; j++) {
02702 rb_ary_store(rb_ary_elt(result, j), i, rb_ary_elt(tmp, j));
02703 }
02704 }
02705 return result;
02706 }
02707
02708
02709
02710
02711
02712
02713
02714
02715
02716
02717
02718
02719
02720 VALUE
02721 rb_ary_replace(VALUE copy, VALUE orig)
02722 {
02723 rb_ary_modify_check(copy);
02724 orig = to_ary(orig);
02725 if (copy == orig) return copy;
02726
02727 if (RARRAY_LEN(orig) <= RARRAY_EMBED_LEN_MAX) {
02728 VALUE *ptr;
02729 VALUE shared = 0;
02730
02731 if (ARY_OWNS_HEAP_P(copy)) {
02732 xfree(RARRAY_PTR(copy));
02733 }
02734 else if (ARY_SHARED_P(copy)) {
02735 shared = ARY_SHARED(copy);
02736 FL_UNSET_SHARED(copy);
02737 }
02738 FL_SET_EMBED(copy);
02739 ptr = RARRAY_PTR(orig);
02740 MEMCPY(RARRAY_PTR(copy), ptr, VALUE, RARRAY_LEN(orig));
02741 if (shared) {
02742 rb_ary_decrement_share(shared);
02743 }
02744 ARY_SET_LEN(copy, RARRAY_LEN(orig));
02745 }
02746 else {
02747 VALUE shared = ary_make_shared(orig);
02748 if (ARY_OWNS_HEAP_P(copy)) {
02749 xfree(RARRAY_PTR(copy));
02750 }
02751 else {
02752 rb_ary_unshare_safe(copy);
02753 }
02754 FL_UNSET_EMBED(copy);
02755 ARY_SET_PTR(copy, RARRAY_PTR(orig));
02756 ARY_SET_LEN(copy, RARRAY_LEN(orig));
02757 rb_ary_set_shared(copy, shared);
02758 }
02759 return copy;
02760 }
02761
02762
02763
02764
02765
02766
02767
02768
02769
02770
02771
02772 VALUE
02773 rb_ary_clear(VALUE ary)
02774 {
02775 rb_ary_modify(ary);
02776 ARY_SET_LEN(ary, 0);
02777 if (ARY_DEFAULT_SIZE * 2 < ARY_CAPA(ary)) {
02778 ary_resize_capa(ary, ARY_DEFAULT_SIZE * 2);
02779 }
02780 return ary;
02781 }
02782
02783
02784
02785
02786
02787
02788
02789
02790
02791
02792
02793
02794
02795
02796
02797
02798
02799
02800
02801
02802
02803
02804
02805
02806
02807
02808 static VALUE
02809 rb_ary_fill(int argc, VALUE *argv, VALUE ary)
02810 {
02811 VALUE item, arg1, arg2;
02812 long beg = 0, end = 0, len = 0;
02813 VALUE *p, *pend;
02814 int block_p = FALSE;
02815
02816 if (rb_block_given_p()) {
02817 block_p = TRUE;
02818 rb_scan_args(argc, argv, "02", &arg1, &arg2);
02819 argc += 1;
02820 }
02821 else {
02822 rb_scan_args(argc, argv, "12", &item, &arg1, &arg2);
02823 }
02824 switch (argc) {
02825 case 1:
02826 beg = 0;
02827 len = RARRAY_LEN(ary);
02828 break;
02829 case 2:
02830 if (rb_range_beg_len(arg1, &beg, &len, RARRAY_LEN(ary), 1)) {
02831 break;
02832 }
02833
02834 case 3:
02835 beg = NIL_P(arg1) ? 0 : NUM2LONG(arg1);
02836 if (beg < 0) {
02837 beg = RARRAY_LEN(ary) + beg;
02838 if (beg < 0) beg = 0;
02839 }
02840 len = NIL_P(arg2) ? RARRAY_LEN(ary) - beg : NUM2LONG(arg2);
02841 break;
02842 }
02843 rb_ary_modify(ary);
02844 if (len < 0) {
02845 return ary;
02846 }
02847 if (beg >= ARY_MAX_SIZE || len > ARY_MAX_SIZE - beg) {
02848 rb_raise(rb_eArgError, "argument too big");
02849 }
02850 end = beg + len;
02851 if (RARRAY_LEN(ary) < end) {
02852 if (end >= ARY_CAPA(ary)) {
02853 ary_resize_capa(ary, end);
02854 }
02855 rb_mem_clear(RARRAY_PTR(ary) + RARRAY_LEN(ary), end - RARRAY_LEN(ary));
02856 ARY_SET_LEN(ary, end);
02857 }
02858
02859 if (block_p) {
02860 VALUE v;
02861 long i;
02862
02863 for (i=beg; i<end; i++) {
02864 v = rb_yield(LONG2NUM(i));
02865 if (i>=RARRAY_LEN(ary)) break;
02866 RARRAY_PTR(ary)[i] = v;
02867 }
02868 }
02869 else {
02870 p = RARRAY_PTR(ary) + beg;
02871 pend = p + len;
02872 while (p < pend) {
02873 *p++ = item;
02874 }
02875 }
02876 return ary;
02877 }
02878
02879
02880
02881
02882
02883
02884
02885
02886
02887
02888
02889 VALUE
02890 rb_ary_plus(VALUE x, VALUE y)
02891 {
02892 VALUE z;
02893 long len;
02894
02895 y = to_ary(y);
02896 len = RARRAY_LEN(x) + RARRAY_LEN(y);
02897 z = rb_ary_new2(len);
02898 MEMCPY(RARRAY_PTR(z), RARRAY_PTR(x), VALUE, RARRAY_LEN(x));
02899 MEMCPY(RARRAY_PTR(z) + RARRAY_LEN(x), RARRAY_PTR(y), VALUE, RARRAY_LEN(y));
02900 ARY_SET_LEN(z, len);
02901 return z;
02902 }
02903
02904
02905
02906
02907
02908
02909
02910
02911
02912
02913
02914 VALUE
02915 rb_ary_concat(VALUE x, VALUE y)
02916 {
02917 rb_ary_modify_check(x);
02918 y = to_ary(y);
02919 if (RARRAY_LEN(y) > 0) {
02920 rb_ary_splice(x, RARRAY_LEN(x), 0, y);
02921 }
02922 return x;
02923 }
02924
02925
02926
02927
02928
02929
02930
02931
02932
02933
02934
02935
02936
02937
02938
02939
02940
02941 static VALUE
02942 rb_ary_times(VALUE ary, VALUE times)
02943 {
02944 VALUE ary2, tmp, *ptr, *ptr2;
02945 long i, t, len;
02946
02947 tmp = rb_check_string_type(times);
02948 if (!NIL_P(tmp)) {
02949 return rb_ary_join(ary, tmp);
02950 }
02951
02952 len = NUM2LONG(times);
02953 if (len == 0) {
02954 ary2 = ary_new(rb_obj_class(ary), 0);
02955 goto out;
02956 }
02957 if (len < 0) {
02958 rb_raise(rb_eArgError, "negative argument");
02959 }
02960 if (ARY_MAX_SIZE/len < RARRAY_LEN(ary)) {
02961 rb_raise(rb_eArgError, "argument too big");
02962 }
02963 len *= RARRAY_LEN(ary);
02964
02965 ary2 = ary_new(rb_obj_class(ary), len);
02966 ARY_SET_LEN(ary2, len);
02967
02968 ptr = RARRAY_PTR(ary);
02969 ptr2 = RARRAY_PTR(ary2);
02970 t = RARRAY_LEN(ary);
02971 for (i=0; i<len; i+=t) {
02972 MEMCPY(ptr2+i, ptr, VALUE, t);
02973 }
02974 out:
02975 OBJ_INFECT(ary2, ary);
02976
02977 return ary2;
02978 }
02979
02980
02981
02982
02983
02984
02985
02986
02987
02988
02989
02990
02991
02992
02993
02994
02995
02996
02997
02998
02999
03000 VALUE
03001 rb_ary_assoc(VALUE ary, VALUE key)
03002 {
03003 long i;
03004 VALUE v;
03005
03006 for (i = 0; i < RARRAY_LEN(ary); ++i) {
03007 v = rb_check_array_type(RARRAY_PTR(ary)[i]);
03008 if (!NIL_P(v) && RARRAY_LEN(v) > 0 &&
03009 rb_equal(RARRAY_PTR(v)[0], key))
03010 return v;
03011 }
03012 return Qnil;
03013 }
03014
03015
03016
03017
03018
03019
03020
03021
03022
03023
03024
03025
03026
03027
03028
03029 VALUE
03030 rb_ary_rassoc(VALUE ary, VALUE value)
03031 {
03032 long i;
03033 VALUE v;
03034
03035 for (i = 0; i < RARRAY_LEN(ary); ++i) {
03036 v = RARRAY_PTR(ary)[i];
03037 if (TYPE(v) == T_ARRAY &&
03038 RARRAY_LEN(v) > 1 &&
03039 rb_equal(RARRAY_PTR(v)[1], value))
03040 return v;
03041 }
03042 return Qnil;
03043 }
03044
03045 static VALUE
03046 recursive_equal(VALUE ary1, VALUE ary2, int recur)
03047 {
03048 long i;
03049
03050 if (recur) return Qtrue;
03051 for (i=0; i<RARRAY_LEN(ary1); i++) {
03052 if (!rb_equal(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i)))
03053 return Qfalse;
03054 }
03055 return Qtrue;
03056 }
03057
03058
03059
03060
03061
03062
03063
03064
03065
03066
03067
03068
03069
03070
03071
03072 static VALUE
03073 rb_ary_equal(VALUE ary1, VALUE ary2)
03074 {
03075 if (ary1 == ary2) return Qtrue;
03076 if (TYPE(ary2) != T_ARRAY) {
03077 if (!rb_respond_to(ary2, rb_intern("to_ary"))) {
03078 return Qfalse;
03079 }
03080 return rb_equal(ary2, ary1);
03081 }
03082 if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return Qfalse;
03083 return rb_exec_recursive_paired(recursive_equal, ary1, ary2, ary2);
03084 }
03085
03086 static VALUE
03087 recursive_eql(VALUE ary1, VALUE ary2, int recur)
03088 {
03089 long i;
03090
03091 if (recur) return Qtrue;
03092 for (i=0; i<RARRAY_LEN(ary1); i++) {
03093 if (!rb_eql(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i)))
03094 return Qfalse;
03095 }
03096 return Qtrue;
03097 }
03098
03099
03100
03101
03102
03103
03104
03105
03106
03107 static VALUE
03108 rb_ary_eql(VALUE ary1, VALUE ary2)
03109 {
03110 if (ary1 == ary2) return Qtrue;
03111 if (TYPE(ary2) != T_ARRAY) return Qfalse;
03112 if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return Qfalse;
03113 return rb_exec_recursive_paired(recursive_eql, ary1, ary2, ary2);
03114 }
03115
03116 static VALUE
03117 recursive_hash(VALUE ary, VALUE dummy, int recur)
03118 {
03119 long i;
03120 st_index_t h;
03121 VALUE n;
03122
03123 h = rb_hash_start(RARRAY_LEN(ary));
03124 if (recur) {
03125 h = rb_hash_uint(h, NUM2LONG(rb_hash(rb_cArray)));
03126 }
03127 else {
03128 for (i=0; i<RARRAY_LEN(ary); i++) {
03129 n = rb_hash(RARRAY_PTR(ary)[i]);
03130 h = rb_hash_uint(h, NUM2LONG(n));
03131 }
03132 }
03133 h = rb_hash_end(h);
03134 return LONG2FIX(h);
03135 }
03136
03137
03138
03139
03140
03141
03142
03143
03144
03145 static VALUE
03146 rb_ary_hash(VALUE ary)
03147 {
03148 return rb_exec_recursive_outer(recursive_hash, ary, 0);
03149 }
03150
03151
03152
03153
03154
03155
03156
03157
03158
03159
03160
03161
03162
03163
03164 VALUE
03165 rb_ary_includes(VALUE ary, VALUE item)
03166 {
03167 long i;
03168
03169 for (i=0; i<RARRAY_LEN(ary); i++) {
03170 if (rb_equal(RARRAY_PTR(ary)[i], item)) {
03171 return Qtrue;
03172 }
03173 }
03174 return Qfalse;
03175 }
03176
03177
03178 static VALUE
03179 recursive_cmp(VALUE ary1, VALUE ary2, int recur)
03180 {
03181 long i, len;
03182
03183 if (recur) return Qundef;
03184 len = RARRAY_LEN(ary1);
03185 if (len > RARRAY_LEN(ary2)) {
03186 len = RARRAY_LEN(ary2);
03187 }
03188 for (i=0; i<len; i++) {
03189 VALUE v = rb_funcall(rb_ary_elt(ary1, i), id_cmp, 1, rb_ary_elt(ary2, i));
03190 if (v != INT2FIX(0)) {
03191 return v;
03192 }
03193 }
03194 return Qundef;
03195 }
03196
03197
03198
03199
03200
03201
03202
03203
03204
03205
03206
03207
03208
03209
03210
03211
03212
03213
03214
03215
03216
03217 VALUE
03218 rb_ary_cmp(VALUE ary1, VALUE ary2)
03219 {
03220 long len;
03221 VALUE v;
03222
03223 ary2 = rb_check_array_type(ary2);
03224 if (NIL_P(ary2)) return Qnil;
03225 if (ary1 == ary2) return INT2FIX(0);
03226 v = rb_exec_recursive_paired(recursive_cmp, ary1, ary2, ary2);
03227 if (v != Qundef) return v;
03228 len = RARRAY_LEN(ary1) - RARRAY_LEN(ary2);
03229 if (len == 0) return INT2FIX(0);
03230 if (len > 0) return INT2FIX(1);
03231 return INT2FIX(-1);
03232 }
03233
03234 static VALUE
03235 ary_add_hash(VALUE hash, VALUE ary)
03236 {
03237 long i;
03238
03239 for (i=0; i<RARRAY_LEN(ary); i++) {
03240 rb_hash_aset(hash, RARRAY_PTR(ary)[i], Qtrue);
03241 }
03242 return hash;
03243 }
03244
03245 static inline VALUE
03246 ary_tmp_hash_new(void)
03247 {
03248 VALUE hash = rb_hash_new();
03249
03250 RBASIC(hash)->klass = 0;
03251 return hash;
03252 }
03253
03254 static VALUE
03255 ary_make_hash(VALUE ary)
03256 {
03257 VALUE hash = ary_tmp_hash_new();
03258 return ary_add_hash(hash, ary);
03259 }
03260
03261 static VALUE
03262 ary_add_hash_by(VALUE hash, VALUE ary)
03263 {
03264 long i;
03265
03266 for (i = 0; i < RARRAY_LEN(ary); ++i) {
03267 VALUE v = rb_ary_elt(ary, i), k = rb_yield(v);
03268 if (rb_hash_lookup2(hash, k, Qundef) == Qundef) {
03269 rb_hash_aset(hash, k, v);
03270 }
03271 }
03272 return hash;
03273 }
03274
03275 static VALUE
03276 ary_make_hash_by(VALUE ary)
03277 {
03278 VALUE hash = ary_tmp_hash_new();
03279 return ary_add_hash_by(hash, ary);
03280 }
03281
03282 static inline void
03283 ary_recycle_hash(VALUE hash)
03284 {
03285 if (RHASH(hash)->ntbl) {
03286 st_table *tbl = RHASH(hash)->ntbl;
03287 RHASH(hash)->ntbl = 0;
03288 st_free_table(tbl);
03289 }
03290 }
03291
03292
03293
03294
03295
03296
03297
03298
03299
03300
03301
03302
03303
03304 static VALUE
03305 rb_ary_diff(VALUE ary1, VALUE ary2)
03306 {
03307 VALUE ary3;
03308 volatile VALUE hash;
03309 long i;
03310
03311 hash = ary_make_hash(to_ary(ary2));
03312 ary3 = rb_ary_new();
03313
03314 for (i=0; i<RARRAY_LEN(ary1); i++) {
03315 if (st_lookup(RHASH_TBL(hash), RARRAY_PTR(ary1)[i], 0)) continue;
03316 rb_ary_push(ary3, rb_ary_elt(ary1, i));
03317 }
03318 ary_recycle_hash(hash);
03319 return ary3;
03320 }
03321
03322
03323
03324
03325
03326
03327
03328
03329
03330
03331
03332
03333 static VALUE
03334 rb_ary_and(VALUE ary1, VALUE ary2)
03335 {
03336 VALUE hash, ary3, v, vv;
03337 long i;
03338
03339 ary2 = to_ary(ary2);
03340 ary3 = rb_ary_new2(RARRAY_LEN(ary1) < RARRAY_LEN(ary2) ?
03341 RARRAY_LEN(ary1) : RARRAY_LEN(ary2));
03342 hash = ary_make_hash(ary2);
03343
03344 if (RHASH_EMPTY_P(hash))
03345 return ary3;
03346
03347 for (i=0; i<RARRAY_LEN(ary1); i++) {
03348 v = vv = rb_ary_elt(ary1, i);
03349 if (st_delete(RHASH_TBL(hash), (st_data_t*)&vv, 0)) {
03350 rb_ary_push(ary3, v);
03351 }
03352 }
03353 ary_recycle_hash(hash);
03354
03355 return ary3;
03356 }
03357
03358
03359
03360
03361
03362
03363
03364
03365
03366
03367
03368
03369 static VALUE
03370 rb_ary_or(VALUE ary1, VALUE ary2)
03371 {
03372 VALUE hash, ary3;
03373 VALUE v, vv;
03374 long i;
03375
03376 ary2 = to_ary(ary2);
03377 ary3 = rb_ary_new2(RARRAY_LEN(ary1)+RARRAY_LEN(ary2));
03378 hash = ary_add_hash(ary_make_hash(ary1), ary2);
03379
03380 for (i=0; i<RARRAY_LEN(ary1); i++) {
03381 v = vv = rb_ary_elt(ary1, i);
03382 if (st_delete(RHASH_TBL(hash), (st_data_t*)&vv, 0)) {
03383 rb_ary_push(ary3, v);
03384 }
03385 }
03386 for (i=0; i<RARRAY_LEN(ary2); i++) {
03387 v = vv = rb_ary_elt(ary2, i);
03388 if (st_delete(RHASH_TBL(hash), (st_data_t*)&vv, 0)) {
03389 rb_ary_push(ary3, v);
03390 }
03391 }
03392 ary_recycle_hash(hash);
03393 return ary3;
03394 }
03395
03396 static int
03397 push_value(st_data_t key, st_data_t val, st_data_t ary)
03398 {
03399 rb_ary_push((VALUE)ary, (VALUE)val);
03400 return ST_CONTINUE;
03401 }
03402
03403
03404
03405
03406
03407
03408
03409
03410
03411
03412
03413
03414
03415
03416
03417
03418
03419 static VALUE
03420 rb_ary_uniq_bang(VALUE ary)
03421 {
03422 VALUE hash, v;
03423 long i, j;
03424
03425 rb_ary_modify_check(ary);
03426 if (RARRAY_LEN(ary) <= 1)
03427 return Qnil;
03428 if (rb_block_given_p()) {
03429 hash = ary_make_hash_by(ary);
03430 if (RARRAY_LEN(ary) == (i = RHASH_SIZE(hash))) {
03431 return Qnil;
03432 }
03433 ary_resize_capa(ary, i);
03434 ARY_SET_LEN(ary, 0);
03435 st_foreach(RHASH_TBL(hash), push_value, ary);
03436 }
03437 else {
03438 hash = ary_make_hash(ary);
03439 if (RARRAY_LEN(ary) == (long)RHASH_SIZE(hash)) {
03440 return Qnil;
03441 }
03442 for (i=j=0; i<RARRAY_LEN(ary); i++) {
03443 st_data_t vv = (st_data_t)(v = rb_ary_elt(ary, i));
03444 if (st_delete(RHASH_TBL(hash), &vv, 0)) {
03445 rb_ary_store(ary, j++, v);
03446 }
03447 }
03448 ARY_SET_LEN(ary, j);
03449 }
03450 ary_recycle_hash(hash);
03451
03452 return ary;
03453 }
03454
03455
03456
03457
03458
03459
03460
03461
03462
03463
03464
03465
03466
03467 static VALUE
03468 rb_ary_uniq(VALUE ary)
03469 {
03470 VALUE hash, uniq, v;
03471 long i;
03472
03473 if (RARRAY_LEN(ary) <= 1)
03474 return rb_ary_dup(ary);
03475 if (rb_block_given_p()) {
03476 hash = ary_make_hash_by(ary);
03477 uniq = ary_new(rb_obj_class(ary), RHASH_SIZE(hash));
03478 st_foreach(RHASH_TBL(hash), push_value, uniq);
03479 }
03480 else {
03481 hash = ary_make_hash(ary);
03482 uniq = ary_new(rb_obj_class(ary), RHASH_SIZE(hash));
03483 for (i=0; i<RARRAY_LEN(ary); i++) {
03484 st_data_t vv = (st_data_t)(v = rb_ary_elt(ary, i));
03485 if (st_delete(RHASH_TBL(hash), &vv, 0)) {
03486 rb_ary_push(uniq, v);
03487 }
03488 }
03489 }
03490 ary_recycle_hash(hash);
03491
03492 return uniq;
03493 }
03494
03495
03496
03497
03498
03499
03500
03501
03502
03503
03504
03505
03506
03507 static VALUE
03508 rb_ary_compact_bang(VALUE ary)
03509 {
03510 VALUE *p, *t, *end;
03511 long n;
03512
03513 rb_ary_modify(ary);
03514 p = t = RARRAY_PTR(ary);
03515 end = p + RARRAY_LEN(ary);
03516
03517 while (t < end) {
03518 if (NIL_P(*t)) t++;
03519 else *p++ = *t++;
03520 }
03521 n = p - RARRAY_PTR(ary);
03522 if (RARRAY_LEN(ary) == n) {
03523 return Qnil;
03524 }
03525 ARY_SET_LEN(ary, n);
03526 if (n * 2 < ARY_CAPA(ary) && ARY_DEFAULT_SIZE * 2 < ARY_CAPA(ary)) {
03527 ary_resize_capa(ary, n * 2);
03528 }
03529
03530 return ary;
03531 }
03532
03533
03534
03535
03536
03537
03538
03539
03540
03541
03542
03543 static VALUE
03544 rb_ary_compact(VALUE ary)
03545 {
03546 ary = rb_ary_dup(ary);
03547 rb_ary_compact_bang(ary);
03548 return ary;
03549 }
03550
03551
03552
03553
03554
03555
03556
03557
03558
03559
03560
03561
03562
03563
03564
03565
03566
03567
03568 static VALUE
03569 rb_ary_count(int argc, VALUE *argv, VALUE ary)
03570 {
03571 long n = 0;
03572
03573 if (argc == 0) {
03574 VALUE *p, *pend;
03575
03576 if (!rb_block_given_p())
03577 return LONG2NUM(RARRAY_LEN(ary));
03578
03579 for (p = RARRAY_PTR(ary), pend = p + RARRAY_LEN(ary); p < pend; p++) {
03580 if (RTEST(rb_yield(*p))) n++;
03581 }
03582 }
03583 else {
03584 VALUE obj, *p, *pend;
03585
03586 rb_scan_args(argc, argv, "1", &obj);
03587 if (rb_block_given_p()) {
03588 rb_warn("given block not used");
03589 }
03590 for (p = RARRAY_PTR(ary), pend = p + RARRAY_LEN(ary); p < pend; p++) {
03591 if (rb_equal(*p, obj)) n++;
03592 }
03593 }
03594
03595 return LONG2NUM(n);
03596 }
03597
03598 static VALUE
03599 flatten(VALUE ary, int level, int *modified)
03600 {
03601 long i = 0;
03602 VALUE stack, result, tmp, elt;
03603 st_table *memo;
03604 st_data_t id;
03605
03606 stack = ary_new(0, ARY_DEFAULT_SIZE);
03607 result = ary_new(0, RARRAY_LEN(ary));
03608 memo = st_init_numtable();
03609 st_insert(memo, (st_data_t)ary, (st_data_t)Qtrue);
03610 *modified = 0;
03611
03612 while (1) {
03613 while (i < RARRAY_LEN(ary)) {
03614 elt = RARRAY_PTR(ary)[i++];
03615 tmp = rb_check_array_type(elt);
03616 if (RBASIC(result)->klass) {
03617 rb_raise(rb_eRuntimeError, "flatten reentered");
03618 }
03619 if (NIL_P(tmp) || (level >= 0 && RARRAY_LEN(stack) / 2 >= level)) {
03620 rb_ary_push(result, elt);
03621 }
03622 else {
03623 *modified = 1;
03624 id = (st_data_t)tmp;
03625 if (st_lookup(memo, id, 0)) {
03626 st_free_table(memo);
03627 rb_raise(rb_eArgError, "tried to flatten recursive array");
03628 }
03629 st_insert(memo, id, (st_data_t)Qtrue);
03630 rb_ary_push(stack, ary);
03631 rb_ary_push(stack, LONG2NUM(i));
03632 ary = tmp;
03633 i = 0;
03634 }
03635 }
03636 if (RARRAY_LEN(stack) == 0) {
03637 break;
03638 }
03639 id = (st_data_t)ary;
03640 st_delete(memo, &id, 0);
03641 tmp = rb_ary_pop(stack);
03642 i = NUM2LONG(tmp);
03643 ary = rb_ary_pop(stack);
03644 }
03645
03646 st_free_table(memo);
03647
03648 RBASIC(result)->klass = rb_class_of(ary);
03649 return result;
03650 }
03651
03652
03653
03654
03655
03656
03657
03658
03659
03660
03661
03662
03663
03664
03665
03666
03667
03668
03669
03670 static VALUE
03671 rb_ary_flatten_bang(int argc, VALUE *argv, VALUE ary)
03672 {
03673 int mod = 0, level = -1;
03674 VALUE result, lv;
03675
03676 rb_scan_args(argc, argv, "01", &lv);
03677 rb_ary_modify_check(ary);
03678 if (!NIL_P(lv)) level = NUM2INT(lv);
03679 if (level == 0) return Qnil;
03680
03681 result = flatten(ary, level, &mod);
03682 if (mod == 0) {
03683 ary_discard(result);
03684 return Qnil;
03685 }
03686 if (!(mod = ARY_EMBED_P(result))) rb_obj_freeze(result);
03687 rb_ary_replace(ary, result);
03688 if (mod) ARY_SET_EMBED_LEN(result, 0);
03689
03690 return ary;
03691 }
03692
03693
03694
03695
03696
03697
03698
03699
03700
03701
03702
03703
03704
03705
03706
03707
03708
03709
03710
03711 static VALUE
03712 rb_ary_flatten(int argc, VALUE *argv, VALUE ary)
03713 {
03714 int mod = 0, level = -1;
03715 VALUE result, lv;
03716
03717 rb_scan_args(argc, argv, "01", &lv);
03718 if (!NIL_P(lv)) level = NUM2INT(lv);
03719 if (level == 0) return ary_make_shared_copy(ary);
03720
03721 result = flatten(ary, level, &mod);
03722 OBJ_INFECT(result, ary);
03723
03724 return result;
03725 }
03726
03727
03728
03729
03730
03731
03732
03733
03734
03735 static VALUE
03736 rb_ary_shuffle_bang(VALUE ary)
03737 {
03738 VALUE *ptr;
03739 long i = RARRAY_LEN(ary);
03740
03741 rb_ary_modify(ary);
03742 ptr = RARRAY_PTR(ary);
03743 while (i) {
03744 long j = (long)(rb_genrand_real()*i);
03745 VALUE tmp = ptr[--i];
03746 ptr[i] = ptr[j];
03747 ptr[j] = tmp;
03748 }
03749 return ary;
03750 }
03751
03752
03753
03754
03755
03756
03757
03758
03759
03760
03761
03762
03763 static VALUE
03764 rb_ary_shuffle(VALUE ary)
03765 {
03766 ary = rb_ary_dup(ary);
03767 rb_ary_shuffle_bang(ary);
03768 return ary;
03769 }
03770
03771
03772
03773
03774
03775
03776
03777
03778
03779
03780
03781
03782
03783
03784
03785
03786 static VALUE
03787 rb_ary_sample(int argc, VALUE *argv, VALUE ary)
03788 {
03789 VALUE nv, result, *ptr;
03790 long n, len, i, j, k, idx[10];
03791
03792 len = RARRAY_LEN(ary);
03793 if (argc == 0) {
03794 if (len == 0) return Qnil;
03795 i = len == 1 ? 0 : (long)(rb_genrand_real()*len);
03796 return RARRAY_PTR(ary)[i];
03797 }
03798 rb_scan_args(argc, argv, "1", &nv);
03799 n = NUM2LONG(nv);
03800 if (n < 0) rb_raise(rb_eArgError, "negative sample number");
03801 ptr = RARRAY_PTR(ary);
03802 len = RARRAY_LEN(ary);
03803 if (n > len) n = len;
03804 switch (n) {
03805 case 0: return rb_ary_new2(0);
03806 case 1:
03807 return rb_ary_new4(1, &ptr[(long)(rb_genrand_real()*len)]);
03808 case 2:
03809 i = (long)(rb_genrand_real()*len);
03810 j = (long)(rb_genrand_real()*(len-1));
03811 if (j >= i) j++;
03812 return rb_ary_new3(2, ptr[i], ptr[j]);
03813 case 3:
03814 i = (long)(rb_genrand_real()*len);
03815 j = (long)(rb_genrand_real()*(len-1));
03816 k = (long)(rb_genrand_real()*(len-2));
03817 {
03818 long l = j, g = i;
03819 if (j >= i) l = i, g = ++j;
03820 if (k >= l && (++k >= g)) ++k;
03821 }
03822 return rb_ary_new3(3, ptr[i], ptr[j], ptr[k]);
03823 }
03824 if ((size_t)n < sizeof(idx)/sizeof(idx[0])) {
03825 VALUE *ptr_result;
03826 long sorted[sizeof(idx)/sizeof(idx[0])];
03827 sorted[0] = idx[0] = (long)(rb_genrand_real()*len);
03828 for (i=1; i<n; i++) {
03829 k = (long)(rb_genrand_real()*--len);
03830 for (j = 0; j < i; ++j) {
03831 if (k < sorted[j]) break;
03832 ++k;
03833 }
03834 memmove(&sorted[j+1], &sorted[j], sizeof(sorted[0])*(i-j));
03835 sorted[j] = idx[i] = k;
03836 }
03837 result = rb_ary_new2(n);
03838 ptr_result = RARRAY_PTR(result);
03839 for (i=0; i<n; i++) {
03840 ptr_result[i] = ptr[idx[i]];
03841 }
03842 }
03843 else {
03844 VALUE *ptr_result;
03845 result = rb_ary_new4(len, ptr);
03846 ptr_result = RARRAY_PTR(result);
03847 RB_GC_GUARD(ary);
03848 for (i=0; i<n; i++) {
03849 j = (long)(rb_genrand_real()*(len-i)) + i;
03850 nv = ptr_result[j];
03851 ptr_result[j] = ptr_result[i];
03852 ptr_result[i] = nv;
03853 }
03854 }
03855 ARY_SET_LEN(result, n);
03856
03857 return result;
03858 }
03859
03860
03861
03862
03863
03864
03865
03866
03867
03868
03869
03870
03871
03872
03873
03874
03875
03876
03877
03878
03879
03880 static VALUE
03881 rb_ary_cycle(int argc, VALUE *argv, VALUE ary)
03882 {
03883 long n, i;
03884 VALUE nv = Qnil;
03885
03886 rb_scan_args(argc, argv, "01", &nv);
03887
03888 RETURN_ENUMERATOR(ary, argc, argv);
03889 if (NIL_P(nv)) {
03890 n = -1;
03891 }
03892 else {
03893 n = NUM2LONG(nv);
03894 if (n <= 0) return Qnil;
03895 }
03896
03897 while (RARRAY_LEN(ary) > 0 && (n < 0 || 0 < n--)) {
03898 for (i=0; i<RARRAY_LEN(ary); i++) {
03899 rb_yield(RARRAY_PTR(ary)[i]);
03900 }
03901 }
03902 return Qnil;
03903 }
03904
03905 #define tmpbuf(n, size) rb_str_tmp_new((n)*(size))
03906 #define tmpbuf_discard(s) (rb_str_resize((s), 0L), RBASIC(s)->klass = rb_cString)
03907 #define tmpary(n) rb_ary_tmp_new(n)
03908 #define tmpary_discard(a) (ary_discard(a), RBASIC(a)->klass = rb_cArray)
03909
03910
03911
03912
03913
03914
03915
03916
03917
03918
03919
03920
03921
03922 static void
03923 permute0(long n, long r, long *p, long index, char *used, VALUE values)
03924 {
03925 long i,j;
03926 for (i = 0; i < n; i++) {
03927 if (used[i] == 0) {
03928 p[index] = i;
03929 if (index < r-1) {
03930 used[i] = 1;
03931 permute0(n, r, p, index+1,
03932 used, values);
03933 used[i] = 0;
03934 }
03935 else {
03936
03937
03938
03939 VALUE result = rb_ary_new2(r);
03940 VALUE *result_array = RARRAY_PTR(result);
03941 const VALUE *values_array = RARRAY_PTR(values);
03942
03943 for (j = 0; j < r; j++) result_array[j] = values_array[p[j]];
03944 ARY_SET_LEN(result, r);
03945 rb_yield(result);
03946 if (RBASIC(values)->klass) {
03947 rb_raise(rb_eRuntimeError, "permute reentered");
03948 }
03949 }
03950 }
03951 }
03952 }
03953
03954
03955
03956
03957
03958
03959
03960
03961
03962
03963
03964
03965
03966
03967
03968
03969
03970
03971
03972
03973
03974
03975
03976
03977
03978
03979
03980 static VALUE
03981 rb_ary_permutation(int argc, VALUE *argv, VALUE ary)
03982 {
03983 VALUE num;
03984 long r, n, i;
03985
03986 n = RARRAY_LEN(ary);
03987 RETURN_ENUMERATOR(ary, argc, argv);
03988 rb_scan_args(argc, argv, "01", &num);
03989 r = NIL_P(num) ? n : NUM2LONG(num);
03990
03991 if (r < 0 || n < r) {
03992
03993 }
03994 else if (r == 0) {
03995 rb_yield(rb_ary_new2(0));
03996 }
03997 else if (r == 1) {
03998 for (i = 0; i < RARRAY_LEN(ary); i++) {
03999 rb_yield(rb_ary_new3(1, RARRAY_PTR(ary)[i]));
04000 }
04001 }
04002 else {
04003 volatile VALUE t0 = tmpbuf(n,sizeof(long));
04004 long *p = (long*)RSTRING_PTR(t0);
04005 volatile VALUE t1 = tmpbuf(n,sizeof(char));
04006 char *used = (char*)RSTRING_PTR(t1);
04007 VALUE ary0 = ary_make_shared_copy(ary);
04008 RBASIC(ary0)->klass = 0;
04009
04010 MEMZERO(used, char, n);
04011
04012 permute0(n, r, p, 0, used, ary0);
04013 tmpbuf_discard(t0);
04014 tmpbuf_discard(t1);
04015 RBASIC(ary0)->klass = rb_cArray;
04016 }
04017 return ary;
04018 }
04019
04020
04021
04022
04023
04024
04025
04026
04027
04028
04029
04030
04031
04032
04033
04034
04035
04036
04037
04038
04039
04040
04041
04042
04043
04044 static VALUE
04045 rb_ary_combination(VALUE ary, VALUE num)
04046 {
04047 long n, i, len;
04048
04049 n = NUM2LONG(num);
04050 RETURN_ENUMERATOR(ary, 1, &num);
04051 len = RARRAY_LEN(ary);
04052 if (n < 0 || len < n) {
04053
04054 }
04055 else if (n == 0) {
04056 rb_yield(rb_ary_new2(0));
04057 }
04058 else if (n == 1) {
04059 for (i = 0; i < len; i++) {
04060 rb_yield(rb_ary_new3(1, RARRAY_PTR(ary)[i]));
04061 }
04062 }
04063 else {
04064 volatile VALUE t0 = tmpbuf(n+1, sizeof(long));
04065 long *stack = (long*)RSTRING_PTR(t0);
04066 volatile VALUE cc = tmpary(n);
04067 VALUE *chosen = RARRAY_PTR(cc);
04068 long lev = 0;
04069
04070 MEMZERO(stack, long, n);
04071 stack[0] = -1;
04072 for (;;) {
04073 chosen[lev] = RARRAY_PTR(ary)[stack[lev+1]];
04074 for (lev++; lev < n; lev++) {
04075 chosen[lev] = RARRAY_PTR(ary)[stack[lev+1] = stack[lev]+1];
04076 }
04077 rb_yield(rb_ary_new4(n, chosen));
04078 if (RBASIC(t0)->klass) {
04079 rb_raise(rb_eRuntimeError, "combination reentered");
04080 }
04081 do {
04082 if (lev == 0) goto done;
04083 stack[lev--]++;
04084 } while (stack[lev+1]+n == len+lev+1);
04085 }
04086 done:
04087 tmpbuf_discard(t0);
04088 tmpary_discard(cc);
04089 }
04090 return ary;
04091 }
04092
04093
04094
04095
04096
04097
04098
04099
04100
04101
04102
04103
04104
04105 static void
04106 rpermute0(long n, long r, long *p, long index, VALUE values)
04107 {
04108 long i, j;
04109 for (i = 0; i < n; i++) {
04110 p[index] = i;
04111 if (index < r-1) {
04112 rpermute0(n, r, p, index+1, values);
04113 }
04114 else {
04115
04116
04117
04118 VALUE result = rb_ary_new2(r);
04119 VALUE *result_array = RARRAY_PTR(result);
04120 const VALUE *values_array = RARRAY_PTR(values);
04121
04122 for (j = 0; j < r; j++) result_array[j] = values_array[p[j]];
04123 ARY_SET_LEN(result, r);
04124 rb_yield(result);
04125 if (RBASIC(values)->klass) {
04126 rb_raise(rb_eRuntimeError, "repeated permute reentered");
04127 }
04128 }
04129 }
04130 }
04131
04132
04133
04134
04135
04136
04137
04138
04139
04140
04141
04142
04143
04144
04145
04146
04147
04148
04149
04150
04151
04152
04153
04154 static VALUE
04155 rb_ary_repeated_permutation(VALUE ary, VALUE num)
04156 {
04157 long r, n, i;
04158
04159 n = RARRAY_LEN(ary);
04160 RETURN_ENUMERATOR(ary, 1, &num);
04161 r = NUM2LONG(num);
04162
04163 if (r < 0) {
04164
04165 }
04166 else if (r == 0) {
04167 rb_yield(rb_ary_new2(0));
04168 }
04169 else if (r == 1) {
04170 for (i = 0; i < RARRAY_LEN(ary); i++) {
04171 rb_yield(rb_ary_new3(1, RARRAY_PTR(ary)[i]));
04172 }
04173 }
04174 else {
04175 volatile VALUE t0 = tmpbuf(r, sizeof(long));
04176 long *p = (long*)RSTRING_PTR(t0);
04177 VALUE ary0 = ary_make_shared_copy(ary);
04178 RBASIC(ary0)->klass = 0;
04179
04180 rpermute0(n, r, p, 0, ary0);
04181 tmpbuf_discard(t0);
04182 RBASIC(ary0)->klass = rb_cArray;
04183 }
04184 return ary;
04185 }
04186
04187 static void
04188 rcombinate0(long n, long r, long *p, long index, long rest, VALUE values)
04189 {
04190 long j;
04191 if (rest > 0) {
04192 for (; index < n; ++index) {
04193 p[r-rest] = index;
04194 rcombinate0(n, r, p, index, rest-1, values);
04195 }
04196 }
04197 else {
04198 VALUE result = rb_ary_new2(r);
04199 VALUE *result_array = RARRAY_PTR(result);
04200 const VALUE *values_array = RARRAY_PTR(values);
04201
04202 for (j = 0; j < r; ++j) result_array[j] = values_array[p[j]];
04203 ARY_SET_LEN(result, r);
04204 rb_yield(result);
04205 if (RBASIC(values)->klass) {
04206 rb_raise(rb_eRuntimeError, "repeated combination reentered");
04207 }
04208 }
04209 }
04210
04211
04212
04213
04214
04215
04216
04217
04218
04219
04220
04221
04222
04223
04224
04225
04226
04227
04228
04229
04230
04231
04232
04233
04234
04235
04236
04237
04238 static VALUE
04239 rb_ary_repeated_combination(VALUE ary, VALUE num)
04240 {
04241 long n, i, len;
04242
04243 n = NUM2LONG(num);
04244 RETURN_ENUMERATOR(ary, 1, &num);
04245 len = RARRAY_LEN(ary);
04246 if (n < 0) {
04247
04248 }
04249 else if (n == 0) {
04250 rb_yield(rb_ary_new2(0));
04251 }
04252 else if (n == 1) {
04253 for (i = 0; i < len; i++) {
04254 rb_yield(rb_ary_new3(1, RARRAY_PTR(ary)[i]));
04255 }
04256 }
04257 else if (len == 0) {
04258
04259 }
04260 else {
04261 volatile VALUE t0 = tmpbuf(n, sizeof(long));
04262 long *p = (long*)RSTRING_PTR(t0);
04263 VALUE ary0 = ary_make_shared_copy(ary);
04264 RBASIC(ary0)->klass = 0;
04265
04266 rcombinate0(len, n, p, 0, n, ary0);
04267 tmpbuf_discard(t0);
04268 RBASIC(ary0)->klass = rb_cArray;
04269 }
04270 return ary;
04271 }
04272
04273
04274
04275
04276
04277
04278
04279
04280
04281
04282
04283
04284
04285
04286
04287
04288
04289
04290
04291
04292
04293 static VALUE
04294 rb_ary_product(int argc, VALUE *argv, VALUE ary)
04295 {
04296 int n = argc+1;
04297 volatile VALUE t0 = tmpary(n);
04298 volatile VALUE t1 = tmpbuf(n, sizeof(int));
04299 VALUE *arrays = RARRAY_PTR(t0);
04300 int *counters = (int*)RSTRING_PTR(t1);
04301 VALUE result = Qnil;
04302 long i,j;
04303 long resultlen = 1;
04304
04305 RBASIC(t0)->klass = 0;
04306 RBASIC(t1)->klass = 0;
04307
04308
04309 ARY_SET_LEN(t0, n);
04310 arrays[0] = ary;
04311 for (i = 1; i < n; i++) arrays[i] = Qnil;
04312 for (i = 1; i < n; i++) arrays[i] = to_ary(argv[i-1]);
04313
04314
04315 for (i = 0; i < n; i++) counters[i] = 0;
04316
04317
04318 if (rb_block_given_p()) {
04319
04320 for (i = 0; i < n; i++) {
04321 if (RARRAY_LEN(arrays[i]) == 0) goto done;
04322 arrays[i] = ary_make_shared_copy(arrays[i]);
04323 }
04324 }
04325 else {
04326
04327 for (i = 0; i < n; i++) {
04328 long k = RARRAY_LEN(arrays[i]), l = resultlen;
04329 if (k == 0) {
04330 result = rb_ary_new2(0);
04331 goto done;
04332 }
04333 resultlen *= k;
04334 if (resultlen < k || resultlen < l || resultlen / k != l) {
04335 rb_raise(rb_eRangeError, "too big to product");
04336 }
04337 }
04338 result = rb_ary_new2(resultlen);
04339 }
04340 for (;;) {
04341 int m;
04342
04343 VALUE subarray = rb_ary_new2(n);
04344 for (j = 0; j < n; j++) {
04345 rb_ary_push(subarray, rb_ary_entry(arrays[j], counters[j]));
04346 }
04347
04348
04349 if(NIL_P(result)) {
04350 FL_SET(t0, FL_USER5);
04351 rb_yield(subarray);
04352 if (! FL_TEST(t0, FL_USER5)) {
04353 rb_raise(rb_eRuntimeError, "product reentered");
04354 }
04355 else {
04356 FL_UNSET(t0, FL_USER5);
04357 }
04358 }
04359 else {
04360 rb_ary_push(result, subarray);
04361 }
04362
04363
04364
04365
04366
04367 m = n-1;
04368 counters[m]++;
04369 while (counters[m] == RARRAY_LEN(arrays[m])) {
04370 counters[m] = 0;
04371
04372 if (--m < 0) goto done;
04373 counters[m]++;
04374 }
04375 }
04376 done:
04377 tmpary_discard(t0);
04378 tmpbuf_discard(t1);
04379
04380 return NIL_P(result) ? ary : result;
04381 }
04382
04383
04384
04385
04386
04387
04388
04389
04390
04391
04392
04393
04394 static VALUE
04395 rb_ary_take(VALUE obj, VALUE n)
04396 {
04397 long len = NUM2LONG(n);
04398 if (len < 0) {
04399 rb_raise(rb_eArgError, "attempt to take negative size");
04400 }
04401 return rb_ary_subseq(obj, 0, len);
04402 }
04403
04404
04405
04406
04407
04408
04409
04410
04411
04412
04413
04414
04415
04416
04417
04418
04419 static VALUE
04420 rb_ary_take_while(VALUE ary)
04421 {
04422 long i;
04423
04424 RETURN_ENUMERATOR(ary, 0, 0);
04425 for (i = 0; i < RARRAY_LEN(ary); i++) {
04426 if (!RTEST(rb_yield(RARRAY_PTR(ary)[i]))) break;
04427 }
04428 return rb_ary_take(ary, LONG2FIX(i));
04429 }
04430
04431
04432
04433
04434
04435
04436
04437
04438
04439
04440
04441
04442
04443 static VALUE
04444 rb_ary_drop(VALUE ary, VALUE n)
04445 {
04446 VALUE result;
04447 long pos = NUM2LONG(n);
04448 if (pos < 0) {
04449 rb_raise(rb_eArgError, "attempt to drop negative size");
04450 }
04451
04452 result = rb_ary_subseq(ary, pos, RARRAY_LEN(ary));
04453 if (result == Qnil) result = rb_ary_new();
04454 return result;
04455 }
04456
04457
04458
04459
04460
04461
04462
04463
04464
04465
04466
04467
04468
04469
04470
04471
04472
04473 static VALUE
04474 rb_ary_drop_while(VALUE ary)
04475 {
04476 long i;
04477
04478 RETURN_ENUMERATOR(ary, 0, 0);
04479 for (i = 0; i < RARRAY_LEN(ary); i++) {
04480 if (!RTEST(rb_yield(RARRAY_PTR(ary)[i]))) break;
04481 }
04482 return rb_ary_drop(ary, LONG2FIX(i));
04483 }
04484
04485
04486
04487
04488
04489
04490
04491
04492
04493
04494 void
04495 Init_Array(void)
04496 {
04497 #undef rb_intern
04498 #define rb_intern(str) rb_intern_const(str)
04499
04500 rb_cArray = rb_define_class("Array", rb_cObject);
04501 rb_include_module(rb_cArray, rb_mEnumerable);
04502
04503 rb_define_alloc_func(rb_cArray, ary_alloc);
04504 rb_define_singleton_method(rb_cArray, "[]", rb_ary_s_create, -1);
04505 rb_define_singleton_method(rb_cArray, "try_convert", rb_ary_s_try_convert, 1);
04506 rb_define_method(rb_cArray, "initialize", rb_ary_initialize, -1);
04507 rb_define_method(rb_cArray, "initialize_copy", rb_ary_replace, 1);
04508
04509 rb_define_method(rb_cArray, "inspect", rb_ary_inspect, 0);
04510 rb_define_alias(rb_cArray, "to_s", "inspect");
04511 rb_define_method(rb_cArray, "to_a", rb_ary_to_a, 0);
04512 rb_define_method(rb_cArray, "to_ary", rb_ary_to_ary_m, 0);
04513 rb_define_method(rb_cArray, "frozen?", rb_ary_frozen_p, 0);
04514
04515 rb_define_method(rb_cArray, "==", rb_ary_equal, 1);
04516 rb_define_method(rb_cArray, "eql?", rb_ary_eql, 1);
04517 rb_define_method(rb_cArray, "hash", rb_ary_hash, 0);
04518
04519 rb_define_method(rb_cArray, "[]", rb_ary_aref, -1);
04520 rb_define_method(rb_cArray, "[]=", rb_ary_aset, -1);
04521 rb_define_method(rb_cArray, "at", rb_ary_at, 1);
04522 rb_define_method(rb_cArray, "fetch", rb_ary_fetch, -1);
04523 rb_define_method(rb_cArray, "first", rb_ary_first, -1);
04524 rb_define_method(rb_cArray, "last", rb_ary_last, -1);
04525 rb_define_method(rb_cArray, "concat", rb_ary_concat, 1);
04526 rb_define_method(rb_cArray, "<<", rb_ary_push, 1);
04527 rb_define_method(rb_cArray, "push", rb_ary_push_m, -1);
04528 rb_define_method(rb_cArray, "pop", rb_ary_pop_m, -1);
04529 rb_define_method(rb_cArray, "shift", rb_ary_shift_m, -1);
04530 rb_define_method(rb_cArray, "unshift", rb_ary_unshift_m, -1);
04531 rb_define_method(rb_cArray, "insert", rb_ary_insert, -1);
04532 rb_define_method(rb_cArray, "each", rb_ary_each, 0);
04533 rb_define_method(rb_cArray, "each_index", rb_ary_each_index, 0);
04534 rb_define_method(rb_cArray, "reverse_each", rb_ary_reverse_each, 0);
04535 rb_define_method(rb_cArray, "length", rb_ary_length, 0);
04536 rb_define_alias(rb_cArray, "size", "length");
04537 rb_define_method(rb_cArray, "empty?", rb_ary_empty_p, 0);
04538 rb_define_method(rb_cArray, "find_index", rb_ary_index, -1);
04539 rb_define_method(rb_cArray, "index", rb_ary_index, -1);
04540 rb_define_method(rb_cArray, "rindex", rb_ary_rindex, -1);
04541 rb_define_method(rb_cArray, "join", rb_ary_join_m, -1);
04542 rb_define_method(rb_cArray, "reverse", rb_ary_reverse_m, 0);
04543 rb_define_method(rb_cArray, "reverse!", rb_ary_reverse_bang, 0);
04544 rb_define_method(rb_cArray, "rotate", rb_ary_rotate_m, -1);
04545 rb_define_method(rb_cArray, "rotate!", rb_ary_rotate_bang, -1);
04546 rb_define_method(rb_cArray, "sort", rb_ary_sort, 0);
04547 rb_define_method(rb_cArray, "sort!", rb_ary_sort_bang, 0);
04548 rb_define_method(rb_cArray, "sort_by!", rb_ary_sort_by_bang, 0);
04549 rb_define_method(rb_cArray, "collect", rb_ary_collect, 0);
04550 rb_define_method(rb_cArray, "collect!", rb_ary_collect_bang, 0);
04551 rb_define_method(rb_cArray, "map", rb_ary_collect, 0);
04552 rb_define_method(rb_cArray, "map!", rb_ary_collect_bang, 0);
04553 rb_define_method(rb_cArray, "select", rb_ary_select, 0);
04554 rb_define_method(rb_cArray, "select!", rb_ary_select_bang, 0);
04555 rb_define_method(rb_cArray, "keep_if", rb_ary_keep_if, 0);
04556 rb_define_method(rb_cArray, "values_at", rb_ary_values_at, -1);
04557 rb_define_method(rb_cArray, "delete", rb_ary_delete, 1);
04558 rb_define_method(rb_cArray, "delete_at", rb_ary_delete_at_m, 1);
04559 rb_define_method(rb_cArray, "delete_if", rb_ary_delete_if, 0);
04560 rb_define_method(rb_cArray, "reject", rb_ary_reject, 0);
04561 rb_define_method(rb_cArray, "reject!", rb_ary_reject_bang, 0);
04562 rb_define_method(rb_cArray, "zip", rb_ary_zip, -1);
04563 rb_define_method(rb_cArray, "transpose", rb_ary_transpose, 0);
04564 rb_define_method(rb_cArray, "replace", rb_ary_replace, 1);
04565 rb_define_method(rb_cArray, "clear", rb_ary_clear, 0);
04566 rb_define_method(rb_cArray, "fill", rb_ary_fill, -1);
04567 rb_define_method(rb_cArray, "include?", rb_ary_includes, 1);
04568 rb_define_method(rb_cArray, "<=>", rb_ary_cmp, 1);
04569
04570 rb_define_method(rb_cArray, "slice", rb_ary_aref, -1);
04571 rb_define_method(rb_cArray, "slice!", rb_ary_slice_bang, -1);
04572
04573 rb_define_method(rb_cArray, "assoc", rb_ary_assoc, 1);
04574 rb_define_method(rb_cArray, "rassoc", rb_ary_rassoc, 1);
04575
04576 rb_define_method(rb_cArray, "+", rb_ary_plus, 1);
04577 rb_define_method(rb_cArray, "*", rb_ary_times, 1);
04578
04579 rb_define_method(rb_cArray, "-", rb_ary_diff, 1);
04580 rb_define_method(rb_cArray, "&", rb_ary_and, 1);
04581 rb_define_method(rb_cArray, "|", rb_ary_or, 1);
04582
04583 rb_define_method(rb_cArray, "uniq", rb_ary_uniq, 0);
04584 rb_define_method(rb_cArray, "uniq!", rb_ary_uniq_bang, 0);
04585 rb_define_method(rb_cArray, "compact", rb_ary_compact, 0);
04586 rb_define_method(rb_cArray, "compact!", rb_ary_compact_bang, 0);
04587 rb_define_method(rb_cArray, "flatten", rb_ary_flatten, -1);
04588 rb_define_method(rb_cArray, "flatten!", rb_ary_flatten_bang, -1);
04589 rb_define_method(rb_cArray, "count", rb_ary_count, -1);
04590 rb_define_method(rb_cArray, "shuffle!", rb_ary_shuffle_bang, 0);
04591 rb_define_method(rb_cArray, "shuffle", rb_ary_shuffle, 0);
04592 rb_define_method(rb_cArray, "sample", rb_ary_sample, -1);
04593 rb_define_method(rb_cArray, "cycle", rb_ary_cycle, -1);
04594 rb_define_method(rb_cArray, "permutation", rb_ary_permutation, -1);
04595 rb_define_method(rb_cArray, "combination", rb_ary_combination, 1);
04596 rb_define_method(rb_cArray, "repeated_permutation", rb_ary_repeated_permutation, 1);
04597 rb_define_method(rb_cArray, "repeated_combination", rb_ary_repeated_combination, 1);
04598 rb_define_method(rb_cArray, "product", rb_ary_product, -1);
04599
04600 rb_define_method(rb_cArray, "take", rb_ary_take, 1);
04601 rb_define_method(rb_cArray, "take_while", rb_ary_take_while, 0);
04602 rb_define_method(rb_cArray, "drop", rb_ary_drop, 1);
04603 rb_define_method(rb_cArray, "drop_while", rb_ary_drop_while, 0);
04604
04605 id_cmp = rb_intern("<=>");
04606 }
04607