00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "ruby.h"
00016 #include "util.h"
00017 #include "st.h"
00018
00019 VALUE rb_cArray;
00020 static ID id_cmp;
00021
00022 #define ARY_DEFAULT_SIZE 16
00023
00024 void
00025 rb_mem_clear(mem, size)
00026 register VALUE *mem;
00027 register long size;
00028 {
00029 while (size--) {
00030 *mem++ = Qnil;
00031 }
00032 }
00033
00034 static inline void
00035 memfill(mem, size, val)
00036 register VALUE *mem;
00037 register long size;
00038 register VALUE val;
00039 {
00040 while (size--) {
00041 *mem++ = val;
00042 }
00043 }
00044
00045 #define ARY_TMPLOCK FL_USER1
00046
00047 static inline void
00048 rb_ary_modify_check(ary)
00049 VALUE ary;
00050 {
00051 if (OBJ_FROZEN(ary)) rb_error_frozen("array");
00052 if (FL_TEST(ary, ARY_TMPLOCK))
00053 rb_raise(rb_eRuntimeError, "can't modify array during iteration");
00054 if (!OBJ_TAINTED(ary) && rb_safe_level() >= 4)
00055 rb_raise(rb_eSecurityError, "Insecure: can't modify array");
00056 }
00057
00058 static void
00059 rb_ary_modify(ary)
00060 VALUE ary;
00061 {
00062 VALUE *ptr;
00063
00064 rb_ary_modify_check(ary);
00065 if (FL_TEST(ary, ELTS_SHARED)) {
00066 ptr = ALLOC_N(VALUE, RARRAY(ary)->len);
00067 FL_UNSET(ary, ELTS_SHARED);
00068 RARRAY(ary)->aux.capa = RARRAY(ary)->len;
00069 MEMCPY(ptr, RARRAY(ary)->ptr, VALUE, RARRAY(ary)->len);
00070 RARRAY(ary)->ptr = ptr;
00071 }
00072 }
00073
00074 VALUE
00075 rb_ary_freeze(ary)
00076 VALUE ary;
00077 {
00078 return rb_obj_freeze(ary);
00079 }
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089 static VALUE
00090 rb_ary_frozen_p(ary)
00091 VALUE ary;
00092 {
00093 if (OBJ_FROZEN(ary)) return Qtrue;
00094 if (FL_TEST(ary, ARY_TMPLOCK)) return Qtrue;
00095 return Qfalse;
00096 }
00097
00098 static VALUE ary_alloc (VALUE);
00099 static VALUE
00100 ary_alloc(klass)
00101 VALUE klass;
00102 {
00103 NEWOBJ(ary, struct RArray);
00104 OBJSETUP(ary, klass, T_ARRAY);
00105
00106 ary->len = 0;
00107 ary->ptr = 0;
00108 ary->aux.capa = 0;
00109
00110 return (VALUE)ary;
00111 }
00112
00113 static VALUE
00114 ary_new(klass, len)
00115 VALUE klass;
00116 long len;
00117 {
00118 VALUE ary = ary_alloc(klass);
00119
00120 if (len < 0) {
00121 rb_raise(rb_eArgError, "negative array size (or size too big)");
00122 }
00123 if (len > 0 && len * sizeof(VALUE) <= len) {
00124 rb_raise(rb_eArgError, "array size too big");
00125 }
00126 if (len == 0) len++;
00127 RARRAY(ary)->ptr = ALLOC_N(VALUE, len);
00128 RARRAY(ary)->aux.capa = len;
00129
00130 return ary;
00131 }
00132
00133 VALUE
00134 rb_ary_new2(len)
00135 long len;
00136 {
00137 return ary_new(rb_cArray, len);
00138 }
00139
00140
00141 VALUE
00142 rb_ary_new()
00143 {
00144 return rb_ary_new2(ARY_DEFAULT_SIZE);
00145 }
00146
00147 #ifdef HAVE_STDARG_PROTOTYPES
00148 #include <stdarg.h>
00149 #define va_init_list(a,b) va_start(a,b)
00150 #else
00151 #include <varargs.h>
00152 #define va_init_list(a,b) va_start(a)
00153 #endif
00154
00155 VALUE
00156 #ifdef HAVE_STDARG_PROTOTYPES
00157 rb_ary_new3(long n, ...)
00158 #else
00159 rb_ary_new3(n, va_alist)
00160 long n;
00161 va_dcl
00162 #endif
00163 {
00164 va_list ar;
00165 VALUE ary;
00166 long i;
00167
00168 ary = rb_ary_new2(n);
00169
00170 va_init_list(ar, n);
00171 for (i=0; i<n; i++) {
00172 RARRAY(ary)->ptr[i] = va_arg(ar, VALUE);
00173 }
00174 va_end(ar);
00175
00176 RARRAY(ary)->len = n;
00177 return ary;
00178 }
00179
00180 VALUE
00181 rb_ary_new4(n, elts)
00182 long n;
00183 const VALUE *elts;
00184 {
00185 VALUE ary;
00186
00187 ary = rb_ary_new2(n);
00188 if (n > 0 && elts) {
00189 MEMCPY(RARRAY(ary)->ptr, elts, VALUE, n);
00190 }
00191 RARRAY(ary)->len = n;
00192
00193 return ary;
00194 }
00195
00196 VALUE
00197 rb_assoc_new(car, cdr)
00198 VALUE car, cdr;
00199 {
00200 VALUE ary;
00201
00202 ary = rb_ary_new2(2);
00203 RARRAY(ary)->ptr[0] = car;
00204 RARRAY(ary)->ptr[1] = cdr;
00205 RARRAY(ary)->len = 2;
00206
00207 return ary;
00208 }
00209
00210 static VALUE
00211 to_ary(ary)
00212 VALUE ary;
00213 {
00214 return rb_convert_type(ary, T_ARRAY, "Array", "to_ary");
00215 }
00216
00217 VALUE
00218 rb_check_array_type(ary)
00219 VALUE ary;
00220 {
00221 return rb_check_convert_type(ary, T_ARRAY, "Array", "to_ary");
00222 }
00223
00224 static VALUE rb_ary_replace (VALUE, VALUE);
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264 static VALUE
00265 rb_ary_initialize(argc, argv, ary)
00266 int argc;
00267 VALUE *argv;
00268 VALUE ary;
00269 {
00270 long len;
00271 VALUE size, val;
00272
00273 if (rb_scan_args(argc, argv, "02", &size, &val) == 0) {
00274 RARRAY(ary)->len = 0;
00275 if (rb_block_given_p()) {
00276 rb_warning("given block not used");
00277 }
00278 return ary;
00279 }
00280
00281 if (argc == 1 && !FIXNUM_P(size)) {
00282 val = rb_check_array_type(size);
00283 if (!NIL_P(val)) {
00284 rb_ary_replace(ary, val);
00285 return ary;
00286 }
00287 }
00288
00289 len = NUM2LONG(size);
00290 if (len < 0) {
00291 rb_raise(rb_eArgError, "negative array size");
00292 }
00293 if (len > 0 && len * (long)sizeof(VALUE) <= len) {
00294 rb_raise(rb_eArgError, "array size too big");
00295 }
00296 rb_ary_modify(ary);
00297 if (len > RARRAY(ary)->aux.capa) {
00298 REALLOC_N(RARRAY(ary)->ptr, VALUE, len);
00299 RARRAY(ary)->aux.capa = len;
00300 }
00301 if (rb_block_given_p()) {
00302 long i;
00303
00304 if (argc == 2) {
00305 rb_warn("block supersedes default value argument");
00306 }
00307 for (i=0; i<len; i++) {
00308 rb_ary_store(ary, i, rb_yield(LONG2NUM(i)));
00309 RARRAY(ary)->len = i + 1;
00310 }
00311 }
00312 else {
00313 memfill(RARRAY(ary)->ptr, len, val);
00314 RARRAY(ary)->len = len;
00315 }
00316
00317 return ary;
00318 }
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329 static VALUE
00330 rb_ary_s_create(argc, argv, klass)
00331 int argc;
00332 VALUE *argv;
00333 VALUE klass;
00334 {
00335 VALUE ary = ary_alloc(klass);
00336
00337 if (argc > 0) {
00338 RARRAY(ary)->ptr = ALLOC_N(VALUE, argc);
00339 MEMCPY(RARRAY(ary)->ptr, argv, VALUE, argc);
00340 }
00341 RARRAY(ary)->len = RARRAY(ary)->aux.capa = argc;
00342
00343 return ary;
00344 }
00345
00346 void
00347 rb_ary_store(ary, idx, val)
00348 VALUE ary;
00349 long idx;
00350 VALUE val;
00351 {
00352 if (idx < 0) {
00353 idx += RARRAY(ary)->len;
00354 if (idx < 0) {
00355 rb_raise(rb_eIndexError, "index %ld out of array",
00356 idx - RARRAY(ary)->len);
00357 }
00358 }
00359
00360 rb_ary_modify(ary);
00361 if (idx >= RARRAY(ary)->aux.capa) {
00362 long new_capa = RARRAY(ary)->aux.capa / 2;
00363
00364 if (new_capa < ARY_DEFAULT_SIZE) {
00365 new_capa = ARY_DEFAULT_SIZE;
00366 }
00367 new_capa += idx;
00368 if (new_capa * (long)sizeof(VALUE) <= new_capa) {
00369 rb_raise(rb_eArgError, "index too big");
00370 }
00371 REALLOC_N(RARRAY(ary)->ptr, VALUE, new_capa);
00372 RARRAY(ary)->aux.capa = new_capa;
00373 }
00374 if (idx > RARRAY(ary)->len) {
00375 rb_mem_clear(RARRAY(ary)->ptr + RARRAY(ary)->len,
00376 idx-RARRAY(ary)->len + 1);
00377 }
00378
00379 if (idx >= RARRAY(ary)->len) {
00380 RARRAY(ary)->len = idx + 1;
00381 }
00382 RARRAY(ary)->ptr[idx] = val;
00383 }
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398 VALUE
00399 rb_ary_push(ary, item)
00400 VALUE ary;
00401 VALUE item;
00402 {
00403 rb_ary_store(ary, RARRAY(ary)->len, item);
00404 return ary;
00405 }
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420 static VALUE
00421 rb_ary_push_m(argc, argv, ary)
00422 int argc;
00423 VALUE *argv;
00424 VALUE ary;
00425 {
00426 while (argc--) {
00427 rb_ary_push(ary, *argv++);
00428 }
00429 return ary;
00430 }
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444 VALUE
00445 rb_ary_pop(ary)
00446 VALUE ary;
00447 {
00448 rb_ary_modify_check(ary);
00449 if (RARRAY(ary)->len == 0) return Qnil;
00450 if (!FL_TEST(ary, ELTS_SHARED) &&
00451 RARRAY(ary)->len * 2 < RARRAY(ary)->aux.capa &&
00452 RARRAY(ary)->aux.capa > ARY_DEFAULT_SIZE) {
00453 RARRAY(ary)->aux.capa = RARRAY(ary)->len * 2;
00454 REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->aux.capa);
00455 }
00456 return RARRAY(ary)->ptr[--RARRAY(ary)->len];
00457 }
00458
00459 static VALUE
00460 ary_make_shared(ary)
00461 VALUE ary;
00462 {
00463 if (!FL_TEST(ary, ELTS_SHARED)) {
00464 NEWOBJ(shared, struct RArray);
00465 OBJSETUP(shared, rb_cArray, T_ARRAY);
00466
00467 shared->len = RARRAY(ary)->len;
00468 shared->ptr = RARRAY(ary)->ptr;
00469 shared->aux.capa = RARRAY(ary)->aux.capa;
00470 RARRAY(ary)->aux.shared = (VALUE)shared;
00471 FL_SET(ary, ELTS_SHARED);
00472 OBJ_FREEZE(shared);
00473 return (VALUE)shared;
00474 }
00475 else {
00476 return RARRAY(ary)->aux.shared;
00477 }
00478 }
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493 VALUE
00494 rb_ary_shift(ary)
00495 VALUE ary;
00496 {
00497 VALUE top;
00498
00499 rb_ary_modify_check(ary);
00500 if (RARRAY(ary)->len == 0) return Qnil;
00501 top = RARRAY(ary)->ptr[0];
00502 ary_make_shared(ary);
00503 RARRAY(ary)->ptr++;
00504 RARRAY(ary)->len--;
00505
00506 return top;
00507 }
00508
00509 VALUE
00510 rb_ary_unshift(ary, item)
00511 VALUE ary, item;
00512 {
00513 rb_ary_modify(ary);
00514 if (RARRAY(ary)->len == RARRAY(ary)->aux.capa) {
00515 long capa_inc = RARRAY(ary)->aux.capa / 2;
00516 if (capa_inc < ARY_DEFAULT_SIZE) {
00517 capa_inc = ARY_DEFAULT_SIZE;
00518 }
00519 RARRAY(ary)->aux.capa += capa_inc;
00520 REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->aux.capa);
00521 }
00522
00523
00524 MEMMOVE(RARRAY(ary)->ptr + 1, RARRAY(ary)->ptr, VALUE, RARRAY(ary)->len);
00525
00526 RARRAY(ary)->len++;
00527 RARRAY(ary)->ptr[0] = item;
00528
00529 return ary;
00530 }
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544 static VALUE
00545 rb_ary_unshift_m(argc, argv, ary)
00546 int argc;
00547 VALUE *argv;
00548 VALUE ary;
00549 {
00550 long len = RARRAY(ary)->len;
00551
00552 if (argc == 0) return ary;
00553
00554
00555 rb_ary_store(ary, len + argc - 1, Qnil);
00556
00557
00558 MEMMOVE(RARRAY(ary)->ptr + argc, RARRAY(ary)->ptr, VALUE, len);
00559 MEMCPY(RARRAY(ary)->ptr, argv, VALUE, argc);
00560
00561 return ary;
00562 }
00563
00564
00565 static inline VALUE
00566 rb_ary_elt(ary, offset)
00567 VALUE ary;
00568 long offset;
00569 {
00570 if (RARRAY(ary)->len == 0) return Qnil;
00571 if (offset < 0 || RARRAY(ary)->len <= offset) {
00572 return Qnil;
00573 }
00574 return RARRAY(ary)->ptr[offset];
00575 }
00576
00577 VALUE
00578 rb_ary_entry(ary, offset)
00579 VALUE ary;
00580 long offset;
00581 {
00582 if (offset < 0) {
00583 offset += RARRAY(ary)->len;
00584 }
00585 return rb_ary_elt(ary, offset);
00586 }
00587
00588 static VALUE
00589 rb_ary_subseq(ary, beg, len)
00590 VALUE ary;
00591 long beg, len;
00592 {
00593 VALUE klass, ary2, shared;
00594 VALUE *ptr;
00595
00596 if (beg > RARRAY(ary)->len) return Qnil;
00597 if (beg < 0 || len < 0) return Qnil;
00598
00599 if (beg + len > RARRAY(ary)->len) {
00600 len = RARRAY(ary)->len - beg;
00601 if (len < 0)
00602 len = 0;
00603 }
00604 klass = rb_obj_class(ary);
00605 if (len == 0) return ary_new(klass, 0);
00606
00607 shared = ary_make_shared(ary);
00608 ptr = RARRAY(ary)->ptr;
00609 ary2 = ary_alloc(klass);
00610 RARRAY(ary2)->ptr = ptr + beg;
00611 RARRAY(ary2)->len = len;
00612 RARRAY(ary2)->aux.shared = shared;
00613 FL_SET(ary2, ELTS_SHARED);
00614
00615 return ary2;
00616 }
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650 VALUE
00651 rb_ary_aref(argc, argv, ary)
00652 int argc;
00653 VALUE *argv;
00654 VALUE ary;
00655 {
00656 VALUE arg;
00657 long beg, len;
00658
00659 if (argc == 2) {
00660 if (SYMBOL_P(argv[0])) {
00661 rb_raise(rb_eTypeError, "Symbol as array index");
00662 }
00663 beg = NUM2LONG(argv[0]);
00664 len = NUM2LONG(argv[1]);
00665 if (beg < 0) {
00666 beg += RARRAY(ary)->len;
00667 }
00668 return rb_ary_subseq(ary, beg, len);
00669 }
00670 if (argc != 1) {
00671 rb_scan_args(argc, argv, "11", 0, 0);
00672 }
00673 arg = argv[0];
00674
00675 if (FIXNUM_P(arg)) {
00676 return rb_ary_entry(ary, FIX2LONG(arg));
00677 }
00678 if (SYMBOL_P(arg)) {
00679 rb_raise(rb_eTypeError, "Symbol as array index");
00680 }
00681
00682 switch (rb_range_beg_len(arg, &beg, &len, RARRAY(ary)->len, 0)) {
00683 case Qfalse:
00684 break;
00685 case Qnil:
00686 return Qnil;
00687 default:
00688 return rb_ary_subseq(ary, beg, len);
00689 }
00690 return rb_ary_entry(ary, NUM2LONG(arg));
00691 }
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708 static VALUE
00709 rb_ary_at(ary, pos)
00710 VALUE ary, pos;
00711 {
00712 return rb_ary_entry(ary, NUM2LONG(pos));
00713 }
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730 static VALUE
00731 rb_ary_first(argc, argv, ary)
00732 int argc;
00733 VALUE *argv;
00734 VALUE ary;
00735 {
00736 if (argc == 0) {
00737 if (RARRAY(ary)->len == 0) return Qnil;
00738 return RARRAY(ary)->ptr[0];
00739 }
00740 else {
00741 VALUE nv, result;
00742 long n, i;
00743
00744 rb_scan_args(argc, argv, "01", &nv);
00745 n = NUM2LONG(nv);
00746 if (n > RARRAY(ary)->len) n = RARRAY(ary)->len;
00747 result = rb_ary_new2(n);
00748 for (i=0; i<n; i++) {
00749 rb_ary_push(result, RARRAY(ary)->ptr[i]);
00750 }
00751 return result;
00752 }
00753 }
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766 static VALUE
00767 rb_ary_last(argc, argv, ary)
00768 int argc;
00769 VALUE *argv;
00770 VALUE ary;
00771 {
00772 if (argc == 0) {
00773 if (RARRAY(ary)->len == 0) return Qnil;
00774 return RARRAY(ary)->ptr[RARRAY(ary)->len-1];
00775 }
00776 else {
00777 VALUE nv, result;
00778 long n, i;
00779
00780 rb_scan_args(argc, argv, "01", &nv);
00781 n = NUM2LONG(nv);
00782 if (n > RARRAY(ary)->len) n = RARRAY(ary)->len;
00783 result = rb_ary_new2(n);
00784 for (i=RARRAY(ary)->len-n; n--; i++) {
00785 rb_ary_push(result, RARRAY(ary)->ptr[i]);
00786 }
00787 return result;
00788 }
00789 }
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811 static VALUE
00812 rb_ary_fetch(argc, argv, ary)
00813 int argc;
00814 VALUE *argv;
00815 VALUE ary;
00816 {
00817 VALUE pos, ifnone;
00818 long block_given;
00819 long idx;
00820
00821 rb_scan_args(argc, argv, "11", &pos, &ifnone);
00822 block_given = rb_block_given_p();
00823 if (block_given && argc == 2) {
00824 rb_warn("block supersedes default value argument");
00825 }
00826 idx = NUM2LONG(pos);
00827
00828 if (idx < 0) {
00829 idx += RARRAY(ary)->len;
00830 }
00831 if (idx < 0 || RARRAY(ary)->len <= idx) {
00832 if (block_given) return rb_yield(pos);
00833 if (argc == 1) {
00834 rb_raise(rb_eIndexError, "index %ld out of array", idx);
00835 }
00836 return ifnone;
00837 }
00838 return RARRAY(ary)->ptr[idx];
00839 }
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854 static VALUE
00855 rb_ary_index(ary, val)
00856 VALUE ary;
00857 VALUE val;
00858 {
00859 long i;
00860
00861 for (i=0; i<RARRAY(ary)->len; i++) {
00862 if (rb_equal(RARRAY(ary)->ptr[i], val))
00863 return LONG2NUM(i);
00864 }
00865 return Qnil;
00866 }
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881 static VALUE
00882 rb_ary_rindex(ary, val)
00883 VALUE ary;
00884 VALUE val;
00885 {
00886 long i = RARRAY(ary)->len;
00887
00888 while (i--) {
00889 if (i > RARRAY(ary)->len) {
00890 i = RARRAY(ary)->len;
00891 continue;
00892 }
00893 if (rb_equal(RARRAY(ary)->ptr[i], val))
00894 return LONG2NUM(i);
00895 }
00896 return Qnil;
00897 }
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907 static VALUE
00908 rb_ary_indexes(argc, argv, ary)
00909 int argc;
00910 VALUE *argv;
00911 VALUE ary;
00912 {
00913 VALUE new_ary;
00914 long i;
00915
00916 rb_warn("Array#%s is deprecated; use Array#values_at", rb_id2name(rb_frame_last_func()));
00917 new_ary = rb_ary_new2(argc);
00918 for (i=0; i<argc; i++) {
00919 rb_ary_push(new_ary, rb_ary_aref(1, argv+i, ary));
00920 }
00921
00922 return new_ary;
00923 }
00924
00925 VALUE
00926 rb_ary_to_ary(obj)
00927 VALUE obj;
00928 {
00929 if (TYPE(obj) == T_ARRAY) {
00930 return obj;
00931 }
00932 if (rb_respond_to(obj, rb_intern("to_ary"))) {
00933 return rb_convert_type(obj, T_ARRAY, "Array", "to_ary");
00934 }
00935 return rb_ary_new3(1, obj);
00936 }
00937
00938 static void
00939 rb_ary_splice(ary, beg, len, rpl)
00940 VALUE ary;
00941 long beg, len;
00942 VALUE rpl;
00943 {
00944 long rlen;
00945
00946 if (len < 0) rb_raise(rb_eIndexError, "negative length (%ld)", len);
00947 if (beg < 0) {
00948 beg += RARRAY(ary)->len;
00949 if (beg < 0) {
00950 beg -= RARRAY(ary)->len;
00951 rb_raise(rb_eIndexError, "index %ld out of array", beg);
00952 }
00953 }
00954 if (beg + len > RARRAY(ary)->len) {
00955 len = RARRAY(ary)->len - beg;
00956 }
00957
00958 if (NIL_P(rpl)) {
00959 rlen = 0;
00960 }
00961 else {
00962 rpl = rb_ary_to_ary(rpl);
00963 rlen = RARRAY(rpl)->len;
00964 }
00965 rb_ary_modify(ary);
00966
00967 if (beg >= RARRAY(ary)->len) {
00968 len = beg + rlen;
00969 if (len >= RARRAY(ary)->aux.capa) {
00970 REALLOC_N(RARRAY(ary)->ptr, VALUE, len);
00971 RARRAY(ary)->aux.capa = len;
00972 }
00973 rb_mem_clear(RARRAY(ary)->ptr + RARRAY(ary)->len, beg - RARRAY(ary)->len);
00974 if (rlen > 0) {
00975 MEMCPY(RARRAY(ary)->ptr + beg, RARRAY(rpl)->ptr, VALUE, rlen);
00976 }
00977 RARRAY(ary)->len = len;
00978 }
00979 else {
00980 long alen;
00981
00982 if (beg + len > RARRAY(ary)->len) {
00983 len = RARRAY(ary)->len - beg;
00984 }
00985
00986 alen = RARRAY(ary)->len + rlen - len;
00987 if (alen >= RARRAY(ary)->aux.capa) {
00988 REALLOC_N(RARRAY(ary)->ptr, VALUE, alen);
00989 RARRAY(ary)->aux.capa = alen;
00990 }
00991
00992 if (len != rlen) {
00993 MEMMOVE(RARRAY(ary)->ptr + beg + rlen, RARRAY(ary)->ptr + beg + len,
00994 VALUE, RARRAY(ary)->len - (beg + len));
00995 RARRAY(ary)->len = alen;
00996 }
00997 if (rlen > 0) {
00998 MEMMOVE(RARRAY(ary)->ptr + beg, RARRAY(rpl)->ptr, VALUE, rlen);
00999 }
01000 }
01001 }
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031 static VALUE
01032 rb_ary_aset(argc, argv, ary)
01033 int argc;
01034 VALUE *argv;
01035 VALUE ary;
01036 {
01037 long offset, beg, len;
01038
01039 if (argc == 3) {
01040 if (SYMBOL_P(argv[0])) {
01041 rb_raise(rb_eTypeError, "Symbol as array index");
01042 }
01043 if (SYMBOL_P(argv[1])) {
01044 rb_raise(rb_eTypeError, "Symbol as subarray length");
01045 }
01046 rb_ary_splice(ary, NUM2LONG(argv[0]), NUM2LONG(argv[1]), argv[2]);
01047 return argv[2];
01048 }
01049 if (argc != 2) {
01050 rb_raise(rb_eArgError, "wrong number of arguments (%d for 2)", argc);
01051 }
01052 if (FIXNUM_P(argv[0])) {
01053 offset = FIX2LONG(argv[0]);
01054 goto fixnum;
01055 }
01056 if (SYMBOL_P(argv[0])) {
01057 rb_raise(rb_eTypeError, "Symbol as array index");
01058 }
01059 if (rb_range_beg_len(argv[0], &beg, &len, RARRAY(ary)->len, 1)) {
01060
01061 rb_ary_splice(ary, beg, len, argv[1]);
01062 return argv[1];
01063 }
01064
01065 offset = NUM2LONG(argv[0]);
01066 fixnum:
01067 rb_ary_store(ary, offset, argv[1]);
01068 return argv[1];
01069 }
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083 static VALUE
01084 rb_ary_insert(argc, argv, ary)
01085 int argc;
01086 VALUE *argv;
01087 VALUE ary;
01088 {
01089 long pos;
01090
01091 if (argc == 1) return ary;
01092 if (argc < 1) {
01093 rb_raise(rb_eArgError, "wrong number of arguments (at least 1)");
01094 }
01095 pos = NUM2LONG(argv[0]);
01096 if (pos == -1) {
01097 pos = RARRAY(ary)->len;
01098 }
01099 if (pos < 0) {
01100 pos++;
01101 }
01102 rb_ary_splice(ary, pos, 0, rb_ary_new4(argc - 1, argv + 1));
01103 return ary;
01104 }
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121 VALUE
01122 rb_ary_each(ary)
01123 VALUE ary;
01124 {
01125 long i;
01126
01127 for (i=0; i<RARRAY(ary)->len; i++) {
01128 rb_yield(RARRAY(ary)->ptr[i]);
01129 }
01130 return ary;
01131 }
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148 static VALUE
01149 rb_ary_each_index(ary)
01150 VALUE ary;
01151 {
01152 long i;
01153
01154 for (i=0; i<RARRAY(ary)->len; i++) {
01155 rb_yield(LONG2NUM(i));
01156 }
01157 return ary;
01158 }
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175 static VALUE
01176 rb_ary_reverse_each(ary)
01177 VALUE ary;
01178 {
01179 long len = RARRAY(ary)->len;
01180
01181 while (len--) {
01182 rb_yield(RARRAY(ary)->ptr[len]);
01183 if (RARRAY(ary)->len < len) {
01184 len = RARRAY(ary)->len;
01185 }
01186 }
01187 return ary;
01188 }
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199 static VALUE
01200 rb_ary_length(ary)
01201 VALUE ary;
01202 {
01203 return LONG2NUM(RARRAY(ary)->len);
01204 }
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215 static VALUE
01216 rb_ary_empty_p(ary)
01217 VALUE ary;
01218 {
01219 if (RARRAY(ary)->len == 0)
01220 return Qtrue;
01221 return Qfalse;
01222 }
01223
01224 VALUE
01225 rb_ary_dup(ary)
01226 VALUE ary;
01227 {
01228 VALUE dup = rb_ary_new2(RARRAY(ary)->len);
01229
01230 DUPSETUP(dup, ary);
01231 MEMCPY(RARRAY(dup)->ptr, RARRAY(ary)->ptr, VALUE, RARRAY(ary)->len);
01232 RARRAY(dup)->len = RARRAY(ary)->len;
01233 return dup;
01234 }
01235
01236 extern VALUE rb_output_fs;
01237
01238 static VALUE
01239 inspect_join(ary, arg)
01240 VALUE ary;
01241 VALUE *arg;
01242 {
01243 return rb_ary_join(arg[0], arg[1]);
01244 }
01245
01246 VALUE
01247 rb_ary_join(ary, sep)
01248 VALUE ary, sep;
01249 {
01250 long len = 1, i;
01251 int taint = Qfalse;
01252 VALUE result, tmp;
01253
01254 if (RARRAY(ary)->len == 0) return rb_str_new(0, 0);
01255 if (OBJ_TAINTED(ary) || OBJ_TAINTED(sep)) taint = Qtrue;
01256
01257 for (i=0; i<RARRAY(ary)->len; i++) {
01258 tmp = rb_check_string_type(RARRAY(ary)->ptr[i]);
01259 len += NIL_P(tmp) ? 10 : RSTRING(tmp)->len;
01260 }
01261 if (!NIL_P(sep)) {
01262 StringValue(sep);
01263 len += RSTRING(sep)->len * (RARRAY(ary)->len - 1);
01264 }
01265 result = rb_str_buf_new(len);
01266 for (i=0; i<RARRAY(ary)->len; i++) {
01267 tmp = RARRAY(ary)->ptr[i];
01268 switch (TYPE(tmp)) {
01269 case T_STRING:
01270 break;
01271 case T_ARRAY:
01272 if (rb_inspecting_p(tmp)) {
01273 tmp = rb_str_new2("[...]");
01274 }
01275 else {
01276 VALUE args[2];
01277
01278 args[0] = tmp;
01279 args[1] = sep;
01280 tmp = rb_protect_inspect(inspect_join, ary, (VALUE)args);
01281 }
01282 break;
01283 default:
01284 tmp = rb_obj_as_string(tmp);
01285 }
01286 if (i > 0 && !NIL_P(sep))
01287 rb_str_buf_append(result, sep);
01288 rb_str_buf_append(result, tmp);
01289 if (OBJ_TAINTED(tmp)) taint = Qtrue;
01290 }
01291
01292 if (taint) OBJ_TAINT(result);
01293 return result;
01294 }
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307 static VALUE
01308 rb_ary_join_m(argc, argv, ary)
01309 int argc;
01310 VALUE *argv;
01311 VALUE ary;
01312 {
01313 VALUE sep;
01314
01315 rb_scan_args(argc, argv, "01", &sep);
01316 if (NIL_P(sep)) sep = rb_output_fs;
01317
01318 return rb_ary_join(ary, sep);
01319 }
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331 VALUE
01332 rb_ary_to_s(ary)
01333 VALUE ary;
01334 {
01335 if (RARRAY(ary)->len == 0) return rb_str_new(0, 0);
01336
01337 return rb_ary_join(ary, rb_output_fs);
01338 }
01339
01340 static ID inspect_key;
01341
01342 struct inspect_arg {
01343 VALUE (*func)();
01344 VALUE arg1, arg2;
01345 };
01346
01347 static VALUE
01348 inspect_call(arg)
01349 struct inspect_arg *arg;
01350 {
01351 return (*arg->func)(arg->arg1, arg->arg2);
01352 }
01353
01354 static VALUE
01355 get_inspect_tbl(create)
01356 int create;
01357 {
01358 VALUE inspect_tbl = rb_thread_local_aref(rb_thread_current(), inspect_key);
01359
01360 if (NIL_P(inspect_tbl)) {
01361 if (create) {
01362 tbl_init:
01363 inspect_tbl = rb_ary_new();
01364 rb_thread_local_aset(rb_thread_current(), inspect_key, inspect_tbl);
01365 }
01366 }
01367 else if (TYPE(inspect_tbl) != T_ARRAY) {
01368 rb_warn("invalid inspect_tbl value");
01369 if (create) goto tbl_init;
01370 rb_thread_local_aset(rb_thread_current(), inspect_key, Qnil);
01371 return Qnil;
01372 }
01373 return inspect_tbl;
01374 }
01375
01376 static VALUE
01377 inspect_ensure(obj)
01378 VALUE obj;
01379 {
01380 VALUE inspect_tbl;
01381
01382 inspect_tbl = get_inspect_tbl(Qfalse);
01383 if (!NIL_P(inspect_tbl)) {
01384 rb_ary_pop(inspect_tbl);
01385 }
01386 return 0;
01387 }
01388
01389 VALUE
01390 rb_protect_inspect(func, obj, arg)
01391 VALUE (*func)(ANYARGS);
01392 VALUE obj, arg;
01393 {
01394 struct inspect_arg iarg;
01395 VALUE inspect_tbl;
01396 VALUE id;
01397
01398 inspect_tbl = get_inspect_tbl(Qtrue);
01399 id = rb_obj_id(obj);
01400 if (rb_ary_includes(inspect_tbl, id)) {
01401 return (*func)(obj, arg);
01402 }
01403 rb_ary_push(inspect_tbl, id);
01404 iarg.func = func;
01405 iarg.arg1 = obj;
01406 iarg.arg2 = arg;
01407
01408 return rb_ensure(inspect_call, (VALUE)&iarg, inspect_ensure, obj);
01409 }
01410
01411 VALUE
01412 rb_inspecting_p(obj)
01413 VALUE obj;
01414 {
01415 VALUE inspect_tbl;
01416
01417 inspect_tbl = get_inspect_tbl(Qfalse);
01418 if (NIL_P(inspect_tbl)) return Qfalse;
01419 return rb_ary_includes(inspect_tbl, rb_obj_id(obj));
01420 }
01421
01422 static VALUE
01423 inspect_ary(ary)
01424 VALUE ary;
01425 {
01426 int tainted = OBJ_TAINTED(ary);
01427 long i;
01428 VALUE s, str;
01429
01430 str = rb_str_buf_new2("[");
01431 for (i=0; i<RARRAY(ary)->len; i++) {
01432 s = rb_inspect(RARRAY(ary)->ptr[i]);
01433 if (OBJ_TAINTED(s)) tainted = Qtrue;
01434 if (i > 0) rb_str_buf_cat2(str, ", ");
01435 rb_str_buf_append(str, s);
01436 }
01437 rb_str_buf_cat2(str, "]");
01438 if (tainted) OBJ_TAINT(str);
01439 return str;
01440 }
01441
01442
01443
01444
01445
01446
01447
01448
01449 static VALUE
01450 rb_ary_inspect(ary)
01451 VALUE ary;
01452 {
01453 if (RARRAY(ary)->len == 0) return rb_str_new2("[]");
01454 if (rb_inspecting_p(ary)) return rb_str_new2("[...]");
01455 return rb_protect_inspect(inspect_ary, ary, 0);
01456 }
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466 static VALUE
01467 rb_ary_to_a(ary)
01468 VALUE ary;
01469 {
01470 if (rb_obj_class(ary) != rb_cArray) {
01471 VALUE dup = rb_ary_new2(RARRAY(ary)->len);
01472 rb_ary_replace(dup, ary);
01473 return dup;
01474 }
01475 return ary;
01476 }
01477
01478
01479
01480
01481
01482
01483
01484
01485 static VALUE
01486 rb_ary_to_ary_m(ary)
01487 VALUE ary;
01488 {
01489 return ary;
01490 }
01491
01492 VALUE
01493 rb_ary_reverse(ary)
01494 VALUE ary;
01495 {
01496 VALUE *p1, *p2;
01497 VALUE tmp;
01498
01499 rb_ary_modify(ary);
01500 if (RARRAY(ary)->len > 1) {
01501 p1 = RARRAY(ary)->ptr;
01502 p2 = p1 + RARRAY(ary)->len - 1;
01503
01504 while (p1 < p2) {
01505 tmp = *p1;
01506 *p1++ = *p2;
01507 *p2-- = tmp;
01508 }
01509 }
01510 return ary;
01511 }
01512
01513
01514
01515
01516
01517
01518
01519
01520
01521
01522
01523
01524 static VALUE
01525 rb_ary_reverse_bang(ary)
01526 VALUE ary;
01527 {
01528 return rb_ary_reverse(ary);
01529 }
01530
01531
01532
01533
01534
01535
01536
01537
01538
01539
01540
01541 static VALUE
01542 rb_ary_reverse_m(ary)
01543 VALUE ary;
01544 {
01545 return rb_ary_reverse(rb_ary_dup(ary));
01546 }
01547
01548 struct ary_sort_data {
01549 VALUE ary;
01550 VALUE *ptr;
01551 long len;
01552 };
01553
01554 static void
01555 ary_sort_check(data)
01556 struct ary_sort_data *data;
01557 {
01558 if (RARRAY(data->ary)->ptr != data->ptr || RARRAY(data->ary)->len != data->len) {
01559 rb_raise(rb_eArgError, "array modified during sort");
01560 }
01561 }
01562
01563 static int
01564 sort_1(a, b, data)
01565 VALUE *a, *b;
01566 struct ary_sort_data *data;
01567 {
01568 VALUE retval = rb_yield_values(2, *a, *b);
01569 int n;
01570
01571 n = rb_cmpint(retval, *a, *b);
01572 ary_sort_check(data);
01573 return n;
01574 }
01575
01576 static int
01577 sort_2(ap, bp, data)
01578 VALUE *ap, *bp;
01579 struct ary_sort_data *data;
01580 {
01581 VALUE retval;
01582 VALUE a = *ap, b = *bp;
01583 int n;
01584
01585 if (FIXNUM_P(a) && FIXNUM_P(b)) {
01586 if ((long)a > (long)b) return 1;
01587 if ((long)a < (long)b) return -1;
01588 return 0;
01589 }
01590 if (TYPE(a) == T_STRING) {
01591 if (TYPE(b) == T_STRING) return rb_str_cmp(a, b);
01592 }
01593
01594 retval = rb_funcall(a, id_cmp, 1, b);
01595 n = rb_cmpint(retval, a, b);
01596 ary_sort_check(data);
01597
01598 return n;
01599 }
01600
01601 static VALUE
01602 sort_internal(ary)
01603 VALUE ary;
01604 {
01605 struct ary_sort_data data;
01606
01607 data.ary = ary;
01608 data.ptr = RARRAY(ary)->ptr; data.len = RARRAY(ary)->len;
01609 qsort(RARRAY(ary)->ptr, RARRAY(ary)->len, sizeof(VALUE),
01610 rb_block_given_p()?sort_1:sort_2, &data);
01611 return ary;
01612 }
01613
01614 static VALUE
01615 sort_unlock(ary)
01616 VALUE ary;
01617 {
01618 FL_UNSET(ary, ARY_TMPLOCK);
01619 return ary;
01620 }
01621
01622
01623
01624
01625
01626
01627
01628
01629
01630
01631
01632
01633
01634
01635
01636
01637
01638 VALUE
01639 rb_ary_sort_bang(ary)
01640 VALUE ary;
01641 {
01642 rb_ary_modify(ary);
01643 if (RARRAY(ary)->len > 1) {
01644 FL_SET(ary, ARY_TMPLOCK);
01645 rb_ensure(sort_internal, ary, sort_unlock, ary);
01646 }
01647 return ary;
01648 }
01649
01650
01651
01652
01653
01654
01655
01656
01657
01658
01659
01660
01661
01662
01663
01664
01665
01666 VALUE
01667 rb_ary_sort(ary)
01668 VALUE ary;
01669 {
01670 ary = rb_ary_dup(ary);
01671 rb_ary_sort_bang(ary);
01672 return ary;
01673 }
01674
01675
01676
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686
01687
01688
01689 static VALUE
01690 rb_ary_collect(ary)
01691 VALUE ary;
01692 {
01693 long i;
01694 VALUE collect;
01695
01696 if (!rb_block_given_p()) {
01697 return rb_ary_new4(RARRAY(ary)->len, RARRAY(ary)->ptr);
01698 }
01699
01700 collect = rb_ary_new2(RARRAY(ary)->len);
01701 for (i = 0; i < RARRAY(ary)->len; i++) {
01702 rb_ary_push(collect, rb_yield(RARRAY(ary)->ptr[i]));
01703 }
01704 return collect;
01705 }
01706
01707
01708
01709
01710
01711
01712
01713
01714
01715
01716
01717
01718
01719
01720
01721 static VALUE
01722 rb_ary_collect_bang(ary)
01723 VALUE ary;
01724 {
01725 long i;
01726
01727 rb_ary_modify(ary);
01728 for (i = 0; i < RARRAY(ary)->len; i++) {
01729 rb_ary_store(ary, i, rb_yield(RARRAY(ary)->ptr[i]));
01730 }
01731 return ary;
01732 }
01733
01734 VALUE
01735 rb_values_at(obj, olen, argc, argv, func)
01736 VALUE obj;
01737 long olen;
01738 int argc;
01739 VALUE *argv;
01740 VALUE (*func) (VALUE,long);
01741 {
01742 VALUE result = rb_ary_new2(argc);
01743 long beg, len, i, j;
01744
01745 for (i=0; i<argc; i++) {
01746 if (FIXNUM_P(argv[i])) {
01747