Commit 85c21aeb by Maarten L. Hekkelman

row as vector

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