Commit 04b7828a by Maarten L. Hekkelman

validator work

parent 9c621eca
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include <cif++/v2/iterator.hpp> #include <cif++/v2/iterator.hpp>
#include <cif++/v2/row.hpp> #include <cif++/v2/row.hpp>
#include <cif++/v2/validate.hpp> #include <cif++/v2/validate.hpp>
namespace cif::v2 namespace cif::v2
{ {
...@@ -127,17 +128,22 @@ class category ...@@ -127,17 +128,22 @@ class category
throw std::runtime_error("No Validator specified"); throw std::runtime_error("No Validator specified");
if (m_cat_validator == nullptr) if (m_cat_validator == nullptr)
m_validator->reportError("undefined Category", true); m_validator->report_error("undefined Category", true);
iset result; iset result;
for (auto &iv : m_cat_validator->mItemValidators) for (auto &iv : m_cat_validator->m_item_validators)
result.insert(iv.mTag); result.insert(iv.m_tag);
return result; return result;
} }
const Validator *get_validator() const { return m_validator; } void set_validator(const validator *v, datablock &db);
const ValidateCategory *get_cat_validator() const { return m_cat_validator; } void update_links(datablock &db);
const validator *get_validator() const { return m_validator; }
const category_validator *get_cat_validator() const { return m_cat_validator; }
bool is_valid() const;
// -------------------------------------------------------------------- // --------------------------------------------------------------------
...@@ -379,6 +385,10 @@ class category ...@@ -379,6 +385,10 @@ class category
// insert_impl(pos, std::move(row)); // insert_impl(pos, std::move(row));
// } // }
iterator erase(iterator pos);
size_t erase(condition &&cond);
size_t erase(condition &&cond, std::function<void(row_handle)> &&visit);
iterator emplace(std::initializer_list<item> items) iterator emplace(std::initializer_list<item> items)
{ {
return this->emplace(items.begin(), items.end()); return this->emplace(items.begin(), items.end());
...@@ -388,29 +398,29 @@ class category ...@@ -388,29 +398,29 @@ class category
iterator emplace(ItemIter b, ItemIter e) iterator emplace(ItemIter b, ItemIter e)
{ {
// First, make sure all mandatory fields are supplied // First, make sure all mandatory fields are supplied
// if (mCatValidator != nullptr and b != e) if (m_cat_validator != nullptr and b != e)
// { {
// for (auto &col : m_columns) for (const auto &[column, iv] : m_columns)
// { {
// auto iv = mCatValidator->getValidatorForItem(col.mName); if (iv == nullptr)
continue;
// if (iv == nullptr) bool seen = false;
// continue;
// bool seen = false; for (auto v = b; v != e; ++v)
{
if (iequals(v->name(), column))
{
iv->operator()(v->value());
// for (auto v = b; v != e; ++v) seen = true;
// { break;
// if (iequals(v->name(), col.mName)) }
// { }
// seen = true;
// break;
// }
// }
// if (not seen and iv->mMandatory) if (not seen and iv->m_mandatory)
// throw std::runtime_error("missing mandatory field " + col.mName + " for category " + mName); throw std::runtime_error("missing mandatory field " + column + " for category " + m_name);
// } }
// if (mIndex != nullptr) // if (mIndex != nullptr)
// { // {
...@@ -433,7 +443,7 @@ class category ...@@ -433,7 +443,7 @@ class category
// isNew = false; // isNew = false;
// } // }
// } // }
// } }
row *r = this->create_row(); row *r = this->create_row();
...@@ -486,12 +496,12 @@ class category ...@@ -486,12 +496,12 @@ class category
break; break;
} }
// if (VERBOSE > 0 and result == m_columns.size() and mCatValidator != nullptr) // validate the name, if it is known at all (since it was not found) if (VERBOSE > 0 and result == m_columns.size() and m_cat_validator != nullptr) // validate the name, if it is known at all (since it was not found)
// { {
// auto iv = mCatValidator->getValidatorForItem(name); auto iv = m_cat_validator->get_validator_for_item(column_name);
// if (iv == nullptr) if (iv == nullptr)
// std::cerr << "Invalid name used '" << name << "' is not a known column in " + mName << std::endl; std::cerr << "Invalid name used '" << name << "' is not a known column in " + m_name << std::endl;
// } }
return result; return result;
} }
...@@ -504,14 +514,14 @@ class category ...@@ -504,14 +514,14 @@ class category
if (result == m_columns.size()) if (result == m_columns.size())
{ {
const ValidateItem *item_validator = nullptr; const item_validator *item_validator = nullptr;
// if (mCatValidator != nullptr) if (m_cat_validator != nullptr)
// { {
// item_validator = mCatValidator->getValidatorForItem(column_name); item_validator = m_cat_validator->get_validator_for_item(column_name);
// if (item_validator == nullptr) if (item_validator == nullptr)
// m_validator->reportError("tag " + std::string(column_name) + " not allowed in category " + mName, false); m_validator->report_error("tag " + std::string(column_name) + " not allowed in category " + m_name, false);
// } }
m_columns.emplace_back(column_name, item_validator); m_columns.emplace_back(column_name, item_validator);
} }
...@@ -523,6 +533,9 @@ class category ...@@ -523,6 +533,9 @@ class category
void update_value(row *row, size_t column, std::string_view value, bool updateLinked, bool validate = true); void update_value(row *row, size_t column, std::string_view value, bool updateLinked, bool validate = true);
private: private:
bool is_orphan(row_handle r) const;
void erase_orphans(condition &&cond);
using allocator_type = std::allocator<void>; using allocator_type = std::allocator<void>;
constexpr allocator_type get_allocator() const constexpr allocator_type get_allocator() const
...@@ -645,15 +658,27 @@ class category ...@@ -645,15 +658,27 @@ class category
struct item_column struct item_column
{ {
std::string m_name; std::string m_name;
const ValidateItem *m_validator; const item_validator *m_validator;
item_column(std::string_view name, const ValidateItem *validator) item_column(std::string_view name, const item_validator *validator)
: m_name(name) : m_name(name)
, m_validator(validator) , m_validator(validator)
{ {
} }
}; };
struct link
{
link(category *linked, const link_validator *v)
: linked(linked)
, v(v)
{
}
category *linked;
const link_validator *v;
};
// proxy methods for every insertion // proxy methods for every insertion
iterator insert_impl(const_iterator pos, row *n); iterator insert_impl(const_iterator pos, row *n);
...@@ -661,8 +686,10 @@ class category ...@@ -661,8 +686,10 @@ class category
std::string m_name; std::string m_name;
std::vector<item_column> m_columns; std::vector<item_column> m_columns;
const Validator *m_validator = nullptr; const validator *m_validator = nullptr;
const ValidateCategory *m_cat_validator = nullptr; const category_validator *m_cat_validator = nullptr;
std::vector<link> m_parent_links, m_child_links;
bool m_cascade = true;
row *m_head = nullptr, *m_tail = nullptr; row *m_head = nullptr, *m_tail = nullptr;
}; };
......
...@@ -63,6 +63,31 @@ class datablock ...@@ -63,6 +63,31 @@ class datablock
const std::string &name() const { return m_name; } const std::string &name() const { return m_name; }
void set_validator(const validator *v)
{
m_validator = v;
for (auto &cat : *this)
cat.set_validator(v, *this);
}
const validator *get_validator() const
{
return m_validator;
}
bool is_valid() const
{
if (m_validator == nullptr)
throw std::runtime_error("Validator not specified");
bool result = true;
for (auto &cat : *this)
result = cat.is_valid() and result;
return result;
}
// -------------------------------------------------------------------- // --------------------------------------------------------------------
bool empty() const { return m_categories.empty(); } bool empty() const { return m_categories.empty(); }
...@@ -102,6 +127,18 @@ class datablock ...@@ -102,6 +127,18 @@ class datablock
return i == m_categories.end() ? s_empty : *i; return i == m_categories.end() ? s_empty : *i;
} }
category *get(std::string_view name)
{
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() ? nullptr : &*i;
}
const category *get(std::string_view name) const
{
return const_cast<datablock *>(this)->get(name);
}
std::tuple<iterator, bool> emplace(std::string_view name) std::tuple<iterator, bool> emplace(std::string_view name)
{ {
bool is_new = true; bool is_new = true;
...@@ -182,6 +219,7 @@ class datablock ...@@ -182,6 +219,7 @@ class datablock
private: private:
category_list m_categories; category_list m_categories;
std::string m_name; std::string m_name;
const validator *m_validator = nullptr;
}; };
} // namespace cif::v2 } // namespace cif::v2
\ No newline at end of file
...@@ -31,6 +31,6 @@ ...@@ -31,6 +31,6 @@
namespace cif::v2 namespace cif::v2
{ {
Validator parse_dictionary(std::string_view name, std::istream &is); validator parse_dictionary(std::string_view name, std::istream &is);
} // namespace cif::v2 } // namespace cif::v2
...@@ -60,6 +60,57 @@ class file ...@@ -60,6 +60,57 @@ class file
file &operator=(const file &) = default; file &operator=(const file &) = default;
file &operator=(file &&) = default; file &operator=(file &&) = default;
void set_validator(const validator *v)
{
m_validator = v;
for (auto &db : *this)
db.set_validator(v);
}
const validator *get_validator() const
{
return m_validator;
}
bool is_valid() const
{
if (m_validator == nullptr)
std::runtime_error("No validator loaded explicitly, cannot continue");
bool result = true;
for (auto &d : *this)
result = d.is_valid() and result;
return result;
}
bool is_valid()
{
if (m_validator == nullptr)
{
if (VERBOSE > 0)
std::cerr << "No dictionary loaded explicitly, loading default" << std::endl;
load_dictionary();
}
bool result = true;
for (auto &d : *this)
result = d.is_valid() and result;
return result;
}
void load_dictionary()
{
load_dictionary("mmcif_ddl");
}
void load_dictionary(std::string_view name)
{
set_validator(&validator_factory::instance()[name]);
}
datablock &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 &c) auto i = std::find_if(m_datablocks.begin(), m_datablocks.end(), [name](const datablock &c)
...@@ -112,27 +163,36 @@ class file ...@@ -112,27 +163,36 @@ class file
bool empty() const { return m_datablocks.empty(); } bool empty() const { return m_datablocks.empty(); }
size_t size() const { return m_datablocks.size(); } size_t size() const { return m_datablocks.size(); }
iterator begin() { return m_datablocks.begin(); }
iterator end() { return m_datablocks.end(); }
const_iterator cbegin() { return m_datablocks.begin(); }
const_iterator cend() { return m_datablocks.end(); }
const_iterator begin() const { return m_datablocks.begin(); }
const_iterator end() const { return m_datablocks.end(); }
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 = m_validator;
// setValidator(nullptr); set_validator(nullptr);
parser p(is, *this); parser p(is, *this);
p.parse_file(); p.parse_file();
// if (saved != nullptr) if (saved != nullptr)
// { {
// setValidator(saved); set_validator(saved);
// (void)isValid(); (void)is_valid();
// } }
} }
private: private:
datablock_list m_datablocks; datablock_list m_datablocks;
std::unique_ptr<Validator> m_validator; const validator* m_validator = nullptr;
}; };
} }
\ No newline at end of file
...@@ -199,7 +199,7 @@ struct item_handle ...@@ -199,7 +199,7 @@ struct item_handle
item_handle &operator=(const T &value) item_handle &operator=(const T &value)
{ {
item v{"", value}; item v{"", value};
m_row_handle.assign(m_column, v.value(), false); assign_value(v);
return *this; return *this;
} }
...@@ -281,6 +281,8 @@ struct item_handle ...@@ -281,6 +281,8 @@ struct item_handle
uint16_t m_column; uint16_t m_column;
row_handle &m_row_handle; row_handle &m_row_handle;
void assign_value(const item &value);
static constexpr const char *s_empty_result = ""; static constexpr const char *s_empty_result = "";
}; };
...@@ -432,6 +434,20 @@ struct item_handle::item_value_as<T, std::enable_if_t<std::is_same_v<T, const ch ...@@ -432,6 +434,20 @@ struct item_handle::item_value_as<T, std::enable_if_t<std::is_same_v<T, const ch
}; };
template <typename T> template <typename T>
struct item_handle::item_value_as<T, std::enable_if_t<std::is_same_v<T, std::string_view>>>
{
// static std::string_view convert(const item_handle &ref)
// {
// return ref.text();
// }
static int compare(const item_handle &ref, const std::string_view &value, bool icase)
{
return icase ? cif::icompare(ref.text(), value) : ref.text().compare(value);
}
};
template <typename T>
struct item_handle::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)
......
...@@ -135,6 +135,7 @@ class row_handle ...@@ -135,6 +135,7 @@ class row_handle
{ {
public: public:
friend class item_handle; friend class item_handle;
friend class category;
row_handle() = default; row_handle() = default;
...@@ -262,6 +263,11 @@ class row_handle ...@@ -262,6 +263,11 @@ class row_handle
uint16_t add_column(std::string_view name); uint16_t add_column(std::string_view name);
operator row*()
{
return m_row;
}
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);
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#pragma once #pragma once
#include <filesystem> #include <filesystem>
#include <mutex>
// duh.. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86164 // duh.. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86164
// #include <regex> // #include <regex>
...@@ -43,19 +44,19 @@ namespace io = boost::iostreams; ...@@ -43,19 +44,19 @@ namespace io = boost::iostreams;
namespace cif::v2 namespace cif::v2
{ {
struct ValidateCategory; struct category_validator;
class ValidatorFactory; class validator_factory;
// -------------------------------------------------------------------- // --------------------------------------------------------------------
class ValidationError : public std::exception class validation_error : public std::exception
{ {
public: public:
ValidationError(const std::string &msg); validation_error(const std::string &msg);
ValidationError(const std::string &cat, const std::string &item, validation_error(const std::string &cat, const std::string &item,
const std::string &msg); const std::string &msg);
const char *what() const noexcept { return mMsg.c_str(); } const char *what() const noexcept { return m_msg.c_str(); }
std::string mMsg; std::string m_msg;
}; };
// -------------------------------------------------------------------- // --------------------------------------------------------------------
...@@ -67,126 +68,120 @@ enum class DDL_PrimitiveType ...@@ -67,126 +68,120 @@ enum class DDL_PrimitiveType
Numb Numb
}; };
DDL_PrimitiveType mapToPrimitiveType(std::string_view s); DDL_PrimitiveType map_to_primitive_type(std::string_view s);
struct ValidateType struct type_validator
{ {
std::string mName; std::string m_name;
DDL_PrimitiveType mPrimitiveType; DDL_PrimitiveType m_primitive_type;
// std::regex mRx; // std::regex mRx;
boost::regex mRx; boost::regex m_rx;
bool operator<(const ValidateType &rhs) const bool operator<(const type_validator &rhs) const
{ {
return icompare(mName, rhs.mName) < 0; return icompare(m_name, rhs.m_name) < 0;
} }
// compare values based on type
// int compare(const std::string& a, const std::string& b) const
// {
// return compare(a.c_str(), b.c_str());
// }
int compare(const char *a, const char *b) const; int compare(const char *a, const char *b) const;
}; };
struct ValidateItem struct item_validator
{ {
std::string mTag; std::string m_tag;
bool mMandatory; bool m_mandatory;
const ValidateType *mType; const type_validator *m_type;
cif::iset mEnums; cif::iset m_enums;
std::string mDefault; std::string m_default;
bool mDefaultIsNull; bool m_default_is_null;
ValidateCategory *mCategory = nullptr; category_validator *m_category = nullptr;
// ItemLinked is used for non-key links // ItemLinked is used for non-key links
struct ItemLinked struct item_link
{ {
ValidateItem *mParent; item_validator *m_parent;
std::string mParentItem; std::string m_parent_item;
std::string mChildItem; std::string m_child_item;
}; };
std::vector<ItemLinked> mLinked; std::vector<item_link> mLinked;
bool operator<(const ValidateItem &rhs) const bool operator<(const item_validator &rhs) const
{ {
return icompare(mTag, rhs.mTag) < 0; return icompare(m_tag, rhs.m_tag) < 0;
} }
bool operator==(const ValidateItem &rhs) const bool operator==(const item_validator &rhs) const
{ {
return iequals(mTag, rhs.mTag); return iequals(m_tag, rhs.m_tag);
} }
void operator()(std::string value) const; void operator()(std::string_view value) const;
}; };
struct ValidateCategory struct category_validator
{ {
std::string mName; std::string m_name;
std::vector<std::string> mKeys; std::vector<std::string> m_keys;
cif::iset mGroups; cif::iset m_groups;
cif::iset mMandatoryFields; cif::iset m_mandatory_fields;
std::set<ValidateItem> mItemValidators; std::set<item_validator> m_item_validators;
bool operator<(const ValidateCategory &rhs) const bool operator<(const category_validator &rhs) const
{ {
return icompare(mName, rhs.mName) < 0; return icompare(m_name, rhs.m_name) < 0;
} }
void addItemValidator(ValidateItem &&v); void addItemValidator(item_validator &&v);
const ValidateItem *getValidatorForItem(std::string_view tag) const; const item_validator *get_validator_for_item(std::string_view tag) const;
const std::set<ValidateItem> &itemValidators() const const std::set<item_validator> &item_validators() const
{ {
return mItemValidators; return m_item_validators;
} }
}; };
struct ValidateLink struct link_validator
{ {
int mLinkGroupID; int m_link_group_id;
std::string mParentCategory; std::string m_parent_category;
std::vector<std::string> mParentKeys; std::vector<std::string> m_parent_keys;
std::string mChildCategory; std::string m_child_category;
std::vector<std::string> mChildKeys; std::vector<std::string> m_child_keys;
std::string mLinkGroupLabel; std::string m_link_group_label;
}; };
// -------------------------------------------------------------------- // --------------------------------------------------------------------
class Validator class validator
{ {
public: public:
Validator(std::string_view name) validator(std::string_view name)
: m_name(name) : m_name(name)
{ {
} }
~Validator() = default; ~validator() = default;
Validator(const Validator &rhs) = delete; validator(const validator &rhs) = delete;
Validator &operator=(const Validator &rhs) = delete; validator &operator=(const validator &rhs) = delete;
Validator(Validator &&rhs) = default; validator(validator &&rhs) = default;
Validator &operator=(Validator &&rhs) = default; validator &operator=(validator &&rhs) = default;
friend class dictionary_parser; friend class dictionary_parser;
void addTypeValidator(ValidateType &&v); void add_type_validator(type_validator &&v);
const ValidateType *getValidatorForType(std::string_view typeCode) const; const type_validator *get_validator_for_type(std::string_view type_code) const;
void addCategoryValidator(ValidateCategory &&v); void add_category_validator(category_validator &&v);
const ValidateCategory *getValidatorForCategory(std::string_view category) const; const category_validator *get_validator_for_category(std::string_view category) const;
void addLinkValidator(ValidateLink &&v); void add_link_validator(link_validator &&v);
std::vector<const ValidateLink *> getLinksForParent(std::string_view category) const; std::vector<const link_validator *> get_links_for_parent(std::string_view category) const;
std::vector<const ValidateLink *> getLinksForChild(std::string_view category) const; std::vector<const link_validator *> get_links_for_child(std::string_view category) const;
void reportError(const std::string &msg, bool fatal) const; void report_error(const std::string &msg, bool fatal) const;
const std::string &name() const { return m_name; } const std::string &name() const { return m_name; }
void set_name(const std::string &name) { m_name = name; } void set_name(const std::string &name) { m_name = name; }
...@@ -196,37 +191,37 @@ class Validator ...@@ -196,37 +191,37 @@ class Validator
private: private:
// name is fully qualified here: // name is fully qualified here:
ValidateItem *getValidatorForItem(std::string_view name) const; item_validator *get_validator_for_item(std::string_view name) const;
std::string m_name; std::string m_name;
std::string m_version; std::string m_version;
bool m_strict = false; bool m_strict = false;
std::set<ValidateType> mTypeValidators; std::set<type_validator> m_type_validators;
std::set<ValidateCategory> mCategoryValidators; std::set<category_validator> m_category_validators;
std::vector<ValidateLink> mLinkValidators; std::vector<link_validator> m_link_validators;
}; };
// -------------------------------------------------------------------- // --------------------------------------------------------------------
class ValidatorFactory class validator_factory
{ {
public: public:
static ValidatorFactory &instance() static validator_factory &instance()
{ {
static ValidatorFactory s_instance; static validator_factory s_instance;
return s_instance; return s_instance;
} }
const Validator &operator[](std::string_view dictionary_name); const validator &operator[](std::string_view dictionary_name);
private: private:
void construct_validator(std::string_view name, std::istream &is); void construct_validator(std::string_view name, std::istream &is);
// -------------------------------------------------------------------- // --------------------------------------------------------------------
ValidatorFactory() = default; validator_factory() = default;
std::mutex mMutex; std::mutex m_mutex;
std::list<Validator> mValidators; std::list<validator> m_validators;
}; };
} // namespace cif::v2 } // namespace cif::v2
...@@ -25,10 +25,371 @@ ...@@ -25,10 +25,371 @@
*/ */
#include <cif++/v2/category.hpp> #include <cif++/v2/category.hpp>
#include <cif++/v2/datablock.hpp>
namespace cif::v2 namespace cif::v2
{ {
template <typename V>
std::string join(const V &arr, std::string_view sep)
{
std::ostringstream s;
if (not arr.empty())
{
auto ai = arr.begin();
auto ni = std::next(ai);
for (;;)
{
s << *ai;
ai = ni;
ni = std::next(ai);
if (ni == arr.end())
break;
s << sep;
}
}
return s.str();
}
void category::set_validator(const validator *v, datablock &db)
{
m_validator = v;
// if (m_index != nullptr)
// {
// delete m_index;
// m_index = nullptr;
// }
if (m_validator != nullptr)
{
m_cat_validator = m_validator->get_validator_for_category(m_name);
// if (m_cat_validator != nullptr)
// {
// m_index = new CatIndex(this);
// m_index->reconstruct();
// //#if DEBUG
// // assert(m_index->size() == size());
// // m_index->validate();
// //#endif
// }
}
else
m_cat_validator = nullptr;
for (auto &&[column, cv] : m_columns)
cv = m_cat_validator ? m_cat_validator->get_validator_for_item(column) : nullptr;
update_links(db);
}
void category::update_links(datablock &db)
{
m_child_links.clear();
m_parent_links.clear();
if (m_validator != nullptr)
{
for (auto link : m_validator->get_links_for_parent(m_name))
{
auto childCat = db.get(link->m_child_category);
if (childCat == nullptr)
continue;
m_child_links.emplace_back(childCat, link);
}
for (auto link : m_validator->get_links_for_child(m_name))
{
auto parentCat = db.get(link->m_parent_category);
if (parentCat == nullptr)
continue;
m_parent_links.emplace_back(parentCat, link);
}
}
}
bool category::is_valid() const
{
bool result = true;
if (m_validator == nullptr)
throw std::runtime_error("no Validator specified");
if (empty())
{
if (VERBOSE > 2)
std::cerr << "Skipping validation of empty Category " << m_name << std::endl;
return true;
}
if (m_cat_validator == nullptr)
{
m_validator->report_error("undefined Category " + m_name, false);
return false;
}
auto mandatory = m_cat_validator->m_mandatory_fields;
for (auto &col : m_columns)
{
auto iv = m_cat_validator->get_validator_for_item(col.m_name);
if (iv == nullptr)
{
m_validator->report_error("Field " + col.m_name + " is not valid in Category " + m_name, false);
result = false;
}
// col.m_validator = iv;
if (col.m_validator != iv)
m_validator->report_error("Column validator is not specified correctly", true);
mandatory.erase(col.m_name);
}
if (not mandatory.empty())
{
m_validator->report_error("In Category " + m_name + " the following mandatory fields are missing: " + join(mandatory, ", "), false);
result = false;
}
//#if not defined(NDEBUG)
// // check index?
// if (m_index)
// {
// m_index->validate();
// for (auto r: *this)
// {
// if (m_index->find(r.mData) != r.mData)
// m_validator->report_error("Key not found in index for Category " + m_name);
// }
// }
//#endif
// validate all values
mandatory = m_cat_validator->m_mandatory_fields;
for (auto ri = m_head; ri != nullptr; ri = ri->m_next)
{
for (size_t cix = 0; cix < m_columns.size(); ++cix)
{
bool seen = false;
auto iv = m_columns[cix].m_validator;
if (iv == nullptr)
{
m_validator->report_error("invalid field " + m_columns[cix].m_name + " for Category " + m_name, false);
result = false;
continue;
}
for (auto vi = ri->m_head; vi != nullptr; vi = vi->m_next)
{
if (vi->m_column_ix == cix)
{
seen = true;
try
{
(*iv)(vi->text());
}
catch (const std::exception &e)
{
m_validator->report_error("Error validating " + m_columns[cix].m_name + ": " + e.what(), false);
continue;
}
}
}
if (seen or ri != m_head)
continue;
if (iv != nullptr and iv->m_mandatory)
{
m_validator->report_error("missing mandatory field " + m_columns[cix].m_name + " for Category " + m_name, false);
result = false;
}
}
}
return result;
}
category::iterator category::erase(iterator pos)
{
row_handle rh = *pos;
row *r = rh;
iterator result = ++pos;
iset keys;
if (m_cat_validator)
keys = iset(m_cat_validator->m_keys.begin(), m_cat_validator->m_keys.end());
if (m_head == nullptr)
throw std::runtime_error("erase");
// if (mIndex != nullptr)
// mIndex->erase(r.mData);
if (r == m_head)
{
m_head = m_head->m_next;
r->m_next = nullptr;
}
else
{
for (auto pi = m_head; pi != nullptr; pi = pi->m_next)
{
if (pi->m_next == r)
{
pi->m_next = r->m_next;
r->m_next = nullptr;
break;
}
}
}
// links are created based on the _pdbx_item_linked_group_list entries
// in mmcif_pdbx_v50.dic dictionary.
//
// For each link group in _pdbx_item_linked_group_list
// a std::set of keys from one category is mapped to another.
// If all values in a child are the same as the specified parent ones
// the child is removed as well, recursively of course.
if (m_validator != nullptr)
{
for (auto &&[childCat, link] : m_child_links)
{
condition cond;
for (size_t ix = 0; ix < link->m_parent_keys.size(); ++ix)
{
std::string_view value = rh[link->m_parent_keys[ix]].text();
cond = std::move(cond) and (key(link->m_child_keys[ix]) == value);
}
childCat->erase_orphans(std::move(cond));
}
}
delete_row(r);
// reset mTail, if needed
if (r == m_tail)
{
m_tail = m_head;
if (m_tail != nullptr)
while (m_tail->m_next != nullptr)
m_tail = m_tail->m_next;
}
return result;
}
size_t category::erase(condition &&cond)
{
size_t result = 0;
cond.prepare(*this);
auto ri = begin();
while (ri != end())
{
if (cond(*ri))
{
ri = erase(ri);
++result;
}
else
++ri;
}
return result;
}
size_t category::erase(condition &&cond, std::function<void(row_handle)> &&visit)
{
size_t result = 0;
cond.prepare(*this);
auto ri = begin();
while (ri != end())
{
if (cond(*ri))
{
visit(*ri);
ri = erase(ri);
++result;
}
else
++ri;
}
return result;
}
bool category::is_orphan(row_handle r) const
{
// be safe
if (m_cat_validator == nullptr)
return false;
bool isOrphan = true;
for (auto &&[parentCat, link] : m_parent_links)
{
condition cond;
for (size_t ix = 0; ix < link->m_child_keys.size(); ++ix)
{
std::string_view value = r[link->m_child_keys[ix]].text();
cond = std::move(cond) and (key(link->m_parent_keys[ix]) == value);
}
// if (VERBOSE > 2)
// std::cerr << "Check condition '" << cond << "' in parent category " << link->mParentCategory << " for child cat " << mName << std::endl;
if (parentCat->exists(std::move(cond)))
{
if (VERBOSE > 2)
std::cerr << "Not removing because row has a parent in category " << link->m_parent_category << std::endl;
isOrphan = false;
break;
}
}
return isOrphan;
}
void category::erase_orphans(condition &&cond)
{
std::vector<row *> remove;
cond.prepare(*this);
for (auto r : *this)
{
if (cond(r) and is_orphan(r))
{
if (VERBOSE > 1)
std::cerr << "Removing orphaned record: " << std::endl
<< r << std::endl
<< std::endl;
remove.push_back(r);
}
}
for (auto r : remove)
erase(iterator(*this, r));
}
void category::update_value(row *row, size_t column, std::string_view value, bool updateLinked, bool validate) void category::update_value(row *row, size_t column, std::string_view value, bool updateLinked, bool validate)
{ {
auto &col = m_columns[column]; auto &col = m_columns[column];
...@@ -50,9 +411,9 @@ void category::update_value(row *row, size_t column, std::string_view value, boo ...@@ -50,9 +411,9 @@ void category::update_value(row *row, size_t column, std::string_view value, boo
std::string oldStrValue = oldValue ? oldValue : ""; std::string oldStrValue = oldValue ? oldValue : "";
// // check the value // check the value
// if (col.m_validator and validate) if (col.m_validator and validate)
// (*col.m_validator)(value); col.m_validator->operator()(value);
// If the field is part of the Key for this Category, remove it from the index // If the field is part of the Key for this Category, remove it from the index
// before updating // before updating
...@@ -60,11 +421,11 @@ void category::update_value(row *row, size_t column, std::string_view value, boo ...@@ -60,11 +421,11 @@ void category::update_value(row *row, size_t column, std::string_view value, boo
bool reinsert = false; bool reinsert = false;
// if (updateLinked and // an update of an Item's value // if (updateLinked and // an update of an Item's value
// cat->mIndex != nullptr and cat->keyFieldsByIndex().count(column)) // cat->m_index != nullptr and cat->keyFieldsByIndex().count(column))
// { // {
// reinsert = cat->mIndex->find(mData); // reinsert = cat->m_index->find(mData);
// if (reinsert) // if (reinsert)
// cat->mIndex->erase(mData); // cat->m_index->erase(mData);
// } // }
// first remove old value with cix // first remove old value with cix
...@@ -112,87 +473,89 @@ void category::update_value(row *row, size_t column, std::string_view value, boo ...@@ -112,87 +473,89 @@ void category::update_value(row *row, size_t column, std::string_view value, boo
// if (reinsert) // if (reinsert)
// cat->mIndex->insert(mData); // cat->mIndex->insert(mData);
// // see if we need to update any child categories that depend on this value // see if we need to update any child categories that depend on this value
// auto iv = col.m_validator; auto iv = col.m_validator;
// if (not skipUpdateLinked and iv != nullptr and mCascade) if (updateLinked and iv != nullptr /*and m_cascade*/)
// { {
// for (auto &&[childCat, linked] : cat->mChildLinks) row_handle rh(*this, *row);
// {
// if (find(linked->mParentKeys.begin(), linked->mParentKeys.end(), iv->mTag) == linked->mParentKeys.end())
// continue;
// Condition cond; for (auto &&[childCat, linked] : m_child_links)
// std::string childTag; {
if (std::find(linked->m_parent_keys.begin(), linked->m_parent_keys.end(), iv->m_tag) == linked->m_parent_keys.end())
continue;
// for (size_t ix = 0; ix < linked->mParentKeys.size(); ++ix) condition cond;
// { std::string childTag;
// std::string pk = linked->mParentKeys[ix];
// std::string ck = linked->mChildKeys[ix];
// // TODO add code to *NOT* test mandatory fields for Empty for (size_t ix = 0; ix < linked->m_parent_keys.size(); ++ix)
{
std::string pk = linked->m_parent_keys[ix];
std::string ck = linked->m_child_keys[ix];
// if (pk == iv->mTag) // TODO add code to *NOT* test mandatory fields for Empty
// {
// 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 (pk == iv->m_tag)
// if (rows.empty()) {
// continue; childTag = ck;
cond = std::move(cond) and key(ck) == oldStrValue;
}
else
{
std::string_view pk_value = rh[pk].text();
if (pk_value.empty())
cond = std::move(cond) and key(ck) == null;
else
cond = std::move(cond) and ((key(ck) == pk_value) or key(ck) == null);
}
}
// // if (cif::VERBOSE > 2) auto rows = childCat->find(std::move(cond));
// // { if (rows.empty())
// // std::cerr << "Parent: " << linked->mParentCategory << " Child: " << linked->mChildCategory << std::endl continue;
// // << cond << std::endl;
// // }
// // Now, suppose there are already rows in child that conform to the new value, // if (cif::VERBOSE > 2)
// // we then skip this renam // {
// std::cerr << "Parent: " << linked->mParentCategory << " Child: " << linked->mChildCategory << std::endl
// << cond << std::endl;
// }
// Condition cond_n; // Now, suppose there are already rows in child that conform to the new value,
// we then skip this renam
// for (size_t ix = 0; ix < linked->mParentKeys.size(); ++ix) condition cond_n;
// {
// std::string pk = linked->mParentKeys[ix];
// std::string ck = linked->mChildKeys[ix];
// // TODO add code to *NOT* test mandatory fields for Empty for (size_t ix = 0; ix < linked->m_parent_keys.size(); ++ix)
{
std::string pk = linked->m_parent_keys[ix];
std::string ck = linked->m_child_keys[ix];
// if (pk == iv->mTag) // TODO add code to *NOT* test mandatory fields for Empty
// 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 (pk == iv->m_tag)
// if (not rows_n.empty()) cond_n = std::move(cond_n) and key(ck) == value;
// { else
// if (cif::VERBOSE > 0) {
// std::cerr << "Will not rename in child category since there are already rows that link to the parent" << std::endl; std::string_view pk_value = rh[pk].text();
if (pk_value.empty())
cond_n = std::move(cond_n) and key(ck) == null;
else
cond_n = std::move(cond_n) and ((key(ck) == pk_value) or key(ck) == null);
}
}
// continue; 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;
// for (auto &cr : rows) continue;
// cr.assign(childTag, value, false); }
// }
// } for (auto cr : rows)
cr.assign(childTag, value, false);
}
}
} }
// proxy methods for every insertion // proxy methods for every insertion
......
...@@ -47,11 +47,11 @@ bool is_column_type_uchar(const category &cat, std::string_view col) ...@@ -47,11 +47,11 @@ bool is_column_type_uchar(const category &cat, std::string_view col)
auto cv = cat.get_cat_validator(); auto cv = cat.get_cat_validator();
if (cv) if (cv)
{ {
auto iv = cv->getValidatorForItem(col); auto iv = cv->get_validator_for_item(col);
if (iv != nullptr and iv->mType != nullptr) if (iv != nullptr and iv->m_type != nullptr)
{ {
auto type = iv->mType; auto type = iv->m_type;
result = type->mPrimitiveType == DDL_PrimitiveType::UChar; result = type->m_primitive_type == DDL_PrimitiveType::UChar;
} }
} }
......
...@@ -43,7 +43,7 @@ inline void replace_all(std::string &s, std::string_view pat, std::string_view r ...@@ -43,7 +43,7 @@ inline void replace_all(std::string &s, std::string_view pat, std::string_view r
class dictionary_parser : public parser class dictionary_parser : public parser
{ {
public: public:
dictionary_parser(Validator &validator, std::istream &is, file &f) dictionary_parser(validator &validator, std::istream &is, file &f)
: parser(is, f) : parser(is, f)
, m_validator(validator) , m_validator(validator)
{ {
...@@ -83,17 +83,17 @@ class dictionary_parser : public parser ...@@ -83,17 +83,17 @@ class dictionary_parser : public parser
// store all validators // store all validators
for (auto &ic : mCategoryValidators) for (auto &ic : mCategoryValidators)
m_validator.addCategoryValidator(std::move(ic)); m_validator.add_category_validator(std::move(ic));
mCategoryValidators.clear(); mCategoryValidators.clear();
for (auto &iv : mItemValidators) for (auto &iv : mItemValidators)
{ {
auto cv = m_validator.getValidatorForCategory(iv.first); auto cv = m_validator.get_validator_for_category(iv.first);
if (cv == nullptr) if (cv == nullptr)
error("Undefined category '" + iv.first); error("Undefined category '" + iv.first);
for (auto &v : iv.second) for (auto &v : iv.second)
const_cast<ValidateCategory *>(cv)->addItemValidator(std::move(v)); const_cast<category_validator *>(cv)->addItemValidator(std::move(v));
} }
// check all item validators for having a typeValidator // check all item validators for having a typeValidator
...@@ -145,15 +145,15 @@ class dictionary_parser : public parser ...@@ -145,15 +145,15 @@ class dictionary_parser : public parser
std::vector<std::string> tags; std::vector<std::string> tags;
while (m_lookahead == CIFToken::Tag) while (m_lookahead == CIFToken::Tag)
{ {
std::string catName, itemName; std::string catName, item_name;
std::tie(catName, itemName) = splitTagName(m_token_value); std::tie(catName, item_name) = splitTagName(m_token_value);
if (cat == dict.end()) if (cat == dict.end())
std::tie(cat, std::ignore) = dict.emplace(catName); std::tie(cat, std::ignore) = dict.emplace(catName);
else if (not iequals(cat->name(), catName)) else if (not iequals(cat->name(), catName))
error("inconsistent categories in loop_"); error("inconsistent categories in loop_");
tags.push_back(itemName); tags.push_back(item_name);
match(CIFToken::Tag); match(CIFToken::Tag);
} }
...@@ -173,8 +173,8 @@ class dictionary_parser : public parser ...@@ -173,8 +173,8 @@ class dictionary_parser : public parser
} }
else else
{ {
std::string catName, itemName; std::string catName, item_name;
std::tie(catName, itemName) = splitTagName(m_token_value); std::tie(catName, item_name) = splitTagName(m_token_value);
if (cat == dict.end() or not iequals(cat->name(), catName)) if (cat == dict.end() or not iequals(cat->name(), catName))
std::tie(cat, std::ignore) = dict.emplace(catName); std::tie(cat, std::ignore) = dict.emplace(catName);
...@@ -183,7 +183,7 @@ class dictionary_parser : public parser ...@@ -183,7 +183,7 @@ class dictionary_parser : public parser
if (cat->empty()) if (cat->empty())
cat->emplace({}); cat->emplace({});
cat->back()[itemName] = m_token_value; cat->back()[item_name] = m_token_value;
match(CIFToken::Value); match(CIFToken::Value);
} }
...@@ -204,7 +204,7 @@ class dictionary_parser : public parser ...@@ -204,7 +204,7 @@ class dictionary_parser : public parser
for (auto g : dict["category_group"]) for (auto g : dict["category_group"])
groups.insert(g["id"].as<std::string>()); groups.insert(g["id"].as<std::string>());
mCategoryValidators.push_back(ValidateCategory{category, keys, groups}); mCategoryValidators.push_back(category_validator{category, keys, groups});
} }
else else
{ {
...@@ -212,9 +212,9 @@ class dictionary_parser : public parser ...@@ -212,9 +212,9 @@ class dictionary_parser : public parser
std::string typeCode; std::string typeCode;
cif::v2::tie(typeCode) = dict["item_type"].front().get("code"); cif::v2::tie(typeCode) = dict["item_type"].front().get("code");
const ValidateType *tv = nullptr; const type_validator *tv = nullptr;
if (not(typeCode.empty() or typeCode == "?")) if (not(typeCode.empty() or typeCode == "?"))
tv = m_validator.getValidatorForType(typeCode); tv = m_validator.get_validator_for_type(typeCode);
iset ess; iset ess;
for (auto e : dict["item_enumeration"]) for (auto e : dict["item_enumeration"])
...@@ -240,10 +240,10 @@ class dictionary_parser : public parser ...@@ -240,10 +240,10 @@ class dictionary_parser : public parser
cif::v2::tie(tagName, category, mandatory) = i.get("name", "category_id", "mandatory_code"); cif::v2::tie(tagName, category, mandatory) = i.get("name", "category_id", "mandatory_code");
std::string catName, itemName; std::string catName, item_name;
std::tie(catName, itemName) = splitTagName(tagName); std::tie(catName, item_name) = splitTagName(tagName);
if (catName.empty() or itemName.empty()) if (catName.empty() or item_name.empty())
error("Invalid tag name in _item.name " + tagName); error("Invalid tag name in _item.name " + tagName);
if (not iequals(category, catName) and not(category.empty() or category == "?")) if (not iequals(category, catName) and not(category.empty() or category == "?"))
...@@ -253,13 +253,13 @@ class dictionary_parser : public parser ...@@ -253,13 +253,13 @@ class dictionary_parser : public parser
auto &ivs = mItemValidators[category]; auto &ivs = mItemValidators[category];
auto vi = find(ivs.begin(), ivs.end(), ValidateItem{itemName}); auto vi = find(ivs.begin(), ivs.end(), item_validator{item_name});
if (vi == ivs.end()) if (vi == ivs.end())
ivs.push_back(ValidateItem{itemName, iequals(mandatory, "yes"), tv, ess, defaultValue, defaultIsNull}); ivs.push_back(item_validator{item_name, iequals(mandatory, "yes"), tv, ess, defaultValue, defaultIsNull});
else else
{ {
// need to update the itemValidator? // need to update the itemValidator?
if (vi->mMandatory != (iequals(mandatory, "yes"))) if (vi->m_mandatory != (iequals(mandatory, "yes")))
{ {
if (VERBOSE > 2) if (VERBOSE > 2)
{ {
...@@ -268,24 +268,24 @@ class dictionary_parser : public parser ...@@ -268,24 +268,24 @@ class dictionary_parser : public parser
if (iequals(tagName, saveFrameName)) if (iequals(tagName, saveFrameName))
std::cerr << "choosing " << mandatory << std::endl; std::cerr << "choosing " << mandatory << std::endl;
else else
std::cerr << "choosing " << (vi->mMandatory ? "Y" : "N") << std::endl; std::cerr << "choosing " << (vi->m_mandatory ? "Y" : "N") << std::endl;
} }
if (iequals(tagName, saveFrameName)) if (iequals(tagName, saveFrameName))
vi->mMandatory = (iequals(mandatory, "yes")); vi->m_mandatory = (iequals(mandatory, "yes"));
} }
if (vi->mType != nullptr and tv != nullptr and vi->mType != tv) if (vi->m_type != nullptr and tv != nullptr and vi->m_type != tv)
{ {
if (VERBOSE > 1) if (VERBOSE > 1)
std::cerr << "inconsistent type for " << tagName << " in dictionary" << std::endl; std::cerr << "inconsistent type for " << tagName << " in dictionary" << std::endl;
} }
// vi->mMandatory = (iequals(mandatory, "yes")); // vi->mMandatory = (iequals(mandatory, "yes"));
if (vi->mType == nullptr) if (vi->m_type == nullptr)
vi->mType = tv; vi->m_type = tv;
vi->mEnums.insert(ess.begin(), ess.end()); vi->m_enums.insert(ess.begin(), ess.end());
// anything else yet? // anything else yet?
// ... // ...
...@@ -349,15 +349,15 @@ class dictionary_parser : public parser ...@@ -349,15 +349,15 @@ class dictionary_parser : public parser
int link_group_id; int link_group_id;
cif::v2::tie(child, parent, link_group_id) = gl.get("child_name", "parent_name", "link_group_id"); cif::v2::tie(child, parent, link_group_id) = gl.get("child_name", "parent_name", "link_group_id");
auto civ = m_validator.getValidatorForItem(child); auto civ = m_validator.get_validator_for_item(child);
if (civ == nullptr) if (civ == nullptr)
error("in pdbx_item_linked_group_list, item '" + child + "' is not specified"); error("in pdbx_item_linked_group_list, item '" + child + "' is not specified");
auto piv = m_validator.getValidatorForItem(parent); auto piv = m_validator.get_validator_for_item(parent);
if (piv == nullptr) if (piv == nullptr)
error("in pdbx_item_linked_group_list, item '" + parent + "' is not specified"); error("in pdbx_item_linked_group_list, item '" + parent + "' is not specified");
key_type key{piv->mCategory->mName, civ->mCategory->mName, link_group_id}; key_type key{piv->m_category->m_name, civ->m_category->m_name, link_group_id};
if (not linkIndex.count(key)) if (not linkIndex.count(key))
{ {
linkIndex[key] = linkKeys.size(); linkIndex[key] = linkKeys.size();
...@@ -365,7 +365,7 @@ class dictionary_parser : public parser ...@@ -365,7 +365,7 @@ class dictionary_parser : public parser
} }
size_t ix = linkIndex.at(key); size_t ix = linkIndex.at(key);
addLink(ix, piv->mTag, civ->mTag); addLink(ix, piv->m_tag, civ->m_tag);
} }
// Only process inline linked items if the linked group list is absent // Only process inline linked items if the linked group list is absent
...@@ -377,15 +377,15 @@ class dictionary_parser : public parser ...@@ -377,15 +377,15 @@ class dictionary_parser : public parser
std::string child, parent; std::string child, parent;
std::tie(child, parent) = li; std::tie(child, parent) = li;
auto civ = m_validator.getValidatorForItem(child); auto civ = m_validator.get_validator_for_item(child);
if (civ == nullptr) if (civ == nullptr)
error("in pdbx_item_linked_group_list, item '" + child + "' is not specified"); error("in pdbx_item_linked_group_list, item '" + child + "' is not specified");
auto piv = m_validator.getValidatorForItem(parent); auto piv = m_validator.get_validator_for_item(parent);
if (piv == nullptr) if (piv == nullptr)
error("in pdbx_item_linked_group_list, item '" + parent + "' is not specified"); error("in pdbx_item_linked_group_list, item '" + parent + "' is not specified");
key_type key{piv->mCategory->mName, civ->mCategory->mName, 0}; key_type key{piv->m_category->m_name, civ->m_category->m_name, 0};
if (not linkIndex.count(key)) if (not linkIndex.count(key))
{ {
linkIndex[key] = linkKeys.size(); linkIndex[key] = linkKeys.size();
...@@ -393,7 +393,7 @@ class dictionary_parser : public parser ...@@ -393,7 +393,7 @@ class dictionary_parser : public parser
} }
size_t ix = linkIndex.at(key); size_t ix = linkIndex.at(key);
addLink(ix, piv->mTag, civ->mTag); addLink(ix, piv->m_tag, civ->m_tag);
} }
} }
...@@ -402,29 +402,29 @@ class dictionary_parser : public parser ...@@ -402,29 +402,29 @@ class dictionary_parser : public parser
// now store the links in the validator // now store the links in the validator
for (auto &kv : linkIndex) for (auto &kv : linkIndex)
{ {
ValidateLink link = {}; link_validator link = {};
std::tie(link.mParentCategory, link.mChildCategory, link.mLinkGroupID) = kv.first; std::tie(link.m_parent_category, link.m_child_category, link.m_link_group_id) = kv.first;
std::tie(link.mParentKeys, link.mChildKeys) = linkKeys[kv.second]; std::tie(link.m_parent_keys, link.m_child_keys) = linkKeys[kv.second];
// look up the label // look up the label
for (auto r : linkedGroup.find("category_id"_key == link.mChildCategory and "link_group_id"_key == link.mLinkGroupID)) for (auto r : linkedGroup.find("category_id"_key == link.m_child_category and "link_group_id"_key == link.m_link_group_id))
{ {
link.mLinkGroupLabel = r["label"].as<std::string>(); link.m_link_group_label = r["label"].as<std::string>();
break; break;
} }
m_validator.addLinkValidator(std::move(link)); m_validator.add_link_validator(std::move(link));
} }
// now make sure the itemType is specified for all itemValidators // now make sure the itemType is specified for all itemValidators
for (auto &cv : m_validator.mCategoryValidators) for (auto &cv : m_validator.m_category_validators)
{ {
for (auto &iv : cv.mItemValidators) for (auto &iv : cv.m_item_validators)
{ {
if (iv.mType == nullptr and cif::VERBOSE >= 0) if (iv.m_type == nullptr and cif::VERBOSE >= 0)
std::cerr << "Missing item_type for " << iv.mTag << std::endl; std::cerr << "Missing item_type for " << iv.m_tag << std::endl;
} }
} }
} }
...@@ -449,10 +449,10 @@ class dictionary_parser : public parser ...@@ -449,10 +449,10 @@ class dictionary_parser : public parser
try try
{ {
ValidateType v = { type_validator v = {
code, mapToPrimitiveType(primitiveCode), boost::regex(construct, boost::regex::extended | boost::regex::optimize)}; code, map_to_primitive_type(primitiveCode), boost::regex(construct, boost::regex::extended | boost::regex::optimize)};
m_validator.addTypeValidator(std::move(v)); m_validator.add_type_validator(std::move(v));
} }
catch (const std::exception &) catch (const std::exception &)
{ {
...@@ -473,19 +473,19 @@ class dictionary_parser : public parser ...@@ -473,19 +473,19 @@ class dictionary_parser : public parser
return result; return result;
} }
Validator &m_validator; validator &m_validator;
bool m_collected_item_types = false; bool m_collected_item_types = false;
std::vector<ValidateCategory> mCategoryValidators; std::vector<category_validator> mCategoryValidators;
std::map<std::string, std::vector<ValidateItem>> mItemValidators; std::map<std::string, std::vector<item_validator>> mItemValidators;
std::set<std::tuple<std::string, std::string>> mLinkedItems; std::set<std::tuple<std::string, std::string>> mLinkedItems;
}; };
// -------------------------------------------------------------------- // --------------------------------------------------------------------
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);
file f; file f;
dictionary_parser p(result, is, f); dictionary_parser p(result, is, f);
......
...@@ -31,13 +31,21 @@ namespace cif::v2 ...@@ -31,13 +31,21 @@ namespace cif::v2
std::string_view item_handle::text() const std::string_view item_handle::text() const
{ {
if (m_row_handle.m_row != nullptr)
{
for (auto iv = m_row_handle.m_row->m_head; iv != nullptr; iv = iv->m_next) for (auto iv = m_row_handle.m_row->m_head; iv != nullptr; iv = iv->m_next)
{ {
if (iv->m_column_ix == m_column) if (iv->m_column_ix == m_column)
return iv->text(); return iv->text();
} }
}
return {}; return {};
} }
void item_handle::assign_value(const item &v)
{
m_row_handle.assign(m_column, v.value(), false);
}
} }
...@@ -28,8 +28,8 @@ ...@@ -28,8 +28,8 @@
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
#include <cif++/v2/validate.hpp>
#include <cif++/v2/dictionary_parser.hpp> #include <cif++/v2/dictionary_parser.hpp>
#include <cif++/v2/validate.hpp>
namespace cif namespace cif
{ {
...@@ -41,19 +41,19 @@ namespace cif::v2 ...@@ -41,19 +41,19 @@ namespace cif::v2
using cif::VERBOSE; using cif::VERBOSE;
ValidationError::ValidationError(const std::string &msg) validation_error::validation_error(const std::string &msg)
: mMsg(msg) : m_msg(msg)
{ {
} }
ValidationError::ValidationError(const std::string &cat, const std::string &item, const std::string &msg) validation_error::validation_error(const std::string &cat, const std::string &item, const std::string &msg)
: mMsg("When validating _" + cat + '.' + item + ": " + msg) : m_msg("When validating _" + cat + '.' + item + ": " + msg)
{ {
} }
// -------------------------------------------------------------------- // --------------------------------------------------------------------
DDL_PrimitiveType mapToPrimitiveType(std::string_view s) DDL_PrimitiveType map_to_primitive_type(std::string_view s)
{ {
DDL_PrimitiveType result; DDL_PrimitiveType result;
if (iequals(s, "char")) if (iequals(s, "char"))
...@@ -63,13 +63,13 @@ DDL_PrimitiveType mapToPrimitiveType(std::string_view s) ...@@ -63,13 +63,13 @@ DDL_PrimitiveType mapToPrimitiveType(std::string_view s)
else if (iequals(s, "numb")) else if (iequals(s, "numb"))
result = DDL_PrimitiveType::Numb; result = DDL_PrimitiveType::Numb;
else else
throw ValidationError("Not a known primitive type"); throw validation_error("Not a known primitive type");
return result; return result;
} }
// -------------------------------------------------------------------- // --------------------------------------------------------------------
int ValidateType::compare(const char *a, const char *b) const int type_validator::compare(const char *a, const char *b) const
{ {
int result = 0; int result = 0;
...@@ -81,7 +81,7 @@ int ValidateType::compare(const char *a, const char *b) const ...@@ -81,7 +81,7 @@ int ValidateType::compare(const char *a, const char *b) const
{ {
try try
{ {
switch (mPrimitiveType) switch (m_primitive_type)
{ {
case DDL_PrimitiveType::Numb: case DDL_PrimitiveType::Numb:
{ {
...@@ -123,7 +123,7 @@ int ValidateType::compare(const char *a, const char *b) const ...@@ -123,7 +123,7 @@ int ValidateType::compare(const char *a, const char *b) const
char ca = *ai; char ca = *ai;
char cb = *bi; char cb = *bi;
if (mPrimitiveType == DDL_PrimitiveType::UChar) if (m_primitive_type == DDL_PrimitiveType::UChar)
{ {
ca = tolower(ca); ca = tolower(ca);
cb = tolower(cb); cb = tolower(cb);
...@@ -161,10 +161,10 @@ int ValidateType::compare(const char *a, const char *b) const ...@@ -161,10 +161,10 @@ int ValidateType::compare(const char *a, const char *b) const
// -------------------------------------------------------------------- // --------------------------------------------------------------------
//void ValidateItem::addLinked(ValidateItem* parent, const std::string& parentItem, const std::string& childItem) // void ValidateItem::addLinked(ValidateItem* parent, const std::string& parentItem, const std::string& childItem)
//{ //{
//// if (mParent != nullptr and VERBOSE) //// if (mParent != nullptr and VERBOSE)
//// cerr << "replacing parent in " << mCategory->mName << " from " << mParent->mCategory->mName << " to " << parent->mCategory->mName << endl; //// cerr << "replacing parent in " << mCategory->m_name << " from " << mParent->mCategory->m_name << " to " << parent->mCategory->m_name << endl;
//// mParent = parent; //// mParent = parent;
// //
// if (mType == nullptr and parent != nullptr) // if (mType == nullptr and parent != nullptr)
...@@ -181,40 +181,40 @@ int ValidateType::compare(const char *a, const char *b) const ...@@ -181,40 +181,40 @@ int ValidateType::compare(const char *a, const char *b) const
// } // }
//} //}
void ValidateItem::operator()(std::string value) const void item_validator::operator()(std::string_view value) const
{ {
if (not value.empty() and value != "?" and value != ".") if (not value.empty() and value != "?" and value != ".")
{ {
if (mType != nullptr and not regex_match(value, mType->mRx)) if (m_type != nullptr and not regex_match(value.begin(), value.end(), m_type->m_rx))
throw ValidationError(mCategory->mName, mTag, "Value '" + value + "' does not match type expression for type " + mType->mName); throw validation_error(m_category->m_name, m_tag, "Value '" + std::string{value} + "' does not match type expression for type " + m_type->m_name);
if (not mEnums.empty()) if (not m_enums.empty())
{ {
if (mEnums.count(value) == 0) if (m_enums.count(std::string{value}) == 0)
throw ValidationError(mCategory->mName, mTag, "Value '" + value + "' is not in the list of allowed values"); throw validation_error(m_category->m_name, m_tag, "Value '" + std::string{value} + "' is not in the list of allowed values");
} }
} }
} }
// -------------------------------------------------------------------- // --------------------------------------------------------------------
void ValidateCategory::addItemValidator(ValidateItem &&v) void category_validator::addItemValidator(item_validator &&v)
{ {
if (v.mMandatory) if (v.m_mandatory)
mMandatoryFields.insert(v.mTag); m_mandatory_fields.insert(v.m_tag);
v.mCategory = this; v.m_category = this;
auto r = mItemValidators.insert(std::move(v)); auto r = m_item_validators.insert(std::move(v));
if (not r.second and VERBOSE >= 4) if (not r.second and VERBOSE >= 4)
std::cout << "Could not add validator for item " << v.mTag << " to category " << mName << std::endl; std::cout << "Could not add validator for item " << v.m_tag << " to category " << m_name << std::endl;
} }
const ValidateItem *ValidateCategory::getValidatorForItem(std::string_view tag) const const item_validator *category_validator::get_validator_for_item(std::string_view tag) const
{ {
const ValidateItem *result = nullptr; const item_validator *result = nullptr;
auto i = mItemValidators.find(ValidateItem{std::string(tag)}); auto i = m_item_validators.find(item_validator{std::string(tag)});
if (i != mItemValidators.end()) if (i != m_item_validators.end())
result = &*i; result = &*i;
else if (VERBOSE > 4) else if (VERBOSE > 4)
std::cout << "No validator for tag " << tag << std::endl; std::cout << "No validator for tag " << tag << std::endl;
...@@ -223,53 +223,53 @@ const ValidateItem *ValidateCategory::getValidatorForItem(std::string_view tag) ...@@ -223,53 +223,53 @@ const ValidateItem *ValidateCategory::getValidatorForItem(std::string_view tag)
// -------------------------------------------------------------------- // --------------------------------------------------------------------
void Validator::addTypeValidator(ValidateType &&v) void validator::add_type_validator(type_validator &&v)
{ {
auto r = mTypeValidators.insert(std::move(v)); auto r = m_type_validators.insert(std::move(v));
if (not r.second and VERBOSE > 4) if (not r.second and VERBOSE > 4)
std::cout << "Could not add validator for type " << v.mName << std::endl; std::cout << "Could not add validator for type " << v.m_name << std::endl;
} }
const ValidateType *Validator::getValidatorForType(std::string_view typeCode) const const type_validator *validator::get_validator_for_type(std::string_view typeCode) const
{ {
const ValidateType *result = nullptr; const type_validator *result = nullptr;
auto i = mTypeValidators.find(ValidateType{std::string(typeCode), DDL_PrimitiveType::Char, boost::regex()}); auto i = m_type_validators.find(type_validator{std::string(typeCode), DDL_PrimitiveType::Char, boost::regex()});
if (i != mTypeValidators.end()) if (i != m_type_validators.end())
result = &*i; result = &*i;
else if (VERBOSE > 4) else if (VERBOSE > 4)
std::cout << "No validator for type " << typeCode << std::endl; std::cout << "No validator for type " << typeCode << std::endl;
return result; return result;
} }
void Validator::addCategoryValidator(ValidateCategory &&v) void validator::add_category_validator(category_validator &&v)
{ {
auto r = mCategoryValidators.insert(std::move(v)); auto r = m_category_validators.insert(std::move(v));
if (not r.second and VERBOSE > 4) if (not r.second and VERBOSE > 4)
std::cout << "Could not add validator for category " << v.mName << std::endl; std::cout << "Could not add validator for category " << v.m_name << std::endl;
} }
const ValidateCategory *Validator::getValidatorForCategory(std::string_view category) const const category_validator *validator::get_validator_for_category(std::string_view category) const
{ {
const ValidateCategory *result = nullptr; const category_validator *result = nullptr;
auto i = mCategoryValidators.find(ValidateCategory{std::string(category)}); auto i = m_category_validators.find(category_validator{std::string(category)});
if (i != mCategoryValidators.end()) if (i != m_category_validators.end())
result = &*i; result = &*i;
else if (VERBOSE > 4) else if (VERBOSE > 4)
std::cout << "No validator for category " << category << std::endl; std::cout << "No validator for category " << category << std::endl;
return result; return result;
} }
ValidateItem *Validator::getValidatorForItem(std::string_view tag) const item_validator *validator::get_validator_for_item(std::string_view tag) const
{ {
ValidateItem *result = nullptr; item_validator *result = nullptr;
std::string cat, item; std::string cat, item;
std::tie(cat, item) = splitTagName(tag); std::tie(cat, item) = splitTagName(tag);
auto *cv = getValidatorForCategory(cat); auto *cv = get_validator_for_category(cat);
if (cv != nullptr) if (cv != nullptr)
result = const_cast<ValidateItem *>(cv->getValidatorForItem(item)); result = const_cast<item_validator *>(cv->get_validator_for_item(item));
if (result == nullptr and VERBOSE > 4) if (result == nullptr and VERBOSE > 4)
std::cout << "No validator for item " << tag << std::endl; std::cout << "No validator for item " << tag << std::endl;
...@@ -277,80 +277,80 @@ ValidateItem *Validator::getValidatorForItem(std::string_view tag) const ...@@ -277,80 +277,80 @@ ValidateItem *Validator::getValidatorForItem(std::string_view tag) const
return result; return result;
} }
void Validator::addLinkValidator(ValidateLink &&v) void validator::add_link_validator(link_validator &&v)
{ {
assert(v.mParentKeys.size() == v.mChildKeys.size()); assert(v.m_parent_keys.size() == v.m_child_keys.size());
if (v.mParentKeys.size() != v.mChildKeys.size()) if (v.m_parent_keys.size() != v.m_child_keys.size())
throw std::runtime_error("unequal number of keys for parent and child in link"); throw std::runtime_error("unequal number of keys for parent and child in link");
auto pcv = getValidatorForCategory(v.mParentCategory); auto pcv = get_validator_for_category(v.m_parent_category);
auto ccv = getValidatorForCategory(v.mChildCategory); auto ccv = get_validator_for_category(v.m_child_category);
if (pcv == nullptr) if (pcv == nullptr)
throw std::runtime_error("unknown parent category " + v.mParentCategory); throw std::runtime_error("unknown parent category " + v.m_parent_category);
if (ccv == nullptr) if (ccv == nullptr)
throw std::runtime_error("unknown child category " + v.mChildCategory); throw std::runtime_error("unknown child category " + v.m_child_category);
for (size_t i = 0; i < v.mParentKeys.size(); ++i) for (size_t i = 0; i < v.m_parent_keys.size(); ++i)
{ {
auto piv = pcv->getValidatorForItem(v.mParentKeys[i]); auto piv = pcv->get_validator_for_item(v.m_parent_keys[i]);
if (piv == nullptr) if (piv == nullptr)
throw std::runtime_error("unknown parent tag _" + v.mParentCategory + '.' + v.mParentKeys[i]); throw std::runtime_error("unknown parent tag _" + v.m_parent_category + '.' + v.m_parent_keys[i]);
auto civ = ccv->getValidatorForItem(v.mChildKeys[i]); auto civ = ccv->get_validator_for_item(v.m_child_keys[i]);
if (civ == nullptr) if (civ == nullptr)
throw std::runtime_error("unknown child tag _" + v.mChildCategory + '.' + v.mChildKeys[i]); throw std::runtime_error("unknown child tag _" + v.m_child_category + '.' + v.m_child_keys[i]);
if (civ->mType == nullptr and piv->mType != nullptr) if (civ->m_type == nullptr and piv->m_type != nullptr)
const_cast<ValidateItem *>(civ)->mType = piv->mType; const_cast<item_validator *>(civ)->m_type = piv->m_type;
} }
mLinkValidators.emplace_back(std::move(v)); m_link_validators.emplace_back(std::move(v));
} }
std::vector<const ValidateLink *> Validator::getLinksForParent(std::string_view category) const std::vector<const link_validator *> validator::get_links_for_parent(std::string_view category) const
{ {
std::vector<const ValidateLink *> result; std::vector<const link_validator *> result;
for (auto &l : mLinkValidators) for (auto &l : m_link_validators)
{ {
if (l.mParentCategory == category) if (l.m_parent_category == category)
result.push_back(&l); result.push_back(&l);
} }
return result; return result;
} }
std::vector<const ValidateLink *> Validator::getLinksForChild(std::string_view category) const std::vector<const link_validator *> validator::get_links_for_child(std::string_view category) const
{ {
std::vector<const ValidateLink *> result; std::vector<const link_validator *> result;
for (auto &l : mLinkValidators) for (auto &l : m_link_validators)
{ {
if (l.mChildCategory == category) if (l.m_child_category == category)
result.push_back(&l); result.push_back(&l);
} }
return result; return result;
} }
void Validator::reportError(const std::string &msg, bool fatal) const void validator::report_error(const std::string &msg, bool fatal) const
{ {
if (m_strict or fatal) if (m_strict or fatal)
throw ValidationError(msg); throw validation_error(msg);
else if (VERBOSE > 0) else if (VERBOSE > 0)
std::cerr << msg << std::endl; std::cerr << msg << std::endl;
} }
// -------------------------------------------------------------------- // --------------------------------------------------------------------
const Validator &ValidatorFactory::operator[](std::string_view dictionary_name) const validator &validator_factory::operator[](std::string_view dictionary_name)
{ {
std::lock_guard lock(mMutex); std::lock_guard lock(m_mutex);
for (auto &validator : mValidators) for (auto &validator : m_validators)
{ {
if (iequals(validator.name(), dictionary_name)) if (iequals(validator.name(), dictionary_name))
return validator; return validator;
...@@ -417,14 +417,14 @@ const Validator &ValidatorFactory::operator[](std::string_view dictionary_name) ...@@ -417,14 +417,14 @@ 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().name(), dictionary_name)); assert(iequals(m_validators.back().name(), dictionary_name));
return mValidators.back(); return m_validators.back();
} }
void ValidatorFactory::construct_validator(std::string_view name, std::istream &is) void validator_factory::construct_validator(std::string_view name, std::istream &is)
{ {
mValidators.emplace_back(parse_dictionary(name, is)); parse_dictionary(name, is);
} }
} // namespace cif } // namespace cif::v2
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
// #include <cif++/CifParser.hpp> // #include <cif++/CifParser.hpp>
#include <cif++/v2/parser.hpp> #include <cif++/v2/parser.hpp>
#include <cif++/v2/dictionary_parser.hpp>
namespace tt = boost::test_tools; namespace tt = boost::test_tools;
...@@ -307,7 +308,7 @@ _test.name ...@@ -307,7 +308,7 @@ _test.name
// test.clear(); // test.clear();
// auto n = test.erase(cif::Key("id") == 1, [](const cif::Row &r) // auto n = test.erase(cif::v2::key("id") == 1, [](const cif::Row &r)
// { // {
// BOOST_CHECK_EQUAL(r["id"].as<int>(), 1); // BOOST_CHECK_EQUAL(r["id"].as<int>(), 1);
// BOOST_CHECK_EQUAL(r["name"].as<std::string>(), "aap"); }); // BOOST_CHECK_EQUAL(r["name"].as<std::string>(), "aap"); });
...@@ -385,171 +386,172 @@ _test.value ...@@ -385,171 +386,172 @@ _test.value
BOOST_CHECK(test.find("value"_key == cif::v2::null).size() == 2); BOOST_CHECK(test.find("value"_key == cif::v2::null).size() == 2);
} }
// // -------------------------------------------------------------------- // --------------------------------------------------------------------
// BOOST_AUTO_TEST_CASE(d1)
// {
// const char dict[] = R"(
// data_test_dict.dic
// _datablock.id test_dict.dic
// _datablock.description
// ;
// A test dictionary
// ;
// _dictionary.title test_dict.dic
// _dictionary.datablock_id test_dict.dic
// _dictionary.version 1.0
// loop_
// _item_type_list.code
// _item_type_list.primitive_code
// _item_type_list.construct
// _item_type_list.detail
// code char
// '[][_,.;:"&<>()/\{}'`~!@#$%A-Za-z0-9*|+-]*'
// ; code item types/single words ...
// ;
// text char
// '[][ \n\t()_,.;:"&<>/\{}'`~!@#$%?+=*A-Za-z0-9|^-]*'
// ; text item types / multi-line text ...
// ;
// int numb
// '[+-]?[0-9]+'
// ; int item types are the subset of numbers that are the negative
// or positive integers.
// ;
// save_cat_1
// _category.description 'A simple test category'
// _category.id cat_1
// _category.mandatory_code no
// _category_key.name '_cat_1.id'
// save_
// save__cat_1.id
// _item.name '_cat_1.id'
// _item.category_id cat_1
// _item.mandatory_code yes
// _item_aliases.dictionary cif_core.dic
// _item_aliases.version 2.0.1
// _item_linked.child_name '_cat_2.parent_id'
// _item_linked.parent_name '_cat_1.id'
// _item_type.code code
// save_
// save__cat_1.name
// _item.name '_cat_1.name'
// _item.category_id cat_1
// _item.mandatory_code yes
// _item_aliases.dictionary cif_core.dic
// _item_aliases.version 2.0.1
// _item_type.code text
// save_
// save_cat_2
// _category.description 'A second simple test category'
// _category.id cat_2
// _category.mandatory_code no
// _category_key.name '_cat_2.id'
// save_
// save__cat_2.id
// _item.name '_cat_2.id'
// _item.category_id cat_2
// _item.mandatory_code yes
// _item_aliases.dictionary cif_core.dic
// _item_aliases.version 2.0.1
// _item_type.code int
// save_
// save__cat_2.parent_id
// _item.name '_cat_2.parent_id'
// _item.category_id cat_2
// _item.mandatory_code yes
// _item_aliases.dictionary cif_core.dic
// _item_aliases.version 2.0.1
// _item_type.code code
// save_
// save__cat_2.desc
// _item.name '_cat_2.desc'
// _item.category_id cat_2
// _item.mandatory_code yes
// _item_aliases.dictionary cif_core.dic
// _item_aliases.version 2.0.1
// _item_type.code text
// save_
// )";
// struct membuf : public std::streambuf BOOST_AUTO_TEST_CASE(d1)
// { {
// membuf(char *text, size_t length) const char dict[] = R"(
// { data_test_dict.dic
// this->setg(text, text, text + length); _datablock.id test_dict.dic
// } _datablock.description
// } buffer(const_cast<char *>(dict), sizeof(dict) - 1); ;
A test dictionary
;
_dictionary.title test_dict.dic
_dictionary.datablock_id test_dict.dic
_dictionary.version 1.0
loop_
_item_type_list.code
_item_type_list.primitive_code
_item_type_list.construct
_item_type_list.detail
code char
'[][_,.;:"&<>()/\{}'`~!@#$%A-Za-z0-9*|+-]*'
; code item types/single words ...
;
text char
'[][ \n\t()_,.;:"&<>/\{}'`~!@#$%?+=*A-Za-z0-9|^-]*'
; text item types / multi-line text ...
;
int numb
'[+-]?[0-9]+'
; int item types are the subset of numbers that are the negative
or positive integers.
;
save_cat_1
_category.description 'A simple test category'
_category.id cat_1
_category.mandatory_code no
_category_key.name '_cat_1.id'
save_
save__cat_1.id
_item.name '_cat_1.id'
_item.category_id cat_1
_item.mandatory_code yes
_item_aliases.dictionary cif_core.dic
_item_aliases.version 2.0.1
_item_linked.child_name '_cat_2.parent_id'
_item_linked.parent_name '_cat_1.id'
_item_type.code code
save_
save__cat_1.name
_item.name '_cat_1.name'
_item.category_id cat_1
_item.mandatory_code yes
_item_aliases.dictionary cif_core.dic
_item_aliases.version 2.0.1
_item_type.code text
save_
save_cat_2
_category.description 'A second simple test category'
_category.id cat_2
_category.mandatory_code no
_category_key.name '_cat_2.id'
save_
save__cat_2.id
_item.name '_cat_2.id'
_item.category_id cat_2
_item.mandatory_code yes
_item_aliases.dictionary cif_core.dic
_item_aliases.version 2.0.1
_item_type.code int
save_
save__cat_2.parent_id
_item.name '_cat_2.parent_id'
_item.category_id cat_2
_item.mandatory_code yes
_item_aliases.dictionary cif_core.dic
_item_aliases.version 2.0.1
_item_type.code code
save_
save__cat_2.desc
_item.name '_cat_2.desc'
_item.category_id cat_2
_item.mandatory_code yes
_item_aliases.dictionary cif_core.dic
_item_aliases.version 2.0.1
_item_type.code text
save_
)";
// std::istream is_dict(&buffer); struct membuf : public std::streambuf
{
membuf(char *text, size_t length)
{
this->setg(text, text, text + length);
}
} buffer(const_cast<char *>(dict), sizeof(dict) - 1);
// cif::Validator validator("test", is_dict); std::istream is_dict(&buffer);
// cif::File f; auto validator = cif::v2::parse_dictionary("test", is_dict);
// f.setValidator(&validator);
// // -------------------------------------------------------------------- cif::v2::file f;
f.set_validator(&validator);
// const char data[] = R"( // --------------------------------------------------------------------
// data_test
// loop_
// _cat_1.id
// _cat_1.name
// 1 Aap
// 2 Noot
// 3 Mies
// loop_ const char data[] = R"(
// _cat_2.id data_test
// _cat_2.parent_id loop_
// _cat_2.desc _cat_1.id
// 1 1 'Een dier' _cat_1.name
// 2 1 'Een andere aap' 1 Aap
// 3 2 'walnoot bijvoorbeeld' 2 Noot
// )"; 3 Mies
// struct data_membuf : public std::streambuf loop_
// { _cat_2.id
// data_membuf(char *text, size_t length) _cat_2.parent_id
// { _cat_2.desc
// this->setg(text, text, text + length); 1 1 'Een dier'
// } 2 1 'Een andere aap'
// } data_buffer(const_cast<char *>(data), sizeof(data) - 1); 3 2 'walnoot bijvoorbeeld'
)";
struct data_membuf : public std::streambuf
{
data_membuf(char *text, size_t length)
{
this->setg(text, text, text + length);
}
} data_buffer(const_cast<char *>(data), sizeof(data) - 1);
// 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"];
// BOOST_CHECK(cat1.size() == 3); BOOST_CHECK(cat1.size() == 3);
// BOOST_CHECK(cat2.size() == 3); BOOST_CHECK(cat2.size() == 3);
// cat1.erase(cif::Key("id") == 1); cat1.erase(cif::v2::key("id") == 1);
// BOOST_CHECK(cat1.size() == 2); BOOST_CHECK(cat1.size() == 2);
// BOOST_CHECK(cat2.size() == 1); BOOST_CHECK(cat2.size() == 1);
// // BOOST_CHECK_THROW(cat2.emplace({ // BOOST_CHECK_THROW(cat2.emplace({
// // { "id", 4 }, // { "id", 4 },
// // { "parent_id", 4 }, // { "parent_id", 4 },
// // { "desc", "moet fout gaan" } // { "desc", "moet fout gaan" }
// // }), std::exception); // }), std::exception);
// BOOST_CHECK_THROW(cat2.emplace({{"id", "vijf"}, // <- invalid value BOOST_CHECK_THROW(cat2.emplace({
// {"parent_id", 2}, {"id", "vijf"}, // <- invalid value
// {"desc", "moet fout gaan"}}), {"parent_id", 2},
// std::exception); {"desc", "moet fout gaan"}}),
// } std::exception);
}
// // -------------------------------------------------------------------- // // --------------------------------------------------------------------
...@@ -621,7 +623,7 @@ _test.value ...@@ -621,7 +623,7 @@ _test.value
// std::istream is_dict(&buffer); // std::istream is_dict(&buffer);
// cif::Validator validator("test", is_dict); // cif::v2::validator validator("test", is_dict);
// cif::File f; // cif::File f;
// f.setValidator(&validator); // f.setValidator(&validator);
...@@ -653,11 +655,11 @@ _test.value ...@@ -653,11 +655,11 @@ _test.value
// BOOST_CHECK(cat1.size() == 3); // BOOST_CHECK(cat1.size() == 3);
// cat1.erase(cif::Key("id") == "AAP"); // cat1.erase(cif::v2::key("id") == "AAP");
// BOOST_CHECK(cat1.size() == 3); // BOOST_CHECK(cat1.size() == 3);
// cat1.erase(cif::Key("id") == "noot"); // cat1.erase(cif::v2::key("id") == "noot");
// BOOST_CHECK(cat1.size() == 2); // BOOST_CHECK(cat1.size() == 2);
// } // }
...@@ -769,7 +771,7 @@ _test.value ...@@ -769,7 +771,7 @@ _test.value
// std::istream is_dict(&buffer); // std::istream is_dict(&buffer);
// cif::Validator validator("test", is_dict); // cif::v2::validator validator("test", is_dict);
// cif::File f; // cif::File f;
// f.setValidator(&validator); // f.setValidator(&validator);
...@@ -813,7 +815,7 @@ _test.value ...@@ -813,7 +815,7 @@ _test.value
// // check a rename in parent and child // // check a rename in parent and child
// for (auto r : cat1.find(cif::Key("id") == 1)) // for (auto r : cat1.find(cif::v2::key("id") == 1))
// { // {
// r["id"] = 10; // r["id"] = 10;
// break; // break;
...@@ -822,15 +824,15 @@ _test.value ...@@ -822,15 +824,15 @@ _test.value
// BOOST_CHECK(cat1.size() == 3); // BOOST_CHECK(cat1.size() == 3);
// BOOST_CHECK(cat2.size() == 4); // BOOST_CHECK(cat2.size() == 4);
// BOOST_CHECK(cat1.find(cif::Key("id") == 1).size() == 0); // BOOST_CHECK(cat1.find(cif::v2::key("id") == 1).size() == 0);
// BOOST_CHECK(cat1.find(cif::Key("id") == 10).size() == 1); // BOOST_CHECK(cat1.find(cif::v2::key("id") == 10).size() == 1);
// BOOST_CHECK(cat2.find(cif::Key("parent_id") == 1).size() == 0); // BOOST_CHECK(cat2.find(cif::v2::key("parent_id") == 1).size() == 0);
// BOOST_CHECK(cat2.find(cif::Key("parent_id") == 10).size() == 2); // BOOST_CHECK(cat2.find(cif::v2::key("parent_id") == 10).size() == 2);
// // check a rename in parent and child, this time only one child should be renamed // // check a rename in parent and child, this time only one child should be renamed
// for (auto r : cat1.find(cif::Key("id") == 2)) // for (auto r : cat1.find(cif::v2::key("id") == 2))
// { // {
// r["id"] = 20; // r["id"] = 20;
// break; // break;
...@@ -839,25 +841,25 @@ _test.value ...@@ -839,25 +841,25 @@ _test.value
// BOOST_CHECK(cat1.size() == 3); // BOOST_CHECK(cat1.size() == 3);
// BOOST_CHECK(cat2.size() == 4); // BOOST_CHECK(cat2.size() == 4);
// BOOST_CHECK(cat1.find(cif::Key("id") == 2).size() == 0); // BOOST_CHECK(cat1.find(cif::v2::key("id") == 2).size() == 0);
// BOOST_CHECK(cat1.find(cif::Key("id") == 20).size() == 1); // BOOST_CHECK(cat1.find(cif::v2::key("id") == 20).size() == 1);
// BOOST_CHECK(cat2.find(cif::Key("parent_id") == 2).size() == 1); // BOOST_CHECK(cat2.find(cif::v2::key("parent_id") == 2).size() == 1);
// BOOST_CHECK(cat2.find(cif::Key("parent_id") == 20).size() == 1); // BOOST_CHECK(cat2.find(cif::v2::key("parent_id") == 20).size() == 1);
// BOOST_CHECK(cat2.find(cif::Key("parent_id") == 2 and cif::Key("name2") == "noot").size() == 0); // BOOST_CHECK(cat2.find(cif::v2::key("parent_id") == 2 and cif::v2::key("name2") == "noot").size() == 0);
// BOOST_CHECK(cat2.find(cif::Key("parent_id") == 2 and cif::Key("name2") == "n2").size() == 1); // BOOST_CHECK(cat2.find(cif::v2::key("parent_id") == 2 and cif::v2::key("name2") == "n2").size() == 1);
// BOOST_CHECK(cat2.find(cif::Key("parent_id") == 20 and cif::Key("name2") == "noot").size() == 1); // BOOST_CHECK(cat2.find(cif::v2::key("parent_id") == 20 and cif::v2::key("name2") == "noot").size() == 1);
// BOOST_CHECK(cat2.find(cif::Key("parent_id") == 20 and cif::Key("name2") == "n2").size() == 0); // BOOST_CHECK(cat2.find(cif::v2::key("parent_id") == 20 and cif::v2::key("name2") == "n2").size() == 0);
// // // -------------------------------------------------------------------- // // // --------------------------------------------------------------------
// // cat1.erase(cif::Key("id") == 10); // // cat1.erase(cif::v2::key("id") == 10);
// // BOOST_CHECK(cat1.size() == 2); // // BOOST_CHECK(cat1.size() == 2);
// // BOOST_CHECK(cat2.size() == 2); // // BOOST_CHECK(cat2.size() == 2);
// // cat1.erase(cif::Key("id") == 20); // // cat1.erase(cif::v2::key("id") == 20);
// // BOOST_CHECK(cat1.size() == 1); // // BOOST_CHECK(cat1.size() == 1);
// // BOOST_CHECK(cat2.size() == 1); // // BOOST_CHECK(cat2.size() == 1);
...@@ -972,7 +974,7 @@ _test.value ...@@ -972,7 +974,7 @@ _test.value
// std::istream is_dict(&buffer); // std::istream is_dict(&buffer);
// cif::Validator validator("test", is_dict); // cif::v2::validator validator("test", is_dict);
// cif::File f; // cif::File f;
// f.setValidator(&validator); // f.setValidator(&validator);
...@@ -1026,7 +1028,7 @@ _test.value ...@@ -1026,7 +1028,7 @@ _test.value
// // check a rename in parent and child // // check a rename in parent and child
// for (auto r : cat1.find(cif::Key("id") == 1)) // for (auto r : cat1.find(cif::v2::key("id") == 1))
// { // {
// r["id"] = 10; // r["id"] = 10;
// break; // break;
...@@ -1035,13 +1037,13 @@ _test.value ...@@ -1035,13 +1037,13 @@ _test.value
// BOOST_CHECK(cat1.size() == 4); // BOOST_CHECK(cat1.size() == 4);
// BOOST_CHECK(cat2.size() == 13); // BOOST_CHECK(cat2.size() == 13);
// BOOST_CHECK(cat1.find(cif::Key("id") == 1).size() == 0); // BOOST_CHECK(cat1.find(cif::v2::key("id") == 1).size() == 0);
// BOOST_CHECK(cat1.find(cif::Key("id") == 10).size() == 1); // BOOST_CHECK(cat1.find(cif::v2::key("id") == 10).size() == 1);
// BOOST_CHECK(cat2.find(cif::Key("parent_id") == 1).size() == 1); // BOOST_CHECK(cat2.find(cif::v2::key("parent_id") == 1).size() == 1);
// BOOST_CHECK(cat2.find(cif::Key("parent_id") == 10).size() == 2); // BOOST_CHECK(cat2.find(cif::v2::key("parent_id") == 10).size() == 2);
// for (auto r : cat1.find(cif::Key("id") == 2)) // for (auto r : cat1.find(cif::v2::key("id") == 2))
// { // {
// r["id"] = 20; // r["id"] = 20;
// break; // break;
...@@ -1050,13 +1052,13 @@ _test.value ...@@ -1050,13 +1052,13 @@ _test.value
// BOOST_CHECK(cat1.size() == 4); // BOOST_CHECK(cat1.size() == 4);
// BOOST_CHECK(cat2.size() == 13); // BOOST_CHECK(cat2.size() == 13);
// BOOST_CHECK(cat1.find(cif::Key("id") == 2).size() == 0); // BOOST_CHECK(cat1.find(cif::v2::key("id") == 2).size() == 0);
// BOOST_CHECK(cat1.find(cif::Key("id") == 20).size() == 1); // BOOST_CHECK(cat1.find(cif::v2::key("id") == 20).size() == 1);
// BOOST_CHECK(cat2.find(cif::Key("parent_id") == 2).size() == 2); // BOOST_CHECK(cat2.find(cif::v2::key("parent_id") == 2).size() == 2);
// BOOST_CHECK(cat2.find(cif::Key("parent_id") == 20).size() == 2); // BOOST_CHECK(cat2.find(cif::v2::key("parent_id") == 20).size() == 2);
// for (auto r : cat1.find(cif::Key("id") == 3)) // for (auto r : cat1.find(cif::v2::key("id") == 3))
// { // {
// r["id"] = 30; // r["id"] = 30;
// break; // break;
...@@ -1065,13 +1067,13 @@ _test.value ...@@ -1065,13 +1067,13 @@ _test.value
// BOOST_CHECK(cat1.size() == 4); // BOOST_CHECK(cat1.size() == 4);
// BOOST_CHECK(cat2.size() == 13); // BOOST_CHECK(cat2.size() == 13);
// BOOST_CHECK(cat1.find(cif::Key("id") == 3).size() == 0); // BOOST_CHECK(cat1.find(cif::v2::key("id") == 3).size() == 0);
// BOOST_CHECK(cat1.find(cif::Key("id") == 30).size() == 1); // BOOST_CHECK(cat1.find(cif::v2::key("id") == 30).size() == 1);
// BOOST_CHECK(cat2.find(cif::Key("parent_id") == 3).size() == 2); // BOOST_CHECK(cat2.find(cif::v2::key("parent_id") == 3).size() == 2);
// BOOST_CHECK(cat2.find(cif::Key("parent_id") == 30).size() == 1); // BOOST_CHECK(cat2.find(cif::v2::key("parent_id") == 30).size() == 1);
// for (auto r : cat1.find(cif::Key("id") == 4)) // for (auto r : cat1.find(cif::v2::key("id") == 4))
// { // {
// r["id"] = 40; // r["id"] = 40;
// break; // break;
...@@ -1080,11 +1082,11 @@ _test.value ...@@ -1080,11 +1082,11 @@ _test.value
// BOOST_CHECK(cat1.size() == 4); // BOOST_CHECK(cat1.size() == 4);
// BOOST_CHECK(cat2.size() == 13); // BOOST_CHECK(cat2.size() == 13);
// BOOST_CHECK(cat1.find(cif::Key("id") == 4).size() == 0); // BOOST_CHECK(cat1.find(cif::v2::key("id") == 4).size() == 0);
// BOOST_CHECK(cat1.find(cif::Key("id") == 10).size() == 1); // BOOST_CHECK(cat1.find(cif::v2::key("id") == 10).size() == 1);
// BOOST_CHECK(cat2.find(cif::Key("parent_id") == 4).size() == 3); // BOOST_CHECK(cat2.find(cif::v2::key("parent_id") == 4).size() == 3);
// BOOST_CHECK(cat2.find(cif::Key("parent_id") == 40).size() == 0); // BOOST_CHECK(cat2.find(cif::v2::key("parent_id") == 40).size() == 0);
// } // }
// // -------------------------------------------------------------------- // // --------------------------------------------------------------------
...@@ -1193,7 +1195,7 @@ _test.value ...@@ -1193,7 +1195,7 @@ _test.value
// std::istream is_dict(&buffer); // std::istream is_dict(&buffer);
// cif::Validator validator("test", is_dict); // cif::v2::validator validator("test", is_dict);
// cif::File f; // cif::File f;
// f.setValidator(&validator); // f.setValidator(&validator);
...@@ -1241,7 +1243,7 @@ _test.value ...@@ -1241,7 +1243,7 @@ _test.value
// // -------------------------------------------------------------------- // // --------------------------------------------------------------------
// // check iterate children // // check iterate children
// auto PR2set = cat1.find(cif::Key("id") == 2); // auto PR2set = cat1.find(cif::v2::key("id") == 2);
// BOOST_ASSERT(PR2set.size() == 1); // BOOST_ASSERT(PR2set.size() == 1);
// auto PR2 = PR2set.front(); // auto PR2 = PR2set.front();
// BOOST_CHECK(PR2["id"].as<int>() == 2); // BOOST_CHECK(PR2["id"].as<int>() == 2);
...@@ -1257,7 +1259,7 @@ _test.value ...@@ -1257,7 +1259,7 @@ _test.value
// // check a rename in parent and child // // check a rename in parent and child
// for (auto r : cat1.find(cif::Key("id") == 1)) // for (auto r : cat1.find(cif::v2::key("id") == 1))
// { // {
// r["id"] = 10; // r["id"] = 10;
// break; // break;
...@@ -1266,17 +1268,17 @@ _test.value ...@@ -1266,17 +1268,17 @@ _test.value
// BOOST_CHECK(cat1.size() == 3); // BOOST_CHECK(cat1.size() == 3);
// BOOST_CHECK(cat2.size() == 7); // BOOST_CHECK(cat2.size() == 7);
// BOOST_CHECK(cat1.find(cif::Key("id") == 1).size() == 0); // BOOST_CHECK(cat1.find(cif::v2::key("id") == 1).size() == 0);
// BOOST_CHECK(cat1.find(cif::Key("id") == 10).size() == 1); // BOOST_CHECK(cat1.find(cif::v2::key("id") == 10).size() == 1);
// BOOST_CHECK(cat2.find(cif::Key("parent_id") == 1).size() == 0); // BOOST_CHECK(cat2.find(cif::v2::key("parent_id") == 1).size() == 0);
// BOOST_CHECK(cat2.find(cif::Key("parent_id2") == 1).size() == 0); // BOOST_CHECK(cat2.find(cif::v2::key("parent_id2") == 1).size() == 0);
// BOOST_CHECK(cat2.find(cif::Key("parent_id3") == 1).size() == 0); // BOOST_CHECK(cat2.find(cif::v2::key("parent_id3") == 1).size() == 0);
// BOOST_CHECK(cat2.find(cif::Key("parent_id") == 10).size() == 1); // BOOST_CHECK(cat2.find(cif::v2::key("parent_id") == 10).size() == 1);
// BOOST_CHECK(cat2.find(cif::Key("parent_id2") == 10).size() == 1); // BOOST_CHECK(cat2.find(cif::v2::key("parent_id2") == 10).size() == 1);
// BOOST_CHECK(cat2.find(cif::Key("parent_id3") == 10).size() == 1); // BOOST_CHECK(cat2.find(cif::v2::key("parent_id3") == 10).size() == 1);
// for (auto r : cat1.find(cif::Key("id") == 2)) // for (auto r : cat1.find(cif::v2::key("id") == 2))
// { // {
// r["id"] = 20; // r["id"] = 20;
// break; // break;
...@@ -1285,17 +1287,17 @@ _test.value ...@@ -1285,17 +1287,17 @@ _test.value
// BOOST_CHECK(cat1.size() == 3); // BOOST_CHECK(cat1.size() == 3);
// BOOST_CHECK(cat2.size() == 7); // BOOST_CHECK(cat2.size() == 7);
// BOOST_CHECK(cat1.find(cif::Key("id") == 2).size() == 0); // BOOST_CHECK(cat1.find(cif::v2::key("id") == 2).size() == 0);
// BOOST_CHECK(cat1.find(cif::Key("id") == 20).size() == 1); // BOOST_CHECK(cat1.find(cif::v2::key("id") == 20).size() == 1);
// BOOST_CHECK(cat2.find(cif::Key("parent_id") == 2).size() == 0); // BOOST_CHECK(cat2.find(cif::v2::key("parent_id") == 2).size() == 0);
// BOOST_CHECK(cat2.find(cif::Key("parent_id2") == 2).size() == 0); // BOOST_CHECK(cat2.find(cif::v2::key("parent_id2") == 2).size() == 0);
// BOOST_CHECK(cat2.find(cif::Key("parent_id3") == 2).size() == 0); // BOOST_CHECK(cat2.find(cif::v2::key("parent_id3") == 2).size() == 0);
// BOOST_CHECK(cat2.find(cif::Key("parent_id") == 20).size() == 2); // BOOST_CHECK(cat2.find(cif::v2::key("parent_id") == 20).size() == 2);
// BOOST_CHECK(cat2.find(cif::Key("parent_id2") == 20).size() == 2); // BOOST_CHECK(cat2.find(cif::v2::key("parent_id2") == 20).size() == 2);
// BOOST_CHECK(cat2.find(cif::Key("parent_id3") == 20).size() == 2); // BOOST_CHECK(cat2.find(cif::v2::key("parent_id3") == 20).size() == 2);
// for (auto r : cat1.find(cif::Key("id") == 3)) // for (auto r : cat1.find(cif::v2::key("id") == 3))
// { // {
// r["id"] = 30; // r["id"] = 30;
// break; // break;
...@@ -1304,27 +1306,27 @@ _test.value ...@@ -1304,27 +1306,27 @@ _test.value
// BOOST_CHECK(cat1.size() == 3); // BOOST_CHECK(cat1.size() == 3);
// BOOST_CHECK(cat2.size() == 7); // BOOST_CHECK(cat2.size() == 7);
// BOOST_CHECK(cat1.find(cif::Key("id") == 3).size() == 0); // BOOST_CHECK(cat1.find(cif::v2::key("id") == 3).size() == 0);
// BOOST_CHECK(cat1.find(cif::Key("id") == 30).size() == 1); // BOOST_CHECK(cat1.find(cif::v2::key("id") == 30).size() == 1);
// BOOST_CHECK(cat2.find(cif::Key("parent_id") == 3).size() == 0); // BOOST_CHECK(cat2.find(cif::v2::key("parent_id") == 3).size() == 0);
// BOOST_CHECK(cat2.find(cif::Key("parent_id2") == 3).size() == 0); // BOOST_CHECK(cat2.find(cif::v2::key("parent_id2") == 3).size() == 0);
// BOOST_CHECK(cat2.find(cif::Key("parent_id3") == 3).size() == 0); // BOOST_CHECK(cat2.find(cif::v2::key("parent_id3") == 3).size() == 0);
// BOOST_CHECK(cat2.find(cif::Key("parent_id") == 30).size() == 1); // BOOST_CHECK(cat2.find(cif::v2::key("parent_id") == 30).size() == 1);
// BOOST_CHECK(cat2.find(cif::Key("parent_id2") == 30).size() == 1); // BOOST_CHECK(cat2.find(cif::v2::key("parent_id2") == 30).size() == 1);
// BOOST_CHECK(cat2.find(cif::Key("parent_id3") == 30).size() == 1); // BOOST_CHECK(cat2.find(cif::v2::key("parent_id3") == 30).size() == 1);
// // test delete // // test delete
// cat1.erase(cif::Key("id") == 10); // cat1.erase(cif::v2::key("id") == 10);
// BOOST_CHECK(cat1.size() == 2); // BOOST_CHECK(cat1.size() == 2);
// BOOST_CHECK(cat2.size() == 4); // BOOST_CHECK(cat2.size() == 4);
// cat1.erase(cif::Key("id") == 20); // cat1.erase(cif::v2::key("id") == 20);
// BOOST_CHECK(cat1.size() == 1); // BOOST_CHECK(cat1.size() == 1);
// BOOST_CHECK(cat2.size() == 1); // BOOST_CHECK(cat2.size() == 1);
// cat1.erase(cif::Key("id") == 30); // cat1.erase(cif::v2::key("id") == 30);
// BOOST_CHECK(cat1.size() == 0); // BOOST_CHECK(cat1.size() == 0);
// BOOST_CHECK(cat2.size() == 0); // BOOST_CHECK(cat2.size() == 0);
// } // }
...@@ -1349,21 +1351,21 @@ _test.value ...@@ -1349,21 +1351,21 @@ _test.value
// auto &db = f.front(); // auto &db = f.front();
// for (auto r : db["test"].find(cif::Key("id") == 1)) // for (auto r : db["test"].find(cif::v2::key("id") == 1))
// { // {
// const auto &[id, name] = r.get<int, std::string>({"id", "name"}); // const auto &[id, name] = r.get<int, std::string>({"id", "name"});
// BOOST_CHECK(id == 1); // BOOST_CHECK(id == 1);
// BOOST_CHECK(name == "aap"); // BOOST_CHECK(name == "aap");
// } // }
// for (auto r : db["test"].find(cif::Key("id") == 4)) // for (auto r : db["test"].find(cif::v2::key("id") == 4))
// { // {
// const auto &[id, name] = r.get<int, std::string>({"id", "name"}); // const auto &[id, name] = r.get<int, std::string>({"id", "name"});
// BOOST_CHECK(id == 4); // BOOST_CHECK(id == 4);
// BOOST_CHECK(name.empty()); // BOOST_CHECK(name.empty());
// } // }
// for (auto r : db["test"].find(cif::Key("id") == 5)) // for (auto r : db["test"].find(cif::v2::key("id") == 5))
// { // {
// const auto &[id, name] = r.get<int, std::string>({"id", "name"}); // const auto &[id, name] = r.get<int, std::string>({"id", "name"});
// BOOST_CHECK(id == 5); // BOOST_CHECK(id == 5);
...@@ -1456,7 +1458,7 @@ _test.value ...@@ -1456,7 +1458,7 @@ _test.value
// } // }
// } // }
// const auto &[id, name] = db["test"].find1<int, std::string>(cif::Key("id") == 1, "id", "name"); // const auto &[id, name] = db["test"].find1<int, std::string>(cif::v2::key("id") == 1, "id", "name");
// BOOST_CHECK(id == 1); // BOOST_CHECK(id == 1);
// BOOST_CHECK(name == "aap"); // BOOST_CHECK(name == "aap");
...@@ -1621,7 +1623,7 @@ _test.value ...@@ -1621,7 +1623,7 @@ _test.value
// } buffer(const_cast<char *>(dict), sizeof(dict) - 1); // } buffer(const_cast<char *>(dict), sizeof(dict) - 1);
// std::istream is_dict(&buffer); // std::istream is_dict(&buffer);
// cif::Validator validator("test", is_dict); // cif::v2::validator validator("test", is_dict);
// cif::File f; // cif::File f;
// f.setValidator(&validator); // f.setValidator(&validator);
......
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