[ruby/strscan] jruby: Check if len++ walked off the end
[ruby.git] / array.c
diff --git a/array.c b/array.c
index c79bae6..59fc342 100644 (file)
--- a/array.c
+++ b/array.c
@@ -27,6 +27,7 @@
 #include "probes.h"
 #include "ruby/encoding.h"
 #include "ruby/st.h"
+#include "ruby/thread.h"
 #include "ruby/util.h"
 #include "vm_core.h"
 #include "builtin.h"
@@ -42,12 +43,12 @@ VALUE rb_cArray_empty_frozen;
 
 /* Flags of RArray
  *
+ * 0:   RARRAY_SHARED_FLAG (equal to ELTS_SHARED)
+ *          The array is shared. The buffer this array points to is owned by
+ *          another array (the shared root).
  * 1:   RARRAY_EMBED_FLAG
  *          The array is embedded (its contents follow the header, rather than
  *          being on a separately allocated buffer).
- * 2:   RARRAY_SHARED_FLAG (equal to ELTS_SHARED)
- *          The array is shared. The buffer this array points to is owned by
- *          another array (the shared root).
  * 3-9: RARRAY_EMBED_LEN
  *          The length of the array when RARRAY_EMBED_FLAG is set.
  * 12:  RARRAY_SHARED_ROOT_FLAG
@@ -263,12 +264,6 @@ ary_verify_(VALUE ary, const char *file, int line)
 
     return ary;
 }
-
-void
-rb_ary_verify(VALUE ary)
-{
-    ary_verify(ary);
-}
 #else
 #define ary_verify(ary) ((void)0)
 #endif
@@ -527,6 +522,8 @@ rb_ary_set_shared(VALUE ary, VALUE shared_root)
 static inline void
 rb_ary_modify_check(VALUE ary)
 {
+    RUBY_ASSERT(ruby_thread_has_gvl_p());
+
     rb_check_frozen(ary);
     ary_verify(ary);
 }
@@ -711,6 +708,8 @@ empty_ary_alloc(VALUE klass)
 static VALUE
 ary_new(VALUE klass, long capa)
 {
+    RUBY_ASSERT(ruby_thread_has_gvl_p());
+
     VALUE ary;
 
     if (capa < 0) {
@@ -1448,33 +1447,32 @@ rb_ary_pop(VALUE ary)
 
 /*
  *  call-seq:
- *    array.pop -> object or nil
- *    array.pop(n) -> new_array
+ *    pop -> object or nil
+ *    pop(count) -> new_array
  *
- *  Removes and returns trailing elements.
+ *  Removes and returns trailing elements of +self+.
  *
- *  When no argument is given and +self+ is not empty,
- *  removes and returns the last element:
+ *  With no argument given, removes and returns the last element, if available;
+ *  otherwise returns +nil+:
  *
  *    a = [:foo, 'bar', 2]
- *    a.pop # => 2
- *    a # => [:foo, "bar"]
- *
- *  Returns +nil+ if the array is empty.
+ *    a.pop  # => 2
+ *    a      # => [:foo, "bar"]
+ *    [].pop # => nil
  *
- *  When a non-negative Integer argument +n+ is given and is in range,
+ *  With non-negative integer argument +count+ given,
+ *  returns a new array containing the trailing +count+ elements of +self+, as available:
  *
- *  removes and returns the last +n+ elements in a new +Array+:
  *    a = [:foo, 'bar', 2]
  *    a.pop(2) # => ["bar", 2]
- *
- *  If +n+ is positive and out of range,
- *  removes and returns all elements:
+ *    a        # => [:foo]
  *
  *    a = [:foo, 'bar', 2]
  *    a.pop(50) # => [:foo, "bar", 2]
+ *    a         # => []
  *
- *  Related: #push, #shift, #unshift.
+ *  Related: Array#push;
+ *  see also {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
  */
 
 static VALUE
