forked from zephyrproject-rtos/zephyr
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhash_map_cxx.cpp
157 lines (123 loc) · 3.07 KB
/
hash_map_cxx.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/*
* Copyright (c) 2022 Meta
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <memory>
#include <unordered_map>
#include <zephyr/sys/hash_map.h>
#include <zephyr/sys/hash_map_cxx.h>
using cxx_map = std::unordered_map<uint64_t, uint64_t>;
static void sys_hashmap_cxx_iter_next(struct sys_hashmap_iterator *it)
{
cxx_map *umap = static_cast<cxx_map *>(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<cxx_map *>(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<cxx_map *>(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<cxx_map *>(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<cxx_map *>(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,
};
}