mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-10-15 06:13:33 +08:00
Map<>::getByIndex()
This commit is contained in:
@@ -36,6 +36,7 @@ class UAVCAN_EXPORT MapBase : Noncopyable
|
||||
template <typename, typename, unsigned> friend class Map;
|
||||
|
||||
UAVCAN_PACKED_BEGIN
|
||||
public:
|
||||
struct KVPair
|
||||
{
|
||||
Key key;
|
||||
@@ -48,6 +49,7 @@ class UAVCAN_EXPORT MapBase : Noncopyable
|
||||
bool match(const Key& rhs) const { return rhs == key; }
|
||||
};
|
||||
|
||||
private:
|
||||
struct KVGroup : LinkedListNode<KVGroup>
|
||||
{
|
||||
enum { NumKV = (MemPoolBlockSize - sizeof(LinkedListNode<KVGroup>)) / sizeof(KVPair) };
|
||||
@@ -166,12 +168,22 @@ public:
|
||||
|
||||
void removeAll();
|
||||
|
||||
/**
|
||||
* Returns a key-value pair located at the specified position from the beginning.
|
||||
* Note that any insertion or deletion may greatly disturb internal ordering, so use with care.
|
||||
* If index is greater than or equal the number of pairs, null pointer will be returned.
|
||||
*/
|
||||
KVPair* getByIndex(unsigned index);
|
||||
const KVPair* getByIndex(unsigned index) const;
|
||||
|
||||
bool isEmpty() const;
|
||||
|
||||
/// For testing
|
||||
unsigned getNumStaticPairs() const;
|
||||
unsigned getSize() const;
|
||||
|
||||
/// For testing
|
||||
/**
|
||||
* For testing, do not use directly.
|
||||
*/
|
||||
unsigned getNumStaticPairs() const;
|
||||
unsigned getNumDynamicPairs() const;
|
||||
};
|
||||
|
||||
@@ -458,10 +470,60 @@ void MapBase<Key, Value>::removeAll()
|
||||
removeWhere(YesPredicate());
|
||||
}
|
||||
|
||||
template <typename Key, typename Value>
|
||||
typename MapBase<Key, Value>::KVPair* MapBase<Key, Value>::getByIndex(unsigned index)
|
||||
{
|
||||
// Checking the static storage
|
||||
for (unsigned i = 0; i < num_static_entries_; i++)
|
||||
{
|
||||
if (!static_[i].match(Key()))
|
||||
{
|
||||
if (index == 0)
|
||||
{
|
||||
return static_ + i;
|
||||
}
|
||||
index--;
|
||||
}
|
||||
}
|
||||
|
||||
// Slowly crawling through the dynamic storage
|
||||
KVGroup* p = list_.get();
|
||||
while (p)
|
||||
{
|
||||
for (int i = 0; i < KVGroup::NumKV; i++)
|
||||
{
|
||||
KVPair* const kv = p->kvs + i;
|
||||
if (!kv->match(Key()))
|
||||
{
|
||||
if (index == 0)
|
||||
{
|
||||
return kv;
|
||||
}
|
||||
index--;
|
||||
}
|
||||
}
|
||||
p = p->getNextListNode();
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
template <typename Key, typename Value>
|
||||
const typename MapBase<Key, Value>::KVPair* MapBase<Key, Value>::getByIndex(unsigned index) const
|
||||
{
|
||||
return const_cast<MapBase<Key, Value>*>(this)->getByIndex(index);
|
||||
}
|
||||
|
||||
template <typename Key, typename Value>
|
||||
bool MapBase<Key, Value>::isEmpty() const
|
||||
{
|
||||
return (getNumStaticPairs() == 0) && (getNumDynamicPairs() == 0);
|
||||
return getSize() == 0;
|
||||
}
|
||||
|
||||
template <typename Key, typename Value>
|
||||
unsigned MapBase<Key, Value>::getSize() const
|
||||
{
|
||||
return getNumStaticPairs() + getNumDynamicPairs();
|
||||
}
|
||||
|
||||
template <typename Key, typename Value>
|
||||
|
||||
@@ -55,6 +55,9 @@ TEST(Map, Basic)
|
||||
ASSERT_FALSE(map->access("hi"));
|
||||
map->remove("foo");
|
||||
ASSERT_EQ(0, pool.getNumUsedBlocks());
|
||||
ASSERT_FALSE(map->getByIndex(0));
|
||||
ASSERT_FALSE(map->getByIndex(1));
|
||||
ASSERT_FALSE(map->getByIndex(10000));
|
||||
|
||||
// Static insertion
|
||||
ASSERT_EQ("a", *map->insert("1", "a"));
|
||||
@@ -63,6 +66,10 @@ TEST(Map, Basic)
|
||||
ASSERT_EQ(2, map->getNumStaticPairs());
|
||||
ASSERT_EQ(0, map->getNumDynamicPairs());
|
||||
|
||||
// Ordering
|
||||
ASSERT_TRUE(map->getByIndex(0)->match("1"));
|
||||
ASSERT_TRUE(map->getByIndex(1)->match("2"));
|
||||
|
||||
// Dynamic insertion
|
||||
ASSERT_EQ("c", *map->insert("3", "c"));
|
||||
ASSERT_EQ(1, pool.getNumUsedBlocks());
|
||||
@@ -79,6 +86,14 @@ TEST(Map, Basic)
|
||||
ASSERT_EQ("d", *map->access("4"));
|
||||
ASSERT_FALSE(map->access("hi"));
|
||||
|
||||
// Ordering
|
||||
ASSERT_TRUE(map->getByIndex(0)->match("1"));
|
||||
ASSERT_TRUE(map->getByIndex(1)->match("2"));
|
||||
ASSERT_TRUE(map->getByIndex(2)->match("3"));
|
||||
ASSERT_TRUE(map->getByIndex(3)->match("4"));
|
||||
ASSERT_FALSE(map->getByIndex(4));
|
||||
ASSERT_FALSE(map->getByIndex(1000));
|
||||
|
||||
// Modifying existing entries
|
||||
*map->access("1") = "A";
|
||||
*map->access("2") = "B";
|
||||
@@ -115,6 +130,11 @@ TEST(Map, Basic)
|
||||
ASSERT_EQ("C", *map->access("3"));
|
||||
ASSERT_EQ("D", *map->access("4"));
|
||||
|
||||
// Ordering has not changed - first dynamic entry has moved to the first static slot
|
||||
ASSERT_TRUE(map->getByIndex(0)->match("3"));
|
||||
ASSERT_TRUE(map->getByIndex(1)->match("2"));
|
||||
ASSERT_TRUE(map->getByIndex(2)->match("4"));
|
||||
|
||||
// Removing another static
|
||||
map->remove("2");
|
||||
ASSERT_EQ(2, map->getNumStaticPairs());
|
||||
@@ -198,11 +218,18 @@ TEST(Map, NoStatic)
|
||||
ASSERT_FALSE(map->access("hi"));
|
||||
map->remove("foo");
|
||||
ASSERT_EQ(0, pool.getNumUsedBlocks());
|
||||
ASSERT_FALSE(map->getByIndex(0));
|
||||
|
||||
// Static insertion
|
||||
// Insertion
|
||||
ASSERT_EQ("a", *map->insert("1", "a"));
|
||||
ASSERT_EQ("b", *map->insert("2", "b"));
|
||||
ASSERT_EQ(1, pool.getNumUsedBlocks());
|
||||
ASSERT_EQ(0, map->getNumStaticPairs());
|
||||
ASSERT_EQ(2, map->getNumDynamicPairs());
|
||||
|
||||
// Ordering
|
||||
ASSERT_TRUE(map->getByIndex(0)->match("1"));
|
||||
ASSERT_TRUE(map->getByIndex(1)->match("2"));
|
||||
ASSERT_FALSE(map->getByIndex(3));
|
||||
ASSERT_FALSE(map->getByIndex(1000));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user