@@ -1513,35 +1511,40 @@ rb_ary_shift(VALUE ary)
 
 /*
  *  call-seq:
- *     array.shift -> object or nil
- *     array.shift(n) -> new_array
+ *    shift -> object or nil
+ *    shift(count) -> new_array or nil
  *
- *  Removes and returns leading elements.
- *
- *  When no argument is given, removes and returns the first element:
- *
- *    a = [:foo, 'bar', 2]
- *    a.shift # => :foo
- *    a # => ['bar', 2]
+ *  Removes and returns leading elements from +self+.
  *
- *  Returns +nil+ if +self+ is empty.
+ *  With no argument, removes and returns one element, if available,
+ *  or +nil+ otherwise:
  *
- *  When positive Integer argument +n+ is given, removes the first +n+ elements;
- *  returns those elements in a new +Array+:
+ *    a = [0, 1, 2, 3]
+ *    a.shift  # => 0
+ *    a        # => [1, 2, 3]
+ *    [].shift # => nil
  *
- *    a = [:foo, 'bar', 2]
- *    a.shift(2) # => [:foo, 'bar']
- *    a # => [2]
+ *  With non-negative numeric argument +count+ given,
+ *  removes and returns the first +count+ elements:
  *
- *  If +n+ is as large as or larger than <tt>self.length</tt>,
- *  removes all elements; returns those elements in a new +Array+:
+ *    a = [0, 1, 2, 3]
+ *    a.shift(2)   # => [0, 1]
+ *    a            # => [2, 3]
+ *    a.shift(1.1) # => [2]
+ *    a            # => [3]
+ *    a.shift(0)   # => []
+ *    a            # => [3]
+ *
+ *  If +count+ is large,
+ *  removes and returns all elements:
  *
- *    a = [:foo, 'bar', 2]
- *    a.shift(3) # => [:foo, 'bar', 2]
+ *    a = [0, 1, 2, 3]
+ *    a.shift(50) # => [0, 1, 2, 3]
+ *    a           # => []
  *
- *  If +n+ is zero, returns a new empty +Array+; +self+ is unmodified.
+ *  If +self+ is empty, returns a new empty array.
  *
- *  Related: #push, #pop, #unshift.
+ *  Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
  */
 
 static VALUE
@@ -1682,14 +1685,16 @@ ary_ensure_room_for_unshift(VALUE ary, int argc)
 
 /*
  *  call-seq:
- *    array.unshift(*objects) -> self
+ *    unshift(*objects) -> self
+ *    prepend(*objects) -> self
  *
  *  Prepends the given +objects+ to +self+:
  *
  *    a = [:foo, 'bar', 2]
  *    a.unshift(:bam, :bat) # => [:bam, :bat, :foo, "bar", 2]
  *
- *  Related: #push, #pop, #shift.
+ *  Related: Array#shift;
+ *  see also {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
  */
 
 VALUE
@@ -1809,7 +1814,7 @@ static VALUE rb_ary_aref2(VALUE ary, VALUE b, VALUE e);
  *  If +index+ is out of range, returns +nil+.
  *
  *  When two Integer arguments +start+ and +length+ are given,
- *  returns a new +Array+ of size +length+ containing successive elements beginning at offset +start+:
+ *  returns a new array of size +length+ containing successive elements beginning at offset +start+:
  *
  *    a = [:foo, 'bar', 2]
  *    a[0, 2] # => [:foo, "bar"]
@@ -1824,7 +1829,7 @@ static VALUE rb_ary_aref2(VALUE ary, VALUE b, VALUE e);
  *    a[2, 2] # => [2]
  *
  *  If <tt>start == self.size</tt> and <tt>length >= 0</tt>,
- *  returns a new empty +Array+.
+ *  returns a new empty array.
  *
  *  If +length+ is negative, returns +nil+.
  *
@@ -1836,7 +1841,7 @@ static VALUE rb_ary_aref2(VALUE ary, VALUE b, VALUE e);
  *    a[0..1] # => [:foo, "bar"]
  *    a[1..2] # => ["bar", 2]
  *
- *  Special case: If <tt>range.start == a.size</tt>, returns a new empty +Array+.
+ *  Special case: If <tt>range.start == a.size</tt>, returns a new empty array.
  *
  *  If <tt>range.end</tt> is negative, calculates the end index from the end:
  *
@@ -1860,7 +1865,7 @@ static VALUE rb_ary_aref2(VALUE ary, VALUE b, VALUE e);
  *    a[4..-1] # => nil
  *
  *  When a single Enumerator::ArithmeticSequence argument +aseq+ is given,
