metamodel: rename 'universal' to 'enum'
[nit.git] / lib / standard / collection / array.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2004-2008 Jean Privat <jean@pryen.org>
4 # Copyright 2008 Floréal Morandat <morandat@lirmm.fr>
5 #
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
12 # another product.
13
14 # This module introduces the standard array structure.
15 # It also implements two other abstract collections : ArrayMap and ArraySet
16 package array
17
18 import abstract_collection
19
20 # One dimention array of objects.
21 class AbstractArrayRead[E]
22 super SequenceRead[E]
23 # The current length
24 redef readable var _length: Int = 0
25
26 redef fun is_empty do return _length == 0
27
28 redef fun has(item)
29 do
30 var i = 0
31 var l = length
32 while i < l do
33 if self[i] == item then return true
34 i += 1
35 end
36 return false
37 end
38
39 redef fun has_only(item)
40 do
41 var i = 0
42 var l = length
43 while i < l do
44 if self[i] != item then return false
45 i += 1
46 end
47 return true
48 end
49
50 redef fun has_key(index) do return index >= 0 and index < length
51
52 redef fun count(item)
53 do
54 var res = 0
55 var i = 0
56 var l = length
57 while i < l do
58 if self[i] == item then res += 1
59 i += 1
60 end
61 return res
62 end
63
64 redef fun index_of(item) do return index_of_from(item, 0)
65
66 fun last_index_of(item: E): Int do return last_index_of_from(item, length-1)
67
68 fun index_of_from(item: E, pos: Int): Int
69 do
70 var i = pos
71 var len = length
72 while i < len do
73 if self[i] == item then
74 return i
75 end
76 i += 1
77 end
78 return -1
79 end
80
81 fun last_index_of_from(item: E, pos: Int): Int
82 do
83 var i = pos
84 while i >= 0 do
85 if self[i] == item then
86 return i
87 else
88 i -= 1
89 end
90 end
91 return -1
92 end
93
94 fun reversed: Array[E]
95 do
96 var cmp = _length
97 var result = new Array[E].with_capacity(cmp)
98 while cmp > 0 do
99 cmp -= 1
100 result.add(self[cmp])
101 end
102 return result
103 end
104
105 protected fun copy_to(start: Int, len: Int, dest: AbstractArray[E], new_start: Int)
106 do
107 # TODO native one
108 var i = len
109 while i > 0 do
110 i -= 1
111 dest[new_start+i] = self[start+i]
112 end
113 end
114
115 redef fun output
116 do
117 var i = 0
118 var l = length
119 while i < l do
120 var e = self[i]
121 if e != null then e.output
122 i += 1
123 end
124 end
125
126 redef fun iterator: ArrayIterator[E] do return new ArrayIterator[E](self)
127
128 # Two arrays are equals if they have the same items in the same order.
129 redef fun ==(o)
130 do
131 if not o isa AbstractArray[E] or o is null then return false
132 var l = length
133 if o.length != l then return false
134 var i = 0
135 while i < l do
136 if self[i] != o[i] then return false
137 i += 1
138 end
139 return true
140 end
141 end
142
143 # Resizeable one dimention array of objects.
144 class AbstractArray[E]
145 super AbstractArrayRead[E]
146 super Sequence[E]
147 fun enlarge(cap: Int) is abstract
148
149 redef fun push(item) do add(item)
150
151 redef fun pop
152 do
153 assert not_empty: not is_empty
154 var r = last
155 _length -= 1
156 return r
157 end
158
159 redef fun shift
160 do
161 assert not_empty: not is_empty
162 var r = first
163 var i = 1
164 var l = length
165 while i < l do
166 self[i-1] = self[i]
167 i += 1
168 end
169 _length = l - 1
170 return r
171 end
172
173 redef fun unshift(item)
174 do
175 var i = length - 1
176 while i > 0 do
177 self[i+1] = self[i]
178 i -= 1
179 end
180 self[0] = item
181 end
182
183 fun insert(item: E, pos: Int)
184 do
185 enlarge(length + 1)
186 copy_to(pos, length-pos, self, pos + 1)
187 self[pos] = item
188 end
189
190 redef fun add(item) do self[length] = item
191
192 redef fun clear do _length = 0
193
194 redef fun remove(item) do remove_at(index_of(item))
195
196 redef fun remove_all(item)
197 do
198 var i = index_of(item)
199 while i >= 0 do
200 remove_at(i)
201 i = index_of_from(item, i)
202 end
203 end
204
205 redef fun remove_at(i)
206 do
207 var l = length
208 if i >= 0 and i < l then
209 var j = i + 1
210 while j < l do
211 self[j-1] = self[j]
212 j += 1
213 end
214 _length = l - 1
215 end
216 end
217 end
218
219 # Resizeable one dimention array of objects.
220 #
221 # Arrays have a literal representation.
222 # a = [12, 32, 8]
223 # is equivalent with:
224 # a = new Array[Int]
225 # a.push(12)
226 # a.push(32)
227 # a.push(8)
228 class Array[E]
229 super AbstractArray[E]
230 super ArrayCapable[E]
231 redef fun iterate
232 !each(e: E)
233 do
234 var i = 0
235 var l = _length
236 var items = _items
237 while i < length do
238 each(items[i])
239 i += 1
240 end
241 end
242
243 redef fun [](index)
244 do
245 assert index: index >= 0 and index < _length
246 return _items[index]
247 end
248
249 redef fun []=(index, item)
250 do
251 assert index: index >= 0 and index < _length + 1
252 if _capacity <= index then
253 enlarge(index + 1)
254 end
255 if _length <= index then
256 _length = index + 1
257 end
258 _items[index] = item
259 end
260
261 redef fun add(item)
262 do
263 var l = _length
264 if _capacity <= l then
265 enlarge(l + 1)
266 end
267 _length = l + 1
268 _items[l] = item
269 end
270
271 redef fun enlarge(cap)
272 do
273 var c = _capacity
274 if cap <= c then return
275 while c <= cap do c = c * 2 + 2
276 var a = calloc_array(c)
277 if _capacity > 0 then _items.copy_to(a, _length)
278 _items = a
279 _capacity = c
280 end
281
282 # Create an empty array.
283 init
284 do
285 _capacity = 0
286 _length = 0
287 end
288
289 # Create an array with some `items'.
290 init with_items(objects: E...)
291 do
292 _items = objects._items
293 _capacity = objects._capacity
294 _length = objects.length
295 end
296
297 # Create an empty array with a given capacity.
298 init with_capacity(cap: Int)
299 do
300 assert positive: cap >= 0
301 _items = calloc_array(cap)
302 _capacity = cap
303 _length = 0
304 end
305
306 # Create an array of `count' elements
307 init filled_with(value: E, count: Int)
308 do
309 assert positive: count >= 0
310 _items = calloc_array(count)
311 _capacity = count
312 _length = count
313 var i = 0
314 while i < count do
315 self[i] = value
316 i += 1
317 end
318 end
319
320 # Create a array filled with a given native array.
321 init with_native(nat: NativeArray[E], size: Int)
322 do
323 assert positive: size >= 0
324 _items = nat
325 _capacity = size
326 _length = size
327 end
328
329 # The internal storage.
330 var _items: nullable NativeArray[E] = null
331
332 # Do not use this method
333 # FIXME: Remove it once modules can intrude non local modules
334 fun intern_items: NativeArray[E] do return _items.as(not null)
335
336 # The size of `_items'.
337 var _capacity: Int = 0
338
339 # Sort the array using the !cmp function.
340 fun sort
341 !cmp(e1,e2: E): Int
342 do
343 sub_sort(0, length-1) !cmp(x,y) = cmp(x, y)
344 end
345
346 # Sort `array' between `from' and `to' indices
347 private fun sub_sort(from: Int, to: Int)
348 !cmp(e1,e2: E): Int
349 do
350 if from >= to then
351 return
352 else if from + 7 < to then
353 var pivot = self[from]
354 var i = from
355 var j = to
356 while j > i do
357 while i <= to and cmp(self[i], pivot) <= 0 do i += 1
358 while j > i and cmp(self[j], pivot) >= 0 do j -= 1
359 if j > i then
360 var t = self[i]
361 self[i] = self[j]
362 self[j] = t
363 end
364 end
365 self[from] = self[i-1]
366 self[i-1] = pivot
367 sub_sort(from, i-2) !cmp(x,y) = cmp(x, y)
368 sub_sort(i, to) !cmp(x,y) = cmp(x, y)
369 else
370 var i = from
371 while i < to do
372 var min = i
373 var min_v = self[i]
374 var j = i
375 while j <= to do
376 if cmp(min_v, self[j]) > 0 then
377 min = j
378 min_v = self[j]
379 end
380 j += 1
381 end
382 if min != i then
383 self[min] = self[i]
384 self[i] = min_v
385 end
386 i += 1
387 end
388 end
389 end
390 end
391
392 # An `Iterator' on `AbstractArray'
393 class ArrayIterator[E]
394 super IndexedIterator[E]
395 redef fun item do return _array[_index]
396
397 # redef fun item=(e) do _array[_index] = e
398
399 redef fun is_ok do return _index < _array.length
400
401 redef fun next do _index += 1
402
403 init(a: AbstractArrayRead[E])
404 do
405 _array = a
406 _index = 0
407 end
408
409 redef readable var _index: Int = 0
410 var _array: AbstractArrayRead[E]
411 end
412
413 # Others collections ##########################################################
414
415 # A set implemented with an Array.
416 class ArraySet[E: Object]
417 super Set[E]
418 # The stored elements.
419 var _array: Array[E]
420
421 redef fun has(e) do return _array.has(e)
422
423 redef fun add(e) do if not _array.has(e) then _array.add(e)
424
425 redef fun is_empty do return _array.is_empty
426
427 redef fun length do return _array.length
428
429 redef fun first
430 do
431 assert _array.length > 0
432 return _array.first
433 end
434
435 redef fun remove(item)
436 do
437 var i = _array.index_of(item)
438 if i >= 0 then remove_at(i)
439 end
440
441 redef fun remove_all(item) do remove(item)
442
443 redef fun clear do _array.clear
444
445 redef fun iterator do return new ArraySetIterator[E](_array.iterator)
446
447 # Assume the capacitydd is at least `cap'.
448 fun enlarge(cap: Int) do _array.enlarge(cap)
449
450 private fun remove_at(i: Int)
451 do
452 _array[i] = _array.last
453 _array.pop
454 end
455
456 # Create an empty set
457 init do _array = new Array[E]
458
459 # Create an empty set with a given capacity.
460 init with_capacity(i: Int) do _array = new Array[E].with_capacity(i)
461 end
462
463 # Iterators on sets implemented with arrays.
464 class ArraySetIterator[E: Object]
465 super Iterator[E]
466
467 redef fun is_ok do return _iter.is_ok
468
469 redef fun next do _iter.next
470
471 redef fun item: E do return _iter.item
472
473 init(iter: ArrayIterator[E]) do _iter = iter
474
475 var _iter: ArrayIterator[E]
476 end
477
478
479 # Associative arrays implemented with an array of (key, value) pairs.
480 class ArrayMap[K: Object, E]
481 super CoupleMap[K, E]
482
483 # O(n)
484 redef fun [](key)
485 do
486 var i = index(key)
487 if i >= 0 then
488 return _items[i].second
489 else
490 abort
491 end
492 end
493
494 # O(n)
495 redef fun []=(key, item)
496 do
497 var i = index(key)
498 if i >= 0 then
499 _items[i].second = item
500 else
501 _items.push(new Couple[K,E](key, item))
502 end
503 end
504
505 # O(n)
506 redef fun has_key(key) do return index(key) >= 0
507
508 # O(n)
509 redef fun has(item)
510 do
511 for i in _items do if i.second == item then return true
512 return false
513 end
514
515 # O(n)
516 redef fun has_only(item)
517 do
518 for i in _items do if i.second != item then return false
519 return true
520 end
521
522 # O(1)
523 redef fun length do return _items.length
524
525 redef fun first do return _items.first.second
526
527 # O(n)
528 redef fun count(item)
529 do
530 var nb = 0
531 for i in _items do if i.second == item then nb += 1
532 return nb
533 end
534
535 redef fun iterator: CoupleMapIterator[K, E] do return new CoupleMapIterator[K, E](_items.iterator)
536
537 redef fun is_empty do return _items.is_empty
538
539 redef fun remove(item)
540 do
541 var i = _items.length - 1
542 while i >= 0 do
543 if _items[i].second == item then
544 remove_at_index(i)
545 return
546 end
547 i -= 1
548 end
549 end
550
551 redef fun remove_all(item: E)
552 do
553 var i = _items.length - 1
554 while i >= 0 do
555 if _items[i].second == item then
556 remove_at_index(i)
557 end
558 i -= 1
559 end
560 end
561
562 redef fun remove_at(key)
563 do
564 var i = index(key)
565 if i >= 0 then remove_at_index(i)
566 end
567
568 redef fun clear do _items.clear
569
570 # Assume the capacity to be at least `cap'.
571 fun enlarge(cap: Int) do _items.enlarge(cap)
572
573 redef fun couple_at(key)
574 do
575 var i = index(key)
576 if i >= 0 then
577 return _items[i]
578 else
579 return null
580 end
581 end
582
583 # Internal storage.
584 var _items: Array[Couple[K,E]]
585
586 # fast remove the ith element of the array
587 private fun remove_at_index(i: Int)
588 do
589 _items[i] = _items.last
590 _items.pop
591 end
592
593 # The last positive result given by a index(1) call
594 var _last_index: Int = 0
595
596 # Where is the `key' in `_item'?
597 # return -1 if not found
598 private fun index(key: K): Int
599 do
600 var l = _last_index
601 if l < _items.length and _items[l].first == key then return l
602
603 var i = 0
604 while i < _items.length do
605 if _items[i].first == key then
606 _last_index = i
607 return i
608 end
609 i += 1
610 end
611 return -1
612 end
613
614 # A new empty map.
615 init
616 do
617 _items = new Array[Couple[K,E]]
618 end
619 end
620
621 # Others tools ################################################################
622
623 redef class Iterator[E]
624 # Interate on `self' and build an array
625 fun to_a: Array[E]
626 do
627 var res = new Array[E]
628 while is_ok do
629 res.add(item)
630 next
631 end
632 return res
633 end
634 end
635
636 redef class Collection[E]
637 # Build a new array from a collection
638 fun to_a: Array[E]
639 do
640 return iterator.to_a
641 end
642 end
643
644 # Native classes ##############################################################
645
646 # Subclasses of this class can create native arrays
647 interface ArrayCapable[E]
648 # Get a new array of `size' elements.
649 protected fun calloc_array(size: Int): NativeArray[E] is intern
650 end
651
652 # Native C array (void ...).
653 universal NativeArray[E]
654 fun [](index: Int): E is intern
655 fun []=(index: Int, item: E) is intern
656 fun copy_to(dest: NativeArray[E], length: Int) is intern
657 #fun =(o: NativeArray[E]): Bool is intern
658 #fun !=(o: NativeArray[E]): Bool is intern
659 end