Line |
Branch |
Exec |
Source |
1 |
|
|
//API for assocarr<mytype> myarr: |
2 |
|
|
//myarr.exists("index") |
3 |
|
|
// Returns a boolean telling whether the entry exists. |
4 |
|
|
// Complexity: O(log n). |
5 |
|
|
//myarr.find("index") |
6 |
|
|
// Returns a mytype& corresponding to the relevant entry. If it doesn't exist, behaviour is undefined. |
7 |
|
|
// Complexity: O(log n). |
8 |
|
|
//myarr.create("index") |
9 |
|
|
// Returns a mytype& corresponding to the relevant entry. If it doesn't exist, it's created. |
10 |
|
|
// Complexity: Worst case O(n), reduced to amortized O(log n) if the element should be at the end (strict weak ordering), or O(log n) if the element |
11 |
|
|
// exists. |
12 |
|
|
//myarr.remove("index") |
13 |
|
|
// Removes the element corresponding to the relevant entry. If it doesn't exist, this structure is left untouched. |
14 |
|
|
// Complexity: Worst case O(n), reduced to amortized O(log n) if the element is at the end. |
15 |
|
|
//myarr.reset() |
16 |
|
|
// Clears the data structure, calling all destructors. It is safe to call this function on an empty structure. |
17 |
|
|
// Complexity: O(n). |
18 |
|
|
//myarr.move("from", "to") |
19 |
|
|
// Moves an element from index "from" to "to". If the source doesn't exist, behaviour is undefined. If the target exists, no action is performed. |
20 |
|
|
// Complexity: O(n). |
21 |
|
|
//myarr["index"] |
22 |
|
|
// Similar to myarr.create("index"), but if the returned entry isn't changed by the next call to any function in the same structure, it's removed. |
23 |
|
|
// if (myarr["index"]) is safe if type can cast to a bool, and myarr["index"]=4 is also valid if the assignment is valid for a type&. However, it is |
24 |
|
|
// not safe to use assocarr<assocarr<int> > myarr; if (myarr["3"]["4"]), since the inner assocarr won't know that it's supposed to be garbage collected, |
25 |
|
|
// and the outer one sees that the inner one changed, so you get pollution and memory waste. However, if (myarr["3"].exists("4")) is safe. |
26 |
|
|
// Complexity: Same as myarr.create(). |
27 |
|
|
//myarr.each(func) |
28 |
|
|
// Calls func() for each entry in the structure. func must match the prototype void func(const char * index, mytype& val), but can be a lambda. No |
29 |
|
|
// non-const function may be called on this structure from inside func(), but it is safe to call const functions of the structure. The function |
30 |
|
|
// calls are in the same order as the indexes, in a strict weak ordering. |
31 |
|
|
// Complexity: O(n). |
32 |
|
|
//Space usage: O(n). |
33 |
|
|
//C++ version: C++98 or C++03, not sure which. |
34 |
|
|
//Serializer support: Yes, if mytype is serializable. |
35 |
|
|
//"Undefined behaviour" means "segfault" in most cases. |
36 |
|
|
|
37 |
|
|
#pragma once |
38 |
|
|
|
39 |
|
|
#include <initializer_list> |
40 |
|
|
#include <unordered_map> |
41 |
|
|
#include "libstr.h" |
42 |
|
|
|
43 |
|
|
template<typename right> |
44 |
|
|
class assocarr { |
45 |
|
|
private: |
46 |
|
|
|
47 |
|
|
std::unordered_map<string, right> storage; |
48 |
|
|
|
49 |
|
|
public: |
50 |
|
|
|
51 |
|
170769 |
bool exists(const char* key) const |
52 |
|
|
{ |
53 |
2/4
✓ Branch 0 taken 60440 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 60440 times.
✗ Branch 3 not taken.
|
170769 |
return storage.find(key) != storage.end(); |
54 |
|
|
} |
55 |
|
|
|
56 |
|
108596 |
right& find(const char* key) |
57 |
|
|
{ |
58 |
2/4
✓ Branch 0 taken 26765 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 26765 times.
✗ Branch 3 not taken.
|
108596 |
return storage.find(key)->second; |
59 |
|
|
} |
60 |
|
|
|
61 |
|
60230 |
right& create(const char* key) |
62 |
|
|
{ |
63 |
2/4
✓ Branch 0 taken 23295 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 23295 times.
✗ Branch 3 not taken.
|
60230 |
return storage[key]; |
64 |
|
|
} |
65 |
|
|
|
66 |
|
786 |
void remove(const char* key) |
67 |
|
|
{ |
68 |
2/4
✓ Branch 0 taken 410 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 410 times.
✗ Branch 3 not taken.
|
786 |
storage.erase(key); |
69 |
|
786 |
} |
70 |
|
|
|
71 |
|
5748 |
void reset() |
72 |
|
|
{ |
73 |
|
5748 |
storage.clear(); |
74 |
|
5748 |
} |
75 |
|
|
|
76 |
|
2090 |
assocarr() |
77 |
|
2090 |
{ |
78 |
|
2090 |
} |
79 |
|
|
|
80 |
|
|
assocarr(std::initializer_list<std::pair<const char*, right>> list) |
81 |
|
|
{ |
82 |
|
|
for (auto& it : list) { |
83 |
|
|
storage.insert(std::move(it)); |
84 |
|
|
} |
85 |
|
|
} |
86 |
|
|
|
87 |
|
✗ |
right& operator[](const char* key) |
88 |
|
|
{ |
89 |
|
✗ |
return create(key); |
90 |
|
|
} |
91 |
|
|
|
92 |
|
|
//void(*func)(const char * key, right& value) |
93 |
|
17784 |
template<typename T> void each(T func) |
94 |
|
|
{ |
95 |
2/2
✓ Branch 0 taken 31037 times.
✓ Branch 1 taken 8907 times.
|
79768 |
for (auto& it : storage) { |
96 |
2/3
✓ Branch 0 taken 15100 times.
✓ Branch 1 taken 629 times.
✗ Branch 2 not taken.
|
61984 |
func(it.first, it.second); |
97 |
|
|
} |
98 |
|
17784 |
} |
99 |
|
|
|
100 |
|
|
}; |
101 |
|
|
|