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 
56 namespace ucommon {
57 
58 class __EXPORT MapRef : public TypeRef
59 {
60 protected:
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 
183 public:
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 
193 template<typename T>
194 inline 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 
200 template<>
201 inline 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 
207 template<>
208 inline 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 
214 template<typename K, typename V>
215 class mapref : public MapRef
216 {
217 protected:
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 
234 public:
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 
359 template<typename T>
360 class listref : public MapRef
361 {
362 protected:
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 
378 public:
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
Linked objects, lists, templates, and containers.
void set(Counted *object)
Set our smart pointer to a specific heap container.
A common object base class with auto-pointer support.
bool is(T &object)
Convenience function to validate object assuming it is castable to bool.
Definition: generics.h:292
const struct sockaddr * addr(Socket::address &address)
A convenience function to convert a socket address list into a socket address.
Definition: socket.h:2089
Atomic pointers and locks.
Thread classes and sychronization objects.
ConditionalLock condlock_t
Convenience type for using conditional locks.
Definition: condition.h:725
Common namespace for all ucommon objects.
Definition: access.h:47
T copy(const T &src)
Convenience function to copy objects.
Definition: generics.h:395
Abstract interfaces and support.
Runtime functions.
A thread-safe atomic heap management system.