/* * Copyright (c) 2022 Meta * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include #include using cxx_map = std::unordered_map; static void sys_hashmap_cxx_iter_next(struct sys_hashmap_iterator *it) { cxx_map *umap = static_cast(it->map->data->buckets); __ASSERT_NO_MSG(umap != nullptr); __ASSERT(it->size == it->map->data->size, "Concurrent modification!"); __ASSERT(sys_hashmap_iterator_has_next(it), "Attempt to access beyond current bound!"); auto it2 = umap->begin(); for (size_t i = 0; i < it->pos; ++i, it2++) ; it->key = it2->first; it->value = it2->second; ++it->pos; } /* * C++ Wrapped Hashmap API */ static void sys_hashmap_cxx_iter(const struct sys_hashmap *map, struct sys_hashmap_iterator *it) { it->map = map; it->next = sys_hashmap_cxx_iter_next; it->state = nullptr; it->key = 0; it->value = 0; it->pos = 0; *((size_t *)&it->size) = map->data->size; } static void sys_hashmap_cxx_clear(struct sys_hashmap *map, sys_hashmap_callback_t cb, void *cookie) { cxx_map *umap = static_cast(map->data->buckets); if (umap == nullptr) { return; } if (cb != nullptr) { for (auto &kv : *umap) { cb(kv.first, kv.second, cookie); } } delete umap; map->data->buckets = nullptr; map->data->n_buckets = 0; map->data->size = 0; } static int sys_hashmap_cxx_insert(struct sys_hashmap *map, uint64_t key, uint64_t value, uint64_t *old_value) { cxx_map *umap = static_cast(map->data->buckets); if (umap == nullptr) { umap = new cxx_map; umap->max_load_factor(map->config->load_factor / 100.0f); map->data->buckets = umap; } auto it = umap->find(key); if (it != umap->end() && old_value != nullptr) { *old_value = it->second; it->second = value; return 0; } try { (*umap)[key] = value; } catch(...) { return -ENOMEM; } ++map->data->size; map->data->n_buckets = umap->bucket_count(); return 1; } static bool sys_hashmap_cxx_remove(struct sys_hashmap *map, uint64_t key, uint64_t *value) { cxx_map *umap = static_cast(map->data->buckets); if (umap == nullptr) { return false; } auto it = umap->find(key); if (it == umap->end()) { return false; } if (value != nullptr) { *value = it->second; } umap->erase(key); --map->data->size; map->data->n_buckets = umap->bucket_count(); if (map->data->size == 0) { delete umap; map->data->n_buckets = 0; map->data->buckets = nullptr; } return true; } static bool sys_hashmap_cxx_get(const struct sys_hashmap *map, uint64_t key, uint64_t *value) { cxx_map *umap = static_cast(map->data->buckets); if (umap == nullptr) { return false; } auto it = umap->find(key); if (it == umap->end()) { return false; } if (value != nullptr) { *value = it->second; } return true; } extern "C" { const struct sys_hashmap_api sys_hashmap_cxx_api = { .iter = sys_hashmap_cxx_iter, .clear = sys_hashmap_cxx_clear, .insert = sys_hashmap_cxx_insert, .remove = sys_hashmap_cxx_remove, .get = sys_hashmap_cxx_get, }; }