Commit 85c21aeb by Maarten L. Hekkelman

row as vector

parent 2f249048
......@@ -14,3 +14,4 @@ Testing/
rsrc/feature-request.txt
test/test-create_sugar_?.cif
test/oprofile_data/
test/perf.data*
......@@ -370,8 +370,8 @@ class category
{
for (auto i = b; i != e; ++i)
{
item_value *new_item = this->create_item(*i);
r->append(new_item);
// item_value *new_item = this->create_item(*i);
r->append(add_column(i->name()), { i->value() });
}
}
catch (...)
......@@ -510,67 +510,6 @@ class category
using char_allocator_type = typename std::allocator_traits<allocator_type>::template rebind_alloc<char>;
using char_allocator_traits = std::allocator_traits<char_allocator_type>;
using item_allocator_type = typename std::allocator_traits<allocator_type>::template rebind_alloc<item_value>;
using item_allocator_traits = std::allocator_traits<item_allocator_type>;
item_allocator_traits::pointer get_item()
{
item_allocator_type ia(get_allocator());
return item_allocator_traits::allocate(ia, 1);
}
item_value *create_item(uint16_t column_ix, std::string_view text)
{
size_t text_length = text.length();
if (text_length + 1 > std::numeric_limits<uint16_t>::max())
throw std::runtime_error("libcifpp does not support string lengths longer than " + std::to_string(std::numeric_limits<uint16_t>::max()) + " bytes");
auto p = this->get_item();
item_allocator_type ia(get_allocator());
item_allocator_traits::construct(ia, p, column_ix, static_cast<uint16_t>(text_length));
char_allocator_type ca(get_allocator());
char *data;
if (text_length >= item_value::kBufferSize)
data = p->m_data = char_allocator_traits::allocate(ca, text_length + 1);
else
data = p->m_local_data;
std::copy(text.begin(), text.end(), data);
data[text_length] = 0;
return p;
}
item_value *create_item(const item &i)
{
uint16_t ix = add_column(i.name());
return create_item(ix, i.value());
}
item_value *create_item(const std::tuple<std::string_view,std::string> &i)
{
const auto &[name, value] = i;
uint16_t ix = add_column(name);
return create_item(ix, value);
}
void delete_item(item_value *iv)
{
if (iv->m_length >= item_value::kBufferSize)
{
char_allocator_type ca(get_allocator());
char_allocator_traits::deallocate(ca, iv->m_data, iv->m_length + 1);
}
item_allocator_type ia(get_allocator());
item_allocator_traits::destroy(ia, iv);
item_allocator_traits::deallocate(ia, iv, 1);
}
using row_allocator_type = typename std::allocator_traits<allocator_type>::template rebind_alloc<row>;
using row_allocator_traits = std::allocator_traits<row_allocator_type>;
......
......@@ -255,8 +255,8 @@ namespace detail
std::string m_item_tag;
size_t m_item_ix = 0;
bool m_icase = false;
std::string m_value;
bool m_icase = false;
std::optional<row_handle> m_single_hit;
};
......
......@@ -179,21 +179,58 @@ class item
struct item_value
{
item_value() = default;
/// \brief constructor
item_value(uint16_t column_ix, uint16_t length)
: m_next(nullptr)
, m_column_ix(column_ix)
, m_length(length)
item_value(std::string_view text)
: m_length(text.length())
{
if (m_length >= kBufferSize)
{
m_data = new char[m_length + 1];
std::copy(text.begin(), text.end(), m_data);
m_data[m_length] = 0;
}
else
{
std::copy(text.begin(), text.end(), m_local_data);
m_local_data[m_length] = 0;
}
}
item_value(item_value &&rhs)
: m_length(std::exchange(rhs.m_length, 0))
, m_data(std::exchange(rhs.m_data, nullptr))
{
}
item_value &operator=(item_value &&rhs)
{
if (this != &rhs)
{
m_length = std::exchange(rhs.m_length, m_length);
m_data = std::exchange(rhs.m_data, m_data);
}
return *this;
}
~item_value()
{
if (m_length >= kBufferSize)
delete[] m_data;
m_data = nullptr;
m_length = 0;
}
item_value() = delete;
item_value(const item_value &) = delete;
item_value &operator=(const item_value &) = delete;
item_value *m_next;
uint16_t m_column_ix;
uint16_t m_length;
explicit operator bool() const
{
return m_length != 0;
}
size_t m_length = 0;
union
{
char m_local_data[8];
......@@ -210,7 +247,8 @@ struct item_value
}
};
static_assert(sizeof(item_value) == 24, "sizeof(item_value) should be 24 bytes");
// static_assert(sizeof(item_value) == 24, "sizeof(item_value) should be 24 bytes");
static_assert(sizeof(item_value) == 16, "sizeof(item_value) should be 16 bytes");
// --------------------------------------------------------------------
// Transient object to access stored data
......
......@@ -103,60 +103,43 @@ auto tie(Ts &...v)
// --------------------------------------------------------------------
/// \brief the row class, this one is not directly accessible from the outside
class row
class row : public std::vector<item_value>
{
public:
row() = default;
item_value* get(size_t ix)
{
return ix < size() ? &at(ix) : nullptr;
}
const item_value* get(size_t ix) const
{
return ix < size() ? &at(ix) : nullptr;
}
private:
friend class item_handle;
friend class category;
friend class category_index;
friend class row_initializer;
template <typename, typename...>
friend class iterator_impl;
friend class category;
void append(item_value *iv)
void append(size_t ix, item_value &&iv)
{
if (m_head == nullptr)
m_head = m_tail = iv;
else
m_tail = m_tail->m_next = iv;
if (ix >= size())
resize(ix + 1);
at(ix) = std::move(iv);
}
void remove(item_value *iv)
void remove(size_t ix)
{
if (iv == m_head)
{
if (m_tail == m_head)
{
assert(iv->m_next == nullptr);
m_head = m_tail = nullptr;
}
else
m_head = m_head->m_next;
}
else
{
for (auto v = m_head; v->m_next != nullptr; v = v->m_next)
{
if (v->m_next != iv)
continue;
v->m_next = iv->m_next;
iv->m_next = nullptr;
if (m_tail == iv)
m_tail = v;
break;
}
}
if (ix < size())
at(ix) = item_value{};
}
row *m_next = nullptr;
item_value *m_head = nullptr, *m_tail = nullptr;
};
// --------------------------------------------------------------------
......
......@@ -847,20 +847,18 @@ bool category::is_valid() const
continue;
}
for (auto vi = ri->m_head; vi != nullptr; vi = vi->m_next)
auto vi = ri->get(cix);
if (vi != nullptr)
{
if (vi->m_column_ix == cix)
seen = true;
try
{
seen = true;
try
{
(*iv)(vi->text());
}
catch (const std::exception &e)
{
m_validator->report_error("Error validating " + m_columns[cix].m_name + ": " + e.what(), false);
continue;
}
(*iv)(vi->text());
}
catch (const std::exception &e)
{
m_validator->report_error("Error validating " + m_columns[cix].m_name + ": " + e.what(), false);
continue;
}
}
......@@ -1406,16 +1404,10 @@ void category::update_value(row *row, size_t column, std::string_view value, boo
auto &col = m_columns[column];
std::string_view oldValue;
for (auto iv = row->m_head; iv != nullptr; iv = iv->m_next)
{
assert(iv != iv->m_next and (iv->m_next == nullptr or iv != iv->m_next->m_next));
if (iv->m_column_ix == column)
{
oldValue = iv->text();
break;
}
}
auto ival = row->get(column);
if (ival != nullptr)
oldValue = ival->text();
if (value == oldValue) // no need to update
return;
......@@ -1439,18 +1431,11 @@ void category::update_value(row *row, size_t column, std::string_view value, boo
}
// first remove old value with cix
for (auto iv = row->m_head; iv != nullptr; iv = iv->m_next)
{
if (iv->m_column_ix != column)
continue;
row->remove(iv);
delete_item(iv);
break;
}
if (ival != nullptr)
row->remove(column);
if (not value.empty())
row->append(create_item(column, value));
row->append(column, { value });
if (reinsert)
m_index->insert(row);
......@@ -1544,10 +1529,13 @@ row *category::clone_row(const row &r)
try
{
for (auto i = r.m_head; i != nullptr; i = i->m_next)
for (size_t ix = 0; ix < r.size(); ++ix)
{
item_value *v = create_item(i->m_column_ix, i->text());
result->append(v);
auto &i = r[ix];
if (not i)
continue;
result->append( ix, { i.text() });
}
}
catch (...)
......@@ -1563,14 +1551,6 @@ void category::delete_row(row *r)
{
if (r != nullptr)
{
auto i = r->m_head;
while (i != nullptr)
{
auto t = i;
i = i->m_next;
delete_item(t);
}
row_allocator_type ra(get_allocator());
row_allocator_traits::destroy(ra, r);
row_allocator_traits::deallocate(ra, r, 1);
......@@ -1582,8 +1562,12 @@ row_handle category::create_copy(row_handle r)
// copy the values
std::vector<item> items;
for (item_value *iv = r.m_row->m_head; iv != nullptr; iv = iv->m_next)
items.emplace_back(m_columns[iv->m_column_ix].m_name, iv->text());
for (size_t ix = 0; ix < r.m_row->size(); ++ix)
{
auto i = r.m_row->get(ix);
if (i != nullptr)
items.emplace_back(m_columns[ix].m_name, i->text());
}
if (m_cat_validator and m_cat_validator->m_keys.size() == 1)
{
......@@ -1604,11 +1588,6 @@ row_handle category::create_copy(row_handle r)
}
return emplace(items.begin(), items.end());
// auto &&[result, inserted] = emplace(items.begin(), items.end());
// // assert(inserted);
// return result;
}
// proxy methods for every insertion
......@@ -1642,42 +1621,16 @@ category::iterator category::insert_impl(const_iterator pos, row *n)
bool seen = false;
for (auto i = n->m_head; i != nullptr; i = i->m_next)
auto i = n->get(ix);
if (i != nullptr)
{
if (i->m_column_ix == ix)
{
iv->operator()(i->text());
seen = true;
break;
}
iv->operator()(i->text());
seen = true;
}
if (not seen and iv->m_mandatory)
throw std::runtime_error("missing mandatory field " + column + " for category " + m_name);
}
// if (m_index != nullptr)
// {
// std::unique_ptr<ItemRow> nr(new ItemRow{nullptr, this, nullptr});
// Row r(nr.get());
// auto keys = keyFields();
// for (auto v = b; v != e; ++v)
// {
// if (keys.count(v->name()))
// r.assign(v->name(), v->value(), true);
// }
// auto test = m_index->find(nr.get());
// if (test != nullptr)
// {
// if (VERBOSE > 1)
// std::cerr << "Not inserting new record in " << m_name << " (duplicate Key)" << std::endl;
// result = test;
// isNew = false;
// }
// }
}
if (m_index != nullptr)
......@@ -1715,134 +1668,15 @@ category::iterator category::insert_impl(const_iterator pos, row *n)
// #endif
}
// category::iterator category::erase_impl(const_iterator pos)
// {
// if (pos == cend())
// return end();
// assert(false);
// // TODO: implement
// // row *n = const_cast<row *>(pos.row());
// // row *cur;
// // if (m_head == n)
// // {
// // m_head = static_cast<row *>(m_head->m_next);
// // if (m_head == nullptr)
// // m_tail = nullptr;
// // n->m_next = 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);
// }
void category::swap_item(size_t column_ix, row_handle &a, row_handle &b)
{
assert(this == a.m_category);
assert(this == b.m_category);
item_value *va = nullptr, *vb = nullptr;
auto ra = a.m_row;
auto rb = b.m_row;
auto &ra = *a.m_row;
auto &rb = *b.m_row;
if (ra->m_head != nullptr and ra->m_head->m_column_ix == column_ix)
{
va = ra->m_head;
ra->m_head = va->m_next;
va->m_next = nullptr;
if (ra->m_tail == va)
ra->m_tail = ra->m_head;
}
else
{
for (auto v = ra->m_head; v->m_next != nullptr; v = v->m_next)
{
if (v->m_next->m_column_ix != column_ix)
continue;
va = v->m_next;
v->m_next = va->m_next;
va->m_next = nullptr;
if (ra->m_tail == va)
ra->m_tail = v;
break;
}
}
if (rb->m_head != nullptr and rb->m_head->m_column_ix == column_ix)
{
vb = rb->m_head;
rb->m_head = vb->m_next;
vb->m_next = nullptr;
if (rb->m_tail == vb)
rb->m_tail = rb->m_head;
}
else
{
for (auto v = rb->m_head; v->m_next != nullptr; v = v->m_next)
{
if (v->m_next->m_column_ix != column_ix)
continue;
vb = v->m_next;
v->m_next = vb->m_next;
vb->m_next = nullptr;
if (rb->m_tail == vb)
rb->m_tail = v;
break;
}
}
if (ra->m_head == nullptr)
ra->m_head = ra->m_tail = vb;
else
{
ra->m_tail->m_next = vb;
ra->m_tail = vb;
}
if (rb->m_head == nullptr)
rb->m_head = rb->m_tail = va;
else
{
rb->m_tail->m_next = va;
rb->m_tail = va;
}
std::swap(ra.at(column_ix), rb.at(column_ix));
}
void category::reorder_by_index()
......@@ -1997,8 +1831,12 @@ void category::write(std::ostream &os, const std::vector<uint16_t> &order, bool
for (auto r = m_head; r != nullptr; r = r->m_next)
{
for (auto v = r->m_head; v != nullptr; v = v->m_next)
for (size_t ix = 0; ix < r->size(); ++ix)
{
auto v = r->get(ix);
if (v == nullptr)
continue;
if (v->text().find('\n') == std::string_view::npos)
{
size_t l = v->text().length();
......@@ -2009,8 +1847,8 @@ void category::write(std::ostream &os, const std::vector<uint16_t> &order, bool
if (l > 132)
continue;
if (columnWidths[v->m_column_ix] < l + 1)
columnWidths[v->m_column_ix] = l + 1;
if (columnWidths[ix] < l + 1)
columnWidths[ix] = l + 1;
}
}
}
......@@ -2024,14 +1862,9 @@ void category::write(std::ostream &os, const std::vector<uint16_t> &order, bool
size_t w = columnWidths[cix];
std::string_view s;
for (auto iv = r->m_head; iv != nullptr; iv = iv->m_next)
{
if (iv->m_column_ix == cix)
{
s = iv->text();
break;
}
}
auto iv = r->get(cix);
if (iv != nullptr)
s = iv->text();
if (s.empty())
s = "?";
......@@ -2083,14 +1916,9 @@ void category::write(std::ostream &os, const std::vector<uint16_t> &order, bool
os << '_' << m_name << '.' << col.m_name << std::string(l - col.m_name.length() - m_name.length() - 2, ' ');
std::string_view s;
for (auto iv = m_head->m_head; iv != nullptr; iv = iv->m_next)
{
if (iv->m_column_ix == cix)
{
s = iv->text();
break;
}
}
auto iv = m_head->get(cix);
if (iv != nullptr)
s = iv->text();
if (s.empty())
s = "?";
......
......@@ -44,11 +44,9 @@ std::string_view item_handle::text() const
{
if (not m_row_handle.empty())
{
for (auto iv = m_row_handle.m_row->m_head; iv != nullptr; iv = iv->m_next)
{
if (iv->m_column_ix == m_column)
return iv->text();
}
auto iv = m_row_handle.m_row->get(m_column);
if (iv != nullptr)
return iv->text();
}
return {};
......
......@@ -90,7 +90,7 @@ float atom::atom_impl::get_property_float(std::string_view name) const
{
auto s = get_property(name);
std::from_chars_result r = std::from_chars(s.data(), s.data() + s.length(), result);
std::from_chars_result r = cif::from_chars(s.data(), s.data() + s.length(), result);
if (r.ec != std::errc() and VERBOSE > 0)
std::cerr << "Error converting " << s << " to number for property " << name << std::endl;
}
......
......@@ -68,8 +68,13 @@ row_initializer::row_initializer(row_handle rh)
row *r = rh.get_row();
auto &cat = *rh.m_category;
for (auto i = r->m_head; i != nullptr; i = i->m_next)
emplace_back(cat.get_column_name(i->m_column_ix), i->text());
for (size_t ix = 0; ix < r->size(); ++ix)
{
auto &i = r->operator[](ix);
if (not i)
continue;
emplace_back(cat.get_column_name(ix), i.text());
}
}
void row_initializer::set_value(std::string_view name, std::string_view value)
......
......@@ -119,7 +119,7 @@ BOOST_AUTO_TEST_CASE(create_sugar_1)
// before it gets destroyed by remove_residue
for (auto r : as.find("label_asym_id"_key == "L"))
auto &ri = ai.emplace_back(r);
/*auto &ri = */ai.emplace_back(r);
s.remove_residue(NAG);
......@@ -158,7 +158,7 @@ BOOST_AUTO_TEST_CASE(create_sugar_2)
for (size_t i = 0; i < 2; ++i)
{
for (auto r : as.find("label_asym_id"_key == "H" and "auth_seq_id"_key == i + 1))
auto &ri = ai[i].emplace_back(r);
/*auto &ri = */ai[i].emplace_back(r);
}
s.remove_branch(bH);
......
......@@ -1661,7 +1661,7 @@ _cat_2.parent_id_2
std::istream is_data(&data_buffer);
f.load(is_data);
auto &cat1 = f.front()["cat_1"];
// auto &cat1 = f.front()["cat_1"];
auto &cat2 = f.front()["cat_2"];
// f.front().validate_links();
......
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