mirror of https://github.com/pvnis/srsRAN_4G.git
adt: create data structure type to represent an array of optional fields
parent
eb4999a18e
commit
8c24cfebd3
@ -0,0 +1,153 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* \section COPYRIGHT
|
||||||
|
*
|
||||||
|
* Copyright 2013-2021 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 SRSRAN_OPTIONAL_TABLE_H
|
||||||
|
#define SRSRAN_OPTIONAL_TABLE_H
|
||||||
|
|
||||||
|
#include "optional.h"
|
||||||
|
#include "srsran/common/srsran_assert.h"
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
namespace srsran {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Array of optional items. The iteration is in order of indexes and correctly skips non-present items
|
||||||
|
* Pointer/References/Iterators remain valid throughout the object lifetime
|
||||||
|
* NOTE: The sorted iteration and pointer validation guarantees add some overhead if the array is very fragmented
|
||||||
|
* @tparam T type of objects
|
||||||
|
* @tparam N static size of max nof items
|
||||||
|
*/
|
||||||
|
template <typename T, size_t N>
|
||||||
|
class optional_table
|
||||||
|
{
|
||||||
|
template <typename Obj>
|
||||||
|
class iterator_impl
|
||||||
|
{
|
||||||
|
using It = iterator_impl<Obj>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using iterator_category = std::forward_iterator_tag;
|
||||||
|
using value_type = Obj;
|
||||||
|
using difference_type = std::ptrdiff_t;
|
||||||
|
using pointer = Obj*;
|
||||||
|
using reference = Obj&;
|
||||||
|
|
||||||
|
iterator_impl() = default;
|
||||||
|
iterator_impl(optional_table<T, N>* parent_, size_t idx_) : parent(parent_), idx(idx_)
|
||||||
|
{
|
||||||
|
if (idx < parent->capacity() and not parent->contains(idx)) {
|
||||||
|
++(*this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
It& operator++()
|
||||||
|
{
|
||||||
|
while (++idx < parent->capacity() and not parent->contains(idx)) {
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
It& operator--()
|
||||||
|
{
|
||||||
|
while (--idx < parent->capacity() and not parent->contains(idx)) {
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
reference operator*() { return parent->operator[](idx); }
|
||||||
|
pointer operator->() { return &parent->operator[](idx); }
|
||||||
|
|
||||||
|
bool operator==(const It& other) const { return idx == other.idx and parent == other.parent; }
|
||||||
|
bool operator!=(const It& other) const { return not(*this == other); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
friend class optional_table<T, N>;
|
||||||
|
|
||||||
|
optional_table<T, N>* parent = nullptr;
|
||||||
|
size_t idx = N;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
using iterator = iterator_impl<T>;
|
||||||
|
using const_iterator = iterator_impl<const T>;
|
||||||
|
|
||||||
|
optional_table() {}
|
||||||
|
optional_table(const optional_table&) = default;
|
||||||
|
optional_table(optional_table&& other) noexcept : vec(std::move(other.vec)), nof_elems(other.nof_elems)
|
||||||
|
{
|
||||||
|
other.nof_elems = 0;
|
||||||
|
}
|
||||||
|
optional_table& operator=(const optional_table&) = default;
|
||||||
|
optional_table& operator =(optional_table&& other) noexcept
|
||||||
|
{
|
||||||
|
vec = std::move(other.vec);
|
||||||
|
nof_elems = other.nof_elems;
|
||||||
|
nof_elems = 0;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find first position that is empty
|
||||||
|
size_t find_first_empty()
|
||||||
|
{
|
||||||
|
if (nof_elems == capacity()) {
|
||||||
|
return N;
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < N; ++i) {
|
||||||
|
if (not vec[i].has_value()) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return N;
|
||||||
|
}
|
||||||
|
template <typename U>
|
||||||
|
void insert(size_t idx, U&& u)
|
||||||
|
{
|
||||||
|
nof_elems += contains(idx) ? 0 : 1;
|
||||||
|
vec[idx] = std::forward<U>(u);
|
||||||
|
}
|
||||||
|
void erase(size_t idx)
|
||||||
|
{
|
||||||
|
if (contains(idx)) {
|
||||||
|
nof_elems--;
|
||||||
|
vec[idx].reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void erase(iterator it) { erase(it.idx); }
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
nof_elems = 0;
|
||||||
|
for (auto& e : *this) {
|
||||||
|
e.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool contains(size_t idx) const { return idx < N and vec[idx].has_value(); }
|
||||||
|
|
||||||
|
T& operator[](size_t idx) { return *vec[idx]; }
|
||||||
|
const T& operator[](size_t idx) const { return *vec[idx]; }
|
||||||
|
|
||||||
|
bool empty() const { return nof_elems == 0; }
|
||||||
|
size_t size() const { return nof_elems; }
|
||||||
|
static size_t capacity() { return N; }
|
||||||
|
|
||||||
|
iterator begin() { return iterator{this, 0}; }
|
||||||
|
iterator end() { return iterator{this, N}; }
|
||||||
|
const_iterator begin() const { return const_iterator{this, 0}; }
|
||||||
|
const_iterator end() const { return const_iterator{this, N}; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
size_t nof_elems = 0;
|
||||||
|
std::array<optional<T>, N> vec;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace srsran
|
||||||
|
|
||||||
|
#endif // SRSRAN_OPTIONAL_TABLE_H
|
@ -0,0 +1,58 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* \section COPYRIGHT
|
||||||
|
*
|
||||||
|
* Copyright 2013-2021 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 "srsran/adt/optional_table.h"
|
||||||
|
#include "srsran/common/test_common.h"
|
||||||
|
|
||||||
|
namespace srsran {
|
||||||
|
|
||||||
|
void test_slot_table()
|
||||||
|
{
|
||||||
|
optional_table<int, 5> table1;
|
||||||
|
TESTASSERT(table1.size() == 0 and table1.empty());
|
||||||
|
|
||||||
|
TESTASSERT(not table1.contains(0));
|
||||||
|
table1.insert(0, 5);
|
||||||
|
TESTASSERT(table1.size() == 1 and not table1.empty());
|
||||||
|
table1.erase(0);
|
||||||
|
TESTASSERT(table1.size() == 0 and table1.empty());
|
||||||
|
table1.insert(1, 3);
|
||||||
|
table1.insert(4, 2);
|
||||||
|
TESTASSERT(table1.size() == 2);
|
||||||
|
TESTASSERT(table1[4] == 2 and table1[1] == 3);
|
||||||
|
|
||||||
|
size_t count = 0;
|
||||||
|
int array[] = {3, 2};
|
||||||
|
for (int e : table1) {
|
||||||
|
TESTASSERT(array[count++] == e);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto it = table1.begin();
|
||||||
|
TESTASSERT(*it == 3);
|
||||||
|
table1.erase(it);
|
||||||
|
TESTASSERT(table1.size() == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace srsran
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
auto& test_log = srslog::fetch_basic_logger("TEST");
|
||||||
|
test_log.set_level(srslog::basic_levels::info);
|
||||||
|
|
||||||
|
srsran::test_init(argc, argv);
|
||||||
|
|
||||||
|
srsran::test_slot_table();
|
||||||
|
|
||||||
|
printf("Success\n");
|
||||||
|
return SRSRAN_SUCCESS;
|
||||||
|
}
|
Loading…
Reference in New Issue