The open source OpenXR runtime
1// Copyright 2019-2020, Collabora, Ltd.
2// SPDX-License-Identifier: BSL-1.0
3/*!
4 * @file
5 * @brief Hashset struct header.
6 * @author Jakob Bornecrantz <jakob@collabora.com>
7 * @ingroup aux_util
8 */
9
10#include "util/u_misc.h"
11#include "util/u_hashset.h"
12
13#include <cstring>
14#include <string>
15#include <unordered_map>
16#include <vector>
17
18
19/*
20 *
21 * Private structs and defines.
22 *
23 */
24
25struct u_hashset
26{
27 std::unordered_map<std::string, struct u_hashset_item *> map = {};
28};
29
30
31/*
32 *
33 * "Exported" functions.
34 *
35 */
36
37extern "C" int
38u_hashset_create(struct u_hashset **out_hashset)
39{
40 auto *hs = new u_hashset;
41 *out_hashset = hs;
42 return 0;
43}
44
45extern "C" int
46u_hashset_destroy(struct u_hashset **hs)
47{
48 delete *hs;
49 *hs = NULL;
50 return 0;
51}
52
53extern "C" int
54u_hashset_find_str(struct u_hashset *hs, const char *str, size_t length, struct u_hashset_item **out_item)
55{
56 std::string key = std::string(str, length);
57 auto search = hs->map.find(key);
58
59 if (search != hs->map.end()) {
60 *out_item = search->second;
61 return 0;
62 }
63 return -1;
64}
65
66extern "C" int
67u_hashset_find_c_str(struct u_hashset *hs, const char *c_str, struct u_hashset_item **out_item)
68{
69 size_t length = strlen(c_str);
70 return u_hashset_find_str(hs, c_str, length, out_item);
71}
72
73extern "C" int
74u_hashset_insert_item(struct u_hashset *hs, struct u_hashset_item *item)
75{
76 std::string key = std::string(item->c_str(), item->length);
77 hs->map[key] = item;
78 return 0;
79}
80
81extern "C" int
82u_hashset_create_and_insert_str(struct u_hashset *hs, const char *str, size_t length, struct u_hashset_item **out_item)
83{
84 struct u_hashset_item *unused = NULL;
85 struct u_hashset_item *item = NULL;
86 size_t size = 0;
87 int ret;
88
89 ret = u_hashset_find_str(hs, str, length, &unused);
90 if (ret >= 0) {
91 return -1;
92 }
93
94 size += sizeof(struct u_hashset_item); // Hashset item.
95 size += length; // String.
96 size += 1; // Null terminate it.
97
98 // Now allocate and setup the path.
99 item = U_CALLOC_WITH_CAST(struct u_hashset_item, size);
100 if (item == NULL) {
101 return -1;
102 }
103
104 item->length = length;
105 // Yes a const cast! D:
106 char *store = const_cast<char *>(item->c_str());
107 for (size_t i = 0; i < length; i++) {
108 store[i] = str[i];
109 }
110 store[length] = '\0';
111
112 std::string key = std::string(item->c_str(), item->length);
113 hs->map[key] = item;
114
115 *out_item = item;
116
117 return 0;
118}
119
120extern "C" int
121u_hashset_create_and_insert_str_c(struct u_hashset *hs, const char *c_str, struct u_hashset_item **out_item)
122{
123 size_t length = strlen(c_str);
124 return u_hashset_create_and_insert_str(hs, c_str, length, out_item);
125}
126
127extern "C" int
128u_hashset_erase_item(struct u_hashset *hs, struct u_hashset_item *item)
129{
130 std::string key = std::string(item->c_str(), item->length);
131 hs->map.erase(key);
132 return 0;
133}
134
135extern "C" int
136u_hashset_erase_str(struct u_hashset *hs, const char *str, size_t length)
137{
138 std::string key = std::string(str, length);
139 hs->map.erase(key);
140 return 0;
141}
142
143extern "C" int
144u_hashset_erase_c_str(struct u_hashset *hs, const char *c_str)
145{
146 size_t length = strlen(c_str);
147 return u_hashset_erase_str(hs, c_str, length);
148}
149
150extern "C" void
151u_hashset_clear_and_call_for_each(struct u_hashset *hs, u_hashset_callback cb, void *priv)
152{
153 std::vector<struct u_hashset_item *> tmp;
154 tmp.reserve(hs->map.size());
155
156 for (auto &n : hs->map) {
157 tmp.push_back(n.second);
158 }
159
160 hs->map.clear();
161
162 for (auto *n : tmp) {
163 cb(n, priv);
164 }
165}