rs_alloc/
hashmap.rs

1//
2// Copyright 2020-Present (c) Raja Lehtihet & Wael El Oraiby
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are met:
6//
7// 1. Redistributions of source code must retain the above copyright notice,
8// this list of conditions and the following disclaimer.
9//
10// 2. Redistributions in binary form must reproduce the above copyright notice,
11// this list of conditions and the following disclaimer in the documentation
12// and/or other materials provided with the distribution.
13//
14// 3. Neither the name of the copyright holder nor the names of its contributors
15// may be used to endorse or promote products derived from this software without
16// specific prior written permission.
17//
18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28// POSSIBILITY OF SUCH DAMAGE.
29//
30
31use core::*;
32use crate::*;
33use crate::hash::*;
34
35
36struct KeyValue<K : Hash + PartialEq, V> {
37    hash    : usize,
38    key     : K,
39    value   : V,
40}
41
42impl<K: Hash + PartialEq, V> KeyValue<K, V> {
43    pub fn is_empty(&self) -> bool { self.hash == 0 }
44}
45
46pub struct HashMap<K: Hash + PartialEq, V> {
47    table   : Unique<KeyValue<K, V>>,
48    capacity: usize,
49    count   : usize,
50}
51
52impl<K: Hash + PartialEq, V> HashMap<K, V> {
53    pub fn new() -> Self {
54        Self {
55            table   : Unique::new(ptr::null_mut()),
56            count   : 0,
57            capacity: 0,
58        }
59    }
60
61    pub fn count(&self) -> usize { self.count }
62
63    #[inline]
64    fn hash(k: &K) -> usize {
65        match k.hash() {
66            0 => 1,
67            h => h,
68        }
69    }
70
71    #[inline]
72    fn next(&self, index: isize) -> isize {
73        let mut ret = index - 1;
74        if ret < 0 { ret += self.capacity as isize }
75        ret
76    }
77
78    fn unchecked_set(&mut self, k: K, v: V) {
79        let hash    = Self::hash(&k);
80        let mut index   = (hash & (self.capacity - 1)) as isize;
81        let entries = unsafe { core::slice::from_raw_parts_mut(self.table.get_mut_ptr(), self.capacity) };
82
83        for _ in 0..self.capacity {
84            let mut e = &mut entries[index as usize];
85            if e.is_empty() {
86                e.key   = k;
87                e.value = v;
88                e.hash  = hash;
89                self.count += 1;
90                return;
91            }
92
93            if hash == e.hash && k == e.key {
94                e.value = v;
95                return;
96            }
97
98            index = self.next(index);
99        }
100        panic!("uncheckedSet shouldn't reach this point");
101    }
102
103    fn new_with_cap(cap: usize) -> Self {
104        Self {
105            table   : Unique::new(unsafe { alloc_array_zeroed(cap) }),
106            count   : 0,
107            capacity: cap,
108        }
109    }
110
111    fn grow(&mut self, new_cap: usize) {
112        let old_entries  = unsafe { core::slice::from_raw_parts(self.table.get_ptr(), self.capacity) };
113        let mut new_hm   = HashMap::<K, V>::new_with_cap(new_cap);
114        for o in old_entries {
115            if !o.is_empty() {
116                unsafe {
117                new_hm.unchecked_set(::core::ptr::read_unaligned(&o.key),
118                                   ::core::ptr::read_unaligned(&o.value));
119                }
120            }
121        }
122
123        unsafe { free_array_ptr(self.table.get_mut_ptr(), self.capacity) };
124        self.count  = 0;
125        self.capacity = 0;
126
127        *self = new_hm;
128    }
129
130    pub fn set(&mut self, k: K, v: V) {
131        if 4 * self.count >= 3 * self.capacity {
132            self.grow(if self.capacity == 0 { 4 } else { self.capacity * 2 });
133        }
134        self.unchecked_set(k, v)
135    }
136
137    pub fn exist(&self, k: K) -> bool {
138        let hash = Self::hash(&k);
139        let mut index   = (hash & (self.capacity - 1)) as isize;
140        let entries = unsafe { core::slice::from_raw_parts(self.table.get_ptr(), self.capacity) };
141
142        for _ in 0..self.capacity {
143            let e = &entries[index as usize];
144            if e.is_empty() {
145                return false;
146            }
147
148            if hash == e.hash && k == e.key {
149                return true;
150            }
151
152            index = self.next(index);
153        }
154        false
155    }
156
157    pub fn get(&self, k: K) -> Option<&V> {
158        let hash = Self::hash(&k);
159        let mut index   = (hash & (self.capacity - 1)) as isize;
160        let entries = unsafe { core::slice::from_raw_parts(self.table.get_ptr(), self.capacity) };
161
162        for _ in 0..self.capacity {
163            let e = &entries[index as usize];
164            if e.is_empty() {
165                return None;
166            }
167
168            if hash == e.hash && k == e.key {
169                return Some(&e.value);
170            }
171
172            index = self.next(index);
173        }
174        None
175    }
176
177    pub fn remove(&mut self, k: K) {
178        let hash = Self::hash(&k);
179        let mut index   = (hash & (self.capacity - 1)) as isize;
180        let entries = unsafe { core::slice::from_raw_parts_mut(self.table.get_mut_ptr(), self.capacity) };
181
182        for _ in 0..self.capacity {
183            let e = &entries[index as usize];
184            if e.is_empty() {
185                return;
186            }
187
188            if hash == e.hash && k == e.key {
189                self.count -= 1;
190                break;
191            }
192
193            index = self.next(index);
194        }
195
196        loop {
197            let empty_index = index;
198            let mut original_index;
199            loop {
200                index = self.next(index);
201                let s = &entries[index as usize];
202                if s.is_empty() {
203                    entries[empty_index as usize].hash = 0;
204                    unsafe { ::core::ptr::read_unaligned(&entries[empty_index as usize]) };  // drop it!
205                    return;
206                }
207
208                original_index   = (s.hash & (self.capacity - 1)) as isize;
209
210                if ! ((index <= original_index && original_index < empty_index)
211                    || (original_index < empty_index && empty_index < index)
212                    || (empty_index < index && index <= original_index)) {
213                    break;
214                }
215            }
216
217            entries[empty_index as usize] = unsafe { ::core::ptr::read_unaligned(&entries[index as usize]) };
218            entries[index as usize].hash = 0;
219        }
220    }
221}
222
223impl<K : Hash + PartialEq, V> Drop for HashMap<K, V> {
224    fn drop(&mut self) {
225            if self.capacity > 0 {
226            let arr      = unsafe { core::slice::from_raw_parts_mut(self.table.get_mut_ptr(), self.capacity) };
227            for kv in arr {
228                if !kv.is_empty() {
229                    unsafe { ptr::drop_in_place(&kv.key as *const K as *mut K) };
230                    unsafe { ptr::drop_in_place(&kv.value as *const V as *mut V) };
231                }
232            }
233            unsafe { free_array_ptr(self.table.get_mut_ptr(), self.capacity) }
234        }
235    }
236}
237
238impl Hash for i32 {
239    fn hash(&self) -> usize { *self as usize }
240}
241
242#[cfg(test)]
243mod test {
244    use super::*;
245    use crate::vec::*;
246
247    #[test]
248    fn test_insert() {
249        let mut hm = HashMap::<i32, i32>::new();
250        for i in 0..100 {
251            hm.set(i, i * 2);
252        }
253
254        for i in 0..100 {
255            let ret = hm.get(i);
256            assert!(ret.is_some());
257            match ret {
258                Some(o) => assert!(*o == i * 2),
259                None => assert!(false)
260            }
261        }
262    }
263
264    #[test]
265    fn test_remove() {
266        let mut hm = HashMap::<i32, i32>::new();
267        for i in 0..100 {
268            hm.set(i, i * 2);
269        }
270
271        for i in 45..55 {
272            hm.remove(i);
273            assert!(hm.exist(i) == false);
274        }
275
276        for i in 0..45 {
277            let ret = hm.get(i);
278            assert!(ret.is_some());
279            match ret {
280                Some(o) => assert!(*o == i * 2),
281                None => assert!(false)
282            }
283        }
284
285        for i in 55..100 {
286            let ret = hm.get(i);
287            assert!(ret.is_some());
288            match ret {
289                Some(o) => assert!(*o == i * 2),
290                None => assert!(false)
291            }
292        }
293
294        for i in 45..55 {
295            assert!(hm.exist(i) == false);
296        }
297
298        assert!(hm.count() == 90);
299    }
300
301    #[test]
302    fn test_vec_insert() {
303        let mut hm = HashMap::<i32, Vec<i32>>::new();
304        for i in 0..100 {
305            let mut v = Vec::new();
306            for j in 0..i * 2 {
307                v.push(j);
308            }
309            hm.set(i, v);
310        }
311
312        for i in 0..100 {
313            let ret = hm.get(i);
314            assert!(ret.is_some());
315            match ret {
316                Some(o) => {
317                    for j in 0..i*2 {
318                        assert!((*o)[j as usize] == j)
319                    }
320                }
321                None => assert!(false)
322            }
323        }
324    }
325/*
326    #[test]
327    fn test_vec_remove() {
328        let mut hm = HashMap::<i32, Vec<i32>>::new();
329        for i in 0..100 {
330            let mut v = Vec::new();
331            for j in 0..i * 2 {
332                v.push(j);
333            }
334            hm.set(i, v);
335        }
336
337        for i in 45..55 {
338            hm.remove(i);
339            assert!(hm.exist(i) == false);
340        }
341
342        for i in 0..45 {
343            let ret = hm.get(i);
344            assert!(ret.is_some());
345            match ret {
346                Some(o) => {
347                    for j in 0..i*2 {
348                        assert!((*o)[j as usize] == j)
349                    }
350                },
351                None => assert!(false)
352            }
353        }
354
355        for i in 55..100 {
356            let ret = hm.get(i);
357            assert!(ret.is_some());
358            match ret {
359                Some(o) => {
360                    for j in 0..i*2 {
361                        assert!((*o)[j as usize] == j)
362                    }
363                },
364                None => assert!(false)
365            }
366        }
367
368        for i in 45..55 {
369            assert!(hm.exist(i) == false);
370        }
371
372        assert!(hm.count() == 90);
373    }
374*/
375}