mirror of https://github.com/pvnis/srsRAN_4G.git
adt addition - implemented reusable circular map
parent
4523ee6087
commit
98d0637ded
@ -0,0 +1,169 @@
|
||||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2020 Software Radio Systems Limited
|
||||
*
|
||||
* By using this file, you agree to the terms and conditions set
|
||||
* forth in the LICENSE file which can be found at the top level of
|
||||
* the distribution.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SRSLTE_ID_MAP_H
|
||||
#define SRSLTE_ID_MAP_H
|
||||
|
||||
#include "expected.h"
|
||||
#include <array>
|
||||
#include <cassert>
|
||||
|
||||
template <typename K, typename T, size_t N>
|
||||
class static_circular_map
|
||||
{
|
||||
static_assert(std::is_integral<K>::value, "Map key must be an integer");
|
||||
|
||||
using obj_t = std::pair<K, T>;
|
||||
using obj_storage_t = typename std::aligned_storage<sizeof(obj_t), alignof(obj_t)>::type;
|
||||
|
||||
public:
|
||||
bool has_key(K id)
|
||||
{
|
||||
size_t idx = id % N;
|
||||
return present[idx] and get_obj_(idx).first == id;
|
||||
}
|
||||
|
||||
bool insert(K id, const T& obj)
|
||||
{
|
||||
size_t idx = id % N;
|
||||
if (present[idx]) {
|
||||
return false;
|
||||
}
|
||||
new (&buffer[idx]) obj_t(id, obj);
|
||||
present[idx] = true;
|
||||
count++;
|
||||
return true;
|
||||
}
|
||||
srslte::error_type<T> insert(K id, T&& obj)
|
||||
{
|
||||
size_t idx = id % N;
|
||||
if (present[idx]) {
|
||||
return srslte::error_type<T>(std::move(obj));
|
||||
}
|
||||
new (&buffer[idx]) obj_t(id, std::move(obj));
|
||||
present[idx] = true;
|
||||
count++;
|
||||
return {};
|
||||
}
|
||||
|
||||
bool erase(K id)
|
||||
{
|
||||
if (not has_key(id)) {
|
||||
return false;
|
||||
}
|
||||
size_t idx = id % N;
|
||||
get_obj_(idx).~obj_t();
|
||||
present[idx] = false;
|
||||
--count;
|
||||
return true;
|
||||
}
|
||||
|
||||
T& operator[](K id)
|
||||
{
|
||||
assert(has_key(id));
|
||||
return get_obj_(id % N).second;
|
||||
}
|
||||
const T& operator[](K id) const
|
||||
{
|
||||
assert(has_key(id));
|
||||
return get_obj_(id % N).second;
|
||||
}
|
||||
|
||||
size_t size() const { return count; }
|
||||
bool empty() const { return count == 0; }
|
||||
bool full() const { return count == N; }
|
||||
size_t capacity() const { return N; }
|
||||
|
||||
class iterator
|
||||
{
|
||||
public:
|
||||
iterator() = default;
|
||||
iterator(static_circular_map<K, T, N>* map, size_t idx_) : ptr(map), idx(idx_)
|
||||
{
|
||||
if (idx < ptr->capacity() and not ptr->present[idx]) {
|
||||
++(*this);
|
||||
}
|
||||
}
|
||||
|
||||
iterator& operator++()
|
||||
{
|
||||
while (++idx < ptr->capacity() and not ptr->present[idx]) {
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
obj_t& operator*() { return ptr->get_obj_(idx); }
|
||||
obj_t* operator->() { return &ptr->get_obj_(idx); }
|
||||
const obj_t* operator*() const { return ptr->buffer[idx]; }
|
||||
const obj_t* operator->() const { return ptr->buffer[idx]; }
|
||||
|
||||
bool operator==(const iterator& other) const { return ptr == other.ptr and idx == other.idx; }
|
||||
bool operator!=(const iterator& other) const { return not(*this == other); }
|
||||
|
||||
private:
|
||||
static_circular_map<K, T, N>* ptr = nullptr;
|
||||
size_t idx = 0;
|
||||
};
|
||||
class const_iterator
|
||||
{
|
||||
public:
|
||||
const_iterator() = default;
|
||||
const_iterator(static_circular_map<K, T, N>* map, size_t idx_) : ptr(map), idx(idx_) {}
|
||||
|
||||
const_iterator& operator++()
|
||||
{
|
||||
while (++idx < ptr->capacity() and not ptr->present[idx]) {
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
const obj_t* operator*() const { return ptr->buffer[idx]; }
|
||||
const obj_t* operator->() const { return ptr->buffer[idx]; }
|
||||
|
||||
bool operator==(const const_iterator& other) const { return ptr == other.ptr and idx == other.idx; }
|
||||
bool operator!=(const const_iterator& other) const { return not(*this == other); }
|
||||
|
||||
private:
|
||||
const static_circular_map<K, T, N>* ptr = nullptr;
|
||||
size_t idx = 0;
|
||||
};
|
||||
|
||||
iterator begin() { return iterator(this, 0); }
|
||||
iterator end() { return iterator(this, N); }
|
||||
const_iterator begin() const { return iterator(this, 0); }
|
||||
const_iterator end() const { return iterator(this, N); }
|
||||
|
||||
iterator find(K id)
|
||||
{
|
||||
if (has_key(id)) {
|
||||
return iterator(this, id % N);
|
||||
}
|
||||
return end();
|
||||
}
|
||||
const_iterator find(K id) const
|
||||
{
|
||||
if (has_key(id)) {
|
||||
return iterator(this, id % N);
|
||||
}
|
||||
return end();
|
||||
}
|
||||
|
||||
private:
|
||||
obj_t& get_obj_(size_t idx) { return reinterpret_cast<obj_t&>(buffer[idx]); }
|
||||
const obj_t& get_obj_(size_t idx) const { return reinterpret_cast<obj_t&>(buffer[idx]); }
|
||||
|
||||
std::array<obj_storage_t, N> buffer;
|
||||
std::array<bool, N> present = {false};
|
||||
size_t count = 0;
|
||||
};
|
||||
|
||||
#endif // SRSLTE_ID_MAP_H
|
@ -0,0 +1,70 @@
|
||||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2020 Software Radio Systems Limited
|
||||
*
|
||||
* By using this file, you agree to the terms and conditions set
|
||||
* forth in the LICENSE file which can be found at the top level of
|
||||
* the distribution.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "srslte/adt/circular_map.h"
|
||||
#include "srslte/common/test_common.h"
|
||||
|
||||
namespace srslte {
|
||||
|
||||
int test_id_map()
|
||||
{
|
||||
static_circular_map<uint32_t, std::string, 16> myobj;
|
||||
TESTASSERT(myobj.size() == 0 and myobj.empty() and not myobj.full());
|
||||
TESTASSERT(myobj.begin() == myobj.end());
|
||||
|
||||
TESTASSERT(not myobj.has_key(0));
|
||||
TESTASSERT(myobj.insert(0, "obj0"));
|
||||
TESTASSERT(myobj.has_key(0) and myobj[0] == "obj0");
|
||||
TESTASSERT(myobj.size() == 1 and not myobj.empty() and not myobj.full());
|
||||
TESTASSERT(myobj.begin() != myobj.end());
|
||||
|
||||
TESTASSERT(not myobj.insert(0, "obj0"));
|
||||
TESTASSERT(myobj.insert(1, "obj1"));
|
||||
TESTASSERT(myobj.has_key(0) and myobj.has_key(1) and myobj[1] == "obj1");
|
||||
TESTASSERT(myobj.size() == 2 and not myobj.empty() and not myobj.full());
|
||||
|
||||
TESTASSERT(myobj.find(1) != myobj.end());
|
||||
TESTASSERT(myobj.find(1)->first == 1);
|
||||
TESTASSERT(myobj.find(1)->second == "obj1");
|
||||
|
||||
// TEST: iteration
|
||||
uint32_t count = 0;
|
||||
for (std::pair<uint32_t, std::string>& obj : myobj) {
|
||||
TESTASSERT(obj.second == "obj" + std::to_string(count++));
|
||||
}
|
||||
|
||||
// TEST: const iteration
|
||||
count = 0;
|
||||
for (const std::pair<uint32_t, std::string>& obj : myobj) {
|
||||
TESTASSERT(obj.second == "obj" + std::to_string(count++));
|
||||
}
|
||||
|
||||
TESTASSERT(myobj.erase(0));
|
||||
TESTASSERT(myobj.erase(1));
|
||||
TESTASSERT(myobj.size() == 0 and myobj.empty());
|
||||
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
} // namespace srslte
|
||||
|
||||
int main()
|
||||
{
|
||||
auto& test_log = srslog::fetch_basic_logger("TEST");
|
||||
test_log.set_level(srslog::basic_levels::info);
|
||||
|
||||
// Start the log backend.
|
||||
srslog::init();
|
||||
|
||||
TESTASSERT(srslte::test_id_map() == SRSLTE_SUCCESS);
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
Loading…
Reference in New Issue