Mercurial > repos > rliterman > csp2
comparison CSP2/CSP2_env/env-d9b9114564458d9d-741b3de822f2aaca6c6caa4325c4afce/include/kj/map.h @ 69:33d812a61356
planemo upload commit 2e9511a184a1ca667c7be0c6321a36dc4e3d116d
author | jpayne |
---|---|
date | Tue, 18 Mar 2025 17:55:14 -0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
67:0e9998148a16 | 69:33d812a61356 |
---|---|
1 // Copyright (c) 2018 Kenton Varda and contributors | |
2 // Licensed under the MIT License: | |
3 // | |
4 // Permission is hereby granted, free of charge, to any person obtaining a copy | |
5 // of this software and associated documentation files (the "Software"), to deal | |
6 // in the Software without restriction, including without limitation the rights | |
7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
8 // copies of the Software, and to permit persons to whom the Software is | |
9 // furnished to do so, subject to the following conditions: | |
10 // | |
11 // The above copyright notice and this permission notice shall be included in | |
12 // all copies or substantial portions of the Software. | |
13 // | |
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
20 // THE SOFTWARE. | |
21 | |
22 #pragma once | |
23 | |
24 #include "table.h" | |
25 #include "hash.h" | |
26 | |
27 KJ_BEGIN_HEADER | |
28 | |
29 namespace kj { | |
30 | |
31 template <typename Key, typename Value> | |
32 class HashMap { | |
33 // A key/value mapping backed by hashing. | |
34 // | |
35 // `Key` must be hashable (via a `.hashCode()` method or `KJ_HASHCODE()`; see `hash.h`) and must | |
36 // implement `operator==()`. Additionally, when performing lookups, you can use key types other | |
37 // than `Key` as long as the other type is also hashable (producing the same hash codes) and | |
38 // there is an `operator==` implementation with `Key` on the left and that other type on the | |
39 // right. For example, if the key type is `String`, you can pass `StringPtr` to `find()`. | |
40 | |
41 public: | |
42 void reserve(size_t size); | |
43 // Pre-allocates space for a map of the given size. | |
44 | |
45 size_t size() const; | |
46 size_t capacity() const; | |
47 void clear(); | |
48 | |
49 struct Entry { | |
50 Key key; | |
51 Value value; | |
52 }; | |
53 | |
54 Entry* begin(); | |
55 Entry* end(); | |
56 const Entry* begin() const; | |
57 const Entry* end() const; | |
58 // Deterministic iteration. If you only ever insert(), iteration order will be insertion order. | |
59 // If you erase(), the erased element is swapped with the last element in the ordering. | |
60 | |
61 Entry& insert(Key key, Value value); | |
62 // Inserts a new entry. Throws if the key already exists. | |
63 | |
64 template <typename Collection> | |
65 void insertAll(Collection&& collection); | |
66 // Given an iterable collection of `Entry`s, inserts all of them into this map. If the | |
67 // input is an rvalue, the entries will be moved rather than copied. | |
68 | |
69 template <typename UpdateFunc> | |
70 Entry& upsert(Key key, Value value, UpdateFunc&& update); | |
71 Entry& upsert(Key key, Value value); | |
72 // Tries to insert a new entry. However, if a duplicate already exists (according to some index), | |
73 // then update(Value& existingValue, Value&& newValue) is called to modify the existing value. | |
74 // If no function is provided, the default is to simply replace the value (but not the key). | |
75 | |
76 template <typename KeyLike> | |
77 kj::Maybe<Value&> find(KeyLike&& key); | |
78 template <typename KeyLike> | |
79 kj::Maybe<const Value&> find(KeyLike&& key) const; | |
80 // Search for a matching key. The input does not have to be of type `Key`; it merely has to | |
81 // be something that the Hasher accepts. | |
82 // | |
83 // Note that the default hasher for String accepts StringPtr. | |
84 | |
85 template <typename KeyLike, typename Func> | |
86 Value& findOrCreate(KeyLike&& key, Func&& createEntry); | |
87 // Like find() but if the key isn't present then call createEntry() to create the corresponding | |
88 // entry and insert it. createEntry() must return type `Entry`. | |
89 | |
90 template <typename KeyLike> | |
91 kj::Maybe<Entry&> findEntry(KeyLike&& key); | |
92 template <typename KeyLike> | |
93 kj::Maybe<const Entry&> findEntry(KeyLike&& key) const; | |
94 template <typename KeyLike, typename Func> | |
95 Entry& findOrCreateEntry(KeyLike&& key, Func&& createEntry); | |
96 // Sometimes you need to see the whole matching Entry, not just the Value. | |
97 | |
98 template <typename KeyLike> | |
99 bool erase(KeyLike&& key); | |
100 // Erase the entry with the matching key. | |
101 // | |
102 // WARNING: This invalidates all pointers and iterators into the map. Use eraseAll() if you need | |
103 // to iterate and erase multiple entries. | |
104 | |
105 void erase(Entry& entry); | |
106 // Erase an entry by reference. | |
107 | |
108 Entry release(Entry& row); | |
109 // Erase an entry and return its content by move. | |
110 | |
111 template <typename Predicate, | |
112 typename = decltype(instance<Predicate>()(instance<Key&>(), instance<Value&>()))> | |
113 size_t eraseAll(Predicate&& predicate); | |
114 // Erase all values for which predicate(key, value) returns true. This scans over the entire map. | |
115 | |
116 private: | |
117 class Callbacks { | |
118 public: | |
119 inline const Key& keyForRow(const Entry& entry) const { return entry.key; } | |
120 inline Key& keyForRow(Entry& entry) const { return entry.key; } | |
121 | |
122 template <typename KeyLike> | |
123 inline bool matches(Entry& e, KeyLike&& key) const { | |
124 return e.key == key; | |
125 } | |
126 template <typename KeyLike> | |
127 inline bool matches(const Entry& e, KeyLike&& key) const { | |
128 return e.key == key; | |
129 } | |
130 template <typename KeyLike> | |
131 inline auto hashCode(KeyLike&& key) const { | |
132 return kj::hashCode(key); | |
133 } | |
134 }; | |
135 | |
136 kj::Table<Entry, HashIndex<Callbacks>> table; | |
137 }; | |
138 | |
139 template <typename Key, typename Value> | |
140 class TreeMap { | |
141 // A key/value mapping backed by a B-tree. | |
142 // | |
143 // `Key` must support `operator<` and `operator==` against other Keys, and against any type | |
144 // which you might want to pass to find() (with `Key` always on the left of the comparison). | |
145 | |
146 public: | |
147 void reserve(size_t size); | |
148 // Pre-allocates space for a map of the given size. | |
149 | |
150 size_t size() const; | |
151 size_t capacity() const; | |
152 void clear(); | |
153 | |
154 struct Entry { | |
155 Key key; | |
156 Value value; | |
157 }; | |
158 | |
159 auto begin(); | |
160 auto end(); | |
161 auto begin() const; | |
162 auto end() const; | |
163 // Iteration is in sorted order by key. | |
164 | |
165 Entry& insert(Key key, Value value); | |
166 // Inserts a new entry. Throws if the key already exists. | |
167 | |
168 template <typename Collection> | |
169 void insertAll(Collection&& collection); | |
170 // Given an iterable collection of `Entry`s, inserts all of them into this map. If the | |
171 // input is an rvalue, the entries will be moved rather than copied. | |
172 | |
173 template <typename UpdateFunc> | |
174 Entry& upsert(Key key, Value value, UpdateFunc&& update); | |
175 Entry& upsert(Key key, Value value); | |
176 // Tries to insert a new entry. However, if a duplicate already exists (according to some index), | |
177 // then update(Value& existingValue, Value&& newValue) is called to modify the existing value. | |
178 // If no function is provided, the default is to simply replace the value (but not the key). | |
179 | |
180 template <typename KeyLike> | |
181 kj::Maybe<Value&> find(KeyLike&& key); | |
182 template <typename KeyLike> | |
183 kj::Maybe<const Value&> find(KeyLike&& key) const; | |
184 // Search for a matching key. The input does not have to be of type `Key`; it merely has to | |
185 // be something that can be compared against `Key`. | |
186 | |
187 template <typename KeyLike, typename Func> | |
188 Value& findOrCreate(KeyLike&& key, Func&& createEntry); | |
189 // Like find() but if the key isn't present then call createEntry() to create the corresponding | |
190 // entry and insert it. createEntry() must return type `Entry`. | |
191 | |
192 template <typename KeyLike> | |
193 kj::Maybe<Entry&> findEntry(KeyLike&& key); | |
194 template <typename KeyLike> | |
195 kj::Maybe<const Entry&> findEntry(KeyLike&& key) const; | |
196 template <typename KeyLike, typename Func> | |
197 Entry& findOrCreateEntry(KeyLike&& key, Func&& createEntry); | |
198 // Sometimes you need to see the whole matching Entry, not just the Value. | |
199 | |
200 template <typename K1, typename K2> | |
201 auto range(K1&& k1, K2&& k2); | |
202 template <typename K1, typename K2> | |
203 auto range(K1&& k1, K2&& k2) const; | |
204 // Returns an iterable range of entries with keys between k1 (inclusive) and k2 (exclusive). | |
205 | |
206 template <typename KeyLike> | |
207 bool erase(KeyLike&& key); | |
208 // Erase the entry with the matching key. | |
209 // | |
210 // WARNING: This invalidates all pointers and iterators into the map. Use eraseAll() if you need | |
211 // to iterate and erase multiple entries. | |
212 | |
213 void erase(Entry& entry); | |
214 // Erase an entry by reference. | |
215 | |
216 Entry release(Entry& row); | |
217 // Erase an entry and return its content by move. | |
218 | |
219 template <typename Predicate, | |
220 typename = decltype(instance<Predicate>()(instance<Key&>(), instance<Value&>()))> | |
221 size_t eraseAll(Predicate&& predicate); | |
222 // Erase all values for which predicate(key, value) returns true. This scans over the entire map. | |
223 | |
224 template <typename K1, typename K2> | |
225 size_t eraseRange(K1&& k1, K2&& k2); | |
226 // Erases all entries with keys between k1 (inclusive) and k2 (exclusive). | |
227 | |
228 private: | |
229 class Callbacks { | |
230 public: | |
231 inline const Key& keyForRow(const Entry& entry) const { return entry.key; } | |
232 inline Key& keyForRow(Entry& entry) const { return entry.key; } | |
233 | |
234 template <typename KeyLike> | |
235 inline bool matches(Entry& e, KeyLike&& key) const { | |
236 return e.key == key; | |
237 } | |
238 template <typename KeyLike> | |
239 inline bool matches(const Entry& e, KeyLike&& key) const { | |
240 return e.key == key; | |
241 } | |
242 template <typename KeyLike> | |
243 inline bool isBefore(Entry& e, KeyLike&& key) const { | |
244 return e.key < key; | |
245 } | |
246 template <typename KeyLike> | |
247 inline bool isBefore(const Entry& e, KeyLike&& key) const { | |
248 return e.key < key; | |
249 } | |
250 }; | |
251 | |
252 kj::Table<Entry, TreeIndex<Callbacks>> table; | |
253 }; | |
254 | |
255 namespace _ { // private | |
256 | |
257 class HashSetCallbacks { | |
258 public: | |
259 template <typename Row> | |
260 inline Row& keyForRow(Row& row) const { return row; } | |
261 | |
262 template <typename T, typename U> | |
263 inline bool matches(T& a, U& b) const { return a == b; } | |
264 template <typename KeyLike> | |
265 inline auto hashCode(KeyLike&& key) const { | |
266 return kj::hashCode(key); | |
267 } | |
268 }; | |
269 | |
270 class TreeSetCallbacks { | |
271 public: | |
272 template <typename Row> | |
273 inline Row& keyForRow(Row& row) const { return row; } | |
274 | |
275 template <typename T, typename U> | |
276 inline bool matches(T& a, U& b) const { return a == b; } | |
277 template <typename T, typename U> | |
278 inline bool isBefore(T& a, U& b) const { return a < b; } | |
279 }; | |
280 | |
281 } // namespace _ (private) | |
282 | |
283 template <typename Element> | |
284 class HashSet: public Table<Element, HashIndex<_::HashSetCallbacks>> { | |
285 // A simple hashtable-based set, using kj::hashCode() and operator==(). | |
286 | |
287 public: | |
288 // Everything is inherited. | |
289 | |
290 template <typename... Params> | |
291 inline bool contains(Params&&... params) const { | |
292 return this->find(kj::fwd<Params>(params)...) != nullptr; | |
293 } | |
294 }; | |
295 | |
296 template <typename Element> | |
297 class TreeSet: public Table<Element, TreeIndex<_::TreeSetCallbacks>> { | |
298 // A simple b-tree-based set, using operator<() and operator==(). | |
299 | |
300 public: | |
301 // Everything is inherited. | |
302 }; | |
303 | |
304 // ======================================================================================= | |
305 // inline implementation details | |
306 | |
307 template <typename Key, typename Value> | |
308 void HashMap<Key, Value>::reserve(size_t size) { | |
309 table.reserve(size); | |
310 } | |
311 | |
312 template <typename Key, typename Value> | |
313 size_t HashMap<Key, Value>::size() const { | |
314 return table.size(); | |
315 } | |
316 template <typename Key, typename Value> | |
317 size_t HashMap<Key, Value>::capacity() const { | |
318 return table.capacity(); | |
319 } | |
320 template <typename Key, typename Value> | |
321 void HashMap<Key, Value>::clear() { | |
322 return table.clear(); | |
323 } | |
324 | |
325 template <typename Key, typename Value> | |
326 typename HashMap<Key, Value>::Entry* HashMap<Key, Value>::begin() { | |
327 return table.begin(); | |
328 } | |
329 template <typename Key, typename Value> | |
330 typename HashMap<Key, Value>::Entry* HashMap<Key, Value>::end() { | |
331 return table.end(); | |
332 } | |
333 template <typename Key, typename Value> | |
334 const typename HashMap<Key, Value>::Entry* HashMap<Key, Value>::begin() const { | |
335 return table.begin(); | |
336 } | |
337 template <typename Key, typename Value> | |
338 const typename HashMap<Key, Value>::Entry* HashMap<Key, Value>::end() const { | |
339 return table.end(); | |
340 } | |
341 | |
342 template <typename Key, typename Value> | |
343 typename HashMap<Key, Value>::Entry& HashMap<Key, Value>::insert(Key key, Value value) { | |
344 return table.insert(Entry { kj::mv(key), kj::mv(value) }); | |
345 } | |
346 | |
347 template <typename Key, typename Value> | |
348 template <typename Collection> | |
349 void HashMap<Key, Value>::insertAll(Collection&& collection) { | |
350 return table.insertAll(kj::fwd<Collection>(collection)); | |
351 } | |
352 | |
353 template <typename Key, typename Value> | |
354 template <typename UpdateFunc> | |
355 typename HashMap<Key, Value>::Entry& HashMap<Key, Value>::upsert( | |
356 Key key, Value value, UpdateFunc&& update) { | |
357 return table.upsert(Entry { kj::mv(key), kj::mv(value) }, | |
358 [&](Entry& existingEntry, Entry&& newEntry) { | |
359 update(existingEntry.value, kj::mv(newEntry.value)); | |
360 }); | |
361 } | |
362 | |
363 template <typename Key, typename Value> | |
364 typename HashMap<Key, Value>::Entry& HashMap<Key, Value>::upsert( | |
365 Key key, Value value) { | |
366 return table.upsert(Entry { kj::mv(key), kj::mv(value) }, | |
367 [&](Entry& existingEntry, Entry&& newEntry) { | |
368 existingEntry.value = kj::mv(newEntry.value); | |
369 }); | |
370 } | |
371 | |
372 template <typename Key, typename Value> | |
373 template <typename KeyLike> | |
374 kj::Maybe<Value&> HashMap<Key, Value>::find(KeyLike&& key) { | |
375 return table.find(key).map([](Entry& e) -> Value& { return e.value; }); | |
376 } | |
377 template <typename Key, typename Value> | |
378 template <typename KeyLike> | |
379 kj::Maybe<const Value&> HashMap<Key, Value>::find(KeyLike&& key) const { | |
380 return table.find(key).map([](const Entry& e) -> const Value& { return e.value; }); | |
381 } | |
382 | |
383 template <typename Key, typename Value> | |
384 template <typename KeyLike, typename Func> | |
385 Value& HashMap<Key, Value>::findOrCreate(KeyLike&& key, Func&& createEntry) { | |
386 return table.findOrCreate(key, kj::fwd<Func>(createEntry)).value; | |
387 } | |
388 | |
389 template <typename Key, typename Value> | |
390 template <typename KeyLike> | |
391 kj::Maybe<typename HashMap<Key, Value>::Entry&> | |
392 HashMap<Key, Value>::findEntry(KeyLike&& key) { | |
393 return table.find(kj::fwd<KeyLike>(key)); | |
394 } | |
395 template <typename Key, typename Value> | |
396 template <typename KeyLike> | |
397 kj::Maybe<const typename HashMap<Key, Value>::Entry&> | |
398 HashMap<Key, Value>::findEntry(KeyLike&& key) const { | |
399 return table.find(kj::fwd<KeyLike>(key)); | |
400 } | |
401 template <typename Key, typename Value> | |
402 template <typename KeyLike, typename Func> | |
403 typename HashMap<Key, Value>::Entry& | |
404 HashMap<Key, Value>::findOrCreateEntry(KeyLike&& key, Func&& createEntry) { | |
405 return table.findOrCreate(kj::fwd<KeyLike>(key), kj::fwd<Func>(createEntry)); | |
406 } | |
407 | |
408 template <typename Key, typename Value> | |
409 template <typename KeyLike> | |
410 bool HashMap<Key, Value>::erase(KeyLike&& key) { | |
411 return table.eraseMatch(key); | |
412 } | |
413 | |
414 template <typename Key, typename Value> | |
415 void HashMap<Key, Value>::erase(Entry& entry) { | |
416 table.erase(entry); | |
417 } | |
418 | |
419 template <typename Key, typename Value> | |
420 typename HashMap<Key, Value>::Entry HashMap<Key, Value>::release(Entry& entry) { | |
421 return table.release(entry); | |
422 } | |
423 | |
424 template <typename Key, typename Value> | |
425 template <typename Predicate, typename> | |
426 size_t HashMap<Key, Value>::eraseAll(Predicate&& predicate) { | |
427 return table.eraseAll([&](Entry& entry) { | |
428 return predicate(entry.key, entry.value); | |
429 }); | |
430 } | |
431 | |
432 // ----------------------------------------------------------------------------- | |
433 | |
434 template <typename Key, typename Value> | |
435 void TreeMap<Key, Value>::reserve(size_t size) { | |
436 table.reserve(size); | |
437 } | |
438 | |
439 template <typename Key, typename Value> | |
440 size_t TreeMap<Key, Value>::size() const { | |
441 return table.size(); | |
442 } | |
443 template <typename Key, typename Value> | |
444 size_t TreeMap<Key, Value>::capacity() const { | |
445 return table.capacity(); | |
446 } | |
447 template <typename Key, typename Value> | |
448 void TreeMap<Key, Value>::clear() { | |
449 return table.clear(); | |
450 } | |
451 | |
452 template <typename Key, typename Value> | |
453 auto TreeMap<Key, Value>::begin() { | |
454 return table.ordered().begin(); | |
455 } | |
456 template <typename Key, typename Value> | |
457 auto TreeMap<Key, Value>::end() { | |
458 return table.ordered().end(); | |
459 } | |
460 template <typename Key, typename Value> | |
461 auto TreeMap<Key, Value>::begin() const { | |
462 return table.ordered().begin(); | |
463 } | |
464 template <typename Key, typename Value> | |
465 auto TreeMap<Key, Value>::end() const { | |
466 return table.ordered().end(); | |
467 } | |
468 | |
469 template <typename Key, typename Value> | |
470 typename TreeMap<Key, Value>::Entry& TreeMap<Key, Value>::insert(Key key, Value value) { | |
471 return table.insert(Entry { kj::mv(key), kj::mv(value) }); | |
472 } | |
473 | |
474 template <typename Key, typename Value> | |
475 template <typename Collection> | |
476 void TreeMap<Key, Value>::insertAll(Collection&& collection) { | |
477 return table.insertAll(kj::fwd<Collection>(collection)); | |
478 } | |
479 | |
480 template <typename Key, typename Value> | |
481 template <typename UpdateFunc> | |
482 typename TreeMap<Key, Value>::Entry& TreeMap<Key, Value>::upsert( | |
483 Key key, Value value, UpdateFunc&& update) { | |
484 return table.upsert(Entry { kj::mv(key), kj::mv(value) }, | |
485 [&](Entry& existingEntry, Entry&& newEntry) { | |
486 update(existingEntry.value, kj::mv(newEntry.value)); | |
487 }); | |
488 } | |
489 | |
490 template <typename Key, typename Value> | |
491 typename TreeMap<Key, Value>::Entry& TreeMap<Key, Value>::upsert( | |
492 Key key, Value value) { | |
493 return table.upsert(Entry { kj::mv(key), kj::mv(value) }, | |
494 [&](Entry& existingEntry, Entry&& newEntry) { | |
495 existingEntry.value = kj::mv(newEntry.value); | |
496 }); | |
497 } | |
498 | |
499 template <typename Key, typename Value> | |
500 template <typename KeyLike> | |
501 kj::Maybe<Value&> TreeMap<Key, Value>::find(KeyLike&& key) { | |
502 return table.find(key).map([](Entry& e) -> Value& { return e.value; }); | |
503 } | |
504 template <typename Key, typename Value> | |
505 template <typename KeyLike> | |
506 kj::Maybe<const Value&> TreeMap<Key, Value>::find(KeyLike&& key) const { | |
507 return table.find(key).map([](const Entry& e) -> const Value& { return e.value; }); | |
508 } | |
509 | |
510 template <typename Key, typename Value> | |
511 template <typename KeyLike, typename Func> | |
512 Value& TreeMap<Key, Value>::findOrCreate(KeyLike&& key, Func&& createEntry) { | |
513 return table.findOrCreate(key, kj::fwd<Func>(createEntry)).value; | |
514 } | |
515 | |
516 template <typename Key, typename Value> | |
517 template <typename KeyLike> | |
518 kj::Maybe<typename TreeMap<Key, Value>::Entry&> | |
519 TreeMap<Key, Value>::findEntry(KeyLike&& key) { | |
520 return table.find(kj::fwd<KeyLike>(key)); | |
521 } | |
522 template <typename Key, typename Value> | |
523 template <typename KeyLike> | |
524 kj::Maybe<const typename TreeMap<Key, Value>::Entry&> | |
525 TreeMap<Key, Value>::findEntry(KeyLike&& key) const { | |
526 return table.find(kj::fwd<KeyLike>(key)); | |
527 } | |
528 template <typename Key, typename Value> | |
529 template <typename KeyLike, typename Func> | |
530 typename TreeMap<Key, Value>::Entry& | |
531 TreeMap<Key, Value>::findOrCreateEntry(KeyLike&& key, Func&& createEntry) { | |
532 return table.findOrCreate(kj::fwd<KeyLike>(key), kj::fwd<Func>(createEntry)); | |
533 } | |
534 | |
535 template <typename Key, typename Value> | |
536 template <typename K1, typename K2> | |
537 auto TreeMap<Key, Value>::range(K1&& k1, K2&& k2) { | |
538 return table.range(kj::fwd<K1>(k1), kj::fwd<K2>(k2)); | |
539 } | |
540 template <typename Key, typename Value> | |
541 template <typename K1, typename K2> | |
542 auto TreeMap<Key, Value>::range(K1&& k1, K2&& k2) const { | |
543 return table.range(kj::fwd<K1>(k1), kj::fwd<K2>(k2)); | |
544 } | |
545 | |
546 template <typename Key, typename Value> | |
547 template <typename KeyLike> | |
548 bool TreeMap<Key, Value>::erase(KeyLike&& key) { | |
549 return table.eraseMatch(key); | |
550 } | |
551 | |
552 template <typename Key, typename Value> | |
553 void TreeMap<Key, Value>::erase(Entry& entry) { | |
554 table.erase(entry); | |
555 } | |
556 | |
557 template <typename Key, typename Value> | |
558 typename TreeMap<Key, Value>::Entry TreeMap<Key, Value>::release(Entry& entry) { | |
559 return table.release(entry); | |
560 } | |
561 | |
562 template <typename Key, typename Value> | |
563 template <typename Predicate, typename> | |
564 size_t TreeMap<Key, Value>::eraseAll(Predicate&& predicate) { | |
565 return table.eraseAll([&](Entry& entry) { | |
566 return predicate(entry.key, entry.value); | |
567 }); | |
568 } | |
569 | |
570 template <typename Key, typename Value> | |
571 template <typename K1, typename K2> | |
572 size_t TreeMap<Key, Value>::eraseRange(K1&& k1, K2&& k2) { | |
573 return table.eraseRange(kj::fwd<K1>(k1), kj::fwd<K2>(k2)); | |
574 } | |
575 | |
576 } // namespace kj | |
577 | |
578 KJ_END_HEADER |