Commit 07131e8b by Maarten L. Hekkelman

copy constructor for category

parent 39b91e74
...@@ -106,25 +106,8 @@ class category_t ...@@ -106,25 +106,8 @@ class category_t
class row class row
{ {
public: public:
row()
: m_next(nullptr)
, m_head(nullptr)
, m_tail(nullptr)
{
}
row(row *next, item_value *data) row() = default;
: m_next(next)
, m_head(data)
, m_tail(data)
{
auto n = m_tail ? m_tail->m_next : nullptr;
while (n != nullptr)
{
m_tail = n;
n = n->m_next;
}
}
private: private:
template <typename> template <typename>
...@@ -135,6 +118,14 @@ class category_t ...@@ -135,6 +118,14 @@ class category_t
friend class category_t; friend class category_t;
void append(item_value *iv)
{
if (m_head == nullptr)
m_head = m_tail = iv;
else
m_tail = m_tail->m_next = iv;
}
row *m_next = nullptr; row *m_next = nullptr;
item_value *m_head = nullptr, *m_tail = nullptr; item_value *m_head = nullptr, *m_tail = nullptr;
}; };
...@@ -152,13 +143,12 @@ class category_t ...@@ -152,13 +143,12 @@ class category_t
, m_name(rhs.m_name) , m_name(rhs.m_name)
, m_columns(rhs.m_columns) , m_columns(rhs.m_columns)
{ {
// for (value_type r : rhs) for (auto r = rhs.m_head; r != nullptr; r = r->m_next)
// this->emplace(r); insert_impl(cend(), clone_row(*r));
} }
category_t(category_t &&) category_t(category_t &&)
{ {
} }
template <typename Alloc2> template <typename Alloc2>
...@@ -177,12 +167,10 @@ class category_t ...@@ -177,12 +167,10 @@ class category_t
category_t &operator=(const category_t &) category_t &operator=(const category_t &)
{ {
} }
category_t &operator=(category_t &&) category_t &operator=(category_t &&)
{ {
} }
~category_t() ~category_t()
...@@ -286,14 +274,19 @@ class category_t ...@@ -286,14 +274,19 @@ class category_t
// -------------------------------------------------------------------- // --------------------------------------------------------------------
iterator emplace(std::initializer_list<item> items) void insert(const_iterator pos, const row &row)
{ {
return this->emplace(items.begin(), items.end()); insert_impl(pos, row);
}
void insert(const_iterator pos, row &&row)
{
insert_impl(pos, std::move(row));
} }
iterator emplace(value_type row) iterator emplace(std::initializer_list<item> items)
{ {
// return return this->emplace(items.begin(), items.end());
} }
template <typename ItemIter> template <typename ItemIter>
...@@ -354,11 +347,7 @@ class category_t ...@@ -354,11 +347,7 @@ class category_t
for (auto i = b; i != e; ++i) for (auto i = b; i != e; ++i)
{ {
item_value *new_item = this->create_item(*i); item_value *new_item = this->create_item(*i);
r->append(new_item);
if (r->m_head == nullptr)
r->m_head = r->m_tail = new_item;
else
r->m_tail = r->m_tail->m_next = new_item;
} }
} }
catch (...) catch (...)
...@@ -368,12 +357,7 @@ class category_t ...@@ -368,12 +357,7 @@ class category_t
throw; throw;
} }
if (m_head == nullptr) return insert_impl(cend(), r);
m_head = m_tail = r;
else
m_tail = m_tail->m_next = r;
return {*this, r};
// result = r; // result = r;
...@@ -493,15 +477,35 @@ class category_t ...@@ -493,15 +477,35 @@ class category_t
return row_allocator_traits::allocate(ra, 1); return row_allocator_traits::allocate(ra, 1);
} }
template <typename... Args> row *create_row()
row *create_row(Args... args)
{ {
auto p = this->get_row(); auto p = this->get_row();
row_allocator_type ra(get_allocator()); row_allocator_type ra(get_allocator());
row_allocator_traits::construct(ra, p, std::forward<Args>(args)...); row_allocator_traits::construct(ra, p);
return p; return p;
} }
row *clone_row(const row &r)
{
row *result = create_row();
try
{
for (auto i = r.m_head; i != nullptr; i = i->m_next)
{
item_value *v = create_item(i->m_column_ix, i->text());
result->append(v);
}
}
catch (...)
{
delete_row(result);
throw;
}
return result;
}
void delete_row(row *r) void delete_row(row *r)
{ {
row_allocator_type ra(get_allocator()); row_allocator_type ra(get_allocator());
...@@ -521,6 +525,84 @@ class category_t ...@@ -521,6 +525,84 @@ class category_t
} }
}; };
// proxy methods for every insertion
iterator insert_impl(const_iterator pos, row *n)
{
assert(n != nullptr);
assert(n->m_next == nullptr);
if (n == nullptr)
throw std::runtime_error("Invalid pointer passed to insert");
// insert at end, most often this is the case
if (pos.m_current == nullptr)
{
if (m_head == nullptr)
m_tail = m_head = n;
else
m_tail = m_tail->m_next = n;
}
else
{
assert(m_head != nullptr);
if (pos.m_current == m_head)
m_head = n->m_next = m_head;
else
n = n->m_next = m_head->m_next;
}
return iterator(*this, n);
}
iterator erase_impl(const_iterator pos)
{
if (pos == cend())
return pos;
row *n = const_cast<row *>(&*pos);
row *cur;
if (m_head == n)
{
m_head = static_cast<row *>(m_head->m_next);
if (m_head != nullptr)
m_head->m_prev = nullptr;
else
m_tail = nullptr;
n->m_next = n->m_prev = n->m_parent = nullptr;
delete_row(n);
cur = m_head;
}
else
{
cur = static_cast<row *>(n->m_next);
if (m_tail == n)
m_tail = static_cast<row *>(n->m_prev);
row *p = m_head;
while (p != nullptr and p->m_next != n)
p = p->m_next;
if (p != nullptr and p->m_next == n)
{
p->m_next = n->m_next;
if (p->m_next != nullptr)
p->m_next->m_prev = p;
n->m_next = nullptr;
}
else
throw std::runtime_error("remove for a row not found in the list");
delete_row(n);
}
return iterator(*this, cur);
}
allocator_type m_allocator; allocator_type m_allocator;
std::string m_name; std::string m_name;
std::vector<item_column, typename std::allocator_traits<allocator_type>::template rebind_alloc<item_column>> m_columns; std::vector<item_column, typename std::allocator_traits<allocator_type>::template rebind_alloc<item_column>> m_columns;
......
...@@ -40,6 +40,9 @@ class iterator_impl ...@@ -40,6 +40,9 @@ class iterator_impl
template <typename, typename...> template <typename, typename...>
friend class iterator_impl; friend class iterator_impl;
template <typename>
friend class category_t;
static constexpr size_t N = sizeof...(Ts); static constexpr size_t N = sizeof...(Ts);
using category_type = Category; using category_type = Category;
......
...@@ -218,9 +218,6 @@ BOOST_AUTO_TEST_CASE(c_2) ...@@ -218,9 +218,6 @@ BOOST_AUTO_TEST_CASE(c_2)
cif::v2::category c2(c); cif::v2::category c2(c);
for (auto r : c)
c2.emplace(r);
BOOST_CHECK(not c2.empty()); BOOST_CHECK(not c2.empty());
BOOST_CHECK_EQUAL(c2.size(), 3); BOOST_CHECK_EQUAL(c2.size(), 3);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment