1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Copyright 2004-2008 Jean Privat <jean@pryen.org>
4 # Copyright 2008 Floréal Morandat <morandat@lirmm.fr>
6 # This file is free software, which comes along with NIT. This software is
7 # distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
8 # without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
9 # PARTICULAR PURPOSE. You can modify it is you want, provided this header
10 # is kept unaltered, and a notification of the changes is added.
11 # You are allowed to redistribute it and sell it, alone or is a part of
14 # This module introduces the standard array structure.
15 # It also implements two other abstract collections : ArrayMap and ArraySet
18 import abstract_collection
20 # Resizeable one dimention array of objects.
21 class AbstractArray[E
]
22 special IndexedCollection[E
]
23 meth enlarge
(cap
: Int) is abstract
26 redef readable attr _length
: Int
28 redef meth is_empty
do return _length
== 0
30 redef meth push
(item
) do add
(item
)
34 assert not_empty
: not is_empty
42 assert not_empty
: not is_empty
54 redef meth unshift
(item
)
64 meth insert
(item
: E
, pos
: Int)
67 copy_to
(pos
, length-pos
, self, pos
+ 1)
71 redef meth add
(item
) do self[length
] = item
73 redef meth clear
do _length
= 0
80 if self[i
] == item
then return true
86 redef meth has_only
(item
)
91 if self[i
] != item
then return false
97 redef meth has_key
(index
) do return index
>= 0 and index
< length
99 redef meth count
(item
)
105 if self[i
] == item
then res
+= 1
111 redef meth index_of
(item
) do return index_of_from
(item
, 0)
113 meth last_index_of
(item
: E
): Int do return last_index_of_from
(item
, length-1
)
115 meth index_of_from
(item
: E
, pos
: Int): Int
120 if self[i
] == item
then
128 meth last_index_of_from
(item
: E
, pos
: Int): Int
132 if self[i
] == item
then
141 meth reversed
: Array[E
]
144 var result
= new Array[E
].with_capacity
(cmp
)
147 result
.add
(self[cmp
])
152 redef meth remove
(item
) do remove_at
(index_of
(item
))
154 redef meth remove_all
(item
)
156 var i
= index_of
(item
)
159 i
= index_of_from
(item
, i
)
163 redef meth remove_at
(i
)
166 if i
>= 0 and i
< l
then
176 protected meth copy_to
(start
: Int, len
: Int, dest
: AbstractArray[E
], new_start
: Int)
182 dest
[new_start
+i
] = self[start
+i
]
192 if e
!= null then e
.output
197 redef meth iterator
: ArrayIterator[E
] do return new ArrayIterator[E
](self)
199 # Two arrays are equals if they have the same items in the same order.
202 if not o
isa AbstractArray[E
] or o
is null then return false
203 assert o
isa AbstractArray[E
]
205 if o
.length
!= l
then return false
208 if self[i
] != o
[i
] then return false
215 # Resizeable one dimention array of objects.
217 # Arrays have a literal representation.
219 # is equivalent with:
225 special AbstractArray[E
]
226 special ArrayCapable[E
]
229 assert index
: index
>= 0 and index
< _length
233 redef meth
[]=(index
, item
)
235 assert index
: index
>= 0 and index
< _length
+ 1
236 if _capacity
<= index
then
239 if _length
<= index
then
245 redef meth enlarge
(cap
)
248 if cap
<= c
then return
249 while c
<= cap
do c
= c
* 2 + 2
250 var a
= calloc_array
(c
)
251 if _capacity
> 0 then _items
.copy_to
(a
, _length
)
256 # Create an empty array.
263 # Create an array with some `items'.
264 init with
(objects
: E
...)
266 _items
= objects
._items
267 _capacity
= objects
._capacity
268 _length
= objects
.length
271 # Create an empty array with a given capacity.
272 init with_capacity
(cap
: Int)
274 assert positive
: cap
>= 0
275 _items
= calloc_array
(cap
)
280 # Create an array of `count' elements
281 init filled_with
(value
: E
, count
: Int)
283 assert positive
: count
>= 0
284 _items
= calloc_array
(count
)
294 # Create a array filled with a given native array.
295 init with_native
(nat
: NativeArray[E
], size
: Int)
297 assert positive
: size
>= 0
303 # The internal storage.
304 attr _items
: NativeArray[E
]
306 # The size of `_items'.
310 # An `Iterator' on `AbstractArray'
311 class ArrayIterator[E
]
312 special IndexedIterator[E
]
313 redef meth item
do return _array
[_index
]
315 redef meth item
=(e
) do _array
[_index
] = e
317 redef meth is_ok
do return _index
< _array
.length
319 redef meth next
do _index
+= 1
321 init(a
: AbstractArray[E
])
323 assert not_nil
: a
!= null
328 redef readable attr _index
: Int
329 attr _array
: AbstractArray[E
]
332 # Others collections ##########################################################
334 # A set implemented with an Array.
337 # The stored elements.
338 attr _array
: Array[E
]
340 redef meth has
(e
) do return _array
.has
(e
)
342 redef meth add
(e
) do if not _array
.has
(e
) then _array
.add
(e
)
344 redef meth is_empty
do return _array
.is_empty
346 redef meth length
do return _array
.length
350 assert _array
.length
> 0
354 redef meth remove
(item
)
356 var i
= _array
.index_of
(item
)
357 if i
>= 0 then remove_at
(i
)
360 redef meth remove_all
(item
) do remove
(item
)
362 redef meth clear
do _array
.clear
364 redef meth iterator
do return new ArraySetIterator[E
](_array
.iterator
)
366 # Assume the capacitydd is at least `cap'.
367 meth enlarge
(cap
: Int) do _array
.enlarge
(cap
)
369 private meth remove_at
(i
: Int)
371 _array
[i
] = _array
.last
375 # Create an empty set
376 init do _array
= new Array[E
]
378 # Create an empty set with a given capacity.
379 init with_capacity
(i
: Int) do _array
= new Array[E
].with_capacity
(i
)
382 # Iterators on sets implemented with arrays.
383 class ArraySetIterator[E
]
386 redef meth is_ok
do return _iter
.is_ok
388 redef meth next
do _iter
.next
390 redef meth item
: E
do return _iter
.item
392 init(iter
: ArrayIterator[E
]) do _iter
= iter
394 attr _iter
: ArrayIterator[E
]
398 # Associative arrays implemented with an array of (key, value) pairs.
400 special CoupleMap[K
, E
]
407 return _items
[i
].second
414 redef meth
[]=(key
, item
)
418 _items
[i
].second
= item
420 _items
.push
(new Couple[K
,E
](key
, item
))
425 redef meth has_key
(key
) do return index
(key
) >= 0
430 for i
in _items
do if i
.second
== item
then return true
435 redef meth has_only
(item
)
437 for i
in _items
do if i
.second
!= item
then return false
442 redef meth length
do return _items
.length
444 redef meth first
do return _items
.first
.first
447 redef meth count
(item
)
450 for i
in _items
do if i
.second
== item
then nb
+= 1
454 redef meth iterator
: CoupleMapIterator[K
, E
] do return new CoupleMapIterator[K
, E
](_items
.iterator
)
456 redef meth is_empty
do return _items
.is_empty
458 redef meth remove
(item
)
460 var i
= _items
.length
- 1
462 if _items
[i
].second
== item
then
470 redef meth remove_all
(item
: E
)
472 var i
= _items
.length
- 1
474 if _items
[i
].second
== item
then
481 redef meth remove_at
(key
)
484 if i
>= 0 then remove_at_index
(i
)
487 redef meth clear
do _items
.clear
489 # Assume the capacity to be at least `cap'.
490 meth enlarge
(cap
: Int) do _items
.enlarge
(cap
)
492 redef meth couple_at
(key
)
503 attr _items
: Array[Couple[K
,E
]]
505 # fast remove the ith element of the array
506 private meth remove_at_index
(i
: Int)
508 _items
[i
] = _items
.last
512 # The last positive result given by a index(1) call
513 attr _last_index
: Int
515 # Where is the `key' in `_item'?
516 # return -1 if not found
517 private meth index
(key
: K
): Int
520 if l
< _items
.length
and _items
[l
].first
== key
then return l
523 while i
< _items
.length
do
524 if _items
[i
].first
== key
then
536 _items
= new Array[Couple[K
,E
]]
540 # Others tools ################################################################
542 redef class Iterator[E
]
543 # Interate on `self' and build an array
546 var res
= new Array[E
]
555 redef class Collection[E
]
556 # Build a new array from a collection
563 # Native classes ##############################################################
565 # Subclasses of this class can create native arrays
566 class ArrayCapable[E
]
567 # Get a new array of `size' elements.
568 protected meth calloc_array
(size
: Int): NativeArray[E
] is intern
571 # Native C array (void ...).
573 meth
[](index
: Int): E
is intern
574 meth
[]=(index
: Int, item
: E
) is intern
575 meth copy_to
(dest
: NativeArray[E
], length
: Int) is intern
576 #meth =(o: NativeArray[E]): Bool is intern
577 #meth !=(o: NativeArray[E]): Bool is intern