From a36565c5b7d921fbfd6e0d0383be65419e04c25c Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Sat, 6 Apr 2019 12:33:01 +0100 Subject: [PATCH] aux/util: Add string hashset --- src/xrt/auxiliary/CMakeLists.txt | 2 + src/xrt/auxiliary/util/u_hashset.cpp | 125 +++++++++++++++++++++++++++ src/xrt/auxiliary/util/u_hashset.h | 88 +++++++++++++++++++ 3 files changed, 215 insertions(+) create mode 100644 src/xrt/auxiliary/util/u_hashset.cpp create mode 100644 src/xrt/auxiliary/util/u_hashset.h diff --git a/src/xrt/auxiliary/CMakeLists.txt b/src/xrt/auxiliary/CMakeLists.txt index 8e7ce6be8..00a15b9a1 100644 --- a/src/xrt/auxiliary/CMakeLists.txt +++ b/src/xrt/auxiliary/CMakeLists.txt @@ -18,6 +18,8 @@ set(SOURCE_FILES util/u_device.c util/u_device.h util/u_documentation.h + util/u_hashset.cpp + util/u_hashset.h util/u_time.cpp util/u_time.h ) diff --git a/src/xrt/auxiliary/util/u_hashset.cpp b/src/xrt/auxiliary/util/u_hashset.cpp new file mode 100644 index 000000000..694fdfc90 --- /dev/null +++ b/src/xrt/auxiliary/util/u_hashset.cpp @@ -0,0 +1,125 @@ +// Copyright 2019, Collabora, Ltd. +// SPDX-License-Identifier: BSL-1.0 +/*! + * @file + * @brief Hashset struct header. + * @author Jakob Bornecrantz + * @ingroup aux_util + */ + +#include "util/u_hashset.h" + +#include +#include +#include + + +/* + * + * Private structs and defines. + * + */ + +struct u_hashset +{ + std::unordered_map map = {}; +}; + + +/* + * + * "Exported" functions. + * + */ + +extern "C" int +u_hashset_create(struct u_hashset **out_hashset) +{ + auto hs = new u_hashset; + *out_hashset = hs; + return 0; +} + +extern "C" int +u_hashset_destroy(struct u_hashset **hs) +{ + delete *hs; + *hs = NULL; + return 0; +} + +extern "C" int +u_hashset_find_str(struct u_hashset *hs, + const char *str, + size_t length, + struct u_hashset_item **out_item) +{ + std::string key = std::string(str, length); + auto search = hs->map.find(key); + + if (search != hs->map.end()) { + *out_item = search->second; + return 0; + } else { + return -1; + } +} + +extern "C" int +u_hashset_find_c_str(struct u_hashset *hs, + const char *c_str, + struct u_hashset_item **out_item) +{ + size_t length = strlen(c_str); + return u_hashset_find_str(hs, c_str, length, out_item); +} + +extern "C" int +u_hashset_insert_item(struct u_hashset *hs, struct u_hashset_item *item) +{ + std::string key = std::string(item->c_str, item->length); + hs->map[key] = item; + return 0; +} + +extern "C" int +u_hashset_erase_item(struct u_hashset *hs, struct u_hashset_item *item) +{ + std::string key = std::string(item->c_str, item->length); + hs->map.erase(key); + return 0; +} + +extern "C" int +u_hashset_erase_str(struct u_hashset *hs, const char *str, size_t length) +{ + std::string key = std::string(str, length); + hs->map.erase(key); + return 0; +} + +extern "C" int +u_hashset_erase_c_str(struct u_hashset *hs, const char *c_str) +{ + size_t length = strlen(c_str); + return u_hashset_erase_str(hs, c_str, length); +} + +extern "C" void +u_hashset_clear_and_call_for_each(struct u_hashset *hs, + u_hashset_callback cb, + void *priv) +{ + std::vector tmp; + tmp.reserve(hs->map.size()); + + for (auto &n : hs->map) { + tmp.push_back(n.second); + } + + hs->map.clear(); + + for (auto n : tmp) { + cb(n, priv); + } +} diff --git a/src/xrt/auxiliary/util/u_hashset.h b/src/xrt/auxiliary/util/u_hashset.h new file mode 100644 index 000000000..61ab4f25e --- /dev/null +++ b/src/xrt/auxiliary/util/u_hashset.h @@ -0,0 +1,88 @@ +// Copyright 2019, Collabora, Ltd. +// SPDX-License-Identifier: BSL-1.0 +/*! + * @file + * @brief Hashset struct header. + * @author Jakob Bornecrantz + * @ingroup aux_util + */ + +#pragma once + +#include "xrt/xrt_compiler.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/*! + * @struct u_hashset + * @ingroup aux_util + * + * Kind of bespoke hashset implementation, where the user is responsible for + * allocating and freeing the items themselves. + * + * This allows embedding the @ref u_hashset_item at the end of structs. + */ +struct u_hashset; + +/*! + * A embeddable hashset item, note that the string directly follows the + * @ref u_hashset_item. + * + * @ingroup aux_util + */ +struct u_hashset_item +{ + size_t hash; + size_t length; + const char c_str[]; +}; + +typedef void (*u_hashset_callback)(struct u_hashset_item *item, void *priv); + +int +u_hashset_create(struct u_hashset **out_hashset); + +int +u_hashset_destroy(struct u_hashset **hs); + +int +u_hashset_find_str(struct u_hashset *hs, + const char *str, + size_t length, + struct u_hashset_item **out_item); + +int +u_hashset_find_c_str(struct u_hashset *hs, + const char *c_str, + struct u_hashset_item **out_item); + +int +u_hashset_insert_item(struct u_hashset *hs, struct u_hashset_item *item); + +int +u_hashset_erase_item(struct u_hashset *hs, struct u_hashset_item *item); + +int +u_hashset_erase_str(struct u_hashset *hs, const char *str, size_t length); + +int +u_hashset_erase_c_str(struct u_hashset *hs, const char *c_str); + +/*! + * First clear the hashset and then call the given callback with each item that + * was in the hashset. + * + * @ingroup aux_util + */ +void +u_hashset_clear_and_call_for_each(struct u_hashset *hs, + u_hashset_callback cb, + void *priv); + + +#ifdef __cplusplus +} +#endif