Commit ab9c4d94 by Maarten L. Hekkelman

compiling again

parent e5eb6225
...@@ -215,7 +215,11 @@ set(project_sources ...@@ -215,7 +215,11 @@ set(project_sources
${PROJECT_SOURCE_DIR}/src/Symmetry.cpp ${PROJECT_SOURCE_DIR}/src/Symmetry.cpp
${PROJECT_SOURCE_DIR}/src/TlsParser.cpp ${PROJECT_SOURCE_DIR}/src/TlsParser.cpp
${PROJECT_SOURCE_DIR}/src/v2/category.cpp
${PROJECT_SOURCE_DIR}/src/v2/dictionary_parser.cpp ${PROJECT_SOURCE_DIR}/src/v2/dictionary_parser.cpp
${PROJECT_SOURCE_DIR}/src/v2/item.cpp
${PROJECT_SOURCE_DIR}/src/v2/parser.cpp
${PROJECT_SOURCE_DIR}/src/v2/row.cpp
${PROJECT_SOURCE_DIR}/src/v2/validate.cpp ${PROJECT_SOURCE_DIR}/src/v2/validate.cpp
) )
......
...@@ -35,47 +35,29 @@ namespace cif::v2 ...@@ -35,47 +35,29 @@ namespace cif::v2
// -------------------------------------------------------------------- // --------------------------------------------------------------------
template <typename Alloc, typename Category> class datablock
class datablock_t
{ {
public: public:
using category_type = Category; using category_list = std::list<category>;
using allocator_type = Alloc;
using category_allocator_type = typename std::allocator_traits<Alloc>::template rebind_alloc<category_type>; using iterator = category_list::iterator;
using category_type_list = std::list<category_type, category_allocator_type>; using const_iterator = category_list::const_iterator;
using iterator = category_type_list::iterator; using reference = typename category_list::reference;
using const_iterator = category_type_list::const_iterator;
using reference = typename category_type_list::reference; datablock() = default;
datablock_t(std::string_view name, const allocator_type &alloc = allocator_type()) datablock(std::string_view name)
: m_categories(alloc) : m_name(name)
, m_name(name)
{ {
} }
datablock_t(const datablock_t &) = default; datablock(const datablock &) = default;
datablock_t(datablock_t &&) = default; datablock(datablock &&) = default;
// template <typename Alloc2> datablock &operator=(const datablock &) = default;
// datablock_t(const datablock_t &db, const Alloc2 &a) datablock &operator=(datablock &&) = default;
// : m_categories(db, a)
// , m_name(db.m_name)
// {
// }
// template <typename Alloc2>
// datablock_t(datablock_t &&db, const Alloc2 &a)
// : base_type(std::move(db), a)
// , m_name(db.m_name)
// {
// }
datablock_t &operator=(const datablock_t &) = default;
datablock_t &operator=(datablock_t &&) = default;
// -------------------------------------------------------------------- // --------------------------------------------------------------------
...@@ -100,9 +82,9 @@ class datablock_t ...@@ -100,9 +82,9 @@ class datablock_t
// -------------------------------------------------------------------- // --------------------------------------------------------------------
category_type &operator[](std::string_view name) category &operator[](std::string_view name)
{ {
auto i = std::find_if(m_categories.begin(), m_categories.end(), [name](const category_type &c) auto i = std::find_if(m_categories.begin(), m_categories.end(), [name](const category &c)
{ return iequals(c.name(), name); }); { return iequals(c.name(), name); });
if (i != m_categories.end()) if (i != m_categories.end())
...@@ -112,10 +94,10 @@ class datablock_t ...@@ -112,10 +94,10 @@ class datablock_t
return m_categories.back(); return m_categories.back();
} }
const category_type &operator[](std::string_view name) const const category &operator[](std::string_view name) const
{ {
static const category_type s_empty; static const category s_empty;
auto i = std::find_if(m_categories.begin(), m_categories.end(), [name](const category_type &c) auto i = std::find_if(m_categories.begin(), m_categories.end(), [name](const category &c)
{ return iequals(c.name(), name); }); { return iequals(c.name(), name); });
return i == m_categories.end() ? s_empty : *i; return i == m_categories.end() ? s_empty : *i;
} }
...@@ -155,53 +137,51 @@ class datablock_t ...@@ -155,53 +137,51 @@ class datablock_t
return std::make_tuple(m_categories.begin(), is_new); return std::make_tuple(m_categories.begin(), is_new);
} }
void write(std::ostream &os) const // void write(std::ostream &os) const
{ // {
// std::shared_lock lock(mLock); // // std::shared_lock lock(mLock);
os << "data_" << m_name << std::endl // os << "data_" << m_name << std::endl
<< "# " << std::endl; // << "# " << std::endl;
// mmcif support, sort of. First write the 'entry' Category // // mmcif support, sort of. First write the 'entry' Category
// and if it exists, _AND_ we have a Validator, write out the // // and if it exists, _AND_ we have a Validator, write out the
// audit_conform record. // // audit_conform record.
for (auto &cat : m_categories) // for (auto &cat : m_categories)
{ // {
if (cat.name() != "entry") // if (cat.name() != "entry")
continue; // continue;
cat.write(os); // cat.write(os);
// if (mValidator != nullptr) // // if (mValidator != nullptr)
// { // // {
// Category auditConform(*this, "audit_conform", nullptr); // // Category auditConform(*this, "audit_conform", nullptr);
// auditConform.emplace({{"dict_name", mValidator->dictName()}, // // auditConform.emplace({{"dict_name", mValidator->dictName()},
// {"dict_version", mValidator->dictVersion()}}); // // {"dict_version", mValidator->dictVersion()}});
// auditConform.write(os); // // auditConform.write(os);
// } // // }
break; // break;
} // }
for (auto &cat : m_categories) // for (auto &cat : m_categories)
{ // {
if (cat.name() != "entry" and cat.name() != "audit_conform") // if (cat.name() != "entry" and cat.name() != "audit_conform")
cat.write(os); // cat.write(os);
} // }
} // }
friend std::ostream &operator<<(std::ostream &os, const datablock_t &db) // friend std::ostream &operator<<(std::ostream &os, const datablock &db)
{ // {
db.write(os); // db.write(os);
return os; // return os;
} // }
private: private:
category_type_list m_categories; category_list m_categories;
std::string m_name; std::string m_name;
}; };
using datablock = datablock_t<>;
} // namespace cif::v2 } // namespace cif::v2
\ No newline at end of file
...@@ -36,20 +36,10 @@ namespace cif::v2 ...@@ -36,20 +36,10 @@ namespace cif::v2
// -------------------------------------------------------------------- // --------------------------------------------------------------------
template < class file
typename Alloc,
typename Datablock,
typename Category>
class file_t
{ {
public: public:
using allocator_type = Alloc; using datablock_list = std::list<datablock>;
using datablock_type = Datablock;
using category_type = typename datablock_type::category_type;
using datablock_allocator_type = typename std::allocator_traits<Alloc>::template rebind_alloc<datablock_type>;
using datablock_list = std::list<datablock_type, datablock_allocator_type>;
using value_type = datablock_list::value_type; using value_type = datablock_list::value_type;
using reference = datablock_list::reference; using reference = datablock_list::reference;
...@@ -58,29 +48,21 @@ class file_t ...@@ -58,29 +48,21 @@ class file_t
using iterator = datablock_list::iterator; using iterator = datablock_list::iterator;
using const_iterator = datablock_list::const_iterator; using const_iterator = datablock_list::const_iterator;
using parser_type = parser_t<allocator_type, file_t, datablock_type, category_type>; file() = default;
file_t() = default;
file_t(const allocator_type &a = allocator_type()) file(std::istream &is)
: m_datablocks(a)
{
}
file_t(std::istream &is, const allocator_type &alloc = allocator_type())
: m_datablocks(alloc)
{ {
load(is); load(is);
} }
file_t(const file_t &) = default; file(const file &) = default;
file_t(file_t &&) = default; file(file &&) = default;
file_t &operator=(const file_t &) = default; file &operator=(const file &) = default;
file_t &operator=(file_t &&) = default; file &operator=(file &&) = default;
datablock_type &operator[](std::string_view name) datablock &operator[](std::string_view name)
{ {
auto i = std::find_if(m_datablocks.begin(), m_datablocks.end(), [name](const datablock_type &c) auto i = std::find_if(m_datablocks.begin(), m_datablocks.end(), [name](const datablock &c)
{ return iequals(c.name(), name); }); { return iequals(c.name(), name); });
if (i != m_datablocks.end()) if (i != m_datablocks.end())
...@@ -90,10 +72,10 @@ class file_t ...@@ -90,10 +72,10 @@ class file_t
return m_datablocks.back(); return m_datablocks.back();
} }
const datablock_type &operator[](std::string_view name) const const datablock &operator[](std::string_view name) const
{ {
static const datablock_type s_empty; static const datablock s_empty;
auto i = std::find_if(m_datablocks.begin(), m_datablocks.end(), [name](const datablock_type &c) auto i = std::find_if(m_datablocks.begin(), m_datablocks.end(), [name](const datablock &c)
{ return iequals(c.name(), name); }); { return iequals(c.name(), name); });
return i == m_datablocks.end() ? s_empty : *i; return i == m_datablocks.end() ? s_empty : *i;
} }
...@@ -133,14 +115,12 @@ class file_t ...@@ -133,14 +115,12 @@ class file_t
reference front() { return m_datablocks.front(); } reference front() { return m_datablocks.front(); }
reference back() { return m_datablocks.back(); } reference back() { return m_datablocks.back(); }
void load(std::istream &is) void load(std::istream &is)
{ {
// auto saved = mValidator; // auto saved = mValidator;
// setValidator(nullptr); // setValidator(nullptr);
parser_type p(is, *this); parser p(is, *this);
p.parse_file(); p.parse_file();
// if (saved != nullptr) // if (saved != nullptr)
...@@ -152,8 +132,7 @@ class file_t ...@@ -152,8 +132,7 @@ class file_t
private: private:
datablock_list m_datablocks; datablock_list m_datablocks;
std::unique_ptr<Validator> m_validator;
}; };
using file = file_t<>;
} }
\ No newline at end of file
...@@ -26,21 +26,27 @@ ...@@ -26,21 +26,27 @@
#pragma once #pragma once
#include <memory> #include <string>
#include <vector>
namespace cif::v2 namespace cif::v2
{ {
template <typename Alloc = std::allocator<void>> class category;
class category_t; class datablock;
class file;
class parser;
template <typename Alloc = std::allocator<void>, typename Category = category_t<Alloc>> class row;
class datablock_t; class row_handle;
template <typename Alloc = std::allocator<void>, typename Datablock = datablock_t<Alloc>, typename Category = typename Datablock::category_type> class item;
class file_t; class item_handle;
// --------------------------------------------------------------------
// let's make life easier
std::vector<std::string> get_category_fields(const category &cat);
template <typename Alloc = std::allocator<void>, typename File = file_t<Alloc>, typename Datablock = datablock_t<Alloc>, typename Category = typename Datablock::category_type>
class parser_t;
} // namespace cif::v2 } // namespace cif::v2
\ No newline at end of file
...@@ -29,12 +29,15 @@ ...@@ -29,12 +29,15 @@
#include <charconv> #include <charconv>
#include <cstring> #include <cstring>
#include <iomanip> #include <iomanip>
#include <iostream>
#include <limits> #include <limits>
#include <memory> #include <memory>
#include <optional> #include <optional>
#include <cif++/CifUtils.hpp> #include <cif++/CifUtils.hpp>
#include <cif++/v2/forward_decl.hpp>
namespace cif namespace cif
{ {
extern int VERBOSE; extern int VERBOSE;
...@@ -80,7 +83,7 @@ class item ...@@ -80,7 +83,7 @@ class item
auto r = cif::to_chars(m_buffer, m_buffer + sizeof(m_buffer) - 1, value, cif::chars_format::general); auto r = cif::to_chars(m_buffer, m_buffer + sizeof(m_buffer) - 1, value, cif::chars_format::general);
if (r.ec != std::errc()) if (r.ec != std::errc())
throw std::runtime_error("Could not format number"); throw std::runtime_error("Could not format number");
assert(r.ptr >= m_buffer and r.ptr < m_buffer + sizeof(m_buffer)); assert(r.ptr >= m_buffer and r.ptr < m_buffer + sizeof(m_buffer));
*r.ptr = 0; *r.ptr = 0;
m_value = std::string_view(m_buffer, r.ptr - m_buffer); m_value = std::string_view(m_buffer, r.ptr - m_buffer);
...@@ -138,13 +141,55 @@ class item ...@@ -138,13 +141,55 @@ class item
}; };
// -------------------------------------------------------------------- // --------------------------------------------------------------------
/// \brief the internal storage for items in a category
///
/// Internal storage, strictly forward linked list with minimal space
/// 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
{
item_value(uint16_t column_ix, uint16_t length)
: m_next(nullptr)
, m_column_ix(column_ix)
, m_length(length)
{
}
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;
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) == 24, "sizeof(item_value) should be 24 bytes");
// --------------------------------------------------------------------
// Transient object to access stored data // Transient object to access stored data
template <typename RowHandle>
struct item_handle struct item_handle
{ {
using row_handle_type = RowHandle;
public: public:
// conversion helper class // conversion helper class
template <typename T, typename = void> template <typename T, typename = void>
...@@ -158,29 +203,6 @@ struct item_handle ...@@ -158,29 +203,6 @@ struct item_handle
return *this; return *this;
} }
// template <typename T, std::enable_if_t<std::is_arithmetic_v<T>, int> = 0>
// item_handle &operator=(const T &value)
// {
// this->operator=(std::to_string(value));
// return *this;
// }
// template <typename T>
// item_handle &operator=(const std::optional<T> &value)
// {
// if (value)
// this->operator=(*value);
// else
// this->operator=("?");
// return *this;
// }
// item_handle &operator=(std::string_view value)
// {
// m_row_handle.assign(m_column, value, false);
// return *this;
// }
template <typename... Ts> template <typename... Ts>
void os(const Ts &...v) void os(const Ts &...v)
{ {
...@@ -199,7 +221,7 @@ struct item_handle ...@@ -199,7 +221,7 @@ struct item_handle
} }
template <typename T> template <typename T>
auto value_or(const T &dv) auto value_or(const T &dv) const
{ {
return empty() ? dv : this->as<T>(); return empty() ? dv : this->as<T>();
} }
...@@ -244,21 +266,12 @@ struct item_handle ...@@ -244,21 +266,12 @@ struct item_handle
// return s_empty_result; // return s_empty_result;
// } // }
std::string_view text() const std::string_view text() const;
{
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();
}
return {};
}
// bool operator!=(const std::string &s) const { return s != c_str(); } // bool operator!=(const std::string &s) const { return s != c_str(); }
// bool operator==(const std::string &s) const { return s == c_str(); } // bool operator==(const std::string &s) const { return s == c_str(); }
item_handle(uint16_t column, row_handle_type &row) item_handle(uint16_t column, row_handle &row)
: m_column(column) : m_column(column)
, m_row_handle(row) , m_row_handle(row)
{ {
...@@ -266,17 +279,15 @@ struct item_handle ...@@ -266,17 +279,15 @@ struct item_handle
private: private:
uint16_t m_column; uint16_t m_column;
row_handle_type &m_row_handle; row_handle &m_row_handle;
// bool mConst = false;
static constexpr const char *s_empty_result = ""; static constexpr const char *s_empty_result = "";
}; };
// So sad that the gcc implementation of from_chars does not support floats yet... // So sad that the gcc implementation of from_chars does not support floats yet...
template <typename Row>
template <typename T> template <typename T>
struct item_handle<Row>::item_value_as<T, std::enable_if_t<std::is_arithmetic_v<T>>> struct item_handle::item_value_as<T, std::enable_if_t<std::is_arithmetic_v<T>>>
{ {
using value_type = std::remove_reference_t<std::remove_cv_t<T>>; using value_type = std::remove_reference_t<std::remove_cv_t<T>>;
...@@ -348,9 +359,8 @@ struct item_handle<Row>::item_value_as<T, std::enable_if_t<std::is_arithmetic_v< ...@@ -348,9 +359,8 @@ struct item_handle<Row>::item_value_as<T, std::enable_if_t<std::is_arithmetic_v<
} }
}; };
template <typename Row>
template <typename T> template <typename T>
struct item_handle<Row>::item_value_as<std::optional<T>> struct item_handle::item_value_as<std::optional<T>>
{ {
static std::optional<T> convert(const item_handle &ref) static std::optional<T> convert(const item_handle &ref)
{ {
...@@ -374,9 +384,8 @@ struct item_handle<Row>::item_value_as<std::optional<T>> ...@@ -374,9 +384,8 @@ struct item_handle<Row>::item_value_as<std::optional<T>>
} }
}; };
template <typename Row>
template <typename T> template <typename T>
struct item_handle<Row>::item_value_as<T, std::enable_if_t<std::is_same_v<T, bool>>> struct item_handle::item_value_as<T, std::enable_if_t<std::is_same_v<T, bool>>>
{ {
static bool convert(const item_handle &ref) static bool convert(const item_handle &ref)
{ {
...@@ -394,9 +403,8 @@ struct item_handle<Row>::item_value_as<T, std::enable_if_t<std::is_same_v<T, boo ...@@ -394,9 +403,8 @@ struct item_handle<Row>::item_value_as<T, std::enable_if_t<std::is_same_v<T, boo
} }
}; };
template <typename Row>
template <size_t N> template <size_t N>
struct item_handle<Row>::item_value_as<char[N]> struct item_handle::item_value_as<char[N]>
{ {
// static std::string_view convert(const item_handle &ref) // static std::string_view convert(const item_handle &ref)
// { // {
...@@ -409,9 +417,8 @@ struct item_handle<Row>::item_value_as<char[N]> ...@@ -409,9 +417,8 @@ struct item_handle<Row>::item_value_as<char[N]>
} }
}; };
template <typename Row>
template <typename T> template <typename T>
struct item_handle<Row>::item_value_as<T, std::enable_if_t<std::is_same_v<T, const char *>>> struct item_handle::item_value_as<T, std::enable_if_t<std::is_same_v<T, const char *>>>
{ {
// static std::string_view convert(const item_handle &ref) // static std::string_view convert(const item_handle &ref)
// { // {
...@@ -424,14 +431,13 @@ struct item_handle<Row>::item_value_as<T, std::enable_if_t<std::is_same_v<T, con ...@@ -424,14 +431,13 @@ struct item_handle<Row>::item_value_as<T, std::enable_if_t<std::is_same_v<T, con
} }
}; };
template <typename Row>
template <typename T> template <typename T>
struct item_handle<Row>::item_value_as<T, std::enable_if_t<std::is_same_v<T, std::string>>> struct item_handle::item_value_as<T, std::enable_if_t<std::is_same_v<T, std::string>>>
{ {
static std::string convert(const item_handle &ref) static std::string convert(const item_handle &ref)
{ {
std::string_view txt = ref.text(); std::string_view txt = ref.text();
return { txt.data(), txt.size() }; return {txt.data(), txt.size()};
} }
static int compare(const item_handle &ref, const std::string &value, bool icase) static int compare(const item_handle &ref, const std::string &value, bool icase)
......
...@@ -27,37 +27,26 @@ ...@@ -27,37 +27,26 @@
#pragma once #pragma once
#include <cif++/v2/item.hpp> #include <cif++/v2/item.hpp>
#include <cif++/v2/condition.hpp>
namespace cif::v2 namespace cif::v2
{ {
template <typename>
class row_handle;
namespace detail namespace detail
{ {
// some helper classes to help create tuple result types // some helper classes to help create tuple result types
template < template <typename... C>
typename Category,
typename... C>
struct get_row_result struct get_row_result
{ {
using category_type = Category;
using row_type = category_type::row;
using row_handle_type = row_handle<category_type>;
using item_handle_type = item_handle<row_type>;
static constexpr size_t N = sizeof...(C); static constexpr size_t N = sizeof...(C);
get_row_result(const row_handle_type &r, std::array<size_t, N> &&columns) get_row_result(const row_handle &r, std::array<size_t, N> &&columns)
: m_row(r) : m_row(r)
, m_columns(std::move(columns)) , m_columns(std::move(columns))
{ {
} }
const item_handle_type operator[](size_t ix) const const item_handle operator[](size_t ix) const
{ {
return m_row[m_columns[ix]]; return m_row[m_columns[ix]];
} }
...@@ -74,7 +63,7 @@ namespace detail ...@@ -74,7 +63,7 @@ namespace detail
return std::tuple<Ts...>{m_row[m_columns[Is]].template as<Ts>()...}; return std::tuple<Ts...>{m_row[m_columns[Is]].template as<Ts>()...};
} }
const row_handle_type &m_row; const row_handle &m_row;
std::array<size_t, N> m_columns; std::array<size_t, N> m_columns;
}; };
...@@ -112,21 +101,39 @@ auto tie(Ts &...v) ...@@ -112,21 +101,39 @@ auto tie(Ts &...v)
} }
// -------------------------------------------------------------------- // --------------------------------------------------------------------
/// \brief row_handle is the way to access data in rows /// \brief the row class, this one is not directly accessible from the outside
template <typename Category> class row
class row_handle
{ {
public: public:
using category_type = Category; row() = default;
using row_type = std::conditional_t<std::is_const_v<category_type>, const typename category_type::row, typename category_type::row>;
using item_handle_type = item_handle<row_handle>; private:
friend class item_handle;
template <typename> template <typename, typename...>
friend class row_handle; friend class iterator_impl;
friend class category;
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;
item_value *m_head = nullptr, *m_tail = nullptr;
};
template <typename> // --------------------------------------------------------------------
/// \brief row_handle is the way to access data in rows
class row_handle
{
public:
friend class item_handle; friend class item_handle;
row_handle() = default; row_handle() = default;
...@@ -137,42 +144,40 @@ class row_handle ...@@ -137,42 +144,40 @@ class row_handle
row_handle &operator=(const row_handle &) = default; row_handle &operator=(const row_handle &) = default;
row_handle &operator=(row_handle &&) = default; row_handle &operator=(row_handle &&) = default;
template <typename C2> row_handle(const category &cat, const row &r)
row_handle(const row_handle<C2> &rhs) : m_category(const_cast<category *>(&cat))
: m_cat(rhs.m_cat) , m_row(const_cast<row *>(&r))
, m_row(rhs.m_row)
{ {
} }
row_handle(category_type &cat, row_type &row) const category &cat() const
: m_cat(&cat)
, m_row(&row)
{ {
return *m_category;
} }
explicit operator bool() const explicit operator bool() const
{ {
return m_cat != nullptr and m_row != nullptr; return m_category != nullptr and m_row != nullptr;
} }
item_handle_type operator[](uint32_t column_ix) item_handle operator[](uint32_t column_ix)
{ {
return item_handle_type(column_ix, *this); return item_handle(column_ix, *this);
} }
const item_handle_type operator[](uint32_t column_ix) const const item_handle operator[](uint32_t column_ix) const
{ {
return item_handle_type(column_ix, const_cast<row_handle &>(*this)); return item_handle(column_ix, const_cast<row_handle &>(*this));
} }
item_handle_type operator[](std::string_view column_name) item_handle operator[](std::string_view column_name)
{ {
return item_handle_type(add_column(column_name), *this); return item_handle(add_column(column_name), *this);
} }
const item_handle_type operator[](std::string_view column_name) const const item_handle operator[](std::string_view column_name) const
{ {
return item_handle_type(get_column_ix(column_name), *this); return item_handle(get_column_ix(column_name), const_cast<row_handle &>(*this));
} }
template <typename... Ts, size_t N> template <typename... Ts, size_t N>
...@@ -183,13 +188,13 @@ class row_handle ...@@ -183,13 +188,13 @@ class row_handle
std::array<size_t, N> cix; std::array<size_t, N> cix;
for (size_t i = 0; i < N; ++i) for (size_t i = 0; i < N; ++i)
cix[i] = get_column_ix(columns[i]); cix[i] = get_column_ix(columns[i]);
return detail::get_row_result<category_type, Ts...>(*this, std::move(cix)); return detail::get_row_result<Ts...>(*this, std::move(cix));
} }
template <typename... C> template <typename... C>
auto get(C... columns) const auto get(C... columns) const
{ {
return detail::get_row_result<category_type, C...>(*this, {get_column_ix(columns)...}); return detail::get_row_result<C...>(*this, {get_column_ix(columns)...});
} }
void assign(const std::vector<item> &values) void assign(const std::vector<item> &values)
...@@ -247,32 +252,23 @@ class row_handle ...@@ -247,32 +252,23 @@ class row_handle
void assign(std::string_view name, std::string_view value, bool updateLinked, bool validate = true) void assign(std::string_view name, std::string_view value, bool updateLinked, bool validate = true)
{ {
assign(m_cat->add_column(name), value, updateLinked, validate); assign(add_column(name), value, updateLinked, validate);
} }
void assign(size_t column, std::string_view value, bool updateLinked, bool validate = true) void assign(size_t column, std::string_view value, bool updateLinked, bool validate = true);
{
m_cat->update_value(m_row, column, value, updateLinked, validate);
}
private: private:
uint16_t get_column_ix(std::string_view name) const uint16_t get_column_ix(std::string_view name) const;
{
return m_cat->get_column_ix(name);
}
uint16_t add_column(std::string_view name) uint16_t add_column(std::string_view name);
{
return m_cat->add_column(name);
}
void assign(const item &i, bool updateLinked) void assign(const item &i, bool updateLinked)
{ {
assign(i.name(), i.value(), updateLinked); assign(i.name(), i.value(), updateLinked);
} }
category_type *m_cat = nullptr; category *m_category = nullptr;
row_type *m_row = nullptr; row *m_row = nullptr;
}; };
} // namespace cif::v2 } // namespace cif::v2
\ No newline at end of file
...@@ -166,7 +166,7 @@ class Validator ...@@ -166,7 +166,7 @@ class Validator
{ {
} }
~Validator(); ~Validator() = default;
Validator(const Validator &rhs) = delete; Validator(const Validator &rhs) = delete;
Validator &operator=(const Validator &rhs) = delete; Validator &operator=(const Validator &rhs) = delete;
...@@ -175,7 +175,6 @@ class Validator ...@@ -175,7 +175,6 @@ class Validator
Validator &operator=(Validator &&rhs); Validator &operator=(Validator &&rhs);
friend class dictionary_parser; friend class dictionary_parser;
// friend class ValidatorFactory;
void addTypeValidator(ValidateType &&v); void addTypeValidator(ValidateType &&v);
const ValidateType *getValidatorForType(std::string_view typeCode) const; const ValidateType *getValidatorForType(std::string_view typeCode) const;
...@@ -189,11 +188,11 @@ class Validator ...@@ -189,11 +188,11 @@ class Validator
void reportError(const std::string &msg, bool fatal) const; void reportError(const std::string &msg, bool fatal) const;
const std::string &dictName() const { return m_name; } const std::string &name() const { return m_name; }
void dictName(const std::string &name) { m_name = name; } void set_name(const std::string &name) { m_name = name; }
const std::string &dictVersion() const { return m_version; } const std::string &version() const { return m_version; }
void dictVersion(const std::string &version) { m_version = version; } void version(const std::string &version) { m_version = version; }
private: private:
// name is fully qualified here: // name is fully qualified here:
...@@ -201,7 +200,7 @@ class Validator ...@@ -201,7 +200,7 @@ class Validator
std::string m_name; std::string m_name;
std::string m_version; std::string m_version;
bool mStrict = false; bool m_strict = false;
std::set<ValidateType> mTypeValidators; std::set<ValidateType> mTypeValidators;
std::set<ValidateCategory> mCategoryValidators; std::set<ValidateCategory> mCategoryValidators;
std::vector<ValidateLink> mLinkValidators; std::vector<ValidateLink> mLinkValidators;
......
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2022 NKI/AVL, Netherlands Cancer Institute
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <cif++/v2/category.hpp>
namespace cif::v2
{
void category::update_value(row *row, size_t column, std::string_view value, bool updateLinked, bool validate)
{
auto &col = m_columns[column];
const char *oldValue = nullptr;
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->c_str();
break;
}
}
if (oldValue != nullptr and value == oldValue) // no need to update
return;
std::string oldStrValue = oldValue ? oldValue : "";
// // check the value
// if (col.m_validator and validate)
// (*col.m_validator)(value);
// If the field is part of the Key for this Category, remove it from the index
// before updating
bool reinsert = false;
// if (updateLinked and // an update of an Item's value
// cat->mIndex != nullptr and cat->keyFieldsByIndex().count(column))
// {
// reinsert = cat->mIndex->find(mData);
// if (reinsert)
// cat->mIndex->erase(mData);
// }
// first remove old value with cix
if (row->m_head == nullptr)
; // nothing to do
else if (row->m_head->m_column_ix == column)
{
auto iv = row->m_head;
row->m_head = iv->m_next;
iv->m_next = nullptr;
delete_item(iv);
}
else
{
for (auto iv = row->m_head; iv->m_next != nullptr; iv = iv->m_next)
{
if (iv->m_next->m_column_ix != column)
continue;
auto nv = iv->m_next;
iv->m_next = nv->m_next;
nv->m_next = nullptr;
delete_item(nv);
break;
}
}
if (not value.empty())
{
auto nv = create_item(column, value);
if (row->m_head == nullptr)
row->m_head = nv;
else
{
auto iv = row->m_head;
while (iv->m_next != nullptr)
iv = iv->m_next;
iv->m_next = nv;
}
}
// if (reinsert)
// cat->mIndex->insert(mData);
// // see if we need to update any child categories that depend on this value
// auto iv = col.m_validator;
// if (not skipUpdateLinked and iv != nullptr and mCascade)
// {
// for (auto &&[childCat, linked] : cat->mChildLinks)
// {
// if (find(linked->mParentKeys.begin(), linked->mParentKeys.end(), iv->mTag) == linked->mParentKeys.end())
// continue;
// Condition cond;
// std::string childTag;
// for (size_t ix = 0; ix < linked->mParentKeys.size(); ++ix)
// {
// std::string pk = linked->mParentKeys[ix];
// std::string ck = linked->mChildKeys[ix];
// // TODO add code to *NOT* test mandatory fields for Empty
// if (pk == iv->mTag)
// {
// childTag = ck;
// cond = std::move(cond) && Key(ck) == oldStrValue;
// }
// else
// {
// const char *pk_value = (*this)[pk].c_str();
// if (*pk_value == 0)
// cond = std::move(cond) && Key(ck) == Empty();
// else
// cond = std::move(cond) && ((Key(ck) == pk_value) or Key(ck) == Empty());
// }
// }
// auto rows = childCat->find(std::move(cond));
// if (rows.empty())
// continue;
// // if (cif::VERBOSE > 2)
// // {
// // std::cerr << "Parent: " << linked->mParentCategory << " Child: " << linked->mChildCategory << std::endl
// // << cond << std::endl;
// // }
// // Now, suppose there are already rows in child that conform to the new value,
// // we then skip this renam
// Condition cond_n;
// for (size_t ix = 0; ix < linked->mParentKeys.size(); ++ix)
// {
// std::string pk = linked->mParentKeys[ix];
// std::string ck = linked->mChildKeys[ix];
// // TODO add code to *NOT* test mandatory fields for Empty
// if (pk == iv->mTag)
// cond_n = std::move(cond_n) && Key(ck) == value;
// else
// {
// const char *pk_value = (*this)[pk].c_str();
// if (*pk_value == 0)
// cond_n = std::move(cond_n) && Key(ck) == Empty();
// else
// cond_n = std::move(cond_n) && ((Key(ck) == pk_value) or Key(ck) == Empty());
// }
// }
// auto rows_n = childCat->find(std::move(cond_n));
// if (not rows_n.empty())
// {
// if (cif::VERBOSE > 0)
// std::cerr << "Will not rename in child category since there are already rows that link to the parent" << std::endl;
// continue;
// }
// for (auto &cr : rows)
// cr.assign(childTag, value, false);
// }
// }
}
// proxy methods for every insertion
category::iterator category::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);
}
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);
}
std::vector<std::string> get_category_fields(const category &cat)
{
return {};
}
} // namespace cif::v2
\ No newline at end of file
...@@ -34,23 +34,24 @@ namespace cif::v2 ...@@ -34,23 +34,24 @@ namespace cif::v2
using namespace literals; using namespace literals;
class dictionary_parser : public parser_t<> inline void replace_all(std::string &s, std::string_view pat, std::string_view rep)
{ {
public: for (std::string::size_type i = s.find(pat); i != std::string::npos; i = s.find(pat, i))
using base_type = parser_t<>; s.replace(i, pat.size(), rep.data(), rep.size());
using file_type = typename base_type::file_type; }
using datablock_type = typename file_type::datablock_type;
using category_type = typename datablock_type::category_type;
dictionary_parser(Validator &validator, std::istream &is, file_type &f) class dictionary_parser : public parser
: base_type(is, f) {
public:
dictionary_parser(Validator &validator, std::istream &is, file &f)
: parser(is, f)
, m_validator(validator) , m_validator(validator)
{ {
} }
void load_dictionary() void load_dictionary()
{ {
std::unique_ptr<datablock_type> dict; std::unique_ptr<datablock> dict;
auto savedDatablock = m_datablock; auto savedDatablock = m_datablock;
try try
...@@ -65,7 +66,7 @@ class dictionary_parser : public parser_t<> ...@@ -65,7 +66,7 @@ class dictionary_parser : public parser_t<>
default: default:
{ {
dict.reset(new datablock_type(m_token_value)); // dummy datablock, for constructing the validator only dict.reset(new datablock(m_token_value)); // dummy datablock, for constructing the validator only
m_datablock = dict.get(); m_datablock = dict.get();
match(CIFToken::DATA); match(CIFToken::DATA);
...@@ -101,14 +102,14 @@ class dictionary_parser : public parser_t<> ...@@ -101,14 +102,14 @@ class dictionary_parser : public parser_t<>
link_items(); link_items();
// store meta information // store meta information
datablock_type::iterator info; datablock::iterator info;
bool n; bool n;
std::tie(info, n) = m_datablock->emplace("dictionary"); std::tie(info, n) = m_datablock->emplace("dictionary");
if (n) if (n)
{ {
auto r = info->front(); auto r = info->front();
m_validator.dictName(r["title"].as<std::string>()); m_validator.set_name(r["title"].as<std::string>());
m_validator.dictVersion(r["version"].as<std::string>()); m_validator.version(r["version"].as<std::string>());
} }
m_datablock = savedDatablock; m_datablock = savedDatablock;
...@@ -129,8 +130,8 @@ class dictionary_parser : public parser_t<> ...@@ -129,8 +130,8 @@ class dictionary_parser : public parser_t<>
bool isCategorySaveFrame = m_token_value[0] != '_'; bool isCategorySaveFrame = m_token_value[0] != '_';
datablock_type dict(m_token_value); datablock dict(m_token_value);
datablock_type::iterator cat = dict.end(); datablock::iterator cat = dict.end();
match(CIFToken::SAVE); match(CIFToken::SAVE);
while (m_lookahead == CIFToken::LOOP or m_lookahead == CIFToken::Tag) while (m_lookahead == CIFToken::LOOP or m_lookahead == CIFToken::Tag)
...@@ -437,14 +438,14 @@ class dictionary_parser : public parser_t<> ...@@ -437,14 +438,14 @@ class dictionary_parser : public parser_t<>
auto &dict = *m_datablock; auto &dict = *m_datablock;
for (auto &t : dict["item_type_list"]) for (auto t : dict["item_type_list"])
{ {
std::string code, primitiveCode, construct; std::string code, primitiveCode, construct;
cif::v2::tie(code, primitiveCode, construct) = t.get("code", "primitive_code", "construct"); cif::v2::tie(code, primitiveCode, construct) = t.get("code", "primitive_code", "construct");
ba::replace_all(construct, "\\n", "\n"); replace_all(construct, "\\n", "\n");
ba::replace_all(construct, "\\t", "\t"); replace_all(construct, "\\t", "\t");
ba::replace_all(construct, "\\\n", ""); replace_all(construct, "\\\n", "");
try try
{ {
...@@ -455,7 +456,7 @@ class dictionary_parser : public parser_t<> ...@@ -455,7 +456,7 @@ class dictionary_parser : public parser_t<>
} }
catch (const std::exception &) catch (const std::exception &)
{ {
std::throw_with_nested(CifParserError(t.lineNr(), "error in regular expression")); std::throw_with_nested(parse_error(/*t.lineNr()*/ 0, "error in regular expression"));
} }
// Do not replace an already defined type validator, this won't work with pdbx_v40 // Do not replace an already defined type validator, this won't work with pdbx_v40
...@@ -482,11 +483,12 @@ class dictionary_parser : public parser_t<> ...@@ -482,11 +483,12 @@ class dictionary_parser : public parser_t<>
// -------------------------------------------------------------------- // --------------------------------------------------------------------
Validator parse_dictionary(std::string_view name, std::istream &is); Validator parse_dictionary(std::string_view name, std::istream &is)
{ {
Validator result(name); Validator result(name);
dictionary_parser p(v, is, file{}); file f;
dictionary_parser p(result, is, f);
p.load_dictionary(); p.load_dictionary();
return result; return result;
......
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2022 NKI/AVL, Netherlands Cancer Institute
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <cif++/v2/row.hpp>
namespace cif::v2
{
std::string_view item_handle::text() const
{
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();
}
return {};
}
}
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2022 NKI/AVL, Netherlands Cancer Institute
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <cif++/v2/category.hpp>
namespace cif::v2
{
void row_handle::assign(size_t column, std::string_view value, bool updateLinked, bool validate)
{
m_category->update_value(m_row, column, value, updateLinked, validate);
}
uint16_t row_handle::get_column_ix(std::string_view name) const
{
return m_category->get_column_ix(name);
}
uint16_t row_handle::add_column(std::string_view name)
{
return m_category->add_column(name);
}
} // namespace cif::v2
\ No newline at end of file
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <cassert>
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
...@@ -217,16 +218,12 @@ const ValidateItem *ValidateCategory::getValidatorForItem(std::string_view tag) ...@@ -217,16 +218,12 @@ const ValidateItem *ValidateCategory::getValidatorForItem(std::string_view tag)
// -------------------------------------------------------------------- // --------------------------------------------------------------------
Validator::Validator(std::string_view name, std::istream &is) // Validator::Validator(std::string_view name, std::istream &is)
: mName(name) // : mName(name)
{ // {
DictParser p(*this, is); // DictParser p(*this, is);
p.loadDictionary(); // p.loadDictionary();
} // }
Validator::~Validator()
{
}
void Validator::addTypeValidator(ValidateType &&v) void Validator::addTypeValidator(ValidateType &&v)
{ {
...@@ -343,7 +340,7 @@ std::vector<const ValidateLink *> Validator::getLinksForChild(std::string_view c ...@@ -343,7 +340,7 @@ std::vector<const ValidateLink *> Validator::getLinksForChild(std::string_view c
void Validator::reportError(const std::string &msg, bool fatal) const void Validator::reportError(const std::string &msg, bool fatal) const
{ {
if (mStrict or fatal) if (m_strict or fatal)
throw ValidationError(msg); throw ValidationError(msg);
else if (VERBOSE > 0) else if (VERBOSE > 0)
std::cerr << msg << std::endl; std::cerr << msg << std::endl;
...@@ -357,7 +354,7 @@ const Validator &ValidatorFactory::operator[](std::string_view dictionary_name) ...@@ -357,7 +354,7 @@ const Validator &ValidatorFactory::operator[](std::string_view dictionary_name)
for (auto &validator : mValidators) for (auto &validator : mValidators)
{ {
if (iequals(validator.m_name, dictionary_name)) if (iequals(validator.name(), dictionary_name))
return validator; return validator;
} }
...@@ -422,12 +419,12 @@ const Validator &ValidatorFactory::operator[](std::string_view dictionary_name) ...@@ -422,12 +419,12 @@ const Validator &ValidatorFactory::operator[](std::string_view dictionary_name)
throw std::runtime_error("Dictionary not found or defined (" + dictionary.string() + ")"); throw std::runtime_error("Dictionary not found or defined (" + dictionary.string() + ")");
} }
assert(iequals(mValidators.back().m_name, dictionary_name)); assert(iequals(mValidators.back().name(), dictionary_name));
return mValidators.back(); return mValidators.back();
} }
void ValiatorFactory::construct_validator(std::string_view name, std::istream &is) void ValidatorFactory::construct_validator(std::string_view name, std::istream &is)
{ {
mValidators.emplace_back(parse_dictionary(name, is)); mValidators.emplace_back(parse_dictionary(name, is));
} }
......
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