#
# This file is free software, which comes along with NIT. This software is
# distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
-# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE. You can modify it is you want, provided this header
# is kept unaltered, and a notification of the changes is added.
# You are allowed to redistribute it and sell it, alone or is a part of
# This module introduces the standard array structure.
# It also implements two other abstract collections : ArrayMap and ArraySet
-module array
+module array is
+ no_warning "useless-type-test" # to avoid warning with nitc while compiling with c_src
+end
import abstract_collection
redef fun index_of(item) do return index_of_from(item, 0)
- redef fun last_index_of(item: E): Int do return last_index_of_from(item, length-1)
+ redef fun last_index_of(item) do return last_index_of_from(item, length-1)
- redef fun index_of_from(item: E, pos: Int): Int
- do
+ redef fun index_of_from(item, pos) do
var i = pos
var len = length
while i < len do
return -1
end
- redef fun last_index_of_from(item: E, pos: Int): Int
- do
+ redef fun last_index_of_from(item, pos) do
var i = pos
while i >= 0 do
if self[i] == item then
end
end
- redef fun iterator: ArrayIterator[E] do return new ArrayIterator[E](self)
+ redef fun iterator: ArrayIterator[E] do
+ var res = _free_iterator
+ if res == null then return new ArrayIterator[E](self)
+ res._index = 0
+ _free_iterator = null
+ return res
+ end
+
+ # An old iterator, free to reuse.
+ # Once an iterator is `finish`, it become reusable.
+ # Since some arrays are iterated a lot, this avoid most of the
+ # continuous allocation/garbage-collection of the needed iterators.
+ private var free_iterator: nullable ArrayIterator[E] = null
+
redef fun reverse_iterator do return new ArrayReverseIterator[E](self)
+
+ # Returns a sub-array containing `count` elements starting from `from`.
+ #
+ # For most cases (see other case bellow),
+ # the first element is `from` and
+ # the last element is `from+count-1`.
+ #
+ # ~~~
+ # var a = [10, 20, 30, 40, 50]
+ # assert a.sub(0, 3) == [10, 20, 30]
+ # assert a.sub(3, 2) == [40, 50]
+ # assert a.sub(3, 1) == [40]
+ # ~~~
+ #
+ # If `count` is 0 or negative then an empty array is returned
+ #
+ # ~~~
+ # assert a.sub(3,0).is_empty
+ # assert a.sub(3,-1).is_empty
+ # ~~~
+ #
+ # If `from < 0` or `from+count>length` then inexistent elements are ignored.
+ # In this case the length of the result is lower than count.
+ #
+ # ~~~
+ # assert a.sub(-2, 4) == [10, 20]
+ # assert a.sub(4, 99) == [50]
+ # assert a.sub(-9, 99) == [10,20,30,40,50]
+ # assert a.sub(-99, 9).is_empty
+ # ~~~
+ fun sub(from: Int, count: Int): Array[E] do
+ if from < 0 then
+ count += from
+ from = 0
+ end
+ if count < 0 then
+ count = 0
+ end
+ var to = from + count
+ if to > length then
+ to = length
+ end
+ var res = new Array[E].with_capacity(to - from)
+ while from < to do
+ res.add(self[from])
+ from += 1
+ end
+ return res
+ end
end
# Resizable one dimension array of objects.
self[0] = item
end
- redef fun insert(item: E, pos: Int)
- do
+ redef fun insert(item, pos) do
enlarge(length + 1)
copy_to(pos, length-pos, self, pos + 1)
self[pos] = item
# Resizable one dimension array of objects.
#
# Arrays have a literal representation.
+#
# var a = [12, 32, 8]
# # is equivalent with:
# var b = new Array[Int]
# assert a == b
class Array[E]
super AbstractArray[E]
+ super Cloneable
redef fun [](index)
do
_items[l] = item
end
+ # Slight optimization for arrays
+ redef fun add_all(items)
+ do
+ var l = _length
+ var nl = l + items.length
+ if _capacity < nl then
+ enlarge nl
+ end
+
+ if items isa Array[E] then
+ var k = 0
+ while l < nl do
+ _items[l] = items._items[k]
+ l += 1
+ k += 1
+ end
+ else
+ for item in items do
+ _items[l] = item
+ l += 1
+ end
+ end
+
+ _length = nl
+ end
+
redef fun enlarge(cap)
do
var c = _capacity
# The internal storage.
private var items: nullable NativeArray[E] = null
- # Do not use this method
- # FIXME: Remove it once modules can intrude non local modules
- fun intern_items: NativeArray[E] do return _items.as(not null)
-
# The size of `_items`.
private var capacity: Int = 0
return true
end
+ # Shallow clone of `self`
+ #
+ # ~~~
+ # var a = [1,2,3]
+ # var b = a.clone
+ # assert a == b
+ # a.add 4
+ # assert a != b
+ # b.add 4
+ # assert a == b
+ # ~~~
+ #
+ # Note that the clone is shallow and elements are shared between `self` and the result.
+ #
+ # ~~~
+ # var aa = [a]
+ # var bb = aa.clone
+ # assert aa == bb
+ # aa.first.add 5
+ # assert aa == bb
+ # ~~~
+ redef fun clone do return to_a
+
# Concatenation of arrays.
#
# Returns a new array built by concatenating `self` and `other` together.
#
# returns a new array built by concatenating `self` `repeat` times.
#
- # var a = [1,2,3]
- # assert (a * 0).is_empty
- # assert a * 1 == [1,2,3]
- # assert a * 2 == [1,2,3,1,2,3]
- # assert (a * 10).length == 30
+ # var a = [1,2,3]
+ # assert (a * 0).is_empty
+ # assert a * 1 == [1,2,3]
+ # assert a * 2 == [1,2,3,1,2,3]
+ # assert (a * 10).length == 30
fun *(repeat: Int): Array[E]
do
assert repeat >= 0
redef var index = 0
var array: AbstractArrayRead[E]
+
+ redef fun finish do _array._free_iterator = self
end
private class ArrayReverseIterator[E]
# Others collections ##########################################################
# A set implemented with an Array.
-class ArraySet[E: Object]
+class ArraySet[E]
super Set[E]
+ super Cloneable
# The stored elements.
private var array: Array[E] is noinit
init with_capacity(i: Int) do _array = new Array[E].with_capacity(i)
redef fun new_set do return new ArraySet[E]
+
+ # Shallow clone of `self`
+ #
+ # ~~~
+ # var a = new ArraySet[Int]
+ # a.add 1
+ # a.add 2
+ # var b = a.clone
+ # assert a == b
+ # a.add 3
+ # assert a != b
+ # b.add 3
+ # assert a == b
+ # ~~~
+ #
+ # Note that the clone is shallow and keys and values are shared between `self` and the result.
+ #
+ # ~~~
+ # var aa = new ArraySet[Array[Int]]
+ # aa.add([1,2])
+ # var bb = aa.clone
+ # assert aa == bb
+ # aa.first.add 5
+ # assert aa == bb
+ # ~~~
+ redef fun clone
+ do
+ var res = new ArraySet[E]
+ res.add_all self
+ return res
+ end
end
# Iterators on sets implemented with arrays.
-private class ArraySetIterator[E: Object]
+private class ArraySetIterator[E]
super Iterator[E]
redef fun is_ok do return _iter.is_ok
# Associative arrays implemented with an array of (key, value) pairs.
-class ArrayMap[K: Object, E]
+class ArrayMap[K, E]
super CoupleMap[K, E]
+ super Cloneable
# O(n)
redef fun [](key)
end
end
- redef var keys: RemovableCollection[K] = new ArrayMapKeys[K, E](self)
- redef var values: RemovableCollection[E] = new ArrayMapValues[K, E](self)
+ redef var keys: RemovableCollection[K] = new ArrayMapKeys[K, E](self) is lazy
+ redef var values: RemovableCollection[E] = new ArrayMapValues[K, E](self) is lazy
# O(1)
redef fun length do return _items.length
end
return -1
end
+
+ # Shallow clone of `self`
+ #
+ # ~~~
+ # var a = new ArrayMap[String,Int]
+ # a["one"] = 1
+ # a["two"] = 2
+ # var b = a.clone
+ # assert a == b
+ # a["zero"] = 0
+ # assert a != b
+ # ~~~
+ #
+ # Note that the clone is shallow and keys and values are shared between `self` and the result.
+ #
+ # ~~~
+ # var aa = new ArrayMap[String, Array[Int]]
+ # aa["two"] = [1,2]
+ # var bb = aa.clone
+ # assert aa == bb
+ # aa["two"].add 5
+ # assert aa == bb
+ # ~~~
+ redef fun clone
+ do
+ var res = new ArrayMap[K,E]
+ res.recover_with self
+ return res
+ end
end
-private class ArrayMapKeys[K: Object, E]
+private class ArrayMapKeys[K, E]
super RemovableCollection[K]
# The original map
var map: ArrayMap[K, E]
redef fun remove_all(key) do self.remove(key)
end
-private class ArrayMapValues[K: Object, E]
+private class ArrayMapValues[K, E]
super RemovableCollection[E]
# The original map
var map: ArrayMap[K, E]