UCommon
mapref.h
Go to the documentation of this file.
1// Copyright (C) 2015 Cherokees of Idaho.
2//
3// This file is part of GNU uCommon C++.
4//
5// GNU uCommon C++ is free software: you can redistribute it and/or modify
6// it under the terms of the GNU Lesser General Public License as published
7// by the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// GNU uCommon C++ is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU Lesser General Public License for more details.
14//
15// You should have received a copy of the GNU Lesser General Public License
16// along with GNU uCommon C++. If not, see <http://www.gnu.org/licenses/>.
17
25#ifndef _UCOMMON_MAPREF_H_
26#define _UCOMMON_MAPREF_H_
27
28#ifndef _UCOMMON_CPR_H_
29#include <ucommon/cpr.h>
30#endif
31
32#ifndef _UCOMMON_ATOMIC_H_
33#include <ucommon/atomic.h>
34#endif
35
36#ifndef _UCOMMON_PROTOCOLS_H_
37#include <ucommon/protocols.h>
38#endif
39
40#ifndef _UCOMMON_OBJECT_H_
41#include <ucommon/object.h>
42#endif
43
44#ifndef _UCOMMON_TYPEREF_H_
45#include <ucommon/typeref.h>
46#endif
47
48#ifndef _UCOMMON_LINKED_H_
49#include <ucommon/linked.h>
50#endif
51
52#ifndef _UCOMMON_THREAD_H_
53#include <ucommon/thread.h>
54#endif
55
56namespace ucommon {
57
58class __EXPORT MapRef : public TypeRef
59{
60protected:
61 class Map;
62 class Instance;
63
64 class __EXPORT Index : public LinkedObject
65 {
66 private:
67 __DELETE_COPY(Index);
68
69 public:
70 friend class Map;
71
72 explicit Index(LinkedObject **origin);
73
74 Index();
75
76 Counted *key, *value;
77 };
78
79 class __EXPORT Map : public Counted
80 {
81 private:
82 __DELETE_COPY(Map);
83
84 protected:
85 friend class Instance;
86
87 virtual void dealloc() __OVERRIDE;
88
89 public:
90 friend class MapRef;
91
92 memalloc pool;
93 condlock_t lock;
94 LinkedObject *free, *last;
95 size_t count, alloc;
96
97 explicit Map(void *addr, size_t indexes, size_t paging = 0);
98
99 inline LinkedObject **get(void) {
100 return reinterpret_cast<LinkedObject **>(((caddr_t)(this)) + sizeof(Map));
101 }
102
103 Index *create(size_t path);
104
105 Index *append();
106
107 void remove(Index *index, size_t path);
108
109 LinkedObject *modify(size_t key = 0);
110
111 LinkedObject *access(size_t key = 0);
112 };
113
114 class __EXPORT Instance
115 {
116 protected:
117 Map *map;
118 LinkedObject *index;
119 size_t path;
120
121 Instance();
122
123 Instance(MapRef& from);
124
125 explicit Instance(Map *map);
126
127 Instance(const Instance& copy);
128
129 void assign(const Instance& copy);
130
131 void assign(MapRef& from);
132
133 void drop(void);
134
135 Counted *key();
136
137 Counted *value();
138
139 public:
140 ~Instance();
141
142 void rewind();
143
144 bool next();
145
146 bool eol();
147
148 bool top();
149
150 inline operator bool() {
151 return index != NULL;
152 }
153
154 inline bool operator!() {
155 return index == NULL;
156 }
157 };
158
159 MapRef(size_t paths, size_t paging = 0);
160 MapRef(const MapRef& copy);
161 MapRef();
162
163 void assign(TypeRef& key, TypeRef& value);
164
165 static Map *create(size_t paths, size_t paging = 0);
166
167 linked_pointer<Index> access(size_t keyvalue = 0);
168
169 linked_pointer<Index> modify(size_t keyvalue = 0);
170
171 void append(TypeRef& value);
172
173 void add(size_t path, TypeRef& key, TypeRef& value);
174
175 void update(Index *ind, TypeRef& value);
176
177 void remove(Index *ind, size_t path = 0);
178
179 void release();
180
181 void commit();
182
183public:
184 size_t count(void);
185
186 size_t used(void);
187
188 void purge(void);
189
190 static size_t index(size_t& key, const uint8_t *addr, size_t len);
191};
192
193template<typename T>
194inline size_t mapkeypath(typeref<T>& object)
195{
196 size_t path = sizeof(T);
197 return MapRef::index(path, (const uint8_t *)(object()), sizeof(T));
198}
199
200template<>
201inline size_t mapkeypath<const char *>(typeref<const char *>& object)
202{
203 size_t path = 1;
204 return MapRef::index(path, (const uint8_t *)(*object), object.len());
205}
206
207template<>
208inline size_t mapkeypath<const uint8_t *>(typeref<const uint8_t *>& object)
209{
210 size_t path = object.size();
211 return MapRef::index(path, *object, object.size());
212}
213
214template<typename K, typename V>
215class mapref : public MapRef
216{
217protected:
218 bool erase(typeref<K>& key) {
219 size_t path = mapkeypath<K>(key);
220 linked_pointer<Index> ip = modify(path);
221 while(is(ip)) {
222 typeref<K> kv(ip->key);
223 if(is(kv) && kv == key) {
224 MapRef::remove(*ip, path);
225 MapRef::commit();
226 return true;
227 }
228 ip.next();
229 }
230 MapRef::commit();
231 return false;
232 }
233
234public:
235 class instance : public MapRef::Instance
236 {
237 public:
238 inline instance(const instance& copy) : Instance(static_cast<const Instance&>(copy)) {};
239
240 inline instance(mapref& from) : Instance(static_cast<MapRef&>(from)) {};
241
242 inline instance() : Instance() {};
243
244 inline typeref<K> key() {
245 return typeref<K>(Instance::key());
246 }
247
248 inline typeref<V> value() {
249 return typeref<V>(Instance::value());
250 }
251
252 inline instance& operator++() {
253 next();
254 return *this;
255 }
256
257 inline instance& operator=(const instance& copy) {
258 assign(static_cast<const Instance&>(copy));
259 return *this;
260 }
261
262 inline instance& operator=(mapref& from) {
263 assign(static_cast<MapRef&>(from));
264 return *this;
265 }
266 };
267
268 inline mapref(const mapref& copy) : MapRef(copy) {};
269
270 inline mapref(size_t paths = 37, size_t paging = 0) : MapRef(paths, paging) {};
271
272 inline mapref& operator=(const mapref& copy) {
274 return *this;
275 }
276
277 inline instance operator*() {
278 return instance(this);
279 }
280
281 void value(typeref<K>& key, typeref<V>& val) {
282 size_t path = mapkeypath<K>(key);
283 linked_pointer<Index> ip = modify(path);
284 while(is(ip)) {
285 typeref<K> kv(ip->key);
286 if(is(kv) && kv == key) {
287 update(*ip, val);
288 commit();
289 return;
290 }
291 ip.next();
292 }
293 add(path, key, val);
294 commit();
295 }
296
297 typeref<V> at(typeref<K>& key) {
298 linked_pointer<Index> ip = access(mapkeypath<K>(key));
299 while(is(ip)) {
300 typeref<K> kv(ip->key);
301 if(is(kv) && kv == key) {
302 typeref<V> result(ip->value);
303 release();
304 return result;
305 }
306 ip.next();
307 }
308 release();
309 return typeref<V>();
310 }
311
312 typeref<V> take(typeref<K>& key) {
313 size_t path = mapkeypath<K>(key);
314 linked_pointer<Index> ip = modify(path);
315 while(is(ip)) {
316 typeref<K> kv(ip->key);
317 if(is(kv) && kv == key) {
318 typeref<V> result(ip->value);
319 if(is(result.is))
320 MapRef::remove(*ip, path);
321 commit();
322 return result;
323 }
324 ip.next();
325 }
326 commit();
327 return typeref<V>();
328 }
329
330 inline bool remove(typeref<K>& key) {
331 return erase(key);
332 }
333
334 inline bool remove(K k) {
335 typeref<K> key(k);
336 return erase(key);
337 }
338
339 inline typeref<V> operator()(typeref<K>& key) {
340 return at(key);
341 }
342
343 inline typeref<V> operator()(K k) {
344 typeref<K> key(k);
345 return at(key);
346 }
347
348 inline void operator()(typeref<K>& key, typeref<V>& val) {
349 value(key, val);
350 }
351
352 inline void operator()(K k, V v) {
353 typeref<K> key(k);
354 typeref<V> val(v);
355 value(key, val);
356 }
357};
358
359template<typename T>
360class listref : public MapRef
361{
362protected:
363 bool erase(typeref<T>& value) {
364 linked_pointer<Index> ip = modify();
365 while(ip) {
366 typeref<T> kv(ip->value);
367 if(is(kv) && kv == value) {
368 MapRef::remove(*ip);
369 MapRef::commit();
370 return true;
371 }
372 ip.next();
373 }
374 MapRef::commit();
375 return false;
376 }
377
378public:
379 class instance : public MapRef::Instance
380 {
381 public:
382 inline instance(const instance& copy) : Instance(static_cast<const Instance&>(copy)) {};
383
384 inline instance(listref& from) : Instance(static_cast<MapRef&>(from)) {};
385
386 inline instance() : Instance() {};
387
388 inline const T& operator*() {
389 return *(Instance::value());
390 }
391
392 inline const T* operator->() {
393 return Instance::value();
394 }
395
396 inline instance& operator++() {
397 next();
398 return *this;
399 }
400
401 inline instance& operator=(const instance& copy) {
402 assign(static_cast<const Instance&>(copy));
403 return *this;
404 }
405
406 inline instance& operator=(listref& from) {
407 assign(static_cast<MapRef&>(from));
408 return *this;
409 }
410 };
411
412 inline listref(const listref& copy) : MapRef(copy) {};
413
414 inline listref(size_t paging = 0) : MapRef(1, paging) {};
415
416 inline listref& operator=(const listref& copy) {
418 return *this;
419 }
420
421 inline instance operator*() {
422 return instance(this);
423 }
424
425 inline listref& operator<<(typeref<T>& value) {
426 append(value);
427 return *this;
428 }
429
430 inline listref& operator<<(T t) {
431 typeref<T> v(t);
432 append(v);
433 return *this;
434 }
435
436 inline bool remove(typeref<T>& key) {
437 return erase(key);
438 }
439
440 inline bool remove(T t) {
441 typeref<T> key(t);
442 return erase(key);
443 }
444
445 inline typeref<T> take(size_t offset) {
446 linked_pointer<Index> ip = modify();
447 while(is(ip) && offset--) {
448 ip.next();
449 }
450 typeref<T> v(ip->value);
451 if(is(v))
452 MapRef::remove(*ip);
453 commit();
454 return v;
455 }
456
457 inline typeref<T> at(size_t offset) {
458 linked_pointer<Index> ip = access();
459 while(ip && offset--) {
460 ip.next();
461 }
462 typeref<T> v(ip->value);
463 release();
464 return v;
465 }
466
467 inline typeref<T> operator[](size_t offset) {
468 return at(offset);
469 }
470};
471
472
473} // namespace
474
475#endif
Runtime functions.
A thread-safe atomic heap management system.
Linked objects, lists, templates, and containers.
Atomic pointers and locks.
Abstract interfaces and support.
Common namespace for all ucommon objects.
Definition access.h:47
T copy(const T &src)
Convenience function to copy objects.
Definition generics.h:395
bool is(T &object)
Convenience function to validate object assuming it is castable to bool.
Definition generics.h:292
void set(Counted *object)
Set our smart pointer to a specific heap container.
A common object base class with auto-pointer support.
Thread classes and sychronization objects.