Commit 1f24937e by Maarten L. Hekkelman

simplify condtion code.

parent aba35c34
......@@ -264,7 +264,7 @@ namespace detail
{
public:
// some conversion helper classes
// conversion helper class
template<typename T, typename = void>
struct item_value_as;
......@@ -318,7 +318,7 @@ namespace detail
template<typename T, std::enable_if_t<std::is_same_v<T, char>, int> = 0>
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>
......@@ -368,7 +368,17 @@ namespace detail
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
{
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
......@@ -703,13 +713,11 @@ struct ConditionImpl
virtual void prepare(const Category& c) {}
virtual bool test(const Category& c, const Row& r) const = 0;
virtual std::string str() const = 0;
};
struct AllConditionImpl : public ConditionImpl
{
virtual bool test(const Category& c, const Row& r) const { return true; }
virtual std::string str() const { return "ALL"; }
};
struct orConditionImpl;
......@@ -761,11 +769,6 @@ class Condition
return mImpl ? mImpl->test(c, r) : false;
}
std::string str() const
{
return mImpl ? mImpl->str() : "";
}
bool empty() const { return mImpl == nullptr; }
friend Condition operator||(Condition&& a, Condition&& b);
......@@ -801,79 +804,10 @@ struct KeyIsEmptyConditionImpl : public ConditionImpl
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;
size_t mItemIx;
valueType mValue;
};
template<>
inline
std::string KeyIsNotConditionImpl<std::string>::str() const
{
return mItemTag + " != " + mValue;
}
struct KeyCompareConditionImpl : public ConditionImpl
{
template<typename COMP>
......@@ -887,11 +821,6 @@ struct KeyCompareConditionImpl : public ConditionImpl
return mComp(c, r);
}
virtual std::string str() const
{
return mItemTag + " compare";
}
std::string mItemTag;
size_t mItemIx;
std::function<bool(const Category&, const Row&)> mComp;
......@@ -909,11 +838,6 @@ struct KeyMatchesConditionImpl : public ConditionImpl
return std::regex_match(r[mItemIx].as<std::string>(), mRx);
}
virtual std::string str() const
{
return mItemTag + " ~= " + "<rx>";
}
std::string mItemTag;
size_t mItemIx;
std::regex mRx;
......@@ -929,11 +853,6 @@ struct anyIsConditionImpl : public ConditionImpl
virtual bool test(const Category& c, const Row& r) const;
virtual std::string str() const
{
return "any == " + std::to_string(mValue);
}
valueType mValue;
};
......@@ -944,11 +863,6 @@ struct anyMatchesConditionImpl : public ConditionImpl
virtual bool test(const Category& c, const Row& r) const;
virtual std::string str() const
{
return "any ~= <rx>";
}
std::regex mRx;
};
......@@ -960,11 +874,6 @@ struct allConditionImpl : public ConditionImpl
{
return true;
}
virtual std::string str() const
{
return "ALL";
}
};
struct andConditionImpl : public ConditionImpl
......@@ -993,11 +902,6 @@ struct andConditionImpl : public ConditionImpl
return mA->test(c, r) and mB->test(c, r);
}
virtual std::string str() const
{
return "(" + mA->str() + ") and (" + mB->str() + ")";
}
ConditionImpl* mA;
ConditionImpl* mB;
};
......@@ -1028,11 +932,6 @@ struct orConditionImpl : public ConditionImpl
return mA->test(c, r) or mB->test(c, r);
}
virtual std::string str() const
{
return "(" + mA->str() + ") or (" + mB->str() + ")";
}
ConditionImpl* mA;
ConditionImpl* mB;
};
......@@ -1060,11 +959,6 @@ struct notConditionImpl : public ConditionImpl
return not mA->test(c, r);
}
virtual std::string str() const
{
return "NOT (" + mA->str() + ")";
}
ConditionImpl* mA;
};
......@@ -1088,13 +982,6 @@ inline Condition operator||(Condition&& a, Condition&& b)
return Condition(std::move(b));
}
inline
std::ostream& operator<<(std::ostream& os, const Condition& rhs)
{
os << rhs.str();
return os;
}
struct Empty {};
struct Key
......@@ -1111,13 +998,15 @@ struct Key
template<typename T>
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)
{
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)
......@@ -1125,7 +1014,8 @@ inline Condition operator==(const Key& key, const detail::ItemReference& v)
if (v.empty())
return Condition(new detail::KeyIsEmptyConditionImpl(key.mItemTag));
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&)
......@@ -1136,41 +1026,41 @@ inline Condition operator==(const Key& key, const Empty&)
template<typename T>
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)
{
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>
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 r[tag].as<T>() > v; }));
{ return r[tag].compare(v) > 0; }));
}
template<typename T>
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 r[tag].as<T>() >= v; }));
{ return r[tag].compare(v) >= 0; }));
}
template<typename T>
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 r[tag].as<T>() < v; }));
{ return r[tag].compare(v) < 0; }));
}
template<typename T>
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 r[tag].as<T>() <= v; }));
{ return r[tag].compare(v) <= 0; }));
}
template<>
......@@ -1783,18 +1673,6 @@ inline void swap(cif::detail::ItemReference& a, cif::detail::ItemReference& b)
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)
{
mItemIx = c.getColumnIndex(mItemTag);
......
......@@ -28,9 +28,6 @@
#include "cif++/Cif++.hpp"
//// the std regex of gcc is crashing....
// #include <boost/regex.hpp>
#include <regex>
#include <set>
......
......@@ -569,6 +569,15 @@ void Datablock::write(std::ostream& os, const std::vector<std::string>& order)
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)
{
mItemIx = c.getColumnIndex(mItemTag);
......@@ -1766,11 +1775,11 @@ bool Category::hasParent(Row r, const Category& parentCat, const ValidateLink& l
{
result = parentCat.exists(std::move(cond));
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;
// 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;
}
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;
// 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;
return result;
}
......@@ -1795,8 +1804,8 @@ bool Category::isOrphan(Row r)
cond = std::move(cond) && (Key(link->mParentKeys[ix]) == value);
}
if (VERBOSE > 2)
std::cerr << "Check condition '" << cond << "' in parent category " << link->mParentCategory << " for child cat " << mName << std::endl;
// 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)))
{
......@@ -2702,9 +2711,9 @@ void Row::swap(size_t cix, ItemRow* a, ItemRow* b)
if (cond[ab].empty())
continue;
if (VERBOSE > 1)
std::cerr << "Fixing link from " << cat->mName << " to " << childCat->mName << " with " << std::endl
<< cond[ab] << std::endl;
// if (VERBOSE > 1)
// std::cerr << "Fixing link from " << cat->mName << " to " << childCat->mName << " with " << std::endl
// << cond[ab] << std::endl;
rs.push_back(childCat->find(std::move(cond[ab])));
}
......
......@@ -26,10 +26,6 @@
#include <boost/algorithm/string.hpp>
//// since gcc's regex is crashing....
// #include <boost/regex.hpp>
// #include <regex>
#include "cif++/Cif++.hpp"
#include "cif++/CifParser.hpp"
#include "cif++/CifValidator.hpp"
......
......@@ -292,6 +292,115 @@ _cat_2.desc
{ "parent_id", 2 },
{ "desc", "moet fout gaan" }
}), 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