Commit 1f24937e by Maarten L. Hekkelman

simplify condtion code.

parent aba35c34
...@@ -246,7 +246,7 @@ class Datablock ...@@ -246,7 +246,7 @@ class Datablock
private: private:
std::list<Category> mCategories; std::list<Category> mCategories;
std::string mName; std::string mName;
Validator* mValidator; Validator* mValidator;
Datablock* mNext; Datablock* mNext;
}; };
...@@ -264,7 +264,7 @@ namespace detail ...@@ -264,7 +264,7 @@ namespace detail
{ {
public: public:
// some conversion helper classes // conversion helper class
template<typename T, typename = void> template<typename T, typename = void>
struct item_value_as; struct item_value_as;
...@@ -318,7 +318,7 @@ namespace detail ...@@ -318,7 +318,7 @@ namespace detail
template<typename T, std::enable_if_t<std::is_same_v<T, char>, int> = 0> template<typename T, std::enable_if_t<std::is_same_v<T, char>, int> = 0>
int compare(const T& value) const int compare(const T& value) const
{ {
return icompare(std::string{value}, c_str()); return cif::icompare(std::string{value}, c_str());
} }
template<typename T, std::enable_if_t<std::is_integral_v<T> and std::is_signed_v<T> and not std::is_same_v<T, char>, int> = 0> template<typename T, std::enable_if_t<std::is_integral_v<T> and std::is_signed_v<T> and not std::is_same_v<T, char>, int> = 0>
...@@ -368,9 +368,19 @@ namespace detail ...@@ -368,9 +368,19 @@ namespace detail
template<typename T, std::enable_if_t<std::is_same_v<std::remove_cv_t<T>, std::string>, int> = 0> template<typename T, std::enable_if_t<std::is_same_v<std::remove_cv_t<T>, std::string>, int> = 0>
int compare(const T& value) const int compare(const T& value) const
{ {
return icompare(c_str(), value.c_str()); return cif::icompare(c_str(), value.c_str());
} }
int compare(const ItemReference& rhs) const
{
return std::strcmp(c_str(), rhs.c_str());
}
int icompare(const std::string& value) const
{
return cif::icompare(c_str(), value.c_str());
}
// empty means either null or unknown // empty means either null or unknown
bool empty() const; bool empty() const;
explicit operator bool() const { return not empty(); } explicit operator bool() const { return not empty(); }
...@@ -703,13 +713,11 @@ struct ConditionImpl ...@@ -703,13 +713,11 @@ struct ConditionImpl
virtual void prepare(const Category& c) {} virtual void prepare(const Category& c) {}
virtual bool test(const Category& c, const Row& r) const = 0; virtual bool test(const Category& c, const Row& r) const = 0;
virtual std::string str() const = 0;
}; };
struct AllConditionImpl : public ConditionImpl struct AllConditionImpl : public ConditionImpl
{ {
virtual bool test(const Category& c, const Row& r) const { return true; } virtual bool test(const Category& c, const Row& r) const { return true; }
virtual std::string str() const { return "ALL"; }
}; };
struct orConditionImpl; struct orConditionImpl;
...@@ -761,11 +769,6 @@ class Condition ...@@ -761,11 +769,6 @@ class Condition
return mImpl ? mImpl->test(c, r) : false; return mImpl ? mImpl->test(c, r) : false;
} }
std::string str() const
{
return mImpl ? mImpl->str() : "";
}
bool empty() const { return mImpl == nullptr; } bool empty() const { return mImpl == nullptr; }
friend Condition operator||(Condition&& a, Condition&& b); friend Condition operator||(Condition&& a, Condition&& b);
...@@ -801,79 +804,10 @@ struct KeyIsEmptyConditionImpl : public ConditionImpl ...@@ -801,79 +804,10 @@ struct KeyIsEmptyConditionImpl : public ConditionImpl
return r[mItemIx].empty(); return r[mItemIx].empty();
} }
virtual std::string str() const
{
return mItemTag + " == <empty>";
}
std::string mItemTag;
size_t mItemIx;
};
template<typename T>
struct KeyIsConditionImpl : public ConditionImpl
{
typedef T valueType;
KeyIsConditionImpl(const std::string& ItemTag, const valueType& value)
: mItemTag(ItemTag), mValue(value) {}
virtual void prepare(const Category& c);
virtual bool test(const Category& c, const Row& r) const
{
return r[mItemIx].template compare<valueType>(mValue) == 0;
}
virtual std::string str() const
{
return mItemTag + " == " + std::to_string(mValue);
}
std::string mItemTag;
size_t mItemIx;
valueType mValue;
};
template<>
inline
std::string KeyIsConditionImpl<std::string>::str() const
{
return mItemTag + " == " + mValue;
}
template<typename T>
struct KeyIsNotConditionImpl : public ConditionImpl
{
typedef T valueType;
KeyIsNotConditionImpl(const std::string& ItemTag, const valueType& value)
: mItemTag(ItemTag), mValue(value) {}
virtual void prepare(const Category& c);
virtual bool test(const Category& c, const Row& r) const
{
return r[mItemIx].template compare<valueType>(mValue) != 0;
}
virtual std::string str() const
{
return mItemTag + " != " + std::to_string(mValue);
}
std::string mItemTag; std::string mItemTag;
size_t mItemIx; size_t mItemIx;
valueType mValue;
}; };
template<>
inline
std::string KeyIsNotConditionImpl<std::string>::str() const
{
return mItemTag + " != " + mValue;
}
struct KeyCompareConditionImpl : public ConditionImpl struct KeyCompareConditionImpl : public ConditionImpl
{ {
template<typename COMP> template<typename COMP>
...@@ -887,11 +821,6 @@ struct KeyCompareConditionImpl : public ConditionImpl ...@@ -887,11 +821,6 @@ struct KeyCompareConditionImpl : public ConditionImpl
return mComp(c, r); return mComp(c, r);
} }
virtual std::string str() const
{
return mItemTag + " compare";
}
std::string mItemTag; std::string mItemTag;
size_t mItemIx; size_t mItemIx;
std::function<bool(const Category&, const Row&)> mComp; std::function<bool(const Category&, const Row&)> mComp;
...@@ -909,11 +838,6 @@ struct KeyMatchesConditionImpl : public ConditionImpl ...@@ -909,11 +838,6 @@ struct KeyMatchesConditionImpl : public ConditionImpl
return std::regex_match(r[mItemIx].as<std::string>(), mRx); return std::regex_match(r[mItemIx].as<std::string>(), mRx);
} }
virtual std::string str() const
{
return mItemTag + " ~= " + "<rx>";
}
std::string mItemTag; std::string mItemTag;
size_t mItemIx; size_t mItemIx;
std::regex mRx; std::regex mRx;
...@@ -929,11 +853,6 @@ struct anyIsConditionImpl : public ConditionImpl ...@@ -929,11 +853,6 @@ struct anyIsConditionImpl : public ConditionImpl
virtual bool test(const Category& c, const Row& r) const; virtual bool test(const Category& c, const Row& r) const;
virtual std::string str() const
{
return "any == " + std::to_string(mValue);
}
valueType mValue; valueType mValue;
}; };
...@@ -944,11 +863,6 @@ struct anyMatchesConditionImpl : public ConditionImpl ...@@ -944,11 +863,6 @@ struct anyMatchesConditionImpl : public ConditionImpl
virtual bool test(const Category& c, const Row& r) const; virtual bool test(const Category& c, const Row& r) const;
virtual std::string str() const
{
return "any ~= <rx>";
}
std::regex mRx; std::regex mRx;
}; };
...@@ -960,11 +874,6 @@ struct allConditionImpl : public ConditionImpl ...@@ -960,11 +874,6 @@ struct allConditionImpl : public ConditionImpl
{ {
return true; return true;
} }
virtual std::string str() const
{
return "ALL";
}
}; };
struct andConditionImpl : public ConditionImpl struct andConditionImpl : public ConditionImpl
...@@ -993,11 +902,6 @@ struct andConditionImpl : public ConditionImpl ...@@ -993,11 +902,6 @@ struct andConditionImpl : public ConditionImpl
return mA->test(c, r) and mB->test(c, r); return mA->test(c, r) and mB->test(c, r);
} }
virtual std::string str() const
{
return "(" + mA->str() + ") and (" + mB->str() + ")";
}
ConditionImpl* mA; ConditionImpl* mA;
ConditionImpl* mB; ConditionImpl* mB;
}; };
...@@ -1028,11 +932,6 @@ struct orConditionImpl : public ConditionImpl ...@@ -1028,11 +932,6 @@ struct orConditionImpl : public ConditionImpl
return mA->test(c, r) or mB->test(c, r); return mA->test(c, r) or mB->test(c, r);
} }
virtual std::string str() const
{
return "(" + mA->str() + ") or (" + mB->str() + ")";
}
ConditionImpl* mA; ConditionImpl* mA;
ConditionImpl* mB; ConditionImpl* mB;
}; };
...@@ -1060,11 +959,6 @@ struct notConditionImpl : public ConditionImpl ...@@ -1060,11 +959,6 @@ struct notConditionImpl : public ConditionImpl
return not mA->test(c, r); return not mA->test(c, r);
} }
virtual std::string str() const
{
return "NOT (" + mA->str() + ")";
}
ConditionImpl* mA; ConditionImpl* mA;
}; };
...@@ -1088,13 +982,6 @@ inline Condition operator||(Condition&& a, Condition&& b) ...@@ -1088,13 +982,6 @@ inline Condition operator||(Condition&& a, Condition&& b)
return Condition(std::move(b)); return Condition(std::move(b));
} }
inline
std::ostream& operator<<(std::ostream& os, const Condition& rhs)
{
os << rhs.str();
return os;
}
struct Empty {}; struct Empty {};
struct Key struct Key
...@@ -1111,13 +998,15 @@ struct Key ...@@ -1111,13 +998,15 @@ struct Key
template<typename T> template<typename T>
Condition operator==(const Key& key, const T& v) Condition operator==(const Key& key, const T& v)
{ {
return Condition(new detail::KeyIsConditionImpl<T>(key.mItemTag, v)); return Condition(new detail::KeyCompareConditionImpl(key.mItemTag, [tag = key.mItemTag, v](const Category& c, const Row& r)
{ return r[tag].compare(v) > 0; }));
} }
inline Condition operator==(const Key& key, const char* v) inline Condition operator==(const Key& key, const char* v)
{ {
std::string value(v ? v : ""); std::string value(v ? v : "");
return Condition(new detail::KeyIsConditionImpl<std::string>(key.mItemTag, value)); return Condition(new detail::KeyCompareConditionImpl(key.mItemTag, [tag = key.mItemTag, value](const Category& c, const Row& r)
{ return r[tag].compare(value) == 0; }));
} }
inline Condition operator==(const Key& key, const detail::ItemReference& v) inline Condition operator==(const Key& key, const detail::ItemReference& v)
...@@ -1125,7 +1014,8 @@ inline Condition operator==(const Key& key, const detail::ItemReference& v) ...@@ -1125,7 +1014,8 @@ inline Condition operator==(const Key& key, const detail::ItemReference& v)
if (v.empty()) if (v.empty())
return Condition(new detail::KeyIsEmptyConditionImpl(key.mItemTag)); return Condition(new detail::KeyIsEmptyConditionImpl(key.mItemTag));
else else
return Condition(new detail::KeyIsConditionImpl<std::string>(key.mItemTag, v.c_str())); return Condition(new detail::KeyCompareConditionImpl(key.mItemTag, [tag = key.mItemTag, v](const Category& c, const Row& r)
{ return r[tag].compare(v); }));
} }
inline Condition operator==(const Key& key, const Empty&) inline Condition operator==(const Key& key, const Empty&)
...@@ -1136,41 +1026,41 @@ inline Condition operator==(const Key& key, const Empty&) ...@@ -1136,41 +1026,41 @@ inline Condition operator==(const Key& key, const Empty&)
template<typename T> template<typename T>
Condition operator!=(const Key& key, const T& v) Condition operator!=(const Key& key, const T& v)
{ {
return Condition(new detail::KeyIsNotConditionImpl<T>(key.mItemTag, v)); return Condition(new detail::notConditionImpl(operator==(key, v)));
} }
inline Condition operator!=(const Key& key, const char* v) inline Condition operator!=(const Key& key, const char* v)
{ {
std::string value(v ? v : ""); std::string value(v ? v : "");
return Condition(new detail::KeyIsNotConditionImpl<std::string>(key.mItemTag, value)); return Condition(new detail::notConditionImpl(operator==(key, value)));
} }
template<typename T> template<typename T>
Condition operator>(const Key& key, const T& v) Condition operator>(const Key& key, const T& v)
{ {
return Condition(new detail::KeyCompareConditionImpl(key.mItemTag, [tag = key.mItemTag, v](const Category& c, const Row& r) return Condition(new detail::KeyCompareConditionImpl(key.mItemTag, [tag = key.mItemTag, v](const Category& c, const Row& r)
{ return r[tag].as<T>() > v; })); { return r[tag].compare(v) > 0; }));
} }
template<typename T> template<typename T>
Condition operator>=(const Key& key, const T& v) Condition operator>=(const Key& key, const T& v)
{ {
return Condition(new detail::KeyCompareConditionImpl(key.mItemTag, [tag = key.mItemTag, v](const Category& c, const Row& r) return Condition(new detail::KeyCompareConditionImpl(key.mItemTag, [tag = key.mItemTag, v](const Category& c, const Row& r)
{ return r[tag].as<T>() >= v; })); { return r[tag].compare(v) >= 0; }));
} }
template<typename T> template<typename T>
Condition operator<(const Key& key, const T& v) Condition operator<(const Key& key, const T& v)
{ {
return Condition(new detail::KeyCompareConditionImpl(key.mItemTag, [tag = key.mItemTag, v](const Category& c, const Row& r) return Condition(new detail::KeyCompareConditionImpl(key.mItemTag, [tag = key.mItemTag, v](const Category& c, const Row& r)
{ return r[tag].as<T>() < v; })); { return r[tag].compare(v) < 0; }));
} }
template<typename T> template<typename T>
Condition operator<=(const Key& key, const T& v) Condition operator<=(const Key& key, const T& v)
{ {
return Condition(new detail::KeyCompareConditionImpl(key.mItemTag, [tag = key.mItemTag, v](const Category& c, const Row& r) return Condition(new detail::KeyCompareConditionImpl(key.mItemTag, [tag = key.mItemTag, v](const Category& c, const Row& r)
{ return r[tag].as<T>() <= v; })); { return r[tag].compare(v) <= 0; }));
} }
template<> template<>
...@@ -1783,18 +1673,6 @@ inline void swap(cif::detail::ItemReference& a, cif::detail::ItemReference& b) ...@@ -1783,18 +1673,6 @@ inline void swap(cif::detail::ItemReference& a, cif::detail::ItemReference& b)
namespace detail namespace detail
{ {
template<typename T>
void KeyIsConditionImpl<T>::prepare(const Category& c)
{
mItemIx = c.getColumnIndex(mItemTag);
}
template<typename T>
void KeyIsNotConditionImpl<T>::prepare(const Category& c)
{
mItemIx = c.getColumnIndex(mItemTag);
}
inline void KeyCompareConditionImpl::prepare(const Category& c) inline void KeyCompareConditionImpl::prepare(const Category& c)
{ {
mItemIx = c.getColumnIndex(mItemTag); mItemIx = c.getColumnIndex(mItemTag);
......
...@@ -28,9 +28,6 @@ ...@@ -28,9 +28,6 @@
#include "cif++/Cif++.hpp" #include "cif++/Cif++.hpp"
//// the std regex of gcc is crashing....
// #include <boost/regex.hpp>
#include <regex> #include <regex>
#include <set> #include <set>
......
...@@ -568,7 +568,16 @@ void Datablock::write(std::ostream& os, const std::vector<std::string>& order) ...@@ -568,7 +568,16 @@ void Datablock::write(std::ostream& os, const std::vector<std::string>& order)
namespace detail namespace detail
{ {
// void ConditionImpl::prepare(const Category& c)
// {
// auto cv = c.getCatValidator();
// if (cv)
// {
// auto iv = cv->getValidatorForItem(mItemTag);
// }
// }
void KeyIsEmptyConditionImpl::prepare(const Category& c) void KeyIsEmptyConditionImpl::prepare(const Category& c)
{ {
mItemIx = c.getColumnIndex(mItemTag); mItemIx = c.getColumnIndex(mItemTag);
...@@ -1766,11 +1775,11 @@ bool Category::hasParent(Row r, const Category& parentCat, const ValidateLink& l ...@@ -1766,11 +1775,11 @@ bool Category::hasParent(Row r, const Category& parentCat, const ValidateLink& l
{ {
result = parentCat.exists(std::move(cond)); result = parentCat.exists(std::move(cond));
if (VERBOSE > 3 or (result == false and VERBOSE > 2)) // if (VERBOSE > 3 or (result == false and VERBOSE > 2))
std::cerr << "result = " << std::boolalpha << result << " for: '" << cond << "' in parent category " << link.mParentCategory << " for child cat " << mName << std::endl; // std::cerr << "result = " << std::boolalpha << result << " for: '" << cond << "' in parent category " << link.mParentCategory << " for child cat " << mName << std::endl;
} }
else if (VERBOSE > 3 and cond.empty()) // else if (VERBOSE > 3 and cond.empty())
std::cerr << "Condition is empty due to missing data in parent category " << link.mParentCategory << " for child cat " << mName << std::endl; // std::cerr << "Condition is empty due to missing data in parent category " << link.mParentCategory << " for child cat " << mName << std::endl;
return result; return result;
} }
...@@ -1795,8 +1804,8 @@ bool Category::isOrphan(Row r) ...@@ -1795,8 +1804,8 @@ bool Category::isOrphan(Row r)
cond = std::move(cond) && (Key(link->mParentKeys[ix]) == value); cond = std::move(cond) && (Key(link->mParentKeys[ix]) == value);
} }
if (VERBOSE > 2) // if (VERBOSE > 2)
std::cerr << "Check condition '" << cond << "' in parent category " << link->mParentCategory << " for child cat " << mName << std::endl; // std::cerr << "Check condition '" << cond << "' in parent category " << link->mParentCategory << " for child cat " << mName << std::endl;
if (parentCat->exists(std::move(cond))) if (parentCat->exists(std::move(cond)))
{ {
...@@ -2702,9 +2711,9 @@ void Row::swap(size_t cix, ItemRow* a, ItemRow* b) ...@@ -2702,9 +2711,9 @@ void Row::swap(size_t cix, ItemRow* a, ItemRow* b)
if (cond[ab].empty()) if (cond[ab].empty())
continue; continue;
if (VERBOSE > 1) // if (VERBOSE > 1)
std::cerr << "Fixing link from " << cat->mName << " to " << childCat->mName << " with " << std::endl // std::cerr << "Fixing link from " << cat->mName << " to " << childCat->mName << " with " << std::endl
<< cond[ab] << std::endl; // << cond[ab] << std::endl;
rs.push_back(childCat->find(std::move(cond[ab]))); rs.push_back(childCat->find(std::move(cond[ab])));
} }
......
...@@ -26,10 +26,6 @@ ...@@ -26,10 +26,6 @@
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
//// since gcc's regex is crashing....
// #include <boost/regex.hpp>
// #include <regex>
#include "cif++/Cif++.hpp" #include "cif++/Cif++.hpp"
#include "cif++/CifParser.hpp" #include "cif++/CifParser.hpp"
#include "cif++/CifValidator.hpp" #include "cif++/CifValidator.hpp"
......
...@@ -292,6 +292,115 @@ _cat_2.desc ...@@ -292,6 +292,115 @@ _cat_2.desc
{ "parent_id", 2 }, { "parent_id", 2 },
{ "desc", "moet fout gaan" } { "desc", "moet fout gaan" }
}), std::exception); }), std::exception);
}
// --------------------------------------------------------------------
BOOST_AUTO_TEST_CASE(d2)
{
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 ...
;
ucode char
'[][_,.;:"&<>()/\{}'`~!@#$%A-Za-z0-9*|+-]*'
; code item types/single words, case insensitive
;
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_type.code code
save_
save__cat_1.c
_item.name '_cat_1.c'
_item.category_id cat_1
_item.mandatory_code yes
_item_type.code ucode
save_
)";
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);
std::istream is_dict(&buffer);
cif::File f;
f.loadDictionary(is_dict);
// --------------------------------------------------------------------
const char data[] = R"(
data_test
loop_
_cat_1.id
_cat_1.c
aap Aap
noot Noot
mies Mies
)";
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);
f.load(is_data);
auto& cat1 = f.firstDatablock()["cat_1"];
BOOST_CHECK(cat1.size() == 3);
cat1.erase(cif::Key("id") == "AAP");
BOOST_CHECK(cat1.size() == 3);
cat1.erase(cif::Key("id") == "noot");
BOOST_CHECK(cat1.size() == 2);
} }
\ No newline at end of file
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