mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-10-25 02:53:33 +08:00
Some headers moved to util/ (map, bitset, linked_list); compile_time.hpp renamed to templates.hpp
This commit is contained in:
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
#include <uavcan/impl_constants.hpp>
|
||||
|
||||
namespace uavcan
|
||||
{
|
||||
/**
|
||||
* STL-like bitset
|
||||
*/
|
||||
template <std::size_t NumBits>
|
||||
class UAVCAN_EXPORT BitSet
|
||||
{
|
||||
enum { NumBytes = (NumBits + 7) / 8 };
|
||||
|
||||
static std::size_t getByteNum(std::size_t bit_num) { return bit_num / 8; }
|
||||
|
||||
static std::size_t getBitNum(const std::size_t bit_num) { return bit_num % 8; }
|
||||
|
||||
static void validatePos(std::size_t& inout_pos)
|
||||
{
|
||||
if (inout_pos >= NumBits)
|
||||
{
|
||||
assert(0);
|
||||
inout_pos = NumBits - 1;
|
||||
}
|
||||
}
|
||||
|
||||
char data_[NumBytes];
|
||||
|
||||
public:
|
||||
class Reference
|
||||
{
|
||||
friend class BitSet;
|
||||
|
||||
BitSet* const parent_;
|
||||
const std::size_t bitpos_;
|
||||
|
||||
Reference(BitSet* arg_parent, std::size_t arg_bitpos)
|
||||
: parent_(arg_parent)
|
||||
, bitpos_(arg_bitpos)
|
||||
{ }
|
||||
|
||||
public:
|
||||
Reference& operator=(bool x)
|
||||
{
|
||||
parent_->set(bitpos_, x);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Reference& operator=(const Reference& x)
|
||||
{
|
||||
parent_->set(bitpos_, x);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator~() const
|
||||
{
|
||||
return !parent_->test(bitpos_);
|
||||
}
|
||||
|
||||
operator bool() const
|
||||
{
|
||||
return parent_->test(bitpos_);
|
||||
}
|
||||
};
|
||||
|
||||
BitSet()
|
||||
: data_()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
BitSet<NumBits>& reset()
|
||||
{
|
||||
std::memset(data_, 0, NumBytes);
|
||||
return *this;
|
||||
}
|
||||
|
||||
BitSet<NumBits>& set()
|
||||
{
|
||||
std::memset(data_, 0xFF, NumBytes);
|
||||
return *this;
|
||||
}
|
||||
|
||||
BitSet<NumBits>& set(std::size_t pos, bool val = true)
|
||||
{
|
||||
validatePos(pos);
|
||||
if (val)
|
||||
{
|
||||
data_[getByteNum(pos)] |= (1 << getBitNum(pos));
|
||||
}
|
||||
else
|
||||
{
|
||||
data_[getByteNum(pos)] &= ~(1 << getBitNum(pos));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool test(std::size_t pos) const
|
||||
{
|
||||
return (data_[getByteNum(pos)] & (1 << getBitNum(pos))) != 0;
|
||||
}
|
||||
|
||||
bool any() const
|
||||
{
|
||||
for (std::size_t i = 0; i < NumBits; ++i)
|
||||
{
|
||||
if (test(i))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::size_t count() const
|
||||
{
|
||||
std::size_t retval = 0;
|
||||
for (std::size_t i = 0; i < NumBits; ++i)
|
||||
{
|
||||
retval += test(i) ? 1U : 0U;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
std::size_t size() const { return NumBits; }
|
||||
|
||||
bool operator[](std::size_t pos) const
|
||||
{
|
||||
return test(pos);
|
||||
}
|
||||
|
||||
Reference operator[](std::size_t pos)
|
||||
{
|
||||
validatePos(pos);
|
||||
return Reference(this, pos);
|
||||
}
|
||||
|
||||
BitSet<NumBits>& operator=(const BitSet<NumBits> & rhs)
|
||||
{
|
||||
if (&rhs == this)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
for (std::size_t i = 0; i < NumBytes; ++i)
|
||||
{
|
||||
data_[i] = rhs.data_[i];
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator!=(const BitSet<NumBits>& rhs) const { return !operator==(rhs); }
|
||||
bool operator==(const BitSet<NumBits>& rhs) const
|
||||
{
|
||||
for (std::size_t i = 0; i < NumBits; ++i)
|
||||
{
|
||||
if (test(i) != rhs.test(i))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <> class BitSet<0>; ///< Invalid instantiation
|
||||
|
||||
|
||||
template <typename Stream, std::size_t NumBits>
|
||||
Stream& operator<<(Stream& s, const BitSet<NumBits>& x)
|
||||
{
|
||||
for (std::size_t i = NumBits; i > 0; --i)
|
||||
{
|
||||
s << (x.test(i-1) ? "1" : "0");
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -7,7 +7,7 @@
|
||||
#include <cstdlib>
|
||||
#include <uavcan/error.hpp>
|
||||
#include <uavcan/impl_constants.hpp>
|
||||
#include <uavcan/util/compile_time.hpp>
|
||||
#include <uavcan/util/templates.hpp>
|
||||
|
||||
#ifndef UAVCAN_CPP_VERSION
|
||||
# error UAVCAN_CPP_VERSION
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Singly-linked list.
|
||||
* Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cassert>
|
||||
#include <uavcan/impl_constants.hpp>
|
||||
|
||||
namespace uavcan
|
||||
{
|
||||
/**
|
||||
* Classes that are supposed to be linked-listed should derive this.
|
||||
*/
|
||||
template <typename T>
|
||||
class UAVCAN_EXPORT LinkedListNode
|
||||
{
|
||||
T* next_;
|
||||
|
||||
protected:
|
||||
LinkedListNode()
|
||||
: next_(NULL)
|
||||
{ }
|
||||
|
||||
~LinkedListNode() { }
|
||||
|
||||
public:
|
||||
T* getNextListNode() const { return next_; }
|
||||
|
||||
void setNextListNode(T* node)
|
||||
{
|
||||
next_ = node;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Linked list root.
|
||||
*/
|
||||
template <typename T>
|
||||
class UAVCAN_EXPORT LinkedListRoot
|
||||
{
|
||||
T* root_;
|
||||
|
||||
public:
|
||||
LinkedListRoot()
|
||||
: root_(NULL)
|
||||
{ }
|
||||
|
||||
T* get() const { return root_; }
|
||||
bool isEmpty() const { return get() == NULL; }
|
||||
|
||||
unsigned getLength() const;
|
||||
|
||||
void insert(T* node);
|
||||
|
||||
/**
|
||||
* Inserts node A immediately before the node B where
|
||||
* predicate(B) -> true.
|
||||
*/
|
||||
template <typename Predicate>
|
||||
void insertBefore(T* node, Predicate predicate);
|
||||
|
||||
void remove(const T* node);
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* LinkedListRoot<>
|
||||
*/
|
||||
template <typename T>
|
||||
unsigned LinkedListRoot<T>::getLength() const
|
||||
{
|
||||
T* node = root_;
|
||||
unsigned cnt = 0;
|
||||
while (node)
|
||||
{
|
||||
cnt++;
|
||||
node = node->getNextListNode();
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void LinkedListRoot<T>::insert(T* node)
|
||||
{
|
||||
assert(node);
|
||||
remove(node); // Making sure there will be no loops
|
||||
node->setNextListNode(root_);
|
||||
root_ = node;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
template <typename Predicate>
|
||||
void LinkedListRoot<T>::insertBefore(T* node, Predicate predicate)
|
||||
{
|
||||
assert(node);
|
||||
remove(node);
|
||||
|
||||
if (root_ == NULL || predicate(root_))
|
||||
{
|
||||
insert(node);
|
||||
}
|
||||
else
|
||||
{
|
||||
T* p = root_;
|
||||
while (p->getNextListNode())
|
||||
{
|
||||
if (predicate(p->getNextListNode()))
|
||||
{
|
||||
break;
|
||||
}
|
||||
p = p->getNextListNode();
|
||||
}
|
||||
node->setNextListNode(p->getNextListNode());
|
||||
p->setNextListNode(node);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void LinkedListRoot<T>::remove(const T* node)
|
||||
{
|
||||
if (root_ == NULL || node == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (root_ == node)
|
||||
{
|
||||
root_ = root_->getNextListNode();
|
||||
}
|
||||
else
|
||||
{
|
||||
T* p = root_;
|
||||
while (p->getNextListNode())
|
||||
{
|
||||
if (p->getNextListNode() == node)
|
||||
{
|
||||
p->setNextListNode(p->getNextListNode()->getNextListNode());
|
||||
break;
|
||||
}
|
||||
p = p->getNextListNode();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,481 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include <uavcan/util/linked_list.hpp>
|
||||
#include <uavcan/impl_constants.hpp>
|
||||
#include <uavcan/dynamic_memory.hpp>
|
||||
#include <uavcan/util/templates.hpp>
|
||||
|
||||
namespace uavcan
|
||||
{
|
||||
/**
|
||||
* Slow but memory efficient KV container.
|
||||
* Type requirements:
|
||||
* Both key and value must be copyable, assignable and default constructible.
|
||||
* Key must implement a comparison operator.
|
||||
* Key's default constructor must initialize the object into invalid state.
|
||||
* Size of Key + Value + padding must not exceed MemPoolBlockSize.
|
||||
*/
|
||||
template <typename Key, typename Value>
|
||||
class UAVCAN_EXPORT MapBase : Noncopyable
|
||||
{
|
||||
template <typename, typename, unsigned> friend class Map;
|
||||
|
||||
UAVCAN_PACKED_BEGIN
|
||||
struct KVPair
|
||||
{
|
||||
Key key;
|
||||
Value value;
|
||||
KVPair() { }
|
||||
KVPair(const Key& arg_key, const Value& arg_value)
|
||||
: key(arg_key)
|
||||
, value(arg_value)
|
||||
{ }
|
||||
bool match(const Key& rhs) const { return rhs == key; }
|
||||
};
|
||||
|
||||
struct KVGroup : LinkedListNode<KVGroup>
|
||||
{
|
||||
enum { NumKV = (MemPoolBlockSize - sizeof(LinkedListNode<KVGroup>)) / sizeof(KVPair) };
|
||||
KVPair kvs[NumKV];
|
||||
|
||||
KVGroup()
|
||||
{
|
||||
StaticAssert<(static_cast<unsigned>(NumKV) > 0)>::check();
|
||||
IsDynamicallyAllocatable<KVGroup>::check();
|
||||
}
|
||||
|
||||
static KVGroup* instantiate(IPoolAllocator& allocator)
|
||||
{
|
||||
void* const praw = allocator.allocate(sizeof(KVGroup));
|
||||
if (praw == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return new (praw) KVGroup();
|
||||
}
|
||||
|
||||
static void destroy(KVGroup*& obj, IPoolAllocator& allocator)
|
||||
{
|
||||
if (obj != NULL)
|
||||
{
|
||||
obj->~KVGroup();
|
||||
allocator.deallocate(obj);
|
||||
obj = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
KVPair* find(const Key& key)
|
||||
{
|
||||
for (unsigned i = 0; i < static_cast<unsigned>(NumKV); i++)
|
||||
{
|
||||
if (kvs[i].match(key))
|
||||
{
|
||||
return kvs + i;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
};
|
||||
UAVCAN_PACKED_END
|
||||
|
||||
LinkedListRoot<KVGroup> list_;
|
||||
IPoolAllocator& allocator_;
|
||||
#if !UAVCAN_TINY
|
||||
KVPair* const static_;
|
||||
const unsigned num_static_entries_;
|
||||
#endif
|
||||
|
||||
KVPair* find(const Key& key);
|
||||
|
||||
#if !UAVCAN_TINY
|
||||
void optimizeStorage();
|
||||
#endif
|
||||
void compact();
|
||||
|
||||
struct YesPredicate
|
||||
{
|
||||
bool operator()(const Key& k, const Value& v) const { (void)k; (void)v; return true; }
|
||||
};
|
||||
|
||||
protected:
|
||||
#if UAVCAN_TINY
|
||||
MapBase(IPoolAllocator& allocator)
|
||||
: allocator_(allocator)
|
||||
{
|
||||
assert(Key() == Key());
|
||||
}
|
||||
#else
|
||||
MapBase(KVPair* static_buf, unsigned num_static_entries, IPoolAllocator& allocator)
|
||||
: allocator_(allocator)
|
||||
, static_(static_buf)
|
||||
, num_static_entries_(num_static_entries)
|
||||
{
|
||||
assert(Key() == Key());
|
||||
}
|
||||
#endif
|
||||
|
||||
/// Derived class destructor must call removeAll();
|
||||
~MapBase() { }
|
||||
|
||||
public:
|
||||
Value* access(const Key& key);
|
||||
|
||||
/// If entry with the same key already exists, it will be replaced
|
||||
Value* insert(const Key& key, const Value& value);
|
||||
|
||||
void remove(const Key& key);
|
||||
|
||||
/**
|
||||
* Remove entries where predicate returns true.
|
||||
* Predicate prototype:
|
||||
* bool (const Key& key, const Value& value)
|
||||
*/
|
||||
template <typename Predicate>
|
||||
void removeWhere(Predicate predicate);
|
||||
|
||||
template <typename Predicate>
|
||||
const Key* findFirstKey(Predicate predicate) const;
|
||||
|
||||
void removeAll();
|
||||
|
||||
bool isEmpty() const;
|
||||
|
||||
/// For testing
|
||||
unsigned getNumStaticPairs() const;
|
||||
|
||||
/// For testing
|
||||
unsigned getNumDynamicPairs() const;
|
||||
};
|
||||
|
||||
|
||||
template <typename Key, typename Value, unsigned NumStaticEntries = 0>
|
||||
class UAVCAN_EXPORT Map : public MapBase<Key, Value>
|
||||
{
|
||||
typename MapBase<Key, Value>::KVPair static_[NumStaticEntries];
|
||||
|
||||
public:
|
||||
|
||||
#if !UAVCAN_TINY
|
||||
|
||||
// This instantiation will not be valid in UAVCAN_TINY mode
|
||||
explicit Map(IPoolAllocator& allocator)
|
||||
: MapBase<Key, Value>(static_, NumStaticEntries, allocator)
|
||||
{ }
|
||||
|
||||
~Map() { this->removeAll(); }
|
||||
|
||||
#endif // !UAVCAN_TINY
|
||||
};
|
||||
|
||||
|
||||
template <typename Key, typename Value>
|
||||
class UAVCAN_EXPORT Map<Key, Value, 0> : public MapBase<Key, Value>
|
||||
{
|
||||
public:
|
||||
explicit Map(IPoolAllocator& allocator)
|
||||
#if UAVCAN_TINY
|
||||
: MapBase<Key, Value>(allocator)
|
||||
#else
|
||||
: MapBase<Key, Value>(NULL, 0, allocator)
|
||||
#endif
|
||||
{ }
|
||||
|
||||
~Map() { this->removeAll(); }
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* MapBase<>
|
||||
*/
|
||||
template <typename Key, typename Value>
|
||||
typename MapBase<Key, Value>::KVPair* MapBase<Key, Value>::find(const Key& key)
|
||||
{
|
||||
#if !UAVCAN_TINY
|
||||
for (unsigned i = 0; i < num_static_entries_; i++)
|
||||
{
|
||||
if (static_[i].match(key))
|
||||
{
|
||||
return static_ + i;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
KVGroup* p = list_.get();
|
||||
while (p)
|
||||
{
|
||||
KVPair* const kv = p->find(key);
|
||||
if (kv)
|
||||
{
|
||||
return kv;
|
||||
}
|
||||
p = p->getNextListNode();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if !UAVCAN_TINY
|
||||
|
||||
template <typename Key, typename Value>
|
||||
void MapBase<Key, Value>::optimizeStorage()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
// Looking for first EMPTY static entry
|
||||
KVPair* stat = NULL;
|
||||
for (unsigned i = 0; i < num_static_entries_; i++)
|
||||
{
|
||||
if (static_[i].match(Key()))
|
||||
{
|
||||
stat = static_ + i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (stat == NULL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Looking for the first NON-EMPTY dynamic entry, erasing immediately
|
||||
KVGroup* p = list_.get();
|
||||
KVPair dyn;
|
||||
while (p)
|
||||
{
|
||||
bool stop = false;
|
||||
for (int i = 0; i < KVGroup::NumKV; i++)
|
||||
{
|
||||
if (!p->kvs[i].match(Key())) // Non empty
|
||||
{
|
||||
dyn = p->kvs[i]; // Copy by value
|
||||
p->kvs[i] = KVPair(); // Erase immediately
|
||||
stop = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (stop)
|
||||
{
|
||||
break;
|
||||
}
|
||||
p = p->getNextListNode();
|
||||
}
|
||||
if (dyn.match(Key()))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Migrating
|
||||
*stat = dyn;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // !UAVCAN_TINY
|
||||
|
||||
template <typename Key, typename Value>
|
||||
void MapBase<Key, Value>::compact()
|
||||
{
|
||||
KVGroup* p = list_.get();
|
||||
while (p)
|
||||
{
|
||||
KVGroup* const next = p->getNextListNode();
|
||||
bool remove_this = true;
|
||||
for (int i = 0; i < KVGroup::NumKV; i++)
|
||||
{
|
||||
if (!p->kvs[i].match(Key()))
|
||||
{
|
||||
remove_this = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (remove_this)
|
||||
{
|
||||
list_.remove(p);
|
||||
KVGroup::destroy(p, allocator_);
|
||||
}
|
||||
p = next;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Key, typename Value>
|
||||
Value* MapBase<Key, Value>::access(const Key& key)
|
||||
{
|
||||
assert(!(key == Key()));
|
||||
KVPair* const kv = find(key);
|
||||
return kv ? &kv->value : NULL;
|
||||
}
|
||||
|
||||
template <typename Key, typename Value>
|
||||
Value* MapBase<Key, Value>::insert(const Key& key, const Value& value)
|
||||
{
|
||||
assert(!(key == Key()));
|
||||
remove(key);
|
||||
|
||||
KVPair* const kv = find(Key());
|
||||
if (kv)
|
||||
{
|
||||
*kv = KVPair(key, value);
|
||||
return &kv->value;
|
||||
}
|
||||
|
||||
KVGroup* const kvg = KVGroup::instantiate(allocator_);
|
||||
if (kvg == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
list_.insert(kvg);
|
||||
kvg->kvs[0] = KVPair(key, value);
|
||||
return &kvg->kvs[0].value;
|
||||
}
|
||||
|
||||
template <typename Key, typename Value>
|
||||
void MapBase<Key, Value>::remove(const Key& key)
|
||||
{
|
||||
assert(!(key == Key()));
|
||||
KVPair* const kv = find(key);
|
||||
if (kv)
|
||||
{
|
||||
*kv = KVPair();
|
||||
#if !UAVCAN_TINY
|
||||
optimizeStorage();
|
||||
#endif
|
||||
compact();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Key, typename Value>
|
||||
template <typename Predicate>
|
||||
void MapBase<Key, Value>::removeWhere(Predicate predicate)
|
||||
{
|
||||
unsigned num_removed = 0;
|
||||
|
||||
#if !UAVCAN_TINY
|
||||
for (unsigned i = 0; i < num_static_entries_; i++)
|
||||
{
|
||||
if (!static_[i].match(Key()))
|
||||
{
|
||||
if (predicate(static_[i].key, static_[i].value))
|
||||
{
|
||||
num_removed++;
|
||||
static_[i] = KVPair();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
KVGroup* p = list_.get();
|
||||
while (p)
|
||||
{
|
||||
for (int i = 0; i < KVGroup::NumKV; i++)
|
||||
{
|
||||
const KVPair* const kv = p->kvs + i;
|
||||
if (!kv->match(Key()))
|
||||
{
|
||||
if (predicate(kv->key, kv->value))
|
||||
{
|
||||
num_removed++;
|
||||
p->kvs[i] = KVPair();
|
||||
}
|
||||
}
|
||||
}
|
||||
p = p->getNextListNode();
|
||||
}
|
||||
|
||||
if (num_removed > 0)
|
||||
{
|
||||
#if !UAVCAN_TINY
|
||||
optimizeStorage();
|
||||
#endif
|
||||
compact();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Key, typename Value>
|
||||
template <typename Predicate>
|
||||
const Key* MapBase<Key, Value>::findFirstKey(Predicate predicate) const
|
||||
{
|
||||
#if !UAVCAN_TINY
|
||||
for (unsigned i = 0; i < num_static_entries_; i++)
|
||||
{
|
||||
if (!static_[i].match(Key()))
|
||||
{
|
||||
if (predicate(static_[i].key, static_[i].value))
|
||||
{
|
||||
return &static_[i].key;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
KVGroup* p = list_.get();
|
||||
while (p)
|
||||
{
|
||||
for (int i = 0; i < KVGroup::NumKV; i++)
|
||||
{
|
||||
const KVPair* const kv = p->kvs + i;
|
||||
if (!kv->match(Key()))
|
||||
{
|
||||
if (predicate(kv->key, kv->value))
|
||||
{
|
||||
return &p->kvs[i].key;
|
||||
}
|
||||
}
|
||||
}
|
||||
p = p->getNextListNode();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
template <typename Key, typename Value>
|
||||
void MapBase<Key, Value>::removeAll()
|
||||
{
|
||||
removeWhere(YesPredicate());
|
||||
}
|
||||
|
||||
template <typename Key, typename Value>
|
||||
bool MapBase<Key, Value>::isEmpty() const
|
||||
{
|
||||
return (getNumStaticPairs() == 0) && (getNumDynamicPairs() == 0);
|
||||
}
|
||||
|
||||
template <typename Key, typename Value>
|
||||
unsigned MapBase<Key, Value>::getNumStaticPairs() const
|
||||
{
|
||||
unsigned num = 0;
|
||||
#if !UAVCAN_TINY
|
||||
for (unsigned i = 0; i < num_static_entries_; i++)
|
||||
{
|
||||
if (!static_[i].match(Key()))
|
||||
{
|
||||
num++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return num;
|
||||
}
|
||||
|
||||
template <typename Key, typename Value>
|
||||
unsigned MapBase<Key, Value>::getNumDynamicPairs() const
|
||||
{
|
||||
unsigned num = 0;
|
||||
KVGroup* p = list_.get();
|
||||
while (p)
|
||||
{
|
||||
for (int i = 0; i < KVGroup::NumKV; i++)
|
||||
{
|
||||
const KVPair* const kv = p->kvs + i;
|
||||
if (!kv->match(Key()))
|
||||
{
|
||||
num++;
|
||||
}
|
||||
}
|
||||
p = p->getNextListNode();
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
#include <uavcan/error.hpp>
|
||||
#include <uavcan/impl_constants.hpp>
|
||||
#include <uavcan/util/compile_time.hpp>
|
||||
#include <uavcan/util/templates.hpp>
|
||||
|
||||
namespace uavcan
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user