1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Copyright 2004-2009 Jean Privat <jean@pryen.org>
5 # This file is free software, which comes along with NIT. This software is
6 # distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
7 # without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
8 # PARTICULAR PURPOSE. You can modify it is you want, provided this header
9 # is kept unaltered, and a notification of the changes is added.
10 # You are allowed to redistribute it and sell it, alone or is a part of
13 # Introduce Hashmap and Hashset.
14 package hash_collection
19 # A HashCollection is an array of HashNode[K] indexed by the K hash value
20 private class HashCollection[K
: Object, N
: HashNode[K
], E
]
22 special ArrayCapable[nullable N
]
23 var _array
: nullable NativeArray[nullable N
] = null # Used to store items
24 var _capacity
: Int = 0 # Size of _array
25 redef readable var _length
: Int = 0 # Number of items in the map
27 readable var _first_item
: nullable N
= null # First added item (used to visit items in nice order)
28 var _last_item
: nullable N
= null # Last added item (same)
30 # The last index accessed
31 var _last_accessed_index
: Int = -1
33 # The last key accessed
34 var _last_accessed_key
: nullable K
= null
36 # Return the index of the k element
37 fun index_at
(k
: K
): Int
41 # Fisrt step: look in the last indexed elt
42 if k
== _last_accessed_key
then return _last_accessed_index
44 # Compute the base position of the key
45 var base
= k
.hash
% _capacity
46 if base
< 0 then base
= - base
48 # Look for the key in the array
52 if c
== null or c
._key
== k
then # REAL equals
53 _last_accessed_index
= cur
54 _last_accessed_key
= k
58 if cur
< 0 then cur
= _capacity
- 1
59 assert no_loop
: cur
!= base
60 if false then break # FIXME remove once unreach loop exits are in c_src
62 abort #FIXME remove once unreach loop exits are in c_src
65 # Add a new node (should be free)
66 fun store
(index
: Int, node
: N
)
68 # Store the item in the list
69 if _first_item
== null then
72 _last_item
._next_item
= node
74 node
._prev_item
= _last_item
75 node
._next_item
= null
77 # Then store it in the array
78 assert _array
[index
] == null
82 l
= (l
+ 5) * 150 / 100
83 if l
>= _capacity
then
88 fun remove_index
(i
: Int)
90 assert correct_index
: i
>= 0 and i
< _capacity
92 assert has_couple
: node
!= null
93 # Remove the item in the list
94 var prev
= node
._prev_item
95 var next
= node
._next_item
97 prev
._next_item
= next
102 next
._prev_item
= prev
106 # Remove the item in the array
109 # Now replaces things before if needed
119 var i2
= index_at
(n
._key
)
122 assert _array
[i2
] == null
130 var i
= _capacity
- 1
138 _last_accessed_key
= null
141 fun enlarge
(cap
: Int)
143 var old_cap
= _capacity
145 # cap = cap * 130 / 100 + 5 + 1000 # /
146 if cap
< _length
+ 1 then cap
= _length
+ 1
147 if cap
<= _capacity
then return
149 _last_accessed_key
= null
152 var new_array
= calloc_array
(cap
)
155 # clean the new array
162 if _capacity
<= old_cap
then return
164 # Reput items in the array
165 var node
= _first_item
166 while node
!= null do
167 var ind
= index_at
(node
._key
)
168 assert new_array
[ind
] == null
169 new_array
[ind
] = node
170 node
= node
._next_item
172 _last_accessed_key
= null
176 private class HashNode[K
]
179 readable writable var _next_item
: nullable N
= null
180 readable writable var _prev_item
: nullable N
= null
189 special HashCollection[K
, HashMapNode[K
, V
], V
]
193 var c
= couple_at
(key
)
201 redef fun has_key
(key
) do return couple_at
(key
) != null
203 redef fun iterator
: HashMapIterator[K
, V
] do return new HashMapIterator[K
,V
](self)
218 return _first_item
._value
221 redef fun is_empty
do return _length
== 0
223 redef fun count
(item
)
227 while i
< _capacity
do
229 if c
!= null and c
._value
== item
then nb
+= 1
238 while i
< _capacity
do
240 if c
!= null and c
._value
== item
then return true
246 redef fun has_only
(item
)
249 while i
< _capacity
do
251 if c
!= null and c
._value
!= item
then return false
257 redef fun []=(key
, v
)
260 var i
= index_at
(key
)
266 store
(i
, new HashMapNode[K
, V
](key
, v
))
270 redef fun remove
(item
)
273 while i
< _capacity
do
275 if c
!= null and c
._value
== item
then
283 redef fun remove_at
(key
) do remove_index
(index_at
(key
))
285 redef fun clear
do raz
287 fun couple_at
(key
: K
): nullable HashMapNode[K
, V
] do return _array
[index_at
(key
)]
297 class HashMapNode[K
, V
]
299 redef type N
: HashMapNode[K
, V
]
309 class HashMapIterator[K
, V
]
310 special MapIterator[K
, V
]
311 redef fun is_ok
do return _node
!= null
319 #redef fun item=(value)
322 # _node.second = value
334 _node
= _node
._next_item
337 # The map to iterate on
338 var _map
: HashMap[K
, V
]
341 var _node
: nullable HashMapNode[K
, V
]
343 init(map
: HashMap[K
, V
])
346 _node
= map
.first_item
352 special HashCollection[E
, HashSetNode[E
], E
]
354 redef fun is_empty
do return _length
== 0
359 return _first_item
._key
364 return _array
[index_at
(item
)] != null
369 var i
= index_at
(item
)
374 store
(i
,new HashSetNode[E
](item
))
378 redef fun remove
(item
) do remove_index
(index_at
(item
))
380 redef fun clear
do raz
382 redef fun iterator
do return new HashSetIterator[E
](self)
394 redef type N
: HashSetNode[E
]
402 class HashSetIterator[E
]
404 redef fun is_ok
do return _node
!= null
415 _node
= _node
._next_item
418 # The set to iterate on
421 # The position in the internal map storage
422 var _node
: nullable HashSetNode[E
]
424 init(set
: HashSet[E
])
427 _node
= set
._first_item