Nebula
Loading...
Searching...
No Matches
dictionary.h
Go to the documentation of this file.
1#pragma once
2//------------------------------------------------------------------------------
27#include "util/array.h"
28#include "util/keyvaluepair.h"
29#include <utility>
30
31//------------------------------------------------------------------------------
32namespace Util
33{
34template<class KEYTYPE, class VALUETYPE> class Dictionary
35{
36public:
48 VALUETYPE& operator[](const KEYTYPE& key);
50 const VALUETYPE& operator[](const KEYTYPE& key) const;
52 SizeT Size() const;
54 void Clear();
56 bool IsEmpty() const;
58 void Reserve(SizeT numElements);
66 IndexT Add(const KEYTYPE& key, const VALUETYPE& value);
68 IndexT Add(KEYTYPE&& key, VALUETYPE&& value);
70 VALUETYPE& Emplace(const KEYTYPE& key);
72 void EndBulkAdd();
76 void Erase(const KEYTYPE& key);
78 void EraseAtIndex(IndexT index);
80 IndexT FindIndex(const KEYTYPE& key) const;
82 bool Contains(const KEYTYPE& key) const;
84 bool Contains(const KEYTYPE& key, IndexT& index) const;
86 const KEYTYPE& KeyAtIndex(IndexT index) const;
88 VALUETYPE& ValueAtIndex(IndexT index);
90 const VALUETYPE& ValueAtIndex(IndexT index) const;
100 template<class RETURNTYPE> RETURNTYPE KeysAs() const;
102 template<class RETURNTYPE> RETURNTYPE ValuesAs() const;
103
107 void clear();
108 void emplace(KEYTYPE&&key, VALUETYPE&&value);
109
110protected:
112 void SortIfDirty() const;
113
116};
117
118//------------------------------------------------------------------------------
121template<class KEYTYPE, class VALUETYPE>
123 inBulkInsert(false)
124{
125 // empty
126}
127
128//------------------------------------------------------------------------------
131template<class KEYTYPE, class VALUETYPE>
134 inBulkInsert(false)
135{
136 #if NEBULA_BOUNDSCHECKS
138 #endif
139}
140
141//------------------------------------------------------------------------------
144template<class KEYTYPE, class VALUETYPE>
146 keyValuePairs(std::move(rhs.keyValuePairs)),
147 inBulkInsert(false)
148{
149#if NEBULA_BOUNDSCHECKS
150 n_assert(!rhs.inBulkInsert);
151#endif
152}
153
154//------------------------------------------------------------------------------
157template<class KEYTYPE, class VALUETYPE>
158inline void
160{
161 #if NEBULA_BOUNDSCHECKS
162 n_assert(!this->inBulkInsert);
164 #endif
165 this->keyValuePairs = rhs.keyValuePairs;
166}
167
168//------------------------------------------------------------------------------
171template<class KEYTYPE, class VALUETYPE>
172inline void
174{
175#if NEBULA_BOUNDSCHECKS
176 n_assert(!this->inBulkInsert);
177 n_assert(!rhs.inBulkInsert);
178#endif
179 this->keyValuePairs = std::move(rhs.keyValuePairs);
180}
181
182//------------------------------------------------------------------------------
185template<class KEYTYPE, class VALUETYPE>
186inline void
188{
189 #if NEBULA_BOUNDSCHECKS
190 n_assert(!this->inBulkInsert);
191 #endif
192 this->keyValuePairs.Clear();
193}
194
195//------------------------------------------------------------------------------
198template<class KEYTYPE, class VALUETYPE>
199inline SizeT
201{
202 return this->keyValuePairs.Size();
203}
204
205//------------------------------------------------------------------------------
208template<class KEYTYPE, class VALUETYPE>
209inline bool
211{
212 return (0 == this->keyValuePairs.Size());
213}
214
215//------------------------------------------------------------------------------
218template<class KEYTYPE, class VALUETYPE>
219inline void
221{
222 this->keyValuePairs.Reserve(numElements);
223}
224
225//------------------------------------------------------------------------------
228template<class KEYTYPE, class VALUETYPE>
229inline void
231{
232 #if NEBULA_BOUNDSCHECKS
233 n_assert(!this->inBulkInsert);
234 #endif
235 this->inBulkInsert = true;
236}
237
238//------------------------------------------------------------------------------
241template<class KEYTYPE, class VALUETYPE>
242inline void
244{
245 #if NEBULA_BOUNDSCHECKS
246 n_assert(this->inBulkInsert);
247 #endif
248 this->keyValuePairs.Sort();
249 this->inBulkInsert = false;
250}
251
252//------------------------------------------------------------------------------
255template<class KEYTYPE, class VALUETYPE>
256inline void
258{
259 if (&rhs == this) return;
260 this->BeginBulkAdd();
261 IndexT i;
262 for (i = 0; i < rhs.keyValuePairs.Size(); i++)
263 {
264 this->keyValuePairs.Append(rhs.keyValuePairs[i]);
265 }
266 this->EndBulkAdd();
267}
268
269
270//------------------------------------------------------------------------------
273template<class KEYTYPE, class VALUETYPE>
274inline IndexT
276{
277 if (this->inBulkInsert)
278 {
279 this->keyValuePairs.Append(kvp);
280 return this->keyValuePairs.Size() - 1;
281 }
282 else
283 {
284 return this->keyValuePairs.InsertSorted(kvp);
285 }
286}
287
288//------------------------------------------------------------------------------
291template<class KEYTYPE, class VALUETYPE>
292inline IndexT
294{
295 if (this->inBulkInsert)
296 {
297 this->keyValuePairs.Append(std::move(kvp));
298 return this->keyValuePairs.Size() - 1;
299 }
300 else
301 {
302 return this->keyValuePairs.InsertSorted(std::move(kvp));
303 }
304}
305
306//------------------------------------------------------------------------------
309template<class KEYTYPE, class VALUETYPE>
310inline IndexT
311Dictionary<KEYTYPE, VALUETYPE>::Add(const KEYTYPE& key, const VALUETYPE& value)
312{
313#if NEBULA_BOUNDSCHECKS
314 //n_assert(!this->Contains(key));
315#endif
316 KeyValuePair<KEYTYPE, VALUETYPE> kvp(key, value);
317 if (this->inBulkInsert)
318 {
319 this->keyValuePairs.Append(kvp);
320 return this->keyValuePairs.Size() - 1;
321 }
322 else
323 {
324 return this->keyValuePairs.InsertSorted(kvp);
325 }
326}
327
328//------------------------------------------------------------------------------
331template<class KEYTYPE, class VALUETYPE>
332inline IndexT
333Dictionary<KEYTYPE, VALUETYPE>::Add(KEYTYPE&& key, VALUETYPE&& value)
334{
335 return this->Add(KeyValuePair<KEYTYPE, VALUETYPE>(std::move(key), std::move(value)));
336}
337
338//------------------------------------------------------------------------------
341template<class KEYTYPE, class VALUETYPE>
342inline VALUETYPE&
344{
345 IndexT i = this->FindIndex(key);
346 if (i == InvalidIndex)
347 {
348 return this->ValueAtIndex(this->Add(key, VALUETYPE()));
349 }
350 else
351 {
352 return this->ValueAtIndex(i);
353 }
354}
355
356//------------------------------------------------------------------------------
359template<class KEYTYPE, class VALUETYPE>
360inline void
362{
363 #if NEBULA_BOUNDSCHECKS
364 n_assert(!this->inBulkInsert);
365 #endif
366 IndexT eraseIndex = this->keyValuePairs.template BinarySearchIndex<KEYTYPE>(key);
367 #if NEBULA_BOUNDSCHECKS
368 n_assert(InvalidIndex != eraseIndex);
369 #endif
370 this->keyValuePairs.EraseIndex(eraseIndex);
371}
372
373//------------------------------------------------------------------------------
376template<class KEYTYPE, class VALUETYPE>
377inline void
379{
380 #if NEBULA_BOUNDSCHECKS
381 n_assert(!this->inBulkInsert);
382 #endif
383 this->keyValuePairs.EraseIndex(index);
384}
385
386//------------------------------------------------------------------------------
389template<class KEYTYPE, class VALUETYPE>
390inline IndexT
392{
393 #if NEBULA_BOUNDSCHECKS
394 n_assert(!this->inBulkInsert);
395 #endif
396 return this->keyValuePairs.template BinarySearchIndex<KEYTYPE>(key);
397}
398
399//------------------------------------------------------------------------------
402template<class KEYTYPE, class VALUETYPE>
403inline bool
405{
406 #if NEBULA_BOUNDSCHECKS
407 n_assert(!this->inBulkInsert);
408 #endif
409 return (InvalidIndex != this->keyValuePairs.template BinarySearchIndex<KEYTYPE>(key));
410}
411
412//------------------------------------------------------------------------------
415template<class KEYTYPE, class VALUETYPE>
416inline bool
417Dictionary<KEYTYPE, VALUETYPE>::Contains(const KEYTYPE& key, IndexT& index) const
418{
419#if NEBULA_BOUNDSCHECKS
420 n_assert(!this->inBulkInsert);
421#endif
422 index = this->keyValuePairs.template BinarySearchIndex<KEYTYPE>(key);
423 return (InvalidIndex != index);
424}
425
426//------------------------------------------------------------------------------
429template<class KEYTYPE, class VALUETYPE>
430inline const KEYTYPE&
432{
433 #if NEBULA_BOUNDSCHECKS
434 n_assert(!this->inBulkInsert);
435 #endif
436 return this->keyValuePairs[index].Key();
437}
438
439//------------------------------------------------------------------------------
442template<class KEYTYPE, class VALUETYPE>
443inline VALUETYPE&
445{
446 #if NEBULA_BOUNDSCHECKS
447 n_assert(!this->inBulkInsert);
448 #endif
449 return this->keyValuePairs[index].Value();
450}
451
452//------------------------------------------------------------------------------
455template<class KEYTYPE, class VALUETYPE>
456inline const VALUETYPE&
458{
459 #if NEBULA_BOUNDSCHECKS
460 n_assert(!this->inBulkInsert);
461 #endif
462 return this->keyValuePairs[index].Value();
463}
464
465//------------------------------------------------------------------------------
468template<class KEYTYPE, class VALUETYPE>
471{
472 #if NEBULA_BOUNDSCHECKS
473 n_assert(!this->inBulkInsert);
474 #endif
475 return this->keyValuePairs[index];
476}
477
478//------------------------------------------------------------------------------
481template<class KEYTYPE, class VALUETYPE>
484{
485 #if NEBULA_BOUNDSCHECKS
486 n_assert(!this->inBulkInsert);
487 #endif
488 return this->keyValuePairs[index];
489}
490
491//------------------------------------------------------------------------------
494template<class KEYTYPE, class VALUETYPE>
495inline VALUETYPE&
497{
498 IndexT keyValuePairIndex = this->FindIndex(key);
499 #if NEBULA_BOUNDSCHECKS
500 n_assert(InvalidIndex != keyValuePairIndex);
501 #endif
502 return this->keyValuePairs[keyValuePairIndex].Value();
503}
504
505//------------------------------------------------------------------------------
508template<class KEYTYPE, class VALUETYPE>
509inline const VALUETYPE&
511{
512 IndexT keyValuePairIndex = this->FindIndex(key);
513 #if NEBULA_BOUNDSCHECKS
514 n_assert(InvalidIndex != keyValuePairIndex);
515 #endif
516 return this->keyValuePairs[keyValuePairIndex].Value();
517}
518
519//------------------------------------------------------------------------------
522template<class KEYTYPE, class VALUETYPE>
523template<class RETURNTYPE>
524RETURNTYPE
526{
527 #if NEBULA_BOUNDSCHECKS
528 n_assert(!this->inBulkInsert);
529 #endif
530 RETURNTYPE result(this->Size(),this->Size());
531 IndexT i;
532 for (i = 0; i < this->keyValuePairs.Size(); i++)
533 {
534 result.Append(this->keyValuePairs[i].Value());
535 }
536 return result;
537}
538
539//------------------------------------------------------------------------------
542template<class KEYTYPE, class VALUETYPE>
543inline Array<VALUETYPE>
548
549//------------------------------------------------------------------------------
552template<class KEYTYPE, class VALUETYPE>
553template<class RETURNTYPE>
554inline RETURNTYPE
556{
557 #if NEBULA_BOUNDSCHECKS
558 n_assert(!this->inBulkInsert);
559 #endif
560 RETURNTYPE result(this->Size(),this->Size());
561 IndexT i;
562 for (i = 0; i < this->keyValuePairs.Size(); i++)
563 {
564 result.Append(this->keyValuePairs[i].Key());
565 }
566 return result;
567}
568
569//------------------------------------------------------------------------------
572template<class KEYTYPE, class VALUETYPE>
573inline Array<KEYTYPE>
578
579//------------------------------------------------------------------------------
582template<class KEYTYPE, class VALUETYPE>
585{
586 return this->keyValuePairs.begin();
587}
588//------------------------------------------------------------------------------
591template<class KEYTYPE, class VALUETYPE>
594{
595 return this->keyValuePairs.end();
596}
597//------------------------------------------------------------------------------
600template<class KEYTYPE, class VALUETYPE>
601inline void
606//------------------------------------------------------------------------------
609template<class KEYTYPE, class VALUETYPE>
610inline void
611Dictionary<KEYTYPE, VALUETYPE>::emplace(KEYTYPE&&key, VALUETYPE&&value)
612{
613 this->Add(std::move(key), std::move(value));
614}
615} // namespace Util
616//------------------------------------------------------------------------------
Nebula's dynamic array class.
Definition array.h:61
void BeginBulkAdd()
begin a bulk insert (array will be sorted at End)
Definition dictionary.h:230
IndexT Add(KEYTYPE &&key, VALUETYPE &&value)
add a key and associated value, consuming rvalues
Definition dictionary.h:333
void operator=(Dictionary< KEYTYPE, VALUETYPE > &&rhs) noexcept
move operator
Definition dictionary.h:173
Dictionary(const Dictionary< KEYTYPE, VALUETYPE > &rhs)
copy constructor
Definition dictionary.h:132
void Reserve(SizeT numElements)
reserve space (useful if number of elements is known beforehand)
Definition dictionary.h:220
bool Contains(const KEYTYPE &key) const
return true if key exists in the array
Definition dictionary.h:404
void Clear()
clear the dictionary
Definition dictionary.h:187
SizeT Size() const
return number of key/value pairs in the dictionary
Definition dictionary.h:200
KeyValuePair< KEYTYPE, VALUETYPE > * end() const
Definition dictionary.h:593
const KEYTYPE & KeyAtIndex(IndexT index) const
get a key at given index
Definition dictionary.h:431
IndexT FindIndex(const KEYTYPE &key) const
find index of key/value pair (InvalidIndex if doesn't exist)
Definition dictionary.h:391
Array< KEYTYPE > KeysAsArray() const
get all keys as an Util::Array
Definition dictionary.h:574
Dictionary(Dictionary< KEYTYPE, VALUETYPE > &&rhs) noexcept
move constructor
Definition dictionary.h:145
const VALUETYPE & ValueAtIndex(IndexT index) const
get a value at given index
Definition dictionary.h:457
IndexT Add(const KeyValuePair< KEYTYPE, VALUETYPE > &kvp)
add a key/value pair
Definition dictionary.h:275
void clear()
Definition dictionary.h:602
void EraseAtIndex(IndexT index)
erase a key at index
Definition dictionary.h:378
const VALUETYPE & operator[](const KEYTYPE &key) const
read-only [] operator
Definition dictionary.h:510
RETURNTYPE ValuesAs() const
get all keys as (typically) an array
Definition dictionary.h:525
bool IsEmpty() const
return true if empty
Definition dictionary.h:210
VALUETYPE & ValueAtIndex(IndexT index)
access to value at given index
Definition dictionary.h:444
RETURNTYPE KeysAs() const
get all keys as (typically) an array
Definition dictionary.h:555
Array< VALUETYPE > ValuesAsArray() const
get all keys as an Util::Array
Definition dictionary.h:544
void emplace(KEYTYPE &&key, VALUETYPE &&value)
Definition dictionary.h:611
void Erase(const KEYTYPE &key)
erase a key and its associated value
Definition dictionary.h:361
VALUETYPE & operator[](const KEYTYPE &key)
read/write [] operator
Definition dictionary.h:496
bool Contains(const KEYTYPE &key, IndexT &index) const
return true if key exists in the array, and saves index
Definition dictionary.h:417
void Merge(const Dictionary< KEYTYPE, VALUETYPE > &rhs)
merge two dictionaries
Definition dictionary.h:257
const KeyValuePair< KEYTYPE, VALUETYPE > & KeyValuePairAtIndex(IndexT index) const
get key/value pair at index
Definition dictionary.h:483
KeyValuePair< KEYTYPE, VALUETYPE > & KeyValuePairAtIndex(IndexT index)
get key/value pair at index
Definition dictionary.h:470
IndexT Add(const KEYTYPE &key, const VALUETYPE &value)
add a key and associated value
Definition dictionary.h:311
KeyValuePair< KEYTYPE, VALUETYPE > * begin() const
functions for stl like behaviour
Definition dictionary.h:584
void EndBulkAdd()
end a bulk insert (this will sort the internal array)
Definition dictionary.h:243
void operator=(const Dictionary< KEYTYPE, VALUETYPE > &rhs)
assignment operator
Definition dictionary.h:159
Array< KeyValuePair< Util::StringAtom, CoreGraphics::BufferId > > keyValuePairs
Definition dictionary.h:114
Dictionary()
default constructor
Definition dictionary.h:122
VALUETYPE & Emplace(const KEYTYPE &key)
creates a new entry of VALUETYPE if key does not exist, or returns the existing element
Definition dictionary.h:343
IndexT Add(KeyValuePair< KEYTYPE, VALUETYPE > &&kvp)
add a key/value pair, consuming rvalues
Definition dictionary.h:293
void SortIfDirty() const
make sure the key value pair array is sorted
Key/Value pair objects are used by most assiociative container classes, like Dictionary or HashTable.
Definition keyvaluepair.h:19
#define n_assert(exp)
Definition debug.h:50
A quad tree designed to return regions of free 2D space.
Definition String.cs:6
static const int InvalidIndex
Definition types.h:47
int SizeT
Definition types.h:42
int IndexT
Definition types.h:41