40 using storage_type = std::vector<std::pair<const K *, T>>;
48 std::pair<const K *, T> &storage_bucket(
int i) {
56 const std::pair<const K *, T> &storage_bucket(
int i)
const {
70 void upgrade_from_empty_to_small() {
71 storage.resize(max_small_size);
75 void upgrade_from_empty_to_large(
int n) {
80 void upgrade_from_small_to_large(
int n) {
81 phm_assert(occupied <= max_small_size) << occupied <<
" " << max_small_size <<
"\n";
86 for (
int i = 0; i < o; i++) {
87 emplace_large(tmp[i].first, std::move(tmp[i].second));
93 T &emplace_empty(
const K *n, T &&t) {
94 upgrade_from_empty_to_small();
95 storage_bucket(0).first = n;
96 storage_bucket(0).second = std::move(t);
98 return storage_bucket(0).second;
101 const T &get_empty(
const K *n)
const {
102 phm_assert(0) <<
"Calling get on an empty PerfectHashMap";
103 return unreachable_value();
106 T &get_empty(
const K *n) {
107 phm_assert(0) <<
"Calling get on an empty PerfectHashMap";
108 return unreachable_value();
111 T &get_or_create_empty(
const K *n) {
113 return emplace_empty(n, T());
116 bool contains_empty(
const K *n)
const {
121 int find_index_small(
const K *n)
const {
123 for (i = 0; i < (int)occupied; i++) {
124 if (storage_bucket(i).first == n) {
131 T &emplace_small(
const K *n, T &&t) {
132 int idx = find_index_small(n);
133 if (idx >= max_small_size) {
134 upgrade_from_small_to_large((
int)(n->max_id));
135 return emplace_large(n, std::move(t));
137 auto &p = storage_bucket(idx);
138 if (p.first ==
nullptr) {
142 p.second = std::move(t);
146 const T &get_small(
const K *n)
const {
147 int idx = find_index_small(n);
148 return storage_bucket(idx).second;
151 T &get_small(
const K *n) {
152 int idx = find_index_small(n);
153 return storage_bucket(idx).second;
156 T &get_or_create_small(
const K *n) {
157 int idx = find_index_small(n);
158 if (idx >= max_small_size) {
159 upgrade_from_small_to_large((
int)(n->max_id));
160 return get_or_create_large(n);
162 auto &p = storage_bucket(idx);
163 if (p.first ==
nullptr) {
170 bool contains_small(
const K *n)
const {
171 int idx = find_index_small(n);
172 return (idx < max_small_size) && (storage_bucket(idx).first == n);
176 T &emplace_large(
const K *n, T &&t) {
177 auto &p = storage_bucket(n->id);
182 p.second = std::move(t);
186 const T &get_large(
const K *n)
const {
187 return storage_bucket(n->id).second;
190 T &get_large(
const K *n) {
191 return storage_bucket(n->id).second;
194 T &get_or_create_large(
const K *n) {
195 auto &p = storage_bucket(n->id);
196 if (p.first ==
nullptr) {
200 return storage_bucket(n->id).second;
203 bool contains_large(
const K *n)
const {
204 return storage_bucket(n->id).first !=
nullptr;
207 void check_key(
const K *n)
const {
217 T &unreachable_value() {
218 return storage_bucket(0).second;
221 const T &unreachable_value()
const {
222 return storage_bucket(0).second;
228 if (state == Empty) {
229 upgrade_from_empty_to_large(n);
230 }
else if (state == Small) {
231 upgrade_from_small_to_large(n);
239 return emplace_empty(n, std::move(t));
241 return emplace_small(n, std::move(t));
243 return emplace_large(n, std::move(t));
245 return unreachable_value();
253 return emplace_empty(n, std::move(tmp));
255 return emplace_small(n, std::move(tmp));
257 return emplace_large(n, std::move(tmp));
259 return unreachable_value();
262 const T &
get(
const K *n)
const {
272 return unreachable_value();
285 return unreachable_value();
292 return get_or_create_empty(n);
294 return get_or_create_small(n);
296 return get_or_create_large(n);
298 return unreachable_value();
305 return contains_empty(n);
307 return contains_small(n);
309 return contains_large(n);
387 if (state == Empty) {
391 it.
iter = storage.data();
392 it.
end = it.
iter + storage.size();
393 if (it.
key() ==
nullptr) {
402 it.
iter = it.
end = storage.data() + storage.size();
407 if (storage.empty()) {
411 it.
iter = storage.data();
412 it.
end = it.
iter + storage.size();
413 if (it.
key() ==
nullptr) {
422 it.
iter = it.
end = storage.data() + storage.size();