map.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
3  */
4 
5 #ifndef UAVCAN_UTIL_MAP_HPP_INCLUDED
6 #define UAVCAN_UTIL_MAP_HPP_INCLUDED
7 
8 #include <cassert>
9 #include <cstdlib>
11 #include <uavcan/build_config.hpp>
15 
16 namespace uavcan
17 {
32 template <typename Key, typename Value>
34 {
35 public:
36  struct KVPair
37  {
38  Value value; // Key and value are swapped because this may allow to reduce padding (depending on types)
39  Key key;
40 
41  KVPair() :
42  value(),
43  key()
44  { }
45 
46  KVPair(const Key& arg_key, const Value& arg_value) :
47  value(arg_value),
48  key(arg_key)
49  { }
50 
51  bool match(const Key& rhs) const { return rhs == key; }
52  };
53 
54 private:
55  struct KVGroup : LinkedListNode<KVGroup>
56  {
57  enum { NumKV = (MemPoolBlockSize - sizeof(LinkedListNode<KVGroup>)) / sizeof(KVPair) };
58  KVPair kvs[NumKV];
59 
61  {
62  StaticAssert<(static_cast<unsigned>(NumKV) > 0)>::check();
64  }
65 
66  static KVGroup* instantiate(IPoolAllocator& allocator)
67  {
68  void* const praw = allocator.allocate(sizeof(KVGroup));
69  if (praw == UAVCAN_NULLPTR)
70  {
71  return UAVCAN_NULLPTR;
72  }
73  return new (praw) KVGroup();
74  }
75 
76  static void destroy(KVGroup*& obj, IPoolAllocator& allocator)
77  {
78  if (obj != UAVCAN_NULLPTR)
79  {
80  obj->~KVGroup();
81  allocator.deallocate(obj);
82  obj = UAVCAN_NULLPTR;
83  }
84  }
85 
86  KVPair* find(const Key& key)
87  {
88  for (unsigned i = 0; i < static_cast<unsigned>(NumKV); i++)
89  {
90  if (kvs[i].match(key))
91  {
92  return kvs + i;
93  }
94  }
95  return UAVCAN_NULLPTR;
96  }
97  };
98 
101 
102  KVPair* findKey(const Key& key);
103 
104  void compact();
105 
107  {
108  bool operator()(const Key&, const Value&) const { return true; }
109  };
110 
111 public:
112  Map(IPoolAllocator& allocator) :
113  allocator_(allocator)
114  {
115  UAVCAN_ASSERT(Key() == Key());
116  }
117 
119  {
120  clear();
121  }
122 
126  Value* access(const Key& key);
127 
131  Value* insert(const Key& key, const Value& value);
132 
136  void remove(const Key& key);
137 
143  template <typename Predicate>
144  void removeAllWhere(Predicate predicate);
145 
151  template <typename Predicate>
152  const Key* find(Predicate predicate) const;
153 
157  void clear();
158 
164  KVPair* getByIndex(unsigned index);
165  const KVPair* getByIndex(unsigned index) const;
166 
170  bool isEmpty() const { return find(YesPredicate()) == UAVCAN_NULLPTR; }
171 
175  unsigned getSize() const;
176 };
177 
178 // ----------------------------------------------------------------------------
179 
180 /*
181  * Map<>
182  */
183 template <typename Key, typename Value>
185 {
186  KVGroup* p = list_.get();
187  while (p)
188  {
189  KVPair* const kv = p->find(key);
190  if (kv)
191  {
192  return kv;
193  }
194  p = p->getNextListNode();
195  }
196  return UAVCAN_NULLPTR;
197 }
198 
199 template <typename Key, typename Value>
201 {
202  KVGroup* p = list_.get();
203  while (p)
204  {
205  KVGroup* const next = p->getNextListNode();
206  bool remove_this = true;
207  for (int i = 0; i < KVGroup::NumKV; i++)
208  {
209  if (!p->kvs[i].match(Key()))
210  {
211  remove_this = false;
212  break;
213  }
214  }
215  if (remove_this)
216  {
217  list_.remove(p);
218  KVGroup::destroy(p, allocator_);
219  }
220  p = next;
221  }
222 }
223 
224 template <typename Key, typename Value>
225 Value* Map<Key, Value>::access(const Key& key)
226 {
227  UAVCAN_ASSERT(!(key == Key()));
228  KVPair* const kv = findKey(key);
229  return kv ? &kv->value : UAVCAN_NULLPTR;
230 }
231 
232 template <typename Key, typename Value>
233 Value* Map<Key, Value>::insert(const Key& key, const Value& value)
234 {
235  UAVCAN_ASSERT(!(key == Key()));
236  remove(key);
237 
238  KVPair* const kv = findKey(Key());
239  if (kv)
240  {
241  *kv = KVPair(key, value);
242  return &kv->value;
243  }
244 
245  KVGroup* const kvg = KVGroup::instantiate(allocator_);
246  if (kvg == UAVCAN_NULLPTR)
247  {
248  return UAVCAN_NULLPTR;
249  }
250  list_.insert(kvg);
251  kvg->kvs[0] = KVPair(key, value);
252  return &kvg->kvs[0].value;
253 }
254 
255 template <typename Key, typename Value>
256 void Map<Key, Value>::remove(const Key& key)
257 {
258  UAVCAN_ASSERT(!(key == Key()));
259  KVPair* const kv = findKey(key);
260  if (kv)
261  {
262  *kv = KVPair();
263  compact();
264  }
265 }
266 
267 template <typename Key, typename Value>
268 template <typename Predicate>
269 void Map<Key, Value>::removeAllWhere(Predicate predicate)
270 {
271  unsigned num_removed = 0;
272 
273  KVGroup* p = list_.get();
274  while (p != UAVCAN_NULLPTR)
275  {
276  KVGroup* const next_group = p->getNextListNode();
277 
278  for (int i = 0; i < KVGroup::NumKV; i++)
279  {
280  const KVPair* const kv = p->kvs + i;
281  if (!kv->match(Key()))
282  {
283  if (predicate(kv->key, kv->value))
284  {
285  num_removed++;
286  p->kvs[i] = KVPair();
287  }
288  }
289  }
290 
291  p = next_group;
292  }
293 
294  if (num_removed > 0)
295  {
296  compact();
297  }
298 }
299 
300 template <typename Key, typename Value>
301 template <typename Predicate>
302 const Key* Map<Key, Value>::find(Predicate predicate) const
303 {
304  KVGroup* p = list_.get();
305  while (p != UAVCAN_NULLPTR)
306  {
307  KVGroup* const next_group = p->getNextListNode();
308 
309  for (int i = 0; i < KVGroup::NumKV; i++)
310  {
311  const KVPair* const kv = p->kvs + i;
312  if (!kv->match(Key()))
313  {
314  if (predicate(kv->key, kv->value))
315  {
316  return &p->kvs[i].key;
317  }
318  }
319  }
320 
321  p = next_group;
322  }
323  return UAVCAN_NULLPTR;
324 }
325 
326 template <typename Key, typename Value>
328 {
329  removeAllWhere(YesPredicate());
330 }
331 
332 template <typename Key, typename Value>
334 {
335  // Slowly crawling through the dynamic storage
336  KVGroup* p = list_.get();
337  while (p != UAVCAN_NULLPTR)
338  {
339  KVGroup* const next_group = p->getNextListNode();
340 
341  for (int i = 0; i < KVGroup::NumKV; i++)
342  {
343  KVPair* const kv = p->kvs + i;
344  if (!kv->match(Key()))
345  {
346  if (index == 0)
347  {
348  return kv;
349  }
350  index--;
351  }
352  }
353 
354  p = next_group;
355  }
356 
357  return UAVCAN_NULLPTR;
358 }
359 
360 template <typename Key, typename Value>
361 const typename Map<Key, Value>::KVPair* Map<Key, Value>::getByIndex(unsigned index) const
362 {
363  return const_cast<Map<Key, Value>*>(this)->getByIndex(index);
364 }
365 
366 template <typename Key, typename Value>
367 unsigned Map<Key, Value>::getSize() const
368 {
369  unsigned num = 0;
370  KVGroup* p = list_.get();
371  while (p)
372  {
373  for (int i = 0; i < KVGroup::NumKV; i++)
374  {
375  const KVPair* const kv = p->kvs + i;
376  if (!kv->match(Key()))
377  {
378  num++;
379  }
380  }
381  p = p->getNextListNode();
382  }
383  return num;
384 }
385 
386 }
387 
388 #endif // UAVCAN_UTIL_MAP_HPP_INCLUDED
check
ROSCPP_DECL bool check()
UAVCAN_NULLPTR
#define UAVCAN_NULLPTR
Definition: libuavcan/libuavcan/include/uavcan/build_config.hpp:51
uavcan::Noncopyable
Definition: templates.hpp:46
templates.hpp
uavcan::Map::find
const Key * find(Predicate predicate) const
Definition: map.hpp:302
dynamic_memory.hpp
uavcan::Map::KVPair::key
Key key
Definition: map.hpp:39
uavcan::Map::list_
LinkedListRoot< KVGroup > list_
Definition: map.hpp:99
uavcan::Map::findKey
KVPair * findKey(const Key &key)
Definition: map.hpp:184
uavcan::Map::YesPredicate::operator()
bool operator()(const Key &, const Value &) const
Definition: map.hpp:108
uavcan::Map::KVGroup::instantiate
static KVGroup * instantiate(IPoolAllocator &allocator)
Definition: map.hpp:66
uavcan::Map::KVPair::value
Value value
Definition: map.hpp:38
uavcan::IPoolAllocator::allocate
virtual void * allocate(std::size_t size)=0
uavcan::Map::Map
Map(IPoolAllocator &allocator)
Definition: map.hpp:112
uavcan::Map::clear
void clear()
Definition: map.hpp:327
uavcan::Map::YesPredicate
Definition: map.hpp:106
uavcan::Map::access
Value * access(const Key &key)
Definition: map.hpp:225
match
static bool match(const uavcan::IncomingTransfer &it, const uavcan::RxFrame &frame, const uint8_t *payload, unsigned payload_len)
Definition: incoming_transfer.cpp:27
placement_new.hpp
uavcan::Map::insert
Value * insert(const Key &key, const Value &value)
Definition: map.hpp:233
uavcan::Map::compact
void compact()
Definition: map.hpp:200
uavcan::IPoolAllocator::deallocate
virtual void deallocate(const void *ptr)=0
uavcan::IsDynamicallyAllocatable::check
static void check()
Definition: libuavcan/libuavcan/include/uavcan/build_config.hpp:246
uavcan::Map
Definition: map.hpp:33
uavcan::Map::KVGroup::KVGroup
KVGroup()
Definition: map.hpp:60
uavcan::Map::getByIndex
KVPair * getByIndex(unsigned index)
Definition: map.hpp:333
uavcan::IPoolAllocator
Definition: dynamic_memory.hpp:21
uavcan::Map::KVPair::KVPair
KVPair(const Key &arg_key, const Value &arg_value)
Definition: map.hpp:46
uavcan::Map::KVGroup
Definition: map.hpp:55
UAVCAN_EXPORT
#define UAVCAN_EXPORT
Definition: libuavcan/libuavcan/include/uavcan/build_config.hpp:108
build_config.hpp
uavcan::Map::isEmpty
bool isEmpty() const
Definition: map.hpp:170
uavcan::MemPoolBlockSize
static const unsigned MemPoolBlockSize
Safe default that should be OK for any platform.
Definition: libuavcan/libuavcan/include/uavcan/build_config.hpp:228
uavcan::Map::KVGroup::find
KVPair * find(const Key &key)
Definition: map.hpp:86
linked_list.hpp
uavcan::Map::removeAllWhere
void removeAllWhere(Predicate predicate)
Definition: map.hpp:269
uavcan::Map::KVPair
Definition: map.hpp:36
uavcan::Map::KVPair::KVPair
KVPair()
Definition: map.hpp:41
uavcan::LinkedListRoot
Definition: linked_list.hpp:44
uavcan::Map::allocator_
IPoolAllocator & allocator_
Definition: map.hpp:100
uavcan::LinkedListNode
Definition: linked_list.hpp:20
uavcan
Definition: libuavcan/libuavcan/include/uavcan/build_config.hpp:204
uavcan::Map::KVPair::match
bool match(const Key &rhs) const
Definition: map.hpp:51
uavcan::Map::getSize
unsigned getSize() const
Definition: map.hpp:367
uavcan::Map::remove
void remove(const Key &key)
Definition: map.hpp:256
uavcan::Map::~Map
~Map()
Definition: map.hpp:118
uavcan::Map::KVGroup::destroy
static void destroy(KVGroup *&obj, IPoolAllocator &allocator)
Definition: map.hpp:76
UAVCAN_ASSERT
#define UAVCAN_ASSERT(x)
Definition: libuavcan/libuavcan/include/uavcan/build_config.hpp:184


uavcan_communicator
Author(s):
autogenerated on Fri Dec 13 2024 03:10:02