Commit ab9c4d94 by Maarten L. Hekkelman

compiling again

parent e5eb6225
......@@ -215,7 +215,11 @@ set(project_sources
${PROJECT_SOURCE_DIR}/src/Symmetry.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/item.cpp
${PROJECT_SOURCE_DIR}/src/v2/parser.cpp
${PROJECT_SOURCE_DIR}/src/v2/row.cpp
${PROJECT_SOURCE_DIR}/src/v2/validate.cpp
)
......
......@@ -35,47 +35,29 @@ namespace cif::v2
// --------------------------------------------------------------------
template <typename Alloc, typename Category>
class datablock_t
class datablock
{
public:
using category_type = Category;
using allocator_type = Alloc;
using category_list = std::list<category>;
using category_allocator_type = typename std::allocator_traits<Alloc>::template rebind_alloc<category_type>;
using category_type_list = std::list<category_type, category_allocator_type>;
using iterator = category_list::iterator;
using const_iterator = category_list::const_iterator;
using iterator = category_type_list::iterator;
using const_iterator = category_type_list::const_iterator;
using reference = typename category_list::reference;
using reference = typename category_type_list::reference;
datablock() = default;
datablock_t(std::string_view name, const allocator_type &alloc = allocator_type())
: m_categories(alloc)
, m_name(name)
datablock(std::string_view 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_t(const datablock_t &db, const Alloc2 &a)
// : 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;
datablock &operator=(const datablock &) = default;
datablock &operator=(datablock &&) = default;
// --------------------------------------------------------------------
......@@ -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); });
if (i != m_categories.end())
......@@ -112,10 +94,10 @@ class datablock_t
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;
auto i = std::find_if(m_categories.begin(), m_categories.end(), [name](const category_type &c)
static const category s_empty;
auto i = std::find_if(m_categories.begin(), m_categories.end(), [name](const category &c)
{ return iequals(c.name(), name); });
return i == m_categories.end() ? s_empty : *i;
}
......@@ -155,53 +137,51 @@ class datablock_t
return std::make_tuple(m_categories.begin(), is_new);
}
void write(std::ostream &os) const
{
// std::shared_lock lock(mLock);
os << "data_" << m_name << std::endl
<< "# " << std::endl;
// mmcif support, sort of. First write the 'entry' Category
// and if it exists, _AND_ we have a Validator, write out the
// audit_conform record.
for (auto &cat : m_categories)
{
if (cat.name() != "entry")
continue;
cat.write(os);
// if (mValidator != nullptr)
// {
// Category auditConform(*this, "audit_conform", nullptr);
// auditConform.emplace({{"dict_name", mValidator->dictName()},
// {"dict_version", mValidator->dictVersion()}});
// auditConform.write(os);
// }
break;
}
for (auto &cat : m_categories)
{
if (cat.name() != "entry" and cat.name() != "audit_conform")
cat.write(os);
}
}
// void write(std::ostream &os) const
// {
// // std::shared_lock lock(mLock);
// os << "data_" << m_name << std::endl
// << "# " << std::endl;
// // mmcif support, sort of. First write the 'entry' Category
// // and if it exists, _AND_ we have a Validator, write out the
// // audit_conform record.
// for (auto &cat : m_categories)
// {
// if (cat.name() != "entry")
// continue;
// cat.write(os);
// // if (mValidator != nullptr)
// // {
// // Category auditConform(*this, "audit_conform", nullptr);
// // auditConform.emplace({{"dict_name", mValidator->dictName()},
// // {"dict_version", mValidator->dictVersion()}});
// // auditConform.write(os);
// // }
// break;
// }
// for (auto &cat : m_categories)
// {
// if (cat.name() != "entry" and cat.name() != "audit_conform")
// cat.write(os);
// }
// }
friend std::ostream &operator<<(std::ostream &os, const datablock_t &db)
{
db.write(os);
return os;
}
// friend std::ostream &operator<<(std::ostream &os, const datablock &db)
// {
// db.write(os);
// return os;
// }
private:
category_type_list m_categories;
category_list m_categories;
std::string m_name;
};
using datablock = datablock_t<>;
} // namespace cif::v2
\ No newline at end of file
......@@ -36,20 +36,10 @@ namespace cif::v2
// --------------------------------------------------------------------
template <
typename Alloc,
typename Datablock,
typename Category>
class file_t
class file
{
public:
using allocator_type = Alloc;
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 datablock_list = std::list<datablock>;
using value_type = datablock_list::value_type;
using reference = datablock_list::reference;
......@@ -58,29 +48,21 @@ class file_t
using iterator = datablock_list::iterator;
using const_iterator = datablock_list::const_iterator;
using parser_type = parser_t<allocator_type, file_t, datablock_type, category_type>;
file_t() = default;
file() = default;
file_t(const allocator_type &a = allocator_type())
: m_datablocks(a)
{
}
file_t(std::istream &is, const allocator_type &alloc = allocator_type())
: m_datablocks(alloc)
file(std::istream &is)
{
load(is);
}
file_t(const file_t &) = default;
file_t(file_t &&) = default;
file_t &operator=(const file_t &) = default;
file_t &operator=(file_t &&) = default;
file(const file &) = default;
file(file &&) = default;
file &operator=(const file &) = 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); });
if (i != m_datablocks.end())
......@@ -90,10 +72,10 @@ class file_t
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;
auto i = std::find_if(m_datablocks.begin(), m_datablocks.end(), [name](const datablock_type &c)
static const datablock s_empty;
auto i = std::find_if(m_datablocks.begin(), m_datablocks.end(), [name](const datablock &c)
{ return iequals(c.name(), name); });
return i == m_datablocks.end() ? s_empty : *i;
}
......@@ -133,14 +115,12 @@ class file_t
reference front() { return m_datablocks.front(); }
reference back() { return m_datablocks.back(); }
void load(std::istream &is)
{
// auto saved = mValidator;
// setValidator(nullptr);
parser_type p(is, *this);
parser p(is, *this);
p.parse_file();
// if (saved != nullptr)
......@@ -152,8 +132,7 @@ class file_t
private:
datablock_list m_datablocks;
std::unique_ptr<Validator> m_validator;
};
using file = file_t<>;
}
\ No newline at end of file
......@@ -26,21 +26,27 @@
#pragma once
#include <memory>
#include <string>
#include <vector>
namespace cif::v2
{
template <typename Alloc = std::allocator<void>>
class category_t;
class category;
class datablock;
class file;
class parser;
template <typename Alloc = std::allocator<void>, typename Category = category_t<Alloc>>
class datablock_t;
class row;
class row_handle;
template <typename Alloc = std::allocator<void>, typename Datablock = datablock_t<Alloc>, typename Category = typename Datablock::category_type>
class file_t;
class item;
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
\ No newline at end of file
......@@ -29,12 +29,15 @@
#include <charconv>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <limits>
#include <memory>
#include <optional>
#include <cif++/CifUtils.hpp>
#include <cif++/v2/forward_decl.hpp>
namespace cif
{
extern int VERBOSE;
......@@ -80,7 +83,7 @@ class item
auto r = cif::to_chars(m_buffer, m_buffer + sizeof(m_buffer) - 1, value, cif::chars_format::general);
if (r.ec != std::errc())
throw std::runtime_error("Could not format number");
assert(r.ptr >= m_buffer and r.ptr < m_buffer + sizeof(m_buffer));
*r.ptr = 0;
m_value = std::string_view(m_buffer, r.ptr - m_buffer);
......@@ -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
template <typename RowHandle>
struct item_handle
{
using row_handle_type = RowHandle;
public:
// conversion helper class
template <typename T, typename = void>
......@@ -158,29 +203,6 @@ struct item_handle
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>
void os(const Ts &...v)
{
......@@ -199,7 +221,7 @@ struct item_handle
}
template <typename T>
auto value_or(const T &dv)
auto value_or(const T &dv) const
{
return empty() ? dv : this->as<T>();
}
......@@ -244,21 +266,12 @@ struct item_handle
// return s_empty_result;
// }
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 {};
}
std::string_view text() const;
// 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_row_handle(row)
{
......@@ -266,17 +279,15 @@ struct item_handle
private:
uint16_t m_column;
row_handle_type &m_row_handle;
// bool mConst = false;
row_handle &m_row_handle;
static constexpr const char *s_empty_result = "";
};
// So sad that the gcc implementation of from_chars does not support floats yet...
template <typename Row>
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>>;
......@@ -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>
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)
{
......@@ -374,9 +384,8 @@ struct item_handle<Row>::item_value_as<std::optional<T>>
}
};
template <typename Row>
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)
{
......@@ -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>
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)
// {
......@@ -409,9 +417,8 @@ struct item_handle<Row>::item_value_as<char[N]>
}
};
template <typename Row>
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)
// {
......@@ -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>
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)
{
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)
......
......@@ -27,37 +27,26 @@
#pragma once
#include <cif++/v2/item.hpp>
#include <cif++/v2/condition.hpp>
namespace cif::v2
{
template <typename>
class row_handle;
namespace detail
{
// some helper classes to help create tuple result types
template <
typename Category,
typename... C>
template <typename... C>
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);
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_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]];
}
......@@ -74,7 +63,7 @@ namespace detail
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;
};
......@@ -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_handle
class row
{
public:
using category_type = Category;
using row_type = std::conditional_t<std::is_const_v<category_type>, const typename category_type::row, typename category_type::row>;
row() = default;
using item_handle_type = item_handle<row_handle>;
private:
friend class item_handle;
template <typename>
friend class row_handle;
template <typename, typename...>
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;
row_handle() = default;
......@@ -137,42 +144,40 @@ class row_handle
row_handle &operator=(const row_handle &) = default;
row_handle &operator=(row_handle &&) = default;
template <typename C2>
row_handle(const row_handle<C2> &rhs)
: m_cat(rhs.m_cat)
, m_row(rhs.m_row)
row_handle(const category &cat, const row &r)
: m_category(const_cast<category *>(&cat))
, m_row(const_cast<row *>(&r))
{
}
row_handle(category_type &cat, row_type &row)
: m_cat(&cat)
, m_row(&row)
const category &cat() const
{
return *m_category;
}
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>
......@@ -183,13 +188,13 @@ class row_handle
std::array<size_t, N> cix;
for (size_t i = 0; i < N; ++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>
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)
......@@ -247,32 +252,23 @@ class row_handle
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)
{
m_cat->update_value(m_row, column, value, updateLinked, validate);
}
void assign(size_t column, std::string_view value, bool updateLinked, bool validate = true);
private:
uint16_t get_column_ix(std::string_view name) const
{
return m_cat->get_column_ix(name);
}
uint16_t get_column_ix(std::string_view name) const;
uint16_t add_column(std::string_view name)
{
return m_cat->add_column(name);
}
uint16_t add_column(std::string_view name);
void assign(const item &i, bool updateLinked)
{
assign(i.name(), i.value(), updateLinked);
}
category_type *m_cat = nullptr;
row_type *m_row = nullptr;
category *m_category = nullptr;
row *m_row = nullptr;
};
} // namespace cif::v2
\ No newline at end of file
......@@ -166,7 +166,7 @@ class Validator
{
}
~Validator();
~Validator() = default;
Validator(const Validator &rhs) = delete;
Validator &operator=(const Validator &rhs) = delete;
......@@ -175,7 +175,6 @@ class Validator
Validator &operator=(Validator &&rhs);
friend class dictionary_parser;
// friend class ValidatorFactory;
void addTypeValidator(ValidateType &&v);
const ValidateType *getValidatorForType(std::string_view typeCode) const;
......@@ -189,11 +188,11 @@ class Validator
void reportError(const std::string &msg, bool fatal) const;
const std::string &dictName() const { return m_name; }
void dictName(const std::string &name) { m_name = name; }
const std::string &name() const { return m_name; }
void set_name(const std::string &name) { m_name = name; }
const std::string &dictVersion() const { return m_version; }
void dictVersion(const std::string &version) { m_version = version; }
const std::string &version() const { return m_version; }
void version(const std::string &version) { m_version = version; }
private:
// name is fully qualified here:
......@@ -201,7 +200,7 @@ class Validator
std::string m_name;
std::string m_version;
bool mStrict = false;
bool m_strict = false;
std::set<ValidateType> mTypeValidators;
std::set<ValidateCategory> mCategoryValidators;
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
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:
using base_type = parser_t<>;
using file_type = typename base_type::file_type;
using datablock_type = typename file_type::datablock_type;
using category_type = typename datablock_type::category_type;
for (std::string::size_type i = s.find(pat); i != std::string::npos; i = s.find(pat, i))
s.replace(i, pat.size(), rep.data(), rep.size());
}
dictionary_parser(Validator &validator, std::istream &is, file_type &f)
: base_type(is, f)
class dictionary_parser : public parser
{
public:
dictionary_parser(Validator &validator, std::istream &is, file &f)
: parser(is, f)
, m_validator(validator)
{
}
void load_dictionary()
{
std::unique_ptr<datablock_type> dict;
std::unique_ptr<datablock> dict;
auto savedDatablock = m_datablock;
try
......@@ -65,7 +66,7 @@ class dictionary_parser : public parser_t<>
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();
match(CIFToken::DATA);
......@@ -101,14 +102,14 @@ class dictionary_parser : public parser_t<>
link_items();
// store meta information
datablock_type::iterator info;
datablock::iterator info;
bool n;
std::tie(info, n) = m_datablock->emplace("dictionary");
if (n)
{
auto r = info->front();
m_validator.dictName(r["title"].as<std::string>());
m_validator.dictVersion(r["version"].as<std::string>());
m_validator.set_name(r["title"].as<std::string>());
m_validator.version(r["version"].as<std::string>());
}
m_datablock = savedDatablock;
......@@ -129,8 +130,8 @@ class dictionary_parser : public parser_t<>
bool isCategorySaveFrame = m_token_value[0] != '_';
datablock_type dict(m_token_value);
datablock_type::iterator cat = dict.end();
datablock dict(m_token_value);
datablock::iterator cat = dict.end();
match(CIFToken::SAVE);
while (m_lookahead == CIFToken::LOOP or m_lookahead == CIFToken::Tag)
......@@ -437,14 +438,14 @@ class dictionary_parser : public parser_t<>
auto &dict = *m_datablock;
for (auto &t : dict["item_type_list"])
for (auto t : dict["item_type_list"])
{
std::string code, primitiveCode, construct;
cif::v2::tie(code, primitiveCode, construct) = t.get("code", "primitive_code", "construct");
ba::replace_all(construct, "\\n", "\n");
ba::replace_all(construct, "\\t", "\t");
ba::replace_all(construct, "\\\n", "");
replace_all(construct, "\\n", "\n");
replace_all(construct, "\\t", "\t");
replace_all(construct, "\\\n", "");
try
{
......@@ -455,7 +456,7 @@ class dictionary_parser : public parser_t<>
}
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
......@@ -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);
dictionary_parser p(v, is, file{});
file f;
dictionary_parser p(result, is, f);
p.load_dictionary();
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 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <cassert>
#include <fstream>
#include <iostream>
......@@ -217,16 +218,12 @@ const ValidateItem *ValidateCategory::getValidatorForItem(std::string_view tag)
// --------------------------------------------------------------------
Validator::Validator(std::string_view name, std::istream &is)
: mName(name)
{
DictParser p(*this, is);
p.loadDictionary();
}
Validator::~Validator()
{
}
// Validator::Validator(std::string_view name, std::istream &is)
// : mName(name)
// {
// DictParser p(*this, is);
// p.loadDictionary();
// }
void Validator::addTypeValidator(ValidateType &&v)
{
......@@ -343,7 +340,7 @@ std::vector<const ValidateLink *> Validator::getLinksForChild(std::string_view c
void Validator::reportError(const std::string &msg, bool fatal) const
{
if (mStrict or fatal)
if (m_strict or fatal)
throw ValidationError(msg);
else if (VERBOSE > 0)
std::cerr << msg << std::endl;
......@@ -357,7 +354,7 @@ const Validator &ValidatorFactory::operator[](std::string_view dictionary_name)
for (auto &validator : mValidators)
{
if (iequals(validator.m_name, dictionary_name))
if (iequals(validator.name(), dictionary_name))
return validator;
}
......@@ -422,12 +419,12 @@ const Validator &ValidatorFactory::operator[](std::string_view dictionary_name)
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();
}
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));
}
......
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