- *  returns an +Array+ of elements corresponding to the indexes produced by
+ *  returns an array of elements corresponding to the indexes produced by
  *  the sequence.
  *
  *    a = ['--', 'data1', '--', 'data2', '--', 'data3']
@@ -2128,20 +2133,20 @@ rb_ary_index(int argc, VALUE *argv, VALUE ary)
 
 /*
  *  call-seq:
- *    array.rindex(object) -> integer or nil
- *    array.rindex {|element| ... } -> integer or nil
- *    array.rindex -> new_enumerator
+ *    rindex(object) -> integer or nil
+ *    rindex {|element| ... } -> integer or nil
+ *    rindex -> new_enumerator
  *
  *  Returns the index of the last element for which <tt>object == element</tt>.
  *
- *  When argument +object+ is given but no block, returns the index of the last such element found:
+ *  With argument +object+ given, returns the index of the last such element found:
  *
  *    a = [:foo, 'bar', 2, 'bar']
  *    a.rindex('bar') # => 3
  *
  *  Returns +nil+ if no such object found.
  *
- *  When a block is given but no argument, calls the block with each successive element;
+ *  With a block given, calls the block with each successive element;
  *  returns the index of the last element for which the block returns a truthy value:
  *
  *    a = [:foo, 'bar', 2, 'bar']
@@ -2149,14 +2154,9 @@ rb_ary_index(int argc, VALUE *argv, VALUE ary)
  *
  *  Returns +nil+ if the block never returns a truthy value.
  *
- *  When neither an argument nor a block is given, returns a new Enumerator:
- *
- *    a = [:foo, 'bar', 2, 'bar']
- *    e = a.rindex
- *    e # => #<Enumerator: [:foo, "bar", 2, "bar"]:rindex>
- *    e.each {|element| element == 'bar' } # => 3
+ *  When neither an argument nor a block is given, returns a new Enumerator.
  *
- *  Related: #index.
+ *  Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
  */
 
 static VALUE
