Main Page | Modules | Alphabetical List | Data Structures | File List | Data Fields | Globals

array.c

Go to the documentation of this file.
00001 /**********************************************************************
00002 
00003   array.c -
00004 
00005   $Author: matz $
00006   $Date: 2005/12/22 07:08:51 $
00007   created at: Fri Aug  6 09:46:12 JST 1993
00008 
00009   Copyright (C) 1993-2003 Yukihiro Matsumoto
00010   Copyright (C) 2000  Network Applied Communication Laboratory, Inc.
00011   Copyright (C) 2000  Information-technology Promotion Agency, Japan
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  *  call-seq:
00083  *     array.frozen?  -> true or false
00084  *
00085  *  Return <code>true</code> if this array is frozen (or temporarily frozen
00086  *  while being sorted).
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  *  call-seq:
00228  *     Array.new(size=0, obj=nil)
00229  *     Array.new(array)
00230  *     Array.new(size) {|index| block }
00231  *
00232  *  Returns a new array. In the first form, the new array is
00233  *  empty. In the second it is created with _size_ copies of _obj_
00234  *  (that is, _size_ references to the same
00235  *  _obj_). The third form creates a copy of the array
00236  *  passed as a parameter (the array is generated by calling
00237  *  to_ary  on the parameter). In the last form, an array
00238  *  of the given size is created. Each element in this array is
00239  *  calculated by passing the element's index to the given block and
00240  *  storing the return value.
00241  *
00242  *     Array.new
00243  *     Array.new(2)
00244  *     Array.new(5, "A")
00245  * 
00246  *     # only one copy of the object is created
00247  *     a = Array.new(2, Hash.new)
00248  *     a[0]['cat'] = 'feline'
00249  *     a
00250  *     a[1]['cat'] = 'Felix'
00251  *     a
00252  * 
00253  *     # here multiple copies are created
00254  *     a = Array.new(2) { Hash.new }
00255  *     a[0]['cat'] = 'feline'
00256  *     a
00257  * 
00258  *     squares = Array.new(5) {|i| i*i}
00259  *     squares
00260  * 
00261  *     copy = Array.new(squares)
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 * Returns a new array populated with the given objects. 
00323 *
00324 *   Array.[]( 1, 'a', /^A/ )
00325 *   Array[ 1, 'a', /^A/ ]
00326 *   [ 1, 'a', /^A/ ]
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  *  call-seq:
00387  *     array << obj            -> array
00388  *  
00389  *  Append---Pushes the given object on to the end of this array. This
00390  *  expression returns the array itself, so several appends
00391  *  may be chained together.
00392  *
00393  *     [ 1, 2 ] << "c" << "d" << [ 3, 4 ]
00394  *             #=>  [ 1, 2, "c", "d", [ 3, 4 ] ]
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  *  call-seq:
00409  *     array.push(obj, ... )   -> array
00410  *  
00411  *  Append---Pushes the given object(s) on to the end of this array. This
00412  *  expression returns the array itself, so several appends
00413  *  may be chained together.
00414  *
00415  *     a = [ "a", "b", "c" ]
00416  *     a.push("d", "e", "f")  
00417  *             #=> ["a", "b", "c", "d", "e", "f"]
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  *  call-seq:
00434  *     array.pop  -> obj or nil
00435  *  
00436  *  Removes the last element from <i>self</i> and returns it, or
00437  *  <code>nil</code> if the array is empty.
00438  *     
00439  *     a = [ "a", "m", "z" ]
00440  *     a.pop   #=> "z"
00441  *     a       #=> ["a", "m"]
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  *  call-seq:
00482  *     array.shift   ->   obj or nil
00483  *  
00484  *  Returns the first element of <i>self</i> and removes it (shifting all
00485  *  other elements down by one). Returns <code>nil</code> if the array
00486  *  is empty.
00487  *     
00488  *     args = [ "-m", "-q", "filename" ]
00489  *     args.shift   #=> "-m"
00490  *     args         #=> ["-q", "filename"]
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++;         /* shift 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     /* sliding items */
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  *  call-seq:
00534  *     array.unshift(obj, ...)  -> array
00535  *  
00536  *  Prepends objects to the front of <i>array</i>.
00537  *  other elements up one.
00538  *     
00539  *     a = [ "b", "c", "d" ]
00540  *     a.unshift("a")   #=> ["a", "b", "c", "d"]
00541  *     a.unshift(1, 2)  #=> [ 1, 2, "a", "b", "c", "d"]
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     /* make rooms by setting the last item */
00555     rb_ary_store(ary, len + argc - 1, Qnil);
00556 
00557     /* sliding items */
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 /* faster version - use this if you don't need to treat negative offset */
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  *  call-seq:
00620  *     array[index]                -> obj      or nil
00621  *     array[start, length]        -> an_array or nil
00622  *     array[range]                -> an_array or nil
00623  *     array.slice(index)          -> obj      or nil
00624  *     array.slice(start, length)  -> an_array or nil
00625  *     array.slice(range)          -> an_array or nil
00626  *
00627  *  Element Reference---Returns the element at _index_,
00628  *  or returns a subarray starting at _start_ and
00629  *  continuing for _length_ elements, or returns a subarray
00630  *  specified by _range_.
00631  *  Negative indices count backward from the end of the
00632  *  array (-1 is the last element). Returns nil if the index
00633  *  (or starting index) are out of range.
00634  *
00635  *     a = [ "a", "b", "c", "d", "e" ]
00636  *     a[2] +  a[0] + a[1]    #=> "cab"
00637  *     a[6]                   #=> nil
00638  *     a[1, 2]                #=> [ "b", "c" ]
00639  *     a[1..3]                #=> [ "b", "c", "d" ]
00640  *     a[4..7]                #=> [ "e" ]
00641  *     a[6..10]               #=> nil
00642  *     a[-3, 3]               #=> [ "c", "d", "e" ]
00643  *     # special cases
00644  *     a[5]                   #=> nil
00645  *     a[5, 1]                #=> []
00646  *     a[5..10]               #=> []
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     /* special case - speeding up */
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     /* check if idx is Range */
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  *  call-seq:
00695  *     array.at(index)   ->   obj  or nil
00696  *
00697  *  Returns the element at _index_. A
00698  *  negative index counts from the end of _self_.  Returns +nil+
00699  *  if the index is out of range. See also <code>Array#[]</code>.
00700  *  (<code>Array#at</code> is slightly faster than <code>Array#[]</code>,
00701  *  as it does not accept ranges and so on.)
00702  *
00703  *     a = [ "a", "b", "c", "d", "e" ]
00704  *     a.at(0)     #=> "a"
00705  *     a.at(-1)    #=> "e"
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  *  call-seq:
00717  *     array.first   ->   obj or nil
00718  *     array.first(n) -> an_array
00719  *
00720  *  Returns the first element, or the first +n+ elements, of the array.
00721  *  If the array is empty, the first form returns <code>nil</code>, and the
00722  *  second form returns an empty array.
00723  *
00724  *     a = [ "q", "r", "s", "t" ]
00725  *     a.first    #=> "q"
00726  *     a.first(1) #=> ["q"]
00727  *     a.first(3) #=> ["q", "r", "s"]
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  *  call-seq:
00757  *     array.last     ->  obj or nil
00758  *     array.last(n)  ->  an_array
00759  *  
00760  *  Returns the last element(s) of <i>self</i>. If the array is empty,
00761  *  the first form returns <code>nil</code>.
00762  *     
00763  *     [ "w", "x", "y", "z" ].last   #=> "z"
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  *  call-seq:
00793  *     array.fetch(index)                    -> obj
00794  *     array.fetch(index, default )          -> obj
00795  *     array.fetch(index) {|index| block }   -> obj
00796  *  
00797  *  Tries to return the element at position <i>index</i>. If the index
00798  *  lies outside the array, the first form throws an
00799  *  <code>IndexError</code> exception, the second form returns
00800  *  <i>default</i>, and the third form returns the value of invoking
00801  *  the block, passing in the index. Negative values of <i>index</i>
00802  *  count from the end of the array.
00803  *     
00804  *     a = [ 11, 22, 33, 44 ]
00805  *     a.fetch(1)               #=> 22
00806  *     a.fetch(-1)              #=> 44
00807  *     a.fetch(4, 'cat')        #=> "cat"
00808  *     a.fetch(4) { |i| i*i }   #=> 16
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  *  call-seq:
00843  *     array.index(obj)   ->  int or nil
00844  *  
00845  *  Returns the index of the first object in <i>self</i> such that is 
00846  *  <code>==</code> to <i>obj</i>. Returns <code>nil</code> if
00847  *  no match is found.
00848  *     
00849  *     a = [ "a", "b", "c" ]
00850  *     a.index("b")   #=> 1
00851  *     a.index("z")   #=> nil
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  *  call-seq:
00870  *     array.rindex(obj)    ->  int or nil
00871  *  
00872  *  Returns the index of the last object in <i>array</i> 
00873  *  <code>==</code> to <i>obj</i>. Returns <code>nil</code> if
00874  *  no match is found.
00875  *     
00876  *     a = [ "a", "b", "b", "b", "c" ]
00877  *     a.rindex("b")   #=> 3
00878  *     a.rindex("z")   #=> nil
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  *  call-seq:
00901  *     array.indexes( i1, i2, ... iN )   -> an_array
00902  *     array.indices( i1, i2, ... iN )   -> an_array
00903  *  
00904  *  Deprecated; use <code>Array#values_at</code>.
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  *  call-seq:
01005  *     array[index]         = obj                     ->  obj
01006  *     array[start, length] = obj or an_array or nil  ->  obj or an_array or nil
01007  *     array[range]         = obj or an_array or nil  ->  obj or an_array or nil
01008  *
01009  *  Element Assignment---Sets the element at _index_,
01010  *  or replaces a subarray starting at _start_ and
01011  *  continuing for _length_ elements, or replaces a subarray
01012  *  specified by _range_.  If indices are greater than
01013  *  the current capacity of the array, the array grows
01014  *  automatically. A negative indices will count backward
01015  *  from the end of the array. Inserts elements if _length_ is
01016  *  zero. If +nil+ is used in the second and third form,
01017  *  deletes elements from _self_. An +IndexError+ is raised if a
01018  *  negative index points past the beginning of the array. See also
01019  *  <code>Array#push</code>, and <code>Array#unshift</code>.
01020  * 
01021  *     a = Array.new
01022  *     a[4] = "4";                 #=> [nil, nil, nil, nil, "4"]
01023  *     a[0, 3] = [ 'a', 'b', 'c' ] #=> ["a", "b", "c", nil, "4"]
01024  *     a[1..2] = [ 1, 2 ]          #=> ["a", 1, 2, nil, "4"]
01025  *     a[0, 2] = "?"               #=> ["?", 2, nil, "4"]
01026  *     a[0..2] = "A"               #=> ["A", "4"]
01027  *     a[-1]   = "Z"               #=> ["A", "Z"]
01028  *     a[1..-1] = nil              #=> ["A"]
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         /* check if idx is Range */
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  *  call-seq:
01073  *     array.insert(index, obj...)  -> array
01074  *  
01075  *  Inserts the given values before the element with the given index
01076  *  (which may be negative).
01077  *     
01078  *     a = %w{ a b c d }
01079  *     a.insert(2, 99)         #=> ["a", "b", 99, "c", "d"]
01080  *     a.insert(-2, 1, 2, 3)   #=> ["a", "b", 99, "c", 1, 2, 3, "d"]
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  *  call-seq:
01108  *     array.each {|item| block }   ->   array
01109  *  
01110  *  Calls <i>block</i> once for each element in <i>self</i>, passing that
01111  *  element as a parameter.
01112  *     
01113  *     a = [ "a", "b", "c" ]
01114  *     a.each {|x| print x, " -- " }
01115  *     
01116  *  produces:
01117  *     
01118  *     a -- b -- c --
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  *  call-seq:
01135  *     array.each_index {|index| block }  ->  array
01136  *  
01137  *  Same as <code>Array#each</code>, but passes the index of the element
01138  *  instead of the element itself.
01139  *     
01140  *     a = [ "a", "b", "c" ]
01141  *     a.each_index {|x| print x, " -- " }
01142  *     
01143  *  produces:
01144  *     
01145  *     0 -- 1 -- 2 --
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  *  call-seq:
01162  *     array.reverse_each {|item| block } 
01163  *  
01164  *  Same as <code>Array#each</code>, but traverses <i>self</i> in reverse
01165  *  order.
01166  *     
01167  *     a = [ "a", "b", "c" ]
01168  *     a.reverse_each {|x| print x, " " }
01169  *     
01170  *  produces:
01171  *     
01172  *     c b a
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  *  call-seq:
01192  *     array.length -> int
01193  *  
01194  *  Returns the number of elements in <i>self</i>. May be zero.
01195  *     
01196  *     [ 1, 2, 3, 4, 5 ].length   #=> 5
01197  */
01198 
01199 static VALUE
01200 rb_ary_length(ary)
01201     VALUE ary;
01202 {
01203     return LONG2NUM(RARRAY(ary)->len);
01204 }
01205 
01206 /*
01207  *  call-seq:
01208  *     array.empty?   -> true or false
01209  *  
01210  *  Returns <code>true</code> if <i>self</i> array contains no elements.
01211  *     
01212  *     [].empty?   #=> true
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  *  call-seq:
01298  *     array.join(sep=$,)    -> str
01299  *  
01300  *  Returns a string created by converting each element of the array to
01301  *  a string, separated by <i>sep</i>.
01302  *     
01303  *     [ "a", "b", "c" ].join        #=> "abc"
01304  *     [ "a", "b", "c" ].join("-")   #=> "a-b-c"
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  *  call-seq:
01323  *     array.to_s -> string
01324  *  
01325  *  Returns _self_<code>.join</code>.
01326  *     
01327  *     [ "a", "e", "i", "o" ].to_s   #=> "aeio"
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  *  call-seq:
01444  *     array.inspect  -> string
01445  *
01446  *  Create a printable version of <i>array</i>.
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  *  call-seq:
01460  *     array.to_a     -> array
01461  *  
01462  *  Returns _self_. If called on a subclass of Array, converts
01463  *  the receiver to an Array object.
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  *  call-seq:
01480  *     array.to_ary -> array
01481  *  
01482  *  Returns _self_.
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; /* points last item */
01503 
01504         while (p1 < p2) {
01505             tmp = *p1;
01506             *p1++ = *p2;
01507             *p2-- = tmp;
01508         }
01509     }
01510     return ary;
01511 }
01512 
01513 /*
01514  *  call-seq:
01515  *     array.reverse!   -> array 
01516  *  
01517  *  Reverses _self_ in place.
01518  *     
01519  *     a = [ "a", "b", "c" ]
01520  *     a.reverse!       #=> ["c", "b", "a"]
01521  *     a                #=> ["c", "b", "a"]
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  *  call-seq:
01533  *     array.reverse -> an_array
01534  *  
01535  *  Returns a new array containing <i>self</i>'s elements in reverse order.
01536  *     
01537  *     [ "a", "b", "c" ].reverse   #=> ["c", "b", "a"]
01538  *     [ 1 ].reverse               #=> [1]
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  *  call-seq:
01624  *     array.sort!                   -> array
01625  *     array.sort! {| a,b | block }  -> array 
01626  *  
01627  *  Sorts _self_. Comparisons for
01628  *  the sort will be done using the <code><=></code> operator or using
01629  *  an optional code block. The block implements a comparison between
01630  *  <i>a</i> and <i>b</i>, returning -1, 0, or +1. See also
01631  *  <code>Enumerable#sort_by</code>.
01632  *     
01633  *     a = [ "d", "a", "e", "c", "b" ]
01634  *     a.sort                    #=> ["a", "b", "c", "d", "e"]
01635  *     a.sort {|x,y| y <=> x }   #=> ["e", "d", "c", "b", "a"]
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);       /* prohibit modification during sort */
01645         rb_ensure(sort_internal, ary, sort_unlock, ary);
01646     }
01647     return ary;
01648 }
01649 
01650 /*
01651  *  call-seq:
01652  *     array.sort                   -> an_array 
01653  *     array.sort {| a,b | block }  -> an_array 
01654  *  
01655  *  Returns a new array created by sorting <i>self</i>. Comparisons for
01656  *  the sort will be done using the <code><=></code> operator or using
01657  *  an optional code block. The block implements a comparison between
01658  *  <i>a</i> and <i>b</i>, returning -1, 0, or +1. See also
01659  *  <code>Enumerable#sort_by</code>.
01660  *     
01661  *     a = [ "d", "a", "e", "c", "b" ]
01662  *     a.sort                    #=> ["a", "b", "c", "d", "e"]
01663  *     a.sort {|x,y| y <=> x }   #=> ["e", "d", "c", "b", "a"]
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  *  call-seq:
01677  *     array.collect {|item| block }  -> an_array
01678  *     array.map     {|item| block }  -> an_array
01679  *  
01680  *  Invokes <i>block</i> once for each element of <i>self</i>. Creates a 
01681  *  new array containing the values returned by the block.
01682  *  See also <code>Enumerable#collect</code>.
01683  *     
01684  *     a = [ "a", "b", "c", "d" ]
01685  *     a.collect {|x| x + "!" }   #=> ["a!", "b!", "c!", "d!"]
01686  *     a                          #=> ["a", "b", "c", "d"]
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  *  call-seq:
01709  *     array.collect! {|item| block }   ->   array
01710  *     array.map!     {|item| block }   ->   array
01711  *
01712  *  Invokes the block once for each element of _self_, replacing the
01713  *  element with the value returned by _block_.
01714  *  See also <code>Enumerable#collect</code>.
01715  *   
01716  *     a = [ "a", "b", "c", "d" ]
01717  *     a.collect! {|x| x + "!" }
01718  *     a             #=>  [ "a!", "b!", "c!", "d!" ]
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             rb_ary_push(result, (*func)(obj, FIX2LONG(argv[i])));
01748             continue;
01749         }
01750         /* check if idx is Range */
01751         switch (rb_range_beg_len(argv[i], &beg, &len, olen, 0)) {
01752           case Qfalse:
01753             break;
01754           case Qnil:
01755             continue;
01756           default:
01757             for (j=0; j<len; j++) {
01758                 rb_ary_push(result, (*func)(obj, j+beg));
01759             }
01760             continue;
01761         }
01762         rb_ary_push(result, (*func)(obj, NUM2LONG(argv[i])));
01763     }
01764     return result;
01765 }
01766 
01767 /* 
01768  *  call-seq:
01769  *     array.values_at(selector,... )  -> an_array
01770  *
01771  *  Returns an array containing the elements in
01772  *  _self_ corresponding to the given selector(s). The selectors
01773  *  may be either integer indices or ranges. 
01774  *  See also <code>Array#select</code>.
01775  * 
01776  *     a = %w{ a b c d e f }
01777  *     a.values_at(1, 3, 5)
01778  *     a.values_at(1, 3, 5, 7)
01779  *     a.values_at(-1, -3, -5, -7)
01780  *     a.values_at(1..3, 2...5)
01781  */
01782 
01783 static VALUE
01784 rb_ary_values_at(argc, argv, ary)
01785     int argc;
01786     VALUE *argv;
01787     VALUE ary;
01788 {
01789     return rb_values_at(ary, RARRAY(ary)->len, argc, argv, rb_ary_entry);
01790 }
01791 
01792 /*
01793  *  call-seq:
01794  *     array.select {|item| block } -> an_array
01795  *  
01796  *  Invokes the block passing in successive elements from <i>array</i>,
01797  *  returning an array containing those elements for which the block
01798  *  returns a true value (equivalent to <code>Enumerable#select</code>).
01799  *     
01800  *     a = %w{ a b c d e f }
01801  *     a.select {|v| v =~ /[aeiou]/}   #=> ["a", "e"]
01802  */
01803 
01804 static VALUE
01805 rb_ary_select(ary)
01806     VALUE ary;
01807 {
01808     VALUE result;
01809     long i;
01810 
01811     result = rb_ary_new2(RARRAY(ary)->len);
01812     for (i = 0; i < RARRAY(ary)->len; i++) {
01813         if (RTEST(rb_yield(RARRAY(ary)->ptr[i]))) {
01814             rb_ary_push(result, rb_ary_elt(ary, i));
01815         }
01816     }
01817     return result;
01818 }
01819 
01820 /*
01821  *  call-seq:
01822  *     array.delete(obj)            -> obj or nil 
01823  *     array.delete(obj) { block }  -> obj or nil
01824  *  
01825  *  Deletes items from <i>self</i> that are equal to <i>obj</i>. If
01826  *  the item is not found, returns <code>nil</code>. If the optional
01827  *  code block is given, returns the result of <i>block</i> if the item
01828  *  is not found.
01829  *     
01830  *     a = [ "a", "b", "b", "b", "c" ]
01831  *     a.delete("b")                   #=> "b"
01832  *     a                               #=> ["a", "c"]
01833  *     a.delete("z")                   #=> nil
01834  *     a.delete("z") { "not found" }   #=> "not found"
01835  */
01836 
01837 VALUE
01838 rb_ary_delete(ary, item)
01839     VALUE ary;
01840     VALUE item;
01841 {
01842     long i1, i2;
01843 
01844     for (i1 = i2 = 0; i1 < RARRAY(ary)->len; i1++) {
01845         VALUE e = RARRAY(ary)->ptr[i1];
01846 
01847         if (rb_equal(e, item)) continue;
01848         if (i1 != i2) {
01849             rb_ary_store(ary, i2, e);
01850         }
01851         i2++;
01852     }
01853     if (RARRAY(ary)->len == i2) {
01854         if (rb_block_given_p()) {
01855             return rb_yield(item);
01856         }
01857         return Qnil;
01858     }
01859 
01860     rb_ary_modify(ary);
01861     if (RARRAY(ary)->len > i2) {
01862         RARRAY(ary)->len = i2;
01863         if (i2 * 2 < RARRAY(ary)->aux.capa &&
01864             RARRAY(ary)->aux.capa > ARY_DEFAULT_SIZE) {
01865             REALLOC_N(RARRAY(ary)->ptr, VALUE, i2 * 2);
01866             RARRAY(ary)->aux.capa = i2 * 2;
01867         }
01868     }
01869 
01870     return item;
01871 }
01872 
01873 VALUE
01874 rb_ary_delete_at(ary, pos)
01875     VALUE ary;
01876     long pos;
01877 {
01878     long i, len = RARRAY(ary)->len;
01879     VALUE del;
01880 
01881     if (pos >= len) return Qnil;
01882     if (pos < 0) {
01883         pos += len;
01884         if (pos < 0) return Qnil;
01885     }
01886 
01887     rb_ary_modify(ary);
01888     del = RARRAY(ary)->ptr[pos];
01889     for (i = pos + 1; i < len; i++, pos++) {
01890         RARRAY(ary)->ptr[pos] = RARRAY(ary)->ptr[i];
01891     }
01892     RARRAY(ary)->len = pos;
01893 
01894     return del;
01895 }
01896 
01897 /*
01898  *  call-seq:
01899  *     array.delete_at(index)  -> obj or nil
01900  *  
01901  *  Deletes the element at the specified index, returning that element,
01902  *  or <code>nil</code> if the index is out of range. See also
01903  *  <code>Array#slice!</code>.
01904  *     
01905  *     a = %w( ant bat cat dog )
01906  *     a.delete_at(2)    #=> "cat"
01907  *     a                 #=> ["ant", "bat", "dog"]
01908  *     a.delete_at(99)   #=> nil
01909  */
01910 
01911 static VALUE
01912 rb_ary_delete_at_m(ary, pos)
01913     VALUE ary, pos;
01914 {
01915     return rb_ary_delete_at(ary, NUM2LONG(pos));
01916 }
01917 
01918 /*
01919  *  call-seq:
01920  *     array.slice!(index)         -> obj or nil
01921  *     array.slice!(start, length) -> sub_array or nil
01922  *     array.slice!(range)         -> sub_array or nil 
01923  *  
01924  *  Deletes the element(s) given by an index (optionally with a length)
01925  *  or by a range. Returns the deleted object, subarray, or
01926  *  <code>nil</code> if the index is out of range. Equivalent to:
01927  *     
01928  *     def slice!(*args)
01929  *       result = self[*args]
01930  *       self[*args] = nil
01931  *       result
01932  *     end
01933  *     
01934  *     a = [ "a", "b", "c" ]
01935  *     a.slice!(1)     #=> "b"
01936  *     a               #=> ["a", "c"]
01937  *     a.slice!(-1)    #=> "c"
01938  *     a               #=> ["a"]
01939  *     a.slice!(100)   #=> nil
01940  *     a               #=> ["a"]
01941  */
01942 
01943 static VALUE
01944 rb_ary_slice_bang(argc, argv, ary)
01945     int argc;
01946     VALUE *argv;
01947     VALUE ary;
01948 {
01949     VALUE arg1, arg2;
01950     long pos, len;
01951 
01952     if (rb_scan_args(argc, argv, "11", &arg1, &arg2) == 2) {
01953         pos = NUM2LONG(arg1);
01954         len = NUM2LONG(arg2);
01955       delete_pos_len:
01956         if (pos < 0) {
01957             pos = RARRAY(ary)->len + pos;
01958         }
01959         arg2 = rb_ary_subseq(ary, pos, len);
01960         rb_ary_splice(ary, pos, len, Qnil);     /* Qnil/rb_ary_new2(0) */
01961         return arg2;
01962     }
01963 
01964     if (!FIXNUM_P(arg1) && rb_range_beg_len(arg1, &pos, &len, RARRAY(ary)->len, 1)) {
01965         goto delete_pos_len;
01966     }
01967 
01968     return rb_ary_delete_at(ary, NUM2LONG(arg1));
01969 }
01970 
01971 /*
01972  *  call-seq:
01973  *     array.reject! {|item| block }  -> array or nil
01974  *  
01975  *  Equivalent to <code>Array#delete_if</code>, deleting elements from
01976  *  _self_ for which the block evaluates to true, but returns
01977  *  <code>nil</code> if no changes were made. Also see
01978  *  <code>Enumerable#reject</code>.
01979  */
01980 
01981 static VALUE
01982 rb_ary_reject_bang(ary)
01983     VALUE ary;
01984 {
01985     long i1, i2;
01986 
01987     rb_ary_modify(ary);
01988     for (i1 = i2 = 0; i1 < RARRAY(ary)->len; i1++) {
01989         VALUE v = RARRAY(ary)->ptr[i1];
01990         if (RTEST(rb_yield(v))) continue;
01991         if (i1 != i2) {
01992             rb_ary_store(ary, i2, v);
01993         }
01994         i2++;
01995     }
01996     if (RARRAY(ary)->len == i2) return Qnil;
01997     if (i2 < RARRAY(ary)->len)
01998         RARRAY(ary)->len = i2;
01999 
02000     return ary;
02001 }
02002 
02003 /*
02004  *  call-seq:
02005  *     array.reject {|item| block }  -> an_array
02006  *  
02007  *  Returns a new array containing the items in _self_
02008  *  for which the block is not true.
02009  */
02010 
02011 static VALUE
02012 rb_ary_reject(ary)
02013     VALUE ary;
02014 {
02015     ary = rb_ary_dup(ary);
02016     rb_ary_reject_bang(ary);
02017     return ary;
02018 }
02019 
02020 /*
02021  *  call-seq:
02022  *     array.delete_if {|item| block }  -> array
02023  *  
02024  *  Deletes every element of <i>self</i> for which <i>block</i> evaluates
02025  *  to <code>true</code>.
02026  *     
02027  *     a = [ "a", "b", "c" ]
02028  *     a.delete_if {|x| x >= "b" }   #=> ["a"]
02029  */
02030 
02031 static VALUE
02032 rb_ary_delete_if(ary)
02033     VALUE ary;
02034 {
02035     rb_ary_reject_bang(ary);
02036     return ary;
02037 }
02038 
02039 /*
02040  *  call-seq:
02041  *     array.zip(arg, ...)                   -> an_array
02042  *     array.zip(arg, ...) {| arr | block }  -> nil
02043  *  
02044  *  Converts any arguments to arrays, then merges elements of
02045  *  <i>self</i> with corresponding elements from each argument. This
02046  *  generates a sequence of <code>self.size</code> <em>n</em>-element
02047  *  arrays, where <em>n</em> is one more that the count of arguments. If
02048  *  the size of any argument is less than <code>enumObj.size</code>,
02049  *  <code>nil</code> values are supplied. If a block given, it is
02050  *  invoked for each output array, otherwise an array of arrays is
02051  *  returned.
02052  *     
02053  *     a = [ 4, 5, 6 ]
02054  *     b = [ 7, 8, 9 ]
02055  *     
02056  *     [1,2,3].zip(a, b)      #=> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
02057  *     [1,2].zip(a,b)         #=> [[1, 4, 7], [2, 5, 8]]
02058  *     a.zip([1,2],[8])       #=> [[4,1,8], [5,2,nil], [6,nil,nil]]
02059  */
02060 
02061 static VALUE
02062 rb_ary_zip(argc, argv, ary)
02063     int argc;
02064     VALUE *argv;
02065     VALUE ary;
02066 {
02067     int i, j;
02068     long len;
02069     VALUE result;
02070 
02071     for (i=0; i<argc; i++) {
02072         argv[i] = to_ary(argv[i]);
02073     }
02074     if (rb_block_given_p()) {
02075         for (i=0; i<RARRAY(ary)->len; i++) {
02076             VALUE tmp = rb_ary_new2(argc+1);
02077 
02078             rb_ary_push(tmp, rb_ary_elt(ary, i));
02079             for (j=0; j<argc; j++) {
02080                 rb_ary_push(tmp, rb_ary_elt(argv[j], i));
02081             }
02082             rb_yield(tmp);
02083         }
02084         return Qnil;
02085     }
02086     len = RARRAY(ary)->len;
02087     result = rb_ary_new2(len);
02088     for (i=0; i<len; i++) {
02089         VALUE tmp = rb_ary_new2(argc+1);
02090 
02091         rb_ary_push(tmp, rb_ary_elt(ary, i));
02092         for (j=0; j<argc; j++) {
02093             rb_ary_push(tmp, rb_ary_elt(argv[j], i));
02094         }
02095         rb_ary_push(result, tmp);
02096     }
02097     return result;
02098 }
02099 
02100 /*
02101  *  call-seq:
02102  *     array.transpose -> an_array
02103  *  
02104  *  Assumes that <i>self</i> is an array of arrays and transposes the
02105  *  rows and columns.
02106  *     
02107  *     a = [[1,2], [3,4], [5,6]]
02108  *     a.transpose   #=> [[1, 3, 5], [2, 4, 6]]
02109  */
02110 
02111 static VALUE
02112 rb_ary_transpose(ary)
02113     VALUE ary;
02114 {
02115     long elen = -1, alen, i, j;
02116     VALUE tmp, result = 0;
02117 
02118     alen = RARRAY(ary)->len;
02119     if (alen == 0) return rb_ary_dup(ary);
02120     for (i=0; i<alen; i++) {
02121         tmp = to_ary(rb_ary_elt(ary, i));
02122         if (elen < 0) {         /* first element */
02123             elen = RARRAY(tmp)->len;
02124             result = rb_ary_new2(elen);
02125             for (j=0; j<elen; j++) {
02126                 rb_ary_store(result, j, rb_ary_new2(alen));
02127             }
02128         }
02129         else if (elen != RARRAY(tmp)->len) {
02130             rb_raise(rb_eIndexError, "element size differs (%d should be %d)",
02131                      RARRAY(tmp)->len, elen);
02132         }
02133         for (j=0; j<elen; j++) {
02134             rb_ary_store(rb_ary_elt(result, j), i, rb_ary_elt(tmp, j));
02135         }
02136     }
02137     return result;
02138 }
02139 
02140 /*
02141  *  call-seq:
02142  *     array.replace(other_array)  -> array
02143  *  
02144  *  Replaces the contents of <i>self</i> with the contents of
02145  *  <i>other_array</i>, truncating or expanding if necessary.
02146  *     
02147  *     a = [ "a", "b", "c", "d", "e" ]
02148  *     a.replace([ "x", "y", "z" ])   #=> ["x", "y", "z"]
02149  *     a                              #=> ["x", "y", "z"]
02150  */
02151 
02152 static VALUE
02153 rb_ary_replace(copy, orig)
02154     VALUE copy, orig;
02155 {
02156     VALUE shared;
02157 
02158     rb_ary_modify(copy);
02159     orig = to_ary(orig);
02160     if (copy == orig) return copy;
02161     shared = ary_make_shared(orig);
02162     if (RARRAY(copy)->ptr && !FL_TEST(copy, ELTS_SHARED))
02163         free(RARRAY(copy)->ptr);
02164     RARRAY(copy)->ptr = RARRAY(orig)->ptr;
02165     RARRAY(copy)->len = RARRAY(orig)->len;
02166     RARRAY(copy)->aux.shared = shared;
02167     FL_SET(copy, ELTS_SHARED);
02168 
02169     return copy;
02170 }
02171 
02172 /* 
02173  *  call-seq:
02174  *     array.clear    ->  array
02175  *
02176  *  Removes all elements from _self_.
02177  *
02178  *     a = [ "a", "b", "c", "d", "e" ]
02179  *     a.clear    #=> [ ]
02180  */
02181 
02182 VALUE
02183 rb_ary_clear(ary)
02184     VALUE ary;
02185 {
02186     rb_ary_modify(ary);
02187     RARRAY(ary)->len = 0;
02188     if (ARY_DEFAULT_SIZE * 2 < RARRAY(ary)->aux.capa) {
02189         REALLOC_N(RARRAY(ary)->ptr, VALUE, ARY_DEFAULT_SIZE * 2);
02190         RARRAY(ary)->aux.capa = ARY_DEFAULT_SIZE * 2;
02191     }
02192     return ary;
02193 }
02194 
02195 /*
02196  *  call-seq:
02197  *     array.fill(obj)                                -> array
02198  *     array.fill(obj, start [, length])              -> array
02199  *     array.fill(obj, range )                        -> array
02200  *     array.fill {|index| block }                    -> array
02201  *     array.fill(start [, length] ) {|index| block } -> array
02202  *     array.fill(range) {|index| block }             -> array
02203  *  
02204  *  The first three forms set the selected elements of <i>self</i> (which
02205  *  may be the entire array) to <i>obj</i>. A <i>start</i> of
02206  *  <code>nil</code> is equivalent to zero. A <i>length</i> of
02207  *  <code>nil</code> is equivalent to <i>self.length</i>. The last three
02208  *  forms fill the array with the value of the block. The block is
02209  *  passed the absolute index of each element to be filled.
02210  *     
02211  *     a = [ "a", "b", "c", "d" ]
02212  *     a.fill("x")              #=> ["x", "x", "x", "x"]
02213  *     a.fill("z", 2, 2)        #=> ["x", "x", "z", "z"]
02214  *     a.fill("y", 0..1)        #=> ["y", "y", "z", "z"]
02215  *     a.fill {|i| i*i}         #=> [0, 1, 4, 9]
02216  *     a.fill(-2) {|i| i*i*i}   #=> [0, 1, 8, 27]
02217  */
02218 
02219 static VALUE
02220 rb_ary_fill(argc, argv, ary)
02221     int argc;
02222     VALUE *argv;
02223     VALUE ary;
02224 {
02225     VALUE item, arg1, arg2;
02226     long beg, end, len;
02227     VALUE *p, *pend;
02228     int block_p = Qfalse;
02229 
02230     if (rb_block_given_p()) {
02231         block_p = Qtrue;
02232         rb_scan_args(argc, argv, "02", &arg1, &arg2);
02233         argc += 1;              /* hackish */
02234     }
02235     else {
02236         rb_scan_args(argc, argv, "12", &item, &arg1, &arg2);
02237     }
02238     switch (argc) {
02239       case 1:
02240         beg = 0;
02241         len = RARRAY(ary)->len;
02242         break;
02243       case 2:
02244         if (rb_range_beg_len(arg1, &beg, &len, RARRAY(ary)->len, 1)) {
02245             break;
02246         }
02247         /* fall through */
02248       case 3:
02249         beg = NIL_P(arg1) ? 0 : NUM2LONG(arg1);
02250         if (beg < 0) {
02251             beg = RARRAY(ary)->len + beg;
02252             if (beg < 0) beg = 0;
02253         }
02254         len = NIL_P(arg2) ? RARRAY(ary)->len - beg : NUM2LONG(arg2);
02255         break;
02256     }
02257     rb_ary_modify(ary);
02258     end = beg + len;
02259     if (end > RARRAY(ary)->len) {
02260         if (end >= RARRAY(ary)->aux.capa) {
02261             REALLOC_N(RARRAY(ary)->ptr, VALUE, end);
02262             RARRAY(ary)->aux.capa = end;
02263         }
02264         rb_mem_clear(RARRAY(ary)->ptr + RARRAY(ary)->len, end - RARRAY(ary)->len);
02265         RARRAY(ary)->len = end;
02266     }
02267 
02268     if (block_p) {
02269         VALUE v;
02270         long i;
02271 
02272         for (i=beg; i<end; i++) {
02273             v = rb_yield(LONG2NUM(i));
02274             if (i>=RARRAY(ary)->len) break;
02275             RARRAY(ary)->ptr[i] = v;
02276         }
02277     }
02278     else {
02279         p = RARRAY(ary)->ptr + beg;
02280         pend = p + len;
02281         while (p < pend) {
02282             *p++ = item;
02283         }
02284     }
02285     return ary;
02286 }
02287 
02288 /* 
02289  *  call-seq:
02290  *     array + other_array   -> an_array
02291  *
02292  *  Concatenation---Returns a new array built by concatenating the
02293  *  two arrays together to produce a third array.
02294  * 
02295  *     [ 1, 2, 3 ] + [ 4, 5 ]    #=> [ 1, 2, 3, 4, 5 ]
02296  */
02297 
02298 VALUE
02299 rb_ary_plus(x, y)
02300     VALUE x, y;
02301 {
02302     VALUE z;
02303     long len;
02304 
02305     y = to_ary(y);
02306     len = RARRAY(x)->len + RARRAY(y)->len;
02307     z = rb_ary_new2(len);
02308     MEMCPY(RARRAY(z)->ptr, RARRAY(x)->ptr, VALUE, RARRAY(x)->len);
02309     MEMCPY(RARRAY(z)->ptr + RARRAY(x)->len, RARRAY(y)->ptr, VALUE, RARRAY(y)->len);
02310     RARRAY(z)->len = len;
02311     return z;
02312 }
02313 
02314 /* 
02315  *  call-seq:
02316  *     array.concat(other_array)   ->  array
02317  *
02318  *  Appends the elements in other_array to _self_.
02319  *  
02320  *     [ "a", "b" ].concat( ["c", "d"] ) #=> [ "a", "b", "c", "d" ]
02321  */
02322 
02323 
02324 VALUE
02325 rb_ary_concat(x, y)
02326     VALUE x, y;
02327 {
02328     y = to_ary(y);
02329     if (RARRAY(y)->len > 0) {
02330         rb_ary_splice(x, RARRAY(x)->len, 0, y);
02331     }
02332     return x;
02333 }
02334 
02335 
02336 /* 
02337  *  call-seq:
02338  *     array * int     ->    an_array
02339  *     array * str     ->    a_string
02340  *
02341  *  Repetition---With a String argument, equivalent to
02342  *  self.join(str). Otherwise, returns a new array
02343  *  built by concatenating the _int_ copies of _self_.
02344  *
02345  *
02346  *     [ 1, 2, 3 ] * 3    #=> [ 1, 2, 3, 1, 2, 3, 1, 2, 3 ]
02347  *     [ 1, 2, 3 ] * ","  #=> "1,2,3"
02348  *
02349  */
02350 
02351 static VALUE
02352 rb_ary_times(ary, times)
02353     VALUE ary, times;
02354 {
02355     VALUE ary2, tmp;
02356     long i, len;
02357 
02358     tmp = rb_check_string_type(times);
02359     if (!NIL_P(tmp)) {
02360         return rb_ary_join(ary, tmp);
02361     }
02362 
02363     len = NUM2LONG(times);
02364     if (len == 0) return ary_new(rb_obj_class(ary), 0);
02365     if (len < 0) {
02366         rb_raise(rb_eArgError, "negative argument");
02367     }
02368     if (LONG_MAX/len < RARRAY(ary)->len) {
02369         rb_raise(rb_eArgError, "argument too big");
02370     }
02371     len *= RARRAY(ary)->len;
02372 
02373     ary2 = ary_new(rb_obj_class(ary), len);
02374     RARRAY(ary2)->len = len;
02375 
02376     for (i=0; i<len; i+=RARRAY(ary)->len) {
02377         MEMCPY(RARRAY(ary2)->ptr+i, RARRAY(ary)->ptr, VALUE, RARRAY(ary)->len);
02378     }
02379     OBJ_INFECT(ary2, ary);
02380 
02381     return ary2;
02382 }
02383 
02384 /* 
02385  *  call-seq:
02386  *     array.assoc(obj)   ->  an_array  or  nil
02387  *
02388  *  Searches through an array whose elements are also arrays
02389  *  comparing _obj_ with the first element of each contained array
02390  *  using obj.==.
02391  *  Returns the first contained array that matches (that
02392  *  is, the first associated array),
02393  *  or +nil+ if no match is found.
02394  *  See also <code>Array#rassoc</code>.
02395  *
02396  *     s1 = [ "colors", "red", "blue", "green" ]
02397  *     s2 = [ "letters", "a", "b", "c" ]
02398  *     s3 = "foo"
02399  *     a  = [ s1, s2, s3 ]
02400  *     a.assoc("letters")  #=> [ "letters", "a", "b", "c" ]
02401  *     a.assoc("foo")      #=> nil
02402  */
02403 
02404 VALUE
02405 rb_ary_assoc(ary, key)
02406     VALUE ary, key;
02407 {
02408     long i;
02409     VALUE v;
02410 
02411     for (i = 0; i < RARRAY(ary)->len; ++i) {
02412         v = RARRAY(ary)->ptr[i];
02413         if (TYPE(v) == T_ARRAY &&
02414             RARRAY(v)->len > 0 &&
02415             rb_equal(RARRAY(v)->ptr[0], key))
02416             return v;
02417     }
02418     return Qnil;
02419 }
02420 
02421 /*
02422  *  call-seq:
02423  *     array.rassoc(key) -> an_array or nil
02424  *  
02425  *  Searches through the array whose elements are also arrays. Compares
02426  *  <em>key</em> with the second element of each contained array using
02427  *  <code>==</code>. Returns the first contained array that matches. See
02428  *  also <code>Array#assoc</code>.
02429  *     
02430  *     a = [ [ 1, "one"], [2, "two"], [3, "three"], ["ii", "two"] ]
02431  *     a.rassoc("two")    #=> [2, "two"]
02432  *     a.rassoc("four")   #=> nil
02433  */
02434 
02435 VALUE
02436 rb_ary_rassoc(ary, value)
02437     VALUE ary, value;
02438 {
02439     long i;
02440     VALUE v;
02441 
02442     for (i = 0; i < RARRAY(ary)->len; ++i) {
02443         v = RARRAY(ary)->ptr[i];
02444         if (TYPE(v) == T_ARRAY &&
02445             RARRAY(v)->len > 1 &&
02446             rb_equal(RARRAY(v)->ptr[1], value))
02447             return v;
02448     }
02449     return Qnil;
02450 }
02451 
02452 /* 
02453  *  call-seq:
02454  *     array == other_array   ->   bool
02455  *
02456  *  Equality---Two arrays are equal if they contain the same number
02457  *  of elements and if each element is equal to (according to
02458  *  Object.==) the corresponding element in the other array.
02459  *
02460  *     [ "a", "c" ]    == [ "a", "c", 7 ]     #=> false
02461  *     [ "a", "c", 7 ] == [ "a", "c", 7 ]     #=> true
02462  *     [ "a", "c", 7 ] == [ "a", "d", "f" ]   #=> false
02463  *
02464  */
02465 
02466 static VALUE
02467 rb_ary_equal(ary1, ary2)
02468     VALUE ary1, ary2;
02469 {
02470     long i;
02471 
02472     if (ary1 == ary2) return Qtrue;
02473     if (TYPE(ary2) != T_ARRAY) {
02474         if (!rb_respond_to(ary2, rb_intern("to_ary"))) {
02475             return Qfalse;
02476         }
02477         return rb_equal(ary2, ary1);
02478     }
02479     if (RARRAY(ary1)->len != RARRAY(ary2)->len) return Qfalse;
02480     for (i=0; i<RARRAY(ary1)->len; i++) {
02481         if (!rb_equal(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i)))
02482             return Qfalse;
02483     }
02484     return Qtrue;
02485 }
02486 
02487 /*
02488  *  call-seq:
02489  *     array.eql?(other)  -> true or false
02490  *
02491  *  Returns <code>true</code> if _array_ and _other_ are the same object,
02492  *  or are both arrays with the same content.
02493  */
02494 
02495 static VALUE
02496 rb_ary_eql(ary1, ary2)
02497     VALUE ary1, ary2;
02498 {
02499     long i;
02500 
02501     if (ary1 == ary2) return Qtrue;
02502     if (TYPE(ary2) != T_ARRAY) return Qfalse;
02503     if (RARRAY(ary1)->len != RARRAY(ary2)->len) return Qfalse;
02504     for (i=0; i<RARRAY(ary1)->len; i++) {
02505         if (!rb_eql(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i)))
02506             return Qfalse;
02507     }
02508     return Qtrue;
02509 }
02510 
02511 /*
02512  *  call-seq:
02513  *     array.hash   -> fixnum
02514  *
02515  *  Compute a hash-code for this array. Two arrays with the same content
02516  *  will have the same hash code (and will compare using <code>eql?</code>).
02517  */
02518 
02519 static VALUE
02520 rb_ary_hash(ary)
02521     VALUE ary;
02522 {
02523     long i, h;
02524     VALUE n;
02525 
02526     h = RARRAY(ary)->len;
02527     for (i=0; i<RARRAY(ary)->len; i++) {
02528         h = (h << 1) | (h<0 ? 1 : 0);
02529         n = rb_hash(RARRAY(ary)->ptr[i]);
02530         h ^= NUM2LONG(n);
02531     }
02532     return LONG2FIX(h);
02533 }
02534 
02535 /*
02536  *  call-seq:
02537  *     array.include?(obj)   -> true or false
02538  *  
02539  *  Returns <code>true</code> if the given object is present in
02540  *  <i>self</i> (that is, if any object <code>==</code> <i>anObject</i>),
02541  *  <code>false</code> otherwise.
02542  *     
02543  *     a = [ "a", "b", "c" ]
02544  *     a.include?("b")   #=> true
02545  *     a.include?("z")   #=> false
02546  */
02547 
02548 VALUE
02549 rb_ary_includes(ary, item)
02550     VALUE ary;
02551     VALUE item;
02552 {
02553     long i;
02554     
02555     for (i=0; i<RARRAY(ary)->len; i++) {
02556         if (rb_equal(RARRAY(ary)->ptr[i], item)) {
02557             return Qtrue;
02558         }
02559     }
02560     return Qfalse;
02561 }
02562 
02563 
02564 /* 
02565  *  call-seq:
02566  *     array <=> other_array   ->  -1, 0, +1
02567  *
02568  *  Comparison---Returns an integer (-1, 0,
02569  *  or +1) if this array is less than, equal to, or greater than
02570  *  other_array.  Each object in each array is compared
02571  *  (using <=>). If any value isn't
02572  *  equal, then that inequality is the return value. If all the
02573  *  values found are equal, then the return is based on a
02574  *  comparison of the array lengths.  Thus, two arrays are
02575  *  ``equal'' according to <code>Array#<=></code> if and only if they have
02576  *  the same length and the value of each element is equal to the
02577  *  value of the corresponding element in the other array.
02578  *  
02579  *     [ "a", "a", "c" ]    <=> [ "a", "b", "c" ]   #=> -1
02580  *     [ 1, 2, 3, 4, 5, 6 ] <=> [ 1, 2 ]            #=> +1
02581  *
02582  */
02583 
02584 VALUE
02585 rb_ary_cmp(ary1, ary2)
02586     VALUE ary1, ary2;
02587 {
02588     long i, len;
02589 
02590     ary2 = to_ary(ary2);
02591     len = RARRAY(ary1)->len;
02592     if (len > RARRAY(ary2)->len) {
02593         len = RARRAY(ary2)->len;
02594     }
02595     for (i=0; i<len; i++) {
02596         VALUE v = rb_funcall(rb_ary_elt(ary1, i), id_cmp, 1, rb_ary_elt(ary2, i));
02597         if (v != INT2FIX(0)) {
02598             return v;
02599         }
02600     }
02601     len = RARRAY(ary1)->len - RARRAY(ary2)->len;
02602     if (len == 0) return INT2FIX(0);
02603     if (len > 0) return INT2FIX(1);
02604     return INT2FIX(-1);
02605 }
02606 
02607 static VALUE
02608 ary_make_hash(ary1, ary2)
02609     VALUE ary1, ary2;
02610 {
02611     VALUE hash = rb_hash_new();
02612     long i;
02613 
02614     for (i=0; i<RARRAY(ary1)->len; i++) {
02615         rb_hash_aset(hash, RARRAY(ary1)->ptr[i], Qtrue);
02616     }
02617     if (ary2) {
02618         for (i=0; i<RARRAY(ary2)->len; i++) {
02619             rb_hash_aset(hash, RARRAY(ary2)->ptr[i], Qtrue);
02620         }
02621     }
02622     return hash;
02623 }
02624 
02625 /* 
02626  *  call-seq:
02627  *     array - other_array    -> an_array
02628  *
02629  *  Array Difference---Returns a new array that is a copy of
02630  *  the original array, removing any items that also appear in
02631  *  other_array. (If you need set-like behavior, see the
02632  *  library class Set.)
02633  *
02634  *     [ 1, 1, 2, 2, 3, 3, 4, 5 ] - [ 1, 2, 4 ]  #=>  [ 3, 3, 5 ]
02635  */
02636 
02637 static VALUE
02638 rb_ary_diff(ary1, ary2)
02639     VALUE ary1, ary2;
02640 {
02641     VALUE ary3;
02642     volatile VALUE hash;
02643     long i;
02644 
02645     hash = ary_make_hash(to_ary(ary2), 0);
02646     ary3 = rb_ary_new();
02647 
02648     for (i=0; i<RARRAY(ary1)->len; i++) {
02649         if (st_lookup(RHASH(hash)->tbl, RARRAY(ary1)->ptr[i], 0)) continue;
02650         rb_ary_push(ary3, rb_ary_elt(ary1, i));
02651     }
02652     return ary3;
02653 }
02654 
02655 /* 
02656  *  call-seq:
02657  *     array & other_array
02658  *
02659  *  Set Intersection---Returns a new array
02660  *  containing elements common to the two arrays, with no duplicates.
02661  *
02662  *     [ 1, 1, 3, 5 ] & [ 1, 2, 3 ]   #=> [ 1, 3 ]
02663  */
02664 
02665 
02666 static VALUE
02667 rb_ary_and(ary1, ary2)
02668     VALUE ary1, ary2;
02669 {
02670     VALUE hash, ary3, v, vv;
02671     long i;
02672 
02673     ary2 = to_ary(ary2);
02674     ary3 = rb_ary_new2(RARRAY(ary1)->len < RARRAY(ary2)->len ?
02675             RARRAY(ary1)->len : RARRAY(ary2)->len);
02676     hash = ary_make_hash(ary2, 0);
02677 
02678     for (i=0; i<RARRAY(ary1)->len; i++) {
02679         v = vv = rb_ary_elt(ary1, i);
02680         if (st_delete(RHASH(hash)->tbl, (st_data_t*)&vv, 0)) {
02681             rb_ary_push(ary3, v);
02682         }
02683     }
02684 
02685     return ary3;
02686 }
02687 
02688 /* 
02689  *  call-seq:
02690  *     array | other_array     ->  an_array
02691  *
02692  *  Set Union---Returns a new array by joining this array with
02693  *  other_array, removing duplicates.
02694  *
02695  *     [ "a", "b", "c" ] | [ "c", "d", "a" ]
02696  *            #=> [ "a", "b", "c", "d" ]
02697  */
02698 
02699 static VALUE
02700 rb_ary_or(ary1, ary2)
02701     VALUE ary1, ary2;
02702 {
02703     VALUE hash, ary3;
02704     VALUE v, vv;
02705     long i;
02706 
02707     ary2 = to_ary(ary2);
02708     ary3 = rb_ary_new2(RARRAY(ary1)->len+RARRAY(ary2)->len);
02709     hash = ary_make_hash(ary1, ary2);
02710 
02711     for (i=0; i<RARRAY(ary1)->len; i++) {
02712         v = vv = rb_ary_elt(ary1, i);
02713         if (st_delete(RHASH(hash)->tbl, (st_data_t*)&vv, 0)) {
02714             rb_ary_push(ary3, v);
02715         }
02716     }
02717     for (i=0; i<RARRAY(ary2)->len; i++) {
02718         v = vv = rb_ary_elt(ary2, i);
02719         if (st_delete(RHASH(hash)->tbl, (st_data_t*)&vv, 0)) {
02720             rb_ary_push(ary3, v);
02721         }
02722     }
02723     return ary3;
02724 }
02725 
02726 /*
02727  *  call-seq:
02728  *     array.uniq! -> array or nil
02729  *  
02730  *  Removes duplicate elements from _self_.
02731  *  Returns <code>nil</code> if no changes are made (that is, no
02732  *  duplicates are found).
02733  *     
02734  *     a = [ "a", "a", "b", "b", "c" ]
02735  *     a.uniq!   #=> ["a", "b", "c"]
02736  *     b = [ "a", "b", "c" ]
02737  *     b.uniq!   #=> nil
02738  */
02739 
02740 static VALUE
02741 rb_ary_uniq_bang(ary)
02742     VALUE ary;
02743 {
02744     VALUE hash, v, vv;
02745     long i, j;
02746 
02747     hash = ary_make_hash(ary, 0);
02748 
02749     if (RARRAY(ary)->len == RHASH(hash)->tbl->num_entries) {
02750         return Qnil;
02751     }
02752     for (i=j=0; i<RARRAY(ary)->len; i++) {
02753         v = vv = rb_ary_elt(ary, i);
02754         if (st_delete(RHASH(hash)->tbl, (st_data_t*)&vv, 0)) {
02755             rb_ary_store(ary, j++, v);
02756         }
02757     }
02758     RARRAY(ary)->len = j;
02759 
02760     return ary;
02761 }
02762 
02763 /*
02764  *  call-seq:
02765  *     array.uniq   -> an_array
02766  *  
02767  *  Returns a new array by removing duplicate values in <i>self</i>.
02768  *     
02769  *     a = [ "a", "a", "b", "b", "c" ]
02770  *     a.uniq   #=> ["a", "b", "c"]
02771  */
02772 
02773 static VALUE
02774 rb_ary_uniq(ary)
02775     VALUE ary;
02776 {
02777     ary = rb_ary_dup(ary);
02778     rb_ary_uniq_bang(ary);
02779     return ary;
02780 }
02781 
02782 /* 
02783  *  call-seq:
02784  *     array.compact!    ->   array  or  nil
02785  *
02786  *  Removes +nil+ elements from array.
02787  *  Returns +nil+ if no changes were made.
02788  *
02789  *     [ "a", nil, "b", nil, "c" ].compact! #=> [ "a", "b", "c" ]
02790  *     [ "a", "b", "c" ].compact!           #=> nil
02791  */
02792 
02793 static VALUE
02794 rb_ary_compact_bang(ary)
02795     VALUE ary;
02796 {
02797     VALUE *p, *t, *end;
02798 
02799     rb_ary_modify(ary);
02800     p = t = RARRAY(ary)->ptr;
02801     end = p + RARRAY(ary)->len;
02802     
02803     while (t < end) {
02804         if (NIL_P(*t)) t++;
02805         else *p++ = *t++;
02806     }
02807     if (RARRAY(ary)->len == (p - RARRAY(ary)->ptr)) {
02808         return Qnil;
02809     }
02810     RARRAY(ary)->len = RARRAY(ary)->aux.capa = (p - RARRAY(ary)->ptr);
02811     REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->len);
02812 
02813     return ary;
02814 }
02815 
02816 /*
02817  *  call-seq:
02818  *     array.compact     ->  an_array
02819  *
02820  *  Returns a copy of _self_ with all +nil+ elements removed.
02821  *
02822  *     [ "a", nil, "b", nil, "c", nil ].compact
02823  *                       #=> [ "a", "b", "c" ]
02824  */
02825 
02826 static VALUE
02827 rb_ary_compact(ary)
02828     VALUE ary;
02829 {
02830     ary = rb_ary_dup(ary);
02831     rb_ary_compact_bang(ary);
02832     return ary;
02833 }
02834 
02835 /*
02836  *  call-seq:
02837  *     array.nitems -> int
02838  *  
02839  *  Returns the number of non-<code>nil</code> elements in _self_.
02840  *  May be zero.
02841  *     
02842  *     [ 1, nil, 3, nil, 5 ].nitems   #=> 3
02843  */
02844 
02845 static VALUE
02846 rb_ary_nitems(ary)
02847     VALUE ary;
02848 {
02849     long n = 0;
02850     VALUE *p, *pend;
02851 
02852     p = RARRAY(ary)->ptr;
02853     pend = p + RARRAY(ary)->len;
02854 
02855     while (p < pend) {
02856         if (!NIL_P(*p)) n++;
02857         p++;
02858     }
02859     return LONG2NUM(n);
02860 }
02861 
02862 static long
02863 flatten(ary, idx, ary2, memo)
02864     VALUE ary;
02865     long idx;
02866     VALUE ary2, memo;
02867 {
02868     VALUE id;
02869     long i = idx;
02870     long n, lim = idx + RARRAY(ary2)->len;
02871 
02872     id = rb_obj_id(ary2);
02873     if (rb_ary_includes(memo, id)) {
02874         rb_raise(rb_eArgError, "tried to flatten recursive array");
02875     }
02876     rb_ary_push(memo, id);
02877     rb_ary_splice(ary, idx, 1, ary2);
02878     while (i < lim) {
02879         VALUE tmp;
02880 
02881         tmp = rb_check_array_type(rb_ary_elt(ary, i));
02882         if (!NIL_P(tmp)) {
02883             n = flatten(ary, i, tmp, memo);
02884             i += n; lim += n;
02885         }
02886         i++;
02887     }
02888     rb_ary_pop(memo);
02889 
02890     return lim - idx - 1;       /* returns number of increased items */
02891 }
02892 
02893 /*
02894  *  call-seq:
02895  *     array.flatten! -> array or nil
02896  *  
02897  *  Flattens _self_ in place.
02898  *  Returns <code>nil</code> if no modifications were made (i.e.,
02899  *  <i>array</i> contains no subarrays.)
02900  *     
02901  *     a = [ 1, 2, [3, [4, 5] ] ]
02902  *     a.flatten!   #=> [1, 2, 3, 4, 5]
02903  *     a.flatten!   #=> nil
02904  *     a            #=> [1, 2, 3, 4, 5]
02905  */
02906 
02907 static VALUE
02908 rb_ary_flatten_bang(ary)
02909     VALUE ary;
02910 {
02911     long i = 0;
02912     int mod = 0;
02913     VALUE memo = Qnil;
02914 
02915     while (i<RARRAY(ary)->len) {
02916         VALUE ary2 = RARRAY(ary)->ptr[i];
02917         VALUE tmp;
02918 
02919         tmp = rb_check_array_type(ary2);
02920         if (!NIL_P(tmp)) {
02921             if (NIL_P(memo)) {
02922                 memo = rb_ary_new();
02923             }
02924             i += flatten(ary, i, tmp, memo);
02925             mod = 1;
02926         }
02927         i++;
02928     }
02929     if (mod == 0) return Qnil;
02930     return ary;
02931 }
02932 
02933 /*
02934  *  call-seq:
02935  *     array.flatten -> an_array
02936  *  
02937  *  Returns a new array that is a one-dimensional flattening of this
02938  *  array (recursively). That is, for every element that is an array,
02939  *  extract its elements into the new array.
02940  *     
02941  *     s = [ 1, 2, 3 ]           #=> [1, 2, 3]
02942  *     t = [ 4, 5, 6, [7, 8] ]   #=> [4, 5, 6, [7, 8]]
02943  *     a = [ s, t, 9, 10 ]       #=> [[1, 2, 3], [4, 5, 6, [7, 8]], 9, 10]
02944  *     a.flatten                 #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10
02945  */
02946 
02947 static VALUE
02948 rb_ary_flatten(ary)
02949     VALUE ary;
02950 {
02951     ary = rb_ary_dup(ary);
02952     rb_ary_flatten_bang(ary);
02953     return ary;
02954 }
02955 
02956 
02957 /* Arrays are ordered, integer-indexed collections of any object. 
02958  * Array indexing starts at 0, as in C or Java.  A negative index is 
02959  * assumed to be relative to the end of the array---that is, an index of -1 
02960  * indicates the last element of the array, -2 is the next to last 
02961  * element in the array, and so on. 
02962  */
02963 
02964 void
02965 Init_Array()
02966 {
02967     rb_cArray  = rb_define_class("Array", rb_cObject);
02968     rb_include_module(rb_cArray, rb_mEnumerable);
02969 
02970     rb_define_alloc_func(rb_cArray, ary_alloc);
02971     rb_define_singleton_method(rb_cArray, "[]", rb_ary_s_create, -1);
02972     rb_define_method(rb_cArray, "initialize", rb_ary_initialize, -1);
02973     rb_define_method(rb_cArray, "initialize_copy", rb_ary_replace, 1);
02974 
02975     rb_define_method(rb_cArray, "to_s", rb_ary_to_s, 0);
02976     rb_define_method(rb_cArray, "inspect", rb_ary_inspect, 0);
02977     rb_define_method(rb_cArray, "to_a", rb_ary_to_a, 0);
02978     rb_define_method(rb_cArray, "to_ary", rb_ary_to_ary_m, 0);
02979     rb_define_method(rb_cArray, "frozen?",  rb_ary_frozen_p, 0);
02980 
02981     rb_define_method(rb_cArray, "==", rb_ary_equal, 1);
02982     rb_define_method(rb_cArray, "eql?", rb_ary_eql, 1);
02983     rb_define_method(rb_cArray, "hash", rb_ary_hash, 0);
02984 
02985     rb_define_method(rb_cArray, "[]", rb_ary_aref, -1);
02986     rb_define_method(rb_cArray, "[]=", rb_ary_aset, -1);
02987     rb_define_method(rb_cArray, "at", rb_ary_at, 1);
02988     rb_define_method(rb_cArray, "fetch", rb_ary_fetch, -1);
02989     rb_define_method(rb_cArray, "first", rb_ary_first, -1);
02990     rb_define_method(rb_cArray, "last", rb_ary_last, -1);
02991     rb_define_method(rb_cArray, "concat", rb_ary_concat, 1);
02992     rb_define_method(rb_cArray, "<<", rb_ary_push, 1);
02993     rb_define_method(rb_cArray, "push", rb_ary_push_m, -1);
02994     rb_define_method(rb_cArray, "pop", rb_ary_pop, 0);
02995     rb_define_method(rb_cArray, "shift", rb_ary_shift, 0);
02996     rb_define_method(rb_cArray, "unshift", rb_ary_unshift_m, -1);
02997     rb_define_method(rb_cArray, "insert", rb_ary_insert, -1);
02998     rb_define_method(rb_cArray, "each", rb_ary_each, 0);
02999     rb_define_method(rb_cArray, "each_index", rb_ary_each_index, 0);
03000     rb_define_method(rb_cArray, "reverse_each", rb_ary_reverse_each, 0);
03001     rb_define_method(rb_cArray, "length", rb_ary_length, 0);
03002     rb_define_alias(rb_cArray,  "size", "length");
03003     rb_define_method(rb_cArray, "empty?", rb_ary_empty_p, 0);
03004     rb_define_method(rb_cArray, "index", rb_ary_index, 1);
03005     rb_define_method(rb_cArray, "rindex", rb_ary_rindex, 1);
03006     rb_define_method(rb_cArray, "indexes", rb_ary_indexes, -1);
03007     rb_define_method(rb_cArray, "indices", rb_ary_indexes, -1);
03008     rb_define_method(rb_cArray, "join", rb_ary_join_m, -1);
03009     rb_define_method(rb_cArray, "reverse", rb_ary_reverse_m, 0);
03010     rb_define_method(rb_cArray, "reverse!", rb_ary_reverse_bang, 0);
03011     rb_define_method(rb_cArray, "sort", rb_ary_sort, 0);
03012     rb_define_method(rb_cArray, "sort!", rb_ary_sort_bang, 0);
03013     rb_define_method(rb_cArray, "collect", rb_ary_collect, 0);
03014     rb_define_method(rb_cArray, "collect!", rb_ary_collect_bang, 0);
03015     rb_define_method(rb_cArray, "map", rb_ary_collect, 0);
03016     rb_define_method(rb_cArray, "map!", rb_ary_collect_bang, 0);
03017     rb_define_method(rb_cArray, "select", rb_ary_select, 0);
03018     rb_define_method(rb_cArray, "values_at", rb_ary_values_at, -1);
03019     rb_define_method(rb_cArray, "delete", rb_ary_delete, 1);
03020     rb_define_method(rb_cArray, "delete_at", rb_ary_delete_at_m, 1);
03021     rb_define_method(rb_cArray, "delete_if", rb_ary_delete_if, 0);
03022     rb_define_method(rb_cArray, "reject", rb_ary_reject, 0);
03023     rb_define_method(rb_cArray, "reject!", rb_ary_reject_bang, 0);
03024     rb_define_method(rb_cArray, "zip", rb_ary_zip, -1);
03025     rb_define_method(rb_cArray, "transpose", rb_ary_transpose, 0);
03026     rb_define_method(rb_cArray, "replace", rb_ary_replace, 1);
03027     rb_define_method(rb_cArray, "clear", rb_ary_clear, 0);
03028     rb_define_method(rb_cArray, "fill", rb_ary_fill, -1);
03029     rb_define_method(rb_cArray, "include?", rb_ary_includes, 1);
03030     rb_define_method(rb_cArray, "<=>", rb_ary_cmp, 1);
03031 
03032     rb_define_method(rb_cArray, "slice", rb_ary_aref, -1);
03033     rb_define_method(rb_cArray, "slice!", rb_ary_slice_bang, -1);
03034 
03035     rb_define_method(rb_cArray, "assoc", rb_ary_assoc, 1);
03036     rb_define_method(rb_cArray, "rassoc", rb_ary_rassoc, 1);
03037 
03038     rb_define_method(rb_cArray, "+", rb_ary_plus, 1);
03039     rb_define_method(rb_cArray, "*", rb_ary_times, 1);
03040 
03041     rb_define_method(rb_cArray, "-", rb_ary_diff, 1);
03042     rb_define_method(rb_cArray, "&", rb_ary_and, 1);
03043     rb_define_method(rb_cArray, "|", rb_ary_or, 1);
03044 
03045     rb_define_method(rb_cArray, "uniq", rb_ary_uniq, 0);
03046     rb_define_method(rb_cArray, "uniq!", rb_ary_uniq_bang, 0);
03047     rb_define_method(rb_cArray, "compact", rb_ary_compact, 0);
03048     rb_define_method(rb_cArray, "compact!", rb_ary_compact_bang, 0);
03049     rb_define_method(rb_cArray, "flatten", rb_ary_flatten, 0);
03050     rb_define_method(rb_cArray, "flatten!", rb_ary_flatten_bang, 0);
03051     rb_define_method(rb_cArray, "nitems", rb_ary_nitems, 0);
03052 
03053     id_cmp = rb_intern("<=>");
03054     inspect_key = rb_intern("__inspect_key__");
03055 }
03056 

Generated on Wed Jan 18 23:31:57 2006 for Ruby by doxygen 1.3.5