Commit 766d5a4d by Maarten L. Hekkelman

case insensitve match, when defined by dictionary

parent 1f24937e
......@@ -365,20 +365,36 @@ namespace detail
return result;
}
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
template<typename T, std::enable_if_t<std::is_same_v<T, std::string>, int> = 0>
int compare(const T& rhs) const
{
return -rhs.compare(c_str());
}
template<typename T, std::enable_if_t<std::is_same_v<T, std::string>, int> = 0>
int icompare(const T& rhs) const
{
return cif::icompare(c_str(), value.c_str());
return cif::icompare(c_str(), rhs);
}
// int compare(const char* rhs) const
// {
// return std::strcmp(c_str(), rhs);
// }
// int icompare(const char* rhs) const
// {
// return cif::icompare(c_str(), rhs);
// }
int compare(const ItemReference& rhs) const
{
return std::strcmp(c_str(), rhs.c_str());
}
int icompare(const std::string& value) const
int icompare(const ItemReference& rhs) const
{
return cif::icompare(c_str(), value.c_str());
return cif::icompare(c_str(), rhs.c_str());
}
// empty means either null or unknown
......@@ -818,12 +834,13 @@ struct KeyCompareConditionImpl : public ConditionImpl
virtual bool test(const Category& c, const Row& r) const
{
return mComp(c, r);
return mComp(c, r, mCaseInsensitive);
}
std::string mItemTag;
size_t mItemIx;
std::function<bool(const Category&, const Row&)> mComp;
bool mCaseInsensitive = false;
std::function<bool(const Category&, const Row&, bool)> mComp;
};
struct KeyMatchesConditionImpl : public ConditionImpl
......@@ -998,15 +1015,21 @@ struct Key
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].compare(v) > 0; }));
return Condition(new detail::KeyCompareConditionImpl(key.mItemTag, [tag = key.mItemTag, v](const Category& c, const Row& r, bool icase)
{ return r[tag].compare(v) == 0; }));
}
inline Condition operator==(const Key& key, const char* v)
{
std::string value(v ? v : "");
return Condition(new detail::KeyCompareConditionImpl(key.mItemTag, [tag = key.mItemTag, value](const Category& c, const Row& r)
{ return r[tag].compare(value) == 0; }));
return Condition(new detail::KeyCompareConditionImpl(key.mItemTag, [tag = key.mItemTag, value](const Category& c, const Row& r, bool icase)
{ return (icase ? r[tag].icompare(value) : r[tag].compare(value)) == 0; }));
}
inline Condition operator==(const Key& key, const std::string& v)
{
return Condition(new detail::KeyCompareConditionImpl(key.mItemTag, [tag = key.mItemTag, v](const Category& c, const Row& r, bool icase)
{ return (icase ? r[tag].icompare(v) : r[tag].compare(v)) == 0; }));
}
inline Condition operator==(const Key& key, const detail::ItemReference& v)
......@@ -1014,8 +1037,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::KeyCompareConditionImpl(key.mItemTag, [tag = key.mItemTag, v](const Category& c, const Row& r)
{ return r[tag].compare(v); }));
return Condition(new detail::KeyCompareConditionImpl(key.mItemTag, [tag = key.mItemTag, v](const Category& c, const Row& r, bool icase)
{ return icase ? r[tag].icompare(v) : r[tag].compare(v); }));
}
inline Condition operator==(const Key& key, const Empty&)
......@@ -1038,7 +1061,7 @@ inline Condition operator!=(const Key& key, const char* v)
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 Condition(new detail::KeyCompareConditionImpl(key.mItemTag, [tag = key.mItemTag, v](const Category& c, const Row& r, bool icase)
{ return r[tag].compare(v) > 0; }));
}
......@@ -1063,6 +1086,62 @@ Condition operator<=(const Key& key, const T& v)
{ return r[tag].compare(v) <= 0; }));
}
template<typename T>
Condition operator>(const Key& key, const char* v)
{
return Condition(new detail::KeyCompareConditionImpl(key.mItemTag, [tag = key.mItemTag, v](const Category& c, const Row& r, bool icase)
{ return (icase ? r[tag].template icompare<std::string>(v) : r[tag].template compare<std::string>(v)) > 0; }));
}
template<typename T>
Condition operator>=(const Key& key, const char* v)
{
return Condition(new detail::KeyCompareConditionImpl(key.mItemTag, [tag = key.mItemTag, v](const Category& c, const Row& r, bool icase)
{ return (icase ? r[tag].template icompare<std::string>(v) : r[tag].template compare<std::string>(v)) >= 0; }));
}
template<typename T>
Condition operator<(const Key& key, const char* v)
{
return Condition(new detail::KeyCompareConditionImpl(key.mItemTag, [tag = key.mItemTag, v](const Category& c, const Row& r, bool icase)
{ return (icase ? r[tag].template icompare<std::string>(v) : r[tag].template compare<std::string>(v)) < 0; }));
}
template<typename T>
Condition operator<=(const Key& key, const char* v)
{
return Condition(new detail::KeyCompareConditionImpl(key.mItemTag, [tag = key.mItemTag, v](const Category& c, const Row& r, bool icase)
{ return (icase ? r[tag].template icompare<std::string>(v) : r[tag].template compare<std::string>(v)) <= 0; }));
}
template<typename T>
Condition operator>(const Key& key, const std::string& v)
{
return Condition(new detail::KeyCompareConditionImpl(key.mItemTag, [tag = key.mItemTag, v](const Category& c, const Row& r, bool icase)
{ return (icase ? r[tag].icompare(v) : r[tag].compare(v)) > 0; }));
}
template<typename T>
Condition operator>=(const Key& key, const std::string& v)
{
return Condition(new detail::KeyCompareConditionImpl(key.mItemTag, [tag = key.mItemTag, v](const Category& c, const Row& r, bool icase)
{ return (icase ? r[tag].icompare(v) : r[tag].compare(v)) >= 0; }));
}
template<typename T>
Condition operator<(const Key& key, const std::string& v)
{
return Condition(new detail::KeyCompareConditionImpl(key.mItemTag, [tag = key.mItemTag, v](const Category& c, const Row& r, bool icase)
{ return (icase ? r[tag].icompare(v) : r[tag].compare(v)) < 0; }));
}
template<typename T>
Condition operator<=(const Key& key, const std::string& v)
{
return Condition(new detail::KeyCompareConditionImpl(key.mItemTag, [tag = key.mItemTag, v](const Category& c, const Row& r, bool icase)
{ return (icase ? r[tag].icompare(v) : r[tag].compare(v)) <= 0; }));
}
template<>
inline
Condition operator==(const Key& key, const std::regex& rx)
......@@ -1670,16 +1749,6 @@ inline void swap(cif::detail::ItemReference& a, cif::detail::ItemReference& b)
a.swap(b);
}
namespace detail
{
inline void KeyCompareConditionImpl::prepare(const Category& c)
{
mItemIx = c.getColumnIndex(mItemTag);
}
}
// --------------------------------------------------------------------
template<typename RowType>
......
......@@ -50,9 +50,9 @@ class ValidationError : public std::exception
// --------------------------------------------------------------------
enum DDL_PrimitiveType
enum class DDL_PrimitiveType
{
ptChar, ptUChar, ptNumb
Char, UChar, Numb
};
DDL_PrimitiveType mapToPrimitiveType(const std::string& s);
......
......@@ -569,14 +569,21 @@ 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 KeyCompareConditionImpl::prepare(const Category& c)
{
mItemIx = c.getColumnIndex(mItemTag);
auto cv = c.getCatValidator();
if (cv)
{
auto iv = cv->getValidatorForItem(mItemTag);
if (iv != nullptr and iv->mType != nullptr)
{
auto type = iv->mType;
mCaseInsensitive = type->mPrimitiveType == DDL_PrimitiveType::UChar;
}
}
}
void KeyIsEmptyConditionImpl::prepare(const Category& c)
{
......
......@@ -53,11 +53,11 @@ DDL_PrimitiveType mapToPrimitiveType(const std::string& s)
{
DDL_PrimitiveType result;
if (iequals(s, "char"))
result = ptChar;
result = DDL_PrimitiveType::Char;
else if (iequals(s, "uchar"))
result = ptUChar;
result = DDL_PrimitiveType::UChar;
else if (iequals(s, "numb"))
result = ptNumb;
result = DDL_PrimitiveType::Numb;
else
throw ValidationError("Not a known primitive type");
return result;
......@@ -79,7 +79,7 @@ int ValidateType::compare(const char* a, const char* b) const
{
switch (mPrimitiveType)
{
case ptNumb:
case DDL_PrimitiveType::Numb:
{
double da = strtod(a, nullptr);
double db = strtod(b, nullptr);
......@@ -95,8 +95,8 @@ int ValidateType::compare(const char* a, const char* b) const
break;
}
case ptUChar:
case ptChar:
case DDL_PrimitiveType::UChar:
case DDL_PrimitiveType::Char:
{
// CIF is guaranteed to have ascii only, therefore this primitive code will do
// also, we're collapsing spaces
......@@ -119,7 +119,7 @@ int ValidateType::compare(const char* a, const char* b) const
char ca = *ai;
char cb = *bi;
if (mPrimitiveType == ptUChar)
if (mPrimitiveType == DDL_PrimitiveType::UChar)
{
ca = toupper(ca);
cb = toupper(cb);
......@@ -238,7 +238,7 @@ const ValidateType* Validator::getValidatorForType(std::string typeCode) const
{
const ValidateType* result = nullptr;
auto i = mTypeValidators.find(ValidateType{ typeCode, ptChar, std::regex() });
auto i = mTypeValidators.find(ValidateType{ typeCode, DDL_PrimitiveType::Char, std::regex() });
if (i != mTypeValidators.end())
result = &*i;
else if (VERBOSE > 4)
......
......@@ -318,7 +318,7 @@ data_test_dict.dic
'[][_,.;:"&<>()/\{}'`~!@#$%A-Za-z0-9*|+-]*'
; code item types/single words ...
;
ucode char
ucode uchar
'[][_,.;:"&<>()/\{}'`~!@#$%A-Za-z0-9*|+-]*'
; code item types/single words, case insensitive
;
......
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