@@ -2303,7 +2303,7 @@ rb_ary_resize(VALUE ary, long len)
         rb_raise(rb_eIndexError, "index %ld too big", len);
     }
     if (len > olen) {
-        if (len >= ARY_CAPA(ary)) {
+        if (len > ARY_CAPA(ary)) {
             ary_double_capa(ary, len);
         }
         ary_mem_clear(ary, olen, len - olen);
@@ -2407,7 +2407,7 @@ ary_aset_by_rb_ary_splice(VALUE ary, long beg, long len, VALUE val)
  *    a[-1] = 'two' # => "two"
  *    a # => [:foo, "bar", "two"]
  *
- *  When Integer arguments +start+ and +length+ are given and +object+ is not an +Array+,
+ *  When Integer arguments +start+ and +length+ are given and +object+ is not an array,
  *  removes <tt>length - 1</tt> elements beginning at offset +start+,
  *  and assigns +object+ at offset +start+:
  *
@@ -2442,7 +2442,7 @@ ary_aset_by_rb_ary_splice(VALUE ary, long beg, long len, VALUE val)
  *    a[1, 5] = 'foo' # => "foo"
  *    a # => [:foo, "foo"]
  *
- *  When Range argument +range+ is given and +object+ is not an +Array+,
+ *  When Range argument +range+ is given and +object+ is not an array,
  *  removes <tt>length - 1</tt> elements beginning at offset +start+,
  *  and assigns +object+ at offset +start+:
  *
@@ -2603,6 +2603,39 @@ ary_fetch_next(VALUE self, VALUE *index, VALUE *value)
     return Qtrue;
 }
 
+/*
+ *  call-seq:
+ *    each {|element| ... } -> self
+ *    each -> new_enumerator
+ *
+ *  With a block given, iterates over the elements of +self+,
+ *  passing each element to the block;
+ *  returns +self+:
+ *
+ *    a = [:foo, 'bar', 2]
+ *    a.each {|element|  puts "#{element.class} #{element}" }
+ *
+ *  Output:
+ *
+ *    Symbol foo
+ *    String bar
+ *    Integer 2
+ *
+ *  Allows the array to be modified during iteration:
+ *
+ *    a = [:foo, 'bar', 2]
+ *    a.each {|element| puts element; a.clear if element.to_s.start_with?('b') }
+ *
+ *  Output:
+ *
+ *    foo
+ *    bar
+ *
+ *  With no block given, returns a new Enumerator.
+ *
+ *  Related: see {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
+ */
+
 VALUE
 rb_ary_each(VALUE ary)
 {
@@ -2637,6 +2670,7 @@ rb_ary_each(VALUE ary)
  *
  *    a = [:foo, 'bar', 2]
  *    a.each_index {|index| puts index; a.clear if index > 0 }
+ *    a # => []
  *
  *  Output:
  *
@@ -2662,47 +2696,26 @@ rb_ary_each_index(VALUE ary)
 
 /*
  *  call-seq:
- *    array.reverse_each {|element| ... } -> self
- *    array.reverse_each -> Enumerator
- *
- *  Iterates backwards over array elements.
+ *    reverse_each {|element| ... } -> self
+ *    reverse_each -> Enumerator
  *
- *  When a block given, passes, in reverse order, each element to the block;
+ *  When a block given, iterates backwards over the elements of +self+,
+ *  passing, in reverse order, each element to the block;
  *  returns +self+:
  *
- *    a = [:foo, 'bar', 2]
- *    a.reverse_each {|element|  puts "#{element.class} #{element}" }
- *
- *  Output:
- *
- *    Integer 2
- *    String bar
- *    Symbol foo
+ *    a = []
+ *    [0, 1, 2].reverse_each {|element| a.push(element) }
+ *    a # => [2, 1, 0]
  *
  *  Allows the array to be modified during iteration:
  *
- *    a = [:foo, 'bar', 2]
- *    a.reverse_each {|element| puts element; a.clear if element.to_s.start_with?('b') }
- *
- *  Output:
- *
- *    2
- *    bar
- *
- *  When no block given, returns a new Enumerator:
- *
- *    a = [:foo, 'bar', 2]
- *    e = a.reverse_each
- *    e # => #<Enumerator: [:foo, "bar", 2]:reverse_each>
- *    a1 = e.each {|element|  puts "#{element.class} #{element}" }
- *
- *  Output:
+ *    a = ['a', 'b', 'c']
+ *    a.reverse_each {|element| a.clear if element.start_with?('b') }
+ *    a # => []
  *
- *    Integer 2
- *    String bar
- *    Symbol foo
+ *  When no block given, returns a new Enumerator.
  *
- *  Related: #each, #each_index.
+ *  Related: see {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
  */
 
 static VALUE
@@ -2745,7 +2758,7 @@ rb_ary_length(VALUE ary)
 
 /*
  *  call-seq:
- *    array.empty?  -> true or false
+ *    empty?  -> true or false
  *
  *  Returns +true+ if the count of elements in +self+ is zero,
  *  +false+ otherwise.
@@ -2914,7 +2927,7 @@ rb_ary_join(VALUE ary, VALUE sep)
 
 /*
  *  call-seq:
- *    array.join(separator = $,) -> new_string
+ *    join(separator = $,) -> new_string
  *
  *  Returns the new string formed by joining the converted elements of +self+;
  *  for each element +element+:
@@ -2977,6 +2990,7 @@ inspect_ary(VALUE ary, VALUE dummy, int recur)
 /*
  *  call-seq:
  *    inspect -> new_string
+ *    to_s -> new_string
  *
  *  Returns the new string formed by calling method <tt>#inspect</tt>
  *  on each array element:
@@ -2984,7 +2998,7 @@ inspect_ary(VALUE ary, VALUE dummy, int recur)
  *    a = [:foo, 'bar', 2]
  *    a.inspect # => "[:foo, \"bar\", 2]"
  *
- *  Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
+ *  Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
  */
 
 static VALUE
@@ -3004,21 +3018,17 @@ rb_ary_to_s(VALUE ary)
  *  call-seq:
  *    to_a -> self or new_array
  *
- *  When +self+ is an instance of +Array+, returns +self+:
+ *  When +self+ is an instance of \Array, returns +self+.
  *
- *    a = [:foo, 'bar', 2]
- *    a.to_a # => [:foo, "bar", 2]
- *
- *  Otherwise, returns a new +Array+ containing the elements of +self+:
+ *  Otherwise, returns a new array containing the elements of +self+:
  *
  *    class MyArray < Array; end
- *    a = MyArray.new(['foo', 'bar', 'two'])
- *    a.instance_of?(Array) # => false
- *    a.kind_of?(Array) # => true
- *    a1 = a.to_a
- *    a1 # => ["foo", "bar", "two"]
- *    a1.class # => Array # Not MyArray
+ *    my_a = MyArray.new(['foo', 'bar', 'two'])
+ *    a = my_a.to_a
+ *    a # => ["foo", "bar", "two"]
+ *    a.class # => Array # Not MyArray.
  *
+ *  Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
  */
 
 static VALUE
@@ -3034,27 +3044,27 @@ rb_ary_to_a(VALUE ary)
 
 /*
  *  call-seq:
- *    array.to_h -> new_hash
- *    array.to_h {|item| ... } -> new_hash
+ *    to_h -> new_hash
+ *    to_h {|element| ... } -> new_hash
  *
- *  Returns a new Hash formed from +self+.
+ *  Returns a new hash formed from +self+.
  *
- *  When a block is given, calls the block with each array element;
- *  the block must return a 2-element +Array+ whose two elements
- *  form a key-value pair in the returned Hash:
+ *  With no block given, each element of +self+ must be a 2-element sub-array;
+ *  forms each sub-array into a key-value pair in the new hash:
  *
- *    a = ['foo', :bar, 1, [2, 3], {baz: 4}]
- *    h = a.to_h {|item| [item, item] }
- *    h # => {"foo"=>"foo", :bar=>:bar, 1=>1, [2, 3]=>[2, 3], {:baz=>4}=>{:baz=>4}}
+ *    a = [['foo', 'zero'], ['bar', 'one'], ['baz', 'two']]
+ *    a.to_h # => {"foo"=>"zero", "bar"=>"one", "baz"=>"two"}
+ *    [].to_h # => {}
  *
- *  When no block is given, +self+ must be an +Array+ of 2-element sub-arrays,
- *  each sub-array is formed into a key-value pair in the new Hash:
+ *  With a block given, the block must return a 2-element array;
+ *  calls the block with each element of +self+;
+ *  forms each returned array into a key-value pair in the returned hash:
  *
- *    [].to_h # => {}
- *    a = [['foo', 'zero'], ['bar', 'one'], ['baz', 'two']]
- *    h = a.to_h
- *    h # => {"foo"=>"zero", "bar"=>"one", "baz"=>"two"}
+ *    a = ['foo', :bar, 1, [2, 3], {baz: 4}]
+ *    a.to_h {|element| [element, element.class] }
+ *    # => {"foo"=>String, :bar=>Symbol, 1=>Integer, [2, 3]=>Array, {:baz=>4}=>Hash}
  *
+ *  Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
  */
 
 static VALUE
@@ -3083,7 +3093,7 @@ rb_ary_to_h(VALUE ary)
 
 /*
  *  call-seq:
- *    array.to_ary -> self
+ *    to_ary -> self
  *
  *  Returns +self+.
  */
@@ -3122,13 +3132,16 @@ rb_ary_reverse(VALUE ary)
 
 /*
  *  call-seq:
- *    array.reverse! -> self
+ *    reverse! -> self
  *
- *  Reverses +self+ in place:
+ *  Reverses the order of the elements of +self+;
+ *  returns +self+:
  *
- *    a = ['foo', 'bar', 'two']
- *    a.reverse! # => ["two", "bar", "foo"]
+ *    a = [0, 1, 2]
+ *    a.reverse! # => [2, 1, 0]
+ *    a          # => [2, 1, 0]
  *
+ *  Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
  */
 
 static VALUE
@@ -3139,14 +3152,13 @@ rb_ary_reverse_bang(VALUE ary)
 
 /*
  *  call-seq:
- *    array.reverse -> new_array
+ *    reverse -> new_array
  *
- *  Returns a new +Array+ with the elements of +self+ in reverse order:
+ *  Returns a new array containing the elements of +self+ in reverse order:
  *
- *    a = ['foo', 'bar', 'two']
- *    a1 = a.reverse
- *    a1 # => ["two", "bar", "foo"]
+ *    [0, 1, 2].reverse # => [2, 1, 0]
  *
+ *  Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
  */
 
 static VALUE