Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit dd78a68

Browse files
committed
added OrderedMap class, original code from Memo Akten, updated for ofxVP
1 parent 5eced54 commit dd78a68

File tree

1 file changed

+277
-0
lines changed

1 file changed

+277
-0
lines changed

‎src/core/ofxVPOrderedMap.h‎

Lines changed: 277 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,277 @@
1+
// __
2+
// ____ ___ ___ ____ ___ ____ / /__ __
3+
// / __ `__ \/ _ \/ __ `__ \/ __ \ / __/ | / /
4+
// / / / / / / __/ / / / / / /_/ // /_ | |/ /
5+
// /_/ /_/ /_/\___/_/ /_/ /_/\____(_)__/ |___/
6+
//
7+
//
8+
// Created by Memo Akten, www.memo.tv
9+
//
10+
// acts like a std::map, but preserves order of insertion
11+
//
12+
// Original code by Memo Akten, updated for ofxVP
13+
//
14+
// Use it with std::shared_ptr:
15+
//
16+
// Ex. ofxVP::OrderedMap<std::string, std::shared_ptr<PatchObject> > patchObjects;
17+
18+
#pragma once
19+
20+
#include "ofMain.h"
21+
22+
namespace ofxVP {
23+
24+
template<typename keyType, typename T>
25+
class OrderedMap {
26+
27+
public:
28+
29+
// get size
30+
int size() const;
31+
32+
// add new item
33+
// item will be cloned, stored internally and added to an stl::map and stl::vector as a pointer
34+
// if T is shared_ptr, ownership is taken care of automatically by shared_ptr
35+
// returns a reference to the new object added
36+
T& push_back(const keyType& key, const T& t);
37+
38+
// return reference to the stored object
39+
// throws an exception of the index or key doesn't exist
40+
T& at(int index); // get by index
41+
const T& at(int index) const; // get by index
42+
43+
T& at(const keyType& key); // get by key
44+
const T& at(const keyType& key) const; // get by key
45+
46+
// [] operator overloads for above
47+
// these also throw an exception if the index or key doesn't exist
48+
T& operator[](int index); // get by index
49+
const T& operator[](int index) const;
50+
51+
T& operator[](const keyType& key); // get by key
52+
const T& operator[](const keyType& key) const;
53+
54+
// get the key for item at index. returns blank if doesn't exist
55+
keyType keyFor(int index) const;
56+
57+
// get the index for item with key. returns -ve if doesn't exist
58+
int indexFor(const keyType& key) const;
59+
60+
// see if key exists
61+
bool exists(const keyType& key) const;
62+
63+
// check if the stored object is null
64+
bool checkNullptr(const T& t) const;
65+
66+
// change key
67+
void changeKey(int index, const keyType& newKey);
68+
void changeKey(const keyType& oldKey, const keyType& newKey);
69+
70+
// erase by key or index
71+
void erase(int index);
72+
void erase(const keyType& key);
73+
74+
// clear
75+
void clear();
76+
77+
78+
// ADVANCED
79+
// if you know the index and the key
80+
// fast erase without any validity checks
81+
void fastErase(int index, const keyType& key);
82+
83+
private:
84+
std::map<keyType, std::pair<T, int> > _map; // the actual data is stored here, along with index in vector
85+
std::vector< keyType > _vector; // vector of keys (to store the order)
86+
87+
void validateIndex(int index, std::string errorMessage) const;
88+
void validateKey(const keyType& key, std::string errorMessage) const;
89+
90+
// if something is erased, the indices in the map need to be updated
91+
void updateMapIndices();
92+
93+
};
94+
95+
//--------------------------------------------------------------
96+
template<typename keyType, typename T>
97+
void OrderedMap<keyType, T>::clear() {
98+
_vector.clear();
99+
_map.clear();
100+
}
101+
102+
//--------------------------------------------------------------
103+
template<typename keyType, typename T>
104+
int OrderedMap<keyType, T>::size() const {
105+
// if these aren't equal, something went wrong somewhere.
106+
if(_map.size() != _vector.size()) throw runtime_error("ofxVP::OrderedMap::size() - map size doesn't equal vector size");
107+
return _vector.size();
108+
}
109+
110+
//--------------------------------------------------------------
111+
template<typename keyType, typename T>
112+
T& OrderedMap<keyType, T>::push_back(const keyType& key, const T& t) {
113+
if(exists(key)) {
114+
throw invalid_argument("ofxVP::OrderedMap::push_back(keyType, T&) - key already exists");
115+
return at(key);
116+
} else {
117+
_map[key] = make_pair(t, _vector.size());
118+
_vector.push_back(key);
119+
size(); // to validate if correctly added to both containers, should be ok
120+
return at(key);
121+
}
122+
}
123+
124+
//--------------------------------------------------------------
125+
template<typename keyType, typename T>
126+
T& OrderedMap<keyType, T>::at(int index) {
127+
validateIndex(index, "ofxVP::OrderedMap::at(int)");
128+
return at(_vector[index]);
129+
}
130+
131+
//--------------------------------------------------------------
132+
template<typename keyType, typename T>
133+
const T& OrderedMap<keyType, T>::at(int index) const {
134+
validateIndex(index, "ofxVP::OrderedMap::at(int)");
135+
return at(_vector[index]);
136+
}
137+
138+
//--------------------------------------------------------------
139+
template<typename keyType, typename T>
140+
T& OrderedMap<keyType, T>::at(const keyType& key) {
141+
validateKey(key, "ofxVP::OrderedMap::at(keyType)");
142+
return _map.at(key).first;
143+
}
144+
145+
//--------------------------------------------------------------
146+
template<typename keyType, typename T>
147+
const T& OrderedMap<keyType, T>::at(const keyType& key) const {
148+
validateKey(key, "ofxVP::OrderedMap::at(keyType)");
149+
return _map.at(key).first;
150+
}
151+
152+
//--------------------------------------------------------------
153+
template<typename keyType, typename T>
154+
T& OrderedMap<keyType, T>::operator[](int index) {
155+
return at(index);
156+
}
157+
158+
//--------------------------------------------------------------
159+
template<typename keyType, typename T>
160+
const T& OrderedMap<keyType, T>::operator[](int index) const {
161+
return at(index);
162+
}
163+
164+
//--------------------------------------------------------------
165+
template<typename keyType, typename T>
166+
T& OrderedMap<keyType, T>::operator[](const keyType& key) {
167+
return at(key);
168+
}
169+
170+
//--------------------------------------------------------------
171+
template<typename keyType, typename T>
172+
const T& OrderedMap<keyType, T>::operator[](const keyType& key) const {
173+
return at(key);
174+
}
175+
176+
//--------------------------------------------------------------
177+
template<typename keyType, typename T>
178+
keyType OrderedMap<keyType, T>::keyFor(int index) const {
179+
validateIndex(index, "ofxVP::OrderedMap::keyFor(int)");
180+
return _vector[index];
181+
}
182+
183+
//--------------------------------------------------------------
184+
template<typename keyType, typename T>
185+
int OrderedMap<keyType, T>::indexFor(const keyType& key) const {
186+
validateKey(key, "ofxVP::OrderedMap::indexFor(keyType)");
187+
return _map.at(key).second;
188+
}
189+
190+
//--------------------------------------------------------------
191+
template<typename keyType, typename T>
192+
void OrderedMap<keyType, T>::changeKey(int index, const keyType& newKey) {
193+
validateIndex(index, "ofxVP::OrderedMap::changeKey(int)");
194+
changeKey(keyFor(index), newKey);
195+
}
196+
197+
//--------------------------------------------------------------
198+
template<typename keyType, typename T>
199+
void OrderedMap<keyType, T>::changeKey(const keyType& oldKey, const keyType& newKey) {
200+
validateKey(oldKey, "ofxVP::OrderedMap::changeKey(keyType)");
201+
202+
// save temp copy
203+
auto t = _map[oldKey];
204+
205+
// erase from map, and reinsert
206+
_map.erase(oldKey);
207+
_map[newKey] = t;
208+
209+
// change key from the vector
210+
_vector.at(t.second) = newKey;
211+
}
212+
213+
//--------------------------------------------------------------
214+
template<typename keyType, typename T>
215+
void OrderedMap<keyType, T>::erase(int index) {
216+
validateIndex(index, "ofxVP::OrderedMap::erase(int)");
217+
fastErase(index, keyFor(index));
218+
size(); // validate map and vector have same sizes to make sure everything worked alright
219+
}
220+
221+
//--------------------------------------------------------------
222+
template<typename keyType, typename T>
223+
void OrderedMap<keyType, T>::erase(const keyType& key) {
224+
validateKey(key, "ofxVP::OrderedMap::erase(keyType)");
225+
fastErase(indexFor(key), key);
226+
size(); // validate map and vector have same sizes to make sure everything worked alright
227+
}
228+
229+
230+
//--------------------------------------------------------------
231+
template<typename keyType, typename T>
232+
void OrderedMap<keyType, T>::fastErase(int index, const keyType& key) {
233+
_map.erase(key);
234+
_vector.erase(_vector.begin() + index);
235+
updateMapIndices();
236+
}
237+
238+
239+
//--------------------------------------------------------------
240+
template<typename keyType, typename T>
241+
bool OrderedMap<keyType, T>::exists(const keyType& key) const {
242+
return _map.find(key) != _map.end();
243+
}
244+
245+
//--------------------------------------------------------------
246+
template<typename keyType, typename T>
247+
bool OrderedMap<keyType, T>::checkNullptr(const T& t) const {
248+
return t == nullptr;
249+
}
250+
251+
//--------------------------------------------------------------
252+
template<typename keyType, typename T>
253+
void OrderedMap<keyType, T>::validateIndex(int index, std::string errorMessage) const {
254+
#ifdef OFXVP_DEBUG
255+
if(index<0 || index >= _vector.size()) throw invalid_argument(errorMessage + " - index doesn't exist");
256+
#endif
257+
}
258+
259+
//--------------------------------------------------------------
260+
template<typename keyType, typename T>
261+
void OrderedMap<keyType, T>::validateKey(const keyType& key, std::string errorMessage) const {
262+
#ifdef OFXVP_DEBUG
263+
if(!exists(key)) throw invalid_argument(errorMessage + " - key doesn't exist");
264+
#endif
265+
}
266+
267+
//--------------------------------------------------------------
268+
template<typename keyType, typename T>
269+
void OrderedMap<keyType, T>::updateMapIndices() {
270+
for(int i=0; i<_vector.size(); i++) {
271+
const keyType& key = _vector[i];
272+
_map[key].second = i;
273+
}
274+
}
275+
276+
277+
} // End namespace ofxVP

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /