Permalink
Browse files

Fixes for 1.9: Change Array#[range]= nil to no longer delete. Moving …

…array element deletion out of []=.
  • Loading branch information...
1 parent 7257070 commit 27e680d34a36f4b5acdd678521d05fc7f8509eda @subwindow subwindow committed Oct 13, 2011
Showing with 466 additions and 232 deletions.
  1. +0 −223 kernel/common/array.rb
  2. +222 −0 kernel/common/array18.rb
  3. +243 −0 kernel/common/array19.rb
  4. +1 −1 lib/19/rss/itunes.rb
  5. +0 −8 spec/tags/19/ruby/core/array/element_set_tags.txt
View
@@ -181,179 +181,6 @@ def [](arg1, arg2=nil)
alias_method :slice, :[]
- def set_index(index, ent, fin=undefined)
- Rubinius.primitive :array_aset
-
- Rubinius.check_frozen
-
- ins_length = nil
- unless fin.equal? undefined
- ins_length = Rubinius::Type.coerce_to ent, Fixnum, :to_int
- ent = fin # 2nd arg (ins_length) is the optional one!
- end
-
- # Normalise Ranges
- if index.kind_of? Range
- if ins_length
- raise ArgumentError, "Second argument invalid with a range"
- end
-
- last = Rubinius::Type.coerce_to index.last, Fixnum, :to_int
- last += @total if last < 0
- last += 1 unless index.exclude_end?
-
- index = Rubinius::Type.coerce_to index.first, Fixnum, :to_int
-
- if index < 0
- index += @total
- raise RangeError, "Range begin #{index-@total} out of bounds" if index < 0
- end
-
- # m..n, m > n allowed
- last = index if index > last
-
- ins_length = last - index
- else
- index = Rubinius::Type.coerce_to index, Fixnum, :to_int
-
- if index < 0
- index += @total
- raise IndexError,"Index #{index-@total} out of bounds" if index < 0
- end
- end
-
- if ins_length
- # ins_length < 0 not allowed
- raise IndexError, "Negative length #{ins_length}" if ins_length < 0
-
- # MRI seems to be forgiving here!
- space = @total - index
- if ins_length > space
- ins_length = space > 0 ? space : 0
- end
-
- replace_count = 0
-
- if ent.nil?
- # optimize for fast removal..
- reg_start = index + ins_length
- reg_length = @total - reg_start
-
- if reg_start <= @total
- # If we're removing from the front, also reset @start to better
- # use the Tuple
- if index == 0
- # Use a shift start optimization if we're only removing one
- # element and the shift started isn't already huge.
- if ins_length == 1
- @start += 1
- else
- @tuple.copy_from @tuple, reg_start + @start, reg_length, 0
- @start = 0
- end
- else
- @tuple.copy_from @tuple, reg_start + @start, reg_length,
- @start + index
- end
-
- # TODO we leave the old references in the Tuple, we should
- # probably clear them out though.
-
- @total -= ins_length
-
- return ent
- end
-
- # This is actually an addition! silly, I know.
- replace_count = 0
- elsif ent.kind_of? Array
- replacement = ent
- replace_count = replacement.size
- replacement = replacement.first if replace_count == 1
- elsif ent.respond_to? :to_ary
- replacement = ent.to_ary
- replace_count = replacement.size
- replacement = replacement.first if replace_count == 1
- else
- replacement = ent
- replace_count = 1
- end
-
- new_total = (index > @total) ? index : @total
- if replace_count > ins_length
- new_total += replace_count - ins_length
- elsif replace_count < ins_length
- new_total -= ins_length - replace_count
- end
-
- if new_total > @tuple.size - @start
- # Expand the size just like #<< does.
- # MRI uses a straight realloc here to the exact size, but
- # realloc can easily include bumper data so it's pretty fast.
- # We simply compensate by using the same logic to reduce
- # having to copy data.
- new_tuple = Rubinius::Tuple.new(new_total + @tuple.size / 2)
-
- new_tuple.copy_from(@tuple, @start, index < @total ? index : @total, 0)
-
- case replace_count
- when 1
- new_tuple[index] = replacement
- when 0
- # nothing
- else
- new_tuple.copy_from(replacement.tuple, replacement.start,
- replace_count, index)
- end
-
- if index < @total
- new_tuple.copy_from(@tuple, @start + index + ins_length,
- @total - index - ins_length,
- index + replace_count)
- end
- @start = 0
- @tuple = new_tuple
- @total = new_total
- else
- # Move the elements to the right
- if index < @total
- right_start = @start + index + ins_length
- right_len = @total - index - ins_length
-
- @tuple.copy_from(@tuple, right_start, right_len,
- @start + index + replace_count)
- end
-
- case replace_count
- when 1
- @tuple[@start + index] = replacement
- when 0
- # nothing
- else
- @tuple.copy_from(replacement.tuple, replacement.start,
- replace_count, @start + index)
- end
-
- @total = new_total
- end
-
- return ent
- else
- nt = @start + index + 1
- reallocate(nt) if @tuple.size < nt
-
- @tuple.put @start + index, ent
- if index >= @total - 1
- @total = index + 1
- end
- return ent
- end
- end
-
- alias_method :[]=, :set_index
-
- private :set_index
-
# Appends the object to the end of the Array.
# Returns self so several appends can be chained.
def <<(obj)
@@ -1315,56 +1142,6 @@ def drop(n)
new_range n, new_size
end
- # Deletes the element(s) given by an index (optionally with a length)
- # or by a range. Returns the deleted object, subarray, or nil if the
- # index is out of range. Equivalent to:
- def slice!(start, length=undefined)
- Rubinius.check_frozen
-
- if length.equal? undefined
- if start.kind_of? Range
- out = self[start]
-
- s = Rubinius::Type.coerce_to start.begin, Fixnum, :to_int
- unless s >= @total or -s > @total
- self[start] = nil
- end
- else
- # make sure that negative values are not passed through to the
- # []= assignment
- start = Rubinius::Type.coerce_to start, Integer, :to_int
- start = start + @total if start < 0
-
- # This is to match the MRI behaviour of not extending the array
- # with nil when specifying an index greater than the length
- # of the array.
- return out unless start >= 0 and start < @total
-
- out = @tuple.at start + @start
-
- # Check for shift style.
- if start == 0
- @tuple.put @start, nil
- @total -= 1
- @start += 1
- else
- self[start, 1] = nil
- end
- end
- else
- start = Rubinius::Type.coerce_to start, Fixnum, :to_int
- length = Rubinius::Type.coerce_to length, Fixnum, :to_int
-
- out = self[start, length]
-
- unless start >= @total or -start > @total
- self[start, length] = nil
- end
- end
-
- out
- end
-
# Returns a new array with elements of this array shuffled.
def shuffle
dup.shuffle!
Oops, something went wrong.

0 comments on commit 27e680d

Please sign in to comment.