24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
26 * POSSIBILITY OF SUCH DAMAGE. |
26 * POSSIBILITY OF SUCH DAMAGE. |
27 */ |
27 */ |
28 |
28 |
29 #include <string.h> |
|
30 #include "cx/hash_map.h" |
29 #include "cx/hash_map.h" |
31 #include "cx/utils.h" |
30 #include "cx/utils.h" |
|
31 |
|
32 #include <string.h> |
|
33 #include <assert.h> |
32 |
34 |
33 struct cx_hash_map_element_s { |
35 struct cx_hash_map_element_s { |
34 /** A pointer to the next element in the current bucket. */ |
36 /** A pointer to the next element in the current bucket. */ |
35 struct cx_hash_map_element_s *next; |
37 struct cx_hash_map_element_s *next; |
36 |
38 |
332 } else { |
334 } else { |
333 return false; |
335 return false; |
334 } |
336 } |
335 } |
337 } |
336 |
338 |
337 static CxIterator cx_hash_map_iterator(CxMap const *map) { |
339 static CxIterator cx_hash_map_iterator( |
|
340 CxMap const *map, |
|
341 enum cx_map_iterator_type type |
|
342 ) { |
338 CxIterator iter; |
343 CxIterator iter; |
339 |
344 |
340 iter.src_handle = map; |
345 iter.src_handle = map; |
341 iter.base.valid = cx_hash_map_iter_valid; |
346 iter.base.valid = cx_hash_map_iter_valid; |
342 iter.base.next = cx_hash_map_iter_next; |
347 iter.base.next = cx_hash_map_iter_next; |
343 iter.base.current = cx_hash_map_iter_current_entry; |
348 |
|
349 switch (type) { |
|
350 case CX_MAP_ITERATOR_PAIRS: |
|
351 iter.base.current = cx_hash_map_iter_current_entry; |
|
352 break; |
|
353 case CX_MAP_ITERATOR_KEYS: |
|
354 iter.base.current = cx_hash_map_iter_current_key; |
|
355 break; |
|
356 case CX_MAP_ITERATOR_VALUES: |
|
357 iter.base.current = cx_hash_map_iter_current_value; |
|
358 break; |
|
359 default: |
|
360 assert(false); |
|
361 } |
|
362 |
344 iter.base.flag_removal = cx_hash_map_iter_flag_rm; |
363 iter.base.flag_removal = cx_hash_map_iter_flag_rm; |
345 iter.base.remove = false; |
364 iter.base.remove = false; |
346 iter.base.mutating = false; |
365 iter.base.mutating = false; |
347 |
366 |
348 iter.slot = 0; |
367 iter.slot = 0; |
365 iter.elem_handle = NULL; |
384 iter.elem_handle = NULL; |
366 iter.kv_data.key = NULL; |
385 iter.kv_data.key = NULL; |
367 iter.kv_data.value = NULL; |
386 iter.kv_data.value = NULL; |
368 } |
387 } |
369 |
388 |
370 return iter; |
|
371 } |
|
372 |
|
373 static CxIterator cx_hash_map_iterator_keys(CxMap const *map) { |
|
374 CxIterator iter = cx_hash_map_iterator(map); |
|
375 iter.base.current = cx_hash_map_iter_current_key; |
|
376 return iter; |
|
377 } |
|
378 |
|
379 static CxIterator cx_hash_map_iterator_values(CxMap const *map) { |
|
380 CxIterator iter = cx_hash_map_iterator(map); |
|
381 iter.base.current = cx_hash_map_iter_current_value; |
|
382 return iter; |
|
383 } |
|
384 |
|
385 static CxMutIterator cx_hash_map_mut_iterator(CxMap *map) { |
|
386 CxIterator it = cx_hash_map_iterator(map); |
|
387 it.base.mutating = true; |
|
388 |
|
389 // we know the iterators share the same memory layout |
|
390 CxMutIterator iter; |
|
391 memcpy(&iter, &it, sizeof(CxMutIterator)); |
|
392 return iter; |
|
393 } |
|
394 |
|
395 static CxMutIterator cx_hash_map_mut_iterator_keys(CxMap *map) { |
|
396 CxMutIterator iter = cx_hash_map_mut_iterator(map); |
|
397 iter.base.current = cx_hash_map_iter_current_key; |
|
398 return iter; |
|
399 } |
|
400 |
|
401 static CxMutIterator cx_hash_map_mut_iterator_values(CxMap *map) { |
|
402 CxMutIterator iter = cx_hash_map_mut_iterator(map); |
|
403 iter.base.current = cx_hash_map_iter_current_value; |
|
404 return iter; |
389 return iter; |
405 } |
390 } |
406 |
391 |
407 static cx_map_class cx_hash_map_class = { |
392 static cx_map_class cx_hash_map_class = { |
408 cx_hash_map_destructor, |
393 cx_hash_map_destructor, |
409 cx_hash_map_clear, |
394 cx_hash_map_clear, |
410 cx_hash_map_put, |
395 cx_hash_map_put, |
411 cx_hash_map_get, |
396 cx_hash_map_get, |
412 cx_hash_map_remove, |
397 cx_hash_map_remove, |
413 cx_hash_map_iterator, |
398 cx_hash_map_iterator, |
414 cx_hash_map_iterator_keys, |
|
415 cx_hash_map_iterator_values, |
|
416 cx_hash_map_mut_iterator, |
|
417 cx_hash_map_mut_iterator_keys, |
|
418 cx_hash_map_mut_iterator_values, |
|
419 }; |
399 }; |
420 |
400 |
421 CxMap *cxHashMapCreate( |
401 CxMap *cxHashMapCreate( |
422 CxAllocator const *allocator, |
402 CxAllocator const *allocator, |
423 size_t itemsize, |
403 size_t itemsize, |