13a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton/******************************************************************************
23a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton *
33a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton *  Copyright (C) 2014 Google, Inc.
43a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton *
53a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton *  Licensed under the Apache License, Version 2.0 (the "License");
63a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton *  you may not use this file except in compliance with the License.
73a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton *  You may obtain a copy of the License at:
83a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton *
93a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton *  http://www.apache.org/licenses/LICENSE-2.0
103a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton *
113a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton *  Unless required by applicable law or agreed to in writing, software
123a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton *  distributed under the License is distributed on an "AS IS" BASIS,
133a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
143a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton *  See the License for the specific language governing permissions and
153a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton *  limitations under the License.
163a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton *
173a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton ******************************************************************************/
183a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton
193a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton#include <assert.h>
203a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton#include <list.h>
213a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton#include <hash_map.h>
223a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton
230f9b91e150e153229235c163861198e23600e636Sharvil Nanavati#include "osi/include/allocator.h"
2453f36a45bd5333db3b55f1d7fbcd7a3362027de0Zach Johnson
253a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Mantonstruct hash_map_t;
263a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton
273a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Mantontypedef struct hash_map_bucket_t {
283a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  list_t *list;
293a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton} hash_map_bucket_t;
303a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton
313a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Mantontypedef struct hash_map_t {
323a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  hash_map_bucket_t *bucket;
333a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  size_t num_bucket;
343a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  size_t hash_size;
353a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  hash_index_fn hash_fn;
363a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  key_free_fn key_fn;
373a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  data_free_fn data_fn;
3853f36a45bd5333db3b55f1d7fbcd7a3362027de0Zach Johnson  const allocator_t *allocator;
39aa3a0114b6f018d0dd296d5bdb113d2f881cbc51Zach Johnson  key_equality_fn keys_are_equal;
403a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton} hash_map_t;
413a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton
4253f36a45bd5333db3b55f1d7fbcd7a3362027de0Zach Johnson// Hidden constructor for list, only to be used by us.
4353f36a45bd5333db3b55f1d7fbcd7a3362027de0Zach Johnsonlist_t *list_new_internal(list_free_cb callback, const allocator_t *zeroed_allocator);
4453f36a45bd5333db3b55f1d7fbcd7a3362027de0Zach Johnson
453a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Mantonstatic void bucket_free_(void *data);
46aa3a0114b6f018d0dd296d5bdb113d2f881cbc51Zach Johnsonstatic bool default_key_equality(const void *x, const void *y);
473a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Mantonstatic hash_map_entry_t *find_bucket_entry_(list_t *hash_bucket_list,
483a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton    const void *key);
493a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton
5053f36a45bd5333db3b55f1d7fbcd7a3362027de0Zach Johnson// Hidden constructor, only to be used by the allocation tracker. Behaves the same as
5153f36a45bd5333db3b55f1d7fbcd7a3362027de0Zach Johnson// |hash_map_new|, except you get to specify the allocator.
52aa3a0114b6f018d0dd296d5bdb113d2f881cbc51Zach Johnsonhash_map_t *hash_map_new_internal(
5353f36a45bd5333db3b55f1d7fbcd7a3362027de0Zach Johnson    size_t num_bucket,
5453f36a45bd5333db3b55f1d7fbcd7a3362027de0Zach Johnson    hash_index_fn hash_fn,
5553f36a45bd5333db3b55f1d7fbcd7a3362027de0Zach Johnson    key_free_fn key_fn,
5653f36a45bd5333db3b55f1d7fbcd7a3362027de0Zach Johnson    data_free_fn data_fn,
57aa3a0114b6f018d0dd296d5bdb113d2f881cbc51Zach Johnson    key_equality_fn equality_fn,
5853f36a45bd5333db3b55f1d7fbcd7a3362027de0Zach Johnson    const allocator_t *zeroed_allocator) {
593a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  assert(hash_fn != NULL);
603a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  assert(num_bucket > 0);
6153f36a45bd5333db3b55f1d7fbcd7a3362027de0Zach Johnson  assert(zeroed_allocator != NULL);
623a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton
6353f36a45bd5333db3b55f1d7fbcd7a3362027de0Zach Johnson  hash_map_t *hash_map = zeroed_allocator->alloc(sizeof(hash_map_t));
643a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  if (hash_map == NULL)
653a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton    return NULL;
663a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton
673a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  hash_map->hash_fn = hash_fn;
683a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  hash_map->key_fn = key_fn;
693a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  hash_map->data_fn = data_fn;
7053f36a45bd5333db3b55f1d7fbcd7a3362027de0Zach Johnson  hash_map->allocator = zeroed_allocator;
71aa3a0114b6f018d0dd296d5bdb113d2f881cbc51Zach Johnson  hash_map->keys_are_equal = equality_fn ? equality_fn : default_key_equality;
723a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton
733a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  hash_map->num_bucket = num_bucket;
7453f36a45bd5333db3b55f1d7fbcd7a3362027de0Zach Johnson  hash_map->bucket = zeroed_allocator->alloc(sizeof(hash_map_bucket_t) * num_bucket);
753a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  if (hash_map->bucket == NULL) {
7653f36a45bd5333db3b55f1d7fbcd7a3362027de0Zach Johnson    zeroed_allocator->free(hash_map);
773a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton    return NULL;
783a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  }
793a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  return hash_map;
803a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton}
813a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton
82aa3a0114b6f018d0dd296d5bdb113d2f881cbc51Zach Johnsonhash_map_t *hash_map_new(
8353f36a45bd5333db3b55f1d7fbcd7a3362027de0Zach Johnson    size_t num_bucket,
8453f36a45bd5333db3b55f1d7fbcd7a3362027de0Zach Johnson    hash_index_fn hash_fn,
8553f36a45bd5333db3b55f1d7fbcd7a3362027de0Zach Johnson    key_free_fn key_fn,
86aa3a0114b6f018d0dd296d5bdb113d2f881cbc51Zach Johnson    data_free_fn data_fn,
87aa3a0114b6f018d0dd296d5bdb113d2f881cbc51Zach Johnson    key_equality_fn equality_fn) {
88aa3a0114b6f018d0dd296d5bdb113d2f881cbc51Zach Johnson  return hash_map_new_internal(num_bucket, hash_fn, key_fn, data_fn, equality_fn, &allocator_calloc);
8953f36a45bd5333db3b55f1d7fbcd7a3362027de0Zach Johnson}
9053f36a45bd5333db3b55f1d7fbcd7a3362027de0Zach Johnson
913a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Mantonvoid hash_map_free(hash_map_t *hash_map) {
923a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  if (hash_map == NULL)
933a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton    return;
943a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  hash_map_clear(hash_map);
9553f36a45bd5333db3b55f1d7fbcd7a3362027de0Zach Johnson  hash_map->allocator->free(hash_map->bucket);
9653f36a45bd5333db3b55f1d7fbcd7a3362027de0Zach Johnson  hash_map->allocator->free(hash_map);
973a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton}
983a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton
993a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Mantonbool hash_map_is_empty(const hash_map_t *hash_map) {
1003a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  assert(hash_map != NULL);
1013a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  return (hash_map->hash_size == 0);
1023a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton}
1033a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton
1043a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Mantonsize_t hash_map_size(const hash_map_t *hash_map) {
1053a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  assert(hash_map != NULL);
1063a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  return hash_map->hash_size;
1073a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton}
1083a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton
1093a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Mantonsize_t hash_map_num_buckets(const hash_map_t *hash_map) {
1103a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  assert(hash_map != NULL);
1113a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  return hash_map->num_bucket;
1123a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton}
1133a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton
1143a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Mantonbool hash_map_has_key(const hash_map_t *hash_map, const void *key) {
1153a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  assert(hash_map != NULL);
1163a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton
1173a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  hash_index_t hash_key = hash_map->hash_fn(key) % hash_map->num_bucket;
1183a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  list_t *hash_bucket_list = hash_map->bucket[hash_key].list;
1193a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton
1203a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  hash_map_entry_t *hash_map_entry = find_bucket_entry_(hash_bucket_list, key);
1213a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  return (hash_map_entry != NULL);
1223a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton}
1233a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton
1243a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Mantonbool hash_map_set(hash_map_t *hash_map, const void *key, void *data) {
1253a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  assert(hash_map != NULL);
1263a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  assert(data != NULL);
1273a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton
1283a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  hash_index_t hash_key = hash_map->hash_fn(key) % hash_map->num_bucket;
1293a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton
1303a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  if (hash_map->bucket[hash_key].list == NULL) {
13153f36a45bd5333db3b55f1d7fbcd7a3362027de0Zach Johnson    hash_map->bucket[hash_key].list = list_new_internal(bucket_free_, hash_map->allocator);
1323a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton    if (hash_map->bucket[hash_key].list == NULL)
1333a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton        return false;
1343a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  }
1353a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  list_t *hash_bucket_list = hash_map->bucket[hash_key].list;
1363a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton
1373a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  hash_map_entry_t *hash_map_entry = find_bucket_entry_(hash_bucket_list, key);
1383a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton
1393a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  if (hash_map_entry) {
1403a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton    // Calls hash_map callback to delete the hash_map_entry.
1413a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton    bool rc = list_remove(hash_bucket_list, hash_map_entry);
1423a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton    assert(rc == true);
1433a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  } else {
1443a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton    hash_map->hash_size++;
1453a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  }
14653f36a45bd5333db3b55f1d7fbcd7a3362027de0Zach Johnson  hash_map_entry = hash_map->allocator->alloc(sizeof(hash_map_entry_t));
1473a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  if (hash_map_entry == NULL)
1483a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton    return false;
1493a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton
1503a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  hash_map_entry->key = key;
1513a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  hash_map_entry->data = data;
1523a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  hash_map_entry->hash_map = hash_map;
1533a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton
1543a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  return list_append(hash_bucket_list, hash_map_entry);
1553a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton}
1563a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton
1573a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Mantonbool hash_map_erase(hash_map_t *hash_map, const void *key) {
1583a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  assert(hash_map != NULL);
1593a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton
1603a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  hash_index_t hash_key = hash_map->hash_fn(key) % hash_map->num_bucket;
1613a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  list_t *hash_bucket_list = hash_map->bucket[hash_key].list;
1623a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton
1633a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  hash_map_entry_t *hash_map_entry = find_bucket_entry_(hash_bucket_list, key);
1643a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  if (hash_map_entry == NULL) {
1653a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton    return false;
1663a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  }
1673a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton
1683a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  hash_map->hash_size--;
1693a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton
1703a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  return list_remove(hash_bucket_list, hash_map_entry);
1713a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton}
1723a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton
1734907b5cc919e103202a940af06a85c1f635932b1Zach Johnsonvoid *hash_map_get(const hash_map_t *hash_map, const void *key) {
1743a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  assert(hash_map != NULL);
1753a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton
1763a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  hash_index_t hash_key = hash_map->hash_fn(key) % hash_map->num_bucket;
1773a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  list_t *hash_bucket_list = hash_map->bucket[hash_key].list;
1783a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton
1793a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  hash_map_entry_t *hash_map_entry = find_bucket_entry_(hash_bucket_list, key);
1803a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  if (hash_map_entry != NULL)
1813a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton    return hash_map_entry->data;
1823a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton
1833a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  return NULL;
1843a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton}
1853a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton
1863a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Mantonvoid hash_map_clear(hash_map_t *hash_map) {
1873a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  assert(hash_map != NULL);
1883a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton
1893a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  for (hash_index_t i = 0; i < hash_map->num_bucket; i++){
1903a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton    if (hash_map->bucket[i].list == NULL)
1913a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton      continue;
1923a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton    list_free(hash_map->bucket[i].list);
1933a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton    hash_map->bucket[i].list = NULL;
1943a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  }
1953a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton}
1963a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton
19753d559ca99e93d442d12c548104f939870862ea6Chris Mantonvoid hash_map_foreach(hash_map_t *hash_map, hash_map_iter_cb callback, void *context) {
19853d559ca99e93d442d12c548104f939870862ea6Chris Manton  assert(hash_map != NULL);
19953d559ca99e93d442d12c548104f939870862ea6Chris Manton  assert(callback != NULL);
20053d559ca99e93d442d12c548104f939870862ea6Chris Manton
20153d559ca99e93d442d12c548104f939870862ea6Chris Manton  for (hash_index_t i = 0; i < hash_map->num_bucket; ++i){
20253d559ca99e93d442d12c548104f939870862ea6Chris Manton    if (hash_map->bucket[i].list == NULL)
20353d559ca99e93d442d12c548104f939870862ea6Chris Manton      continue;
20453d559ca99e93d442d12c548104f939870862ea6Chris Manton    for (const list_node_t *iter = list_begin(hash_map->bucket[i].list);
20553d559ca99e93d442d12c548104f939870862ea6Chris Manton        iter != list_end(hash_map->bucket[i].list);
20653d559ca99e93d442d12c548104f939870862ea6Chris Manton        iter = list_next(iter)) {
20753d559ca99e93d442d12c548104f939870862ea6Chris Manton       hash_map_entry_t *hash_map_entry = (hash_map_entry_t *)list_node(iter);
20853d559ca99e93d442d12c548104f939870862ea6Chris Manton       if (!callback(hash_map_entry, context))
20953d559ca99e93d442d12c548104f939870862ea6Chris Manton        return;
21053d559ca99e93d442d12c548104f939870862ea6Chris Manton    }
21153d559ca99e93d442d12c548104f939870862ea6Chris Manton  }
21253d559ca99e93d442d12c548104f939870862ea6Chris Manton}
21353d559ca99e93d442d12c548104f939870862ea6Chris Manton
2143a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Mantonstatic void bucket_free_(void *data) {
2153a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  assert(data != NULL);
2163a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  hash_map_entry_t *hash_map_entry = (hash_map_entry_t *)data;
21753f36a45bd5333db3b55f1d7fbcd7a3362027de0Zach Johnson  const hash_map_t *hash_map = hash_map_entry->hash_map;
2183a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton
21953f36a45bd5333db3b55f1d7fbcd7a3362027de0Zach Johnson  if (hash_map->key_fn)
22053f36a45bd5333db3b55f1d7fbcd7a3362027de0Zach Johnson    hash_map->key_fn((void *)hash_map_entry->key);
22153f36a45bd5333db3b55f1d7fbcd7a3362027de0Zach Johnson  if (hash_map->data_fn)
22253f36a45bd5333db3b55f1d7fbcd7a3362027de0Zach Johnson    hash_map->data_fn(hash_map_entry->data);
22353f36a45bd5333db3b55f1d7fbcd7a3362027de0Zach Johnson  hash_map->allocator->free(hash_map_entry);
2243a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton}
2253a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton
2263a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Mantonstatic hash_map_entry_t * find_bucket_entry_(list_t *hash_bucket_list,
2273a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton    const void *key) {
2283a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton
2293a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  if (hash_bucket_list == NULL)
2303a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton    return NULL;
2313a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton
2323a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  for (const list_node_t *iter = list_begin(hash_bucket_list);
2333a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton      iter != list_end(hash_bucket_list);
2343a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton      iter = list_next(iter)) {
2353a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton    hash_map_entry_t *hash_map_entry = (hash_map_entry_t *)list_node(iter);
236aa3a0114b6f018d0dd296d5bdb113d2f881cbc51Zach Johnson    if (hash_map_entry->hash_map->keys_are_equal(hash_map_entry->key, key)) {
2373a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton      return hash_map_entry;
2383a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton    }
2393a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  }
2403a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton  return NULL;
2413a2ee939c61a1c3f57fa3eb99899ba908c41e7d5Chris Manton}
242aa3a0114b6f018d0dd296d5bdb113d2f881cbc51Zach Johnson
243aa3a0114b6f018d0dd296d5bdb113d2f881cbc51Zach Johnsonstatic bool default_key_equality(const void *x, const void *y) {
244aa3a0114b6f018d0dd296d5bdb113d2f881cbc51Zach Johnson  return x == y;
245aa3a0114b6f018d0dd296d5bdb113d2f881cbc51Zach Johnson}
246