Commit 4a1d9c8f by Maarten L. Hekkelman

New storage layout for item_value

parent 26c86282
...@@ -83,6 +83,14 @@ class category_t ...@@ -83,6 +83,14 @@ class category_t
auto r = m_head; auto r = m_head;
while (r != nullptr) while (r != nullptr)
{ {
auto i = r->m_head;
while (i != nullptr)
{
auto ti = i->m_next;
delete_item(i);
i = ti;
}
auto t = r->m_next; auto t = r->m_next;
delete_row(r); delete_row(r);
r = t; r = t;
...@@ -149,19 +157,23 @@ class category_t ...@@ -149,19 +157,23 @@ class category_t
// } // }
// } // }
auto r = create_row(m_head, nullptr); auto r = create_row(m_head, nullptr);
std::vector<item_value *> item_values; if (m_head == nullptr)
// std::transform(b, e, std::back_inserter(item_values), [this](Item &i) { return this->create_item(i); }); m_head = m_tail = r;
else
m_tail = m_tail->m_next = r;
for (auto i = b; i != e; ++i) for (auto i = b; i != e; ++i)
item_values.push_back(this->create_item(*i)); {
std::unique_ptr<item_value> new_item(this->create_item(*i));
if (r->m_head == nullptr)
r->m_head = r->m_tail = new_item.release();
else
r->m_tail = r->m_tail->m_next = new_item.release();
}
for (auto p : item_values)
delete_item(p);
return {}; return {};
...@@ -203,9 +215,9 @@ class category_t ...@@ -203,9 +215,9 @@ class category_t
// -------------------------------------------------------------------- // --------------------------------------------------------------------
/// \brief Return the index number for \a column_name /// \brief Return the index number for \a column_name
uint32_t get_column_ix(std::string_view column_name) const uint16_t get_column_ix(std::string_view column_name) const
{ {
uint32_t result; uint16_t result;
for (result = 0; result < m_columns.size(); ++result) for (result = 0; result < m_columns.size(); ++result)
{ {
...@@ -223,7 +235,7 @@ class category_t ...@@ -223,7 +235,7 @@ class category_t
return result; return result;
} }
uint32_t add_column(std::string_view column_name) uint16_t add_column(std::string_view column_name)
{ {
using namespace std::literals; using namespace std::literals;
...@@ -317,17 +329,6 @@ class category_t ...@@ -317,17 +329,6 @@ class category_t
row_allocator_traits::deallocate(ra, r, 1); row_allocator_traits::deallocate(ra, r, 1);
} }
constexpr static size_t calculate_item_size(const char* text)
{
return calculate_item_size(strlen(text));
}
constexpr static size_t calculate_item_size(size_t text_len)
{
size_t raw_size = sizeof(item_value) + text_len + 1 - 4;
return raw_size / sizeof(item_value) + ((raw_size % sizeof(item_value)) ? 1 : 0);
}
using item_allocator_type = typename std::allocator_traits<Alloc>::template rebind_alloc<item_value>; using item_allocator_type = typename std::allocator_traits<Alloc>::template rebind_alloc<item_value>;
using item_allocator_traits = std::allocator_traits<item_allocator_type>; using item_allocator_traits = std::allocator_traits<item_allocator_type>;
...@@ -343,15 +344,15 @@ class category_t ...@@ -343,15 +344,15 @@ class category_t
// }; // };
item_allocator_traits::pointer get_item(size_t item_size) item_allocator_traits::pointer get_item()
{ {
item_allocator_type ia(get_allocator()); item_allocator_type ia(get_allocator());
return item_allocator_traits::allocate(ia, item_size); return item_allocator_traits::allocate(ia, 1);
} }
item_value *create_item(uint32_t column_ix, const char *text) item_value *create_item(uint16_t column_ix, std::string_view text)
{ {
auto p = this->get_item(calculate_item_size(text)); auto p = this->get_item();
item_allocator_type ia(get_allocator()); item_allocator_type ia(get_allocator());
item_allocator_traits::construct(ia, p, column_ix, text); item_allocator_traits::construct(ia, p, column_ix, text);
return p; return p;
...@@ -359,7 +360,7 @@ class category_t ...@@ -359,7 +360,7 @@ class category_t
item_value *create_item(const item &i) item_value *create_item(const item &i)
{ {
uint32_t ix = get_column_ix(i.name()); uint16_t ix = get_column_ix(i.name());
return create_item(ix, i.c_str()); return create_item(ix, i.c_str());
} }
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <iomanip> #include <iomanip>
#include <memory> #include <memory>
#include <optional> #include <optional>
#include <limits>
namespace cif::v2 namespace cif::v2
{ {
...@@ -109,22 +110,67 @@ class item ...@@ -109,22 +110,67 @@ class item
// -------------------------------------------------------------------- // --------------------------------------------------------------------
// Internal storage, strictly forward linked list with minimal space // Internal storage, strictly forward linked list with minimal space
// requirements. // requirements. Strings of size 7 or shorter are stored internally.
// Typically, more than 99% of the strings in an mmCIF file are less
// than 8 bytes in length.
struct item_value struct item_value
{ {
item_value(uint32_t column_ix, const char *value) item_value(uint16_t column_ix, const char *value)
: m_column_ix(column_ix) : item_value(column_ix, std::string_view{value})
{ {
strcpy(m_text, value);
} }
item_value(uint16_t column_ix, std::string_view value)
: m_next(nullptr)
, m_length(value.length())
{
if (value.length() > 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");
char *data;
if (m_length >= kBufferSize)
data = m_data = new char[m_length];
else
data = m_local_data;
std::copy(value.begin(), value.end(), data);
data[m_length] = 0;
}
~item_value()
{
if (m_length >= kBufferSize)
delete [] m_data;
}
item_value() = delete;
item_value(const item_value &) = delete;
item_value &operator=(const item_value &) = delete;
item_value *m_next; item_value *m_next;
uint32_t m_column_ix; uint16_t m_column_ix;
char m_text[4]; uint16_t m_length;
union
{
char m_local_data[8];
char *m_data;
};
static constexpr size_t kBufferSize = sizeof(m_local_data);
std::string_view text() const
{
return { m_length >= kBufferSize ? m_data : m_local_data, m_length };
}
const char *c_str() const
{
return m_length >= kBufferSize ? m_data : m_local_data;
}
}; };
static_assert(sizeof(item_value) == 2 * sizeof(void*), "Item value should be two pointers in size..."); static_assert(sizeof(item_value) == 24, "sizeof(item_value) should be 24 bytes");
// -------------------------------------------------------------------- // --------------------------------------------------------------------
// Transient object to access stored data // Transient object to access stored data
......
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