mirror of
https://github.com/matrix-construct/construct
synced 2024-11-25 08:12:37 +01:00
ircd: Split out overgrown components from stringops.h
This commit is contained in:
parent
d53744b3f8
commit
de94e95422
8 changed files with 383 additions and 325 deletions
127
include/ircd/cmp.h
Normal file
127
include/ircd/cmp.h
Normal file
|
@ -0,0 +1,127 @@
|
|||
// Matrix Construct
|
||||
//
|
||||
// Copyright (C) Matrix Construct Developers, Authors & Contributors
|
||||
// Copyright (C) 2016-2019 Jason Volk <jason@zemos.net>
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice is present in all copies. The
|
||||
// full license for this software is available in the LICENSE file.
|
||||
|
||||
#pragma once
|
||||
#define HAVE_IRCD_CMP_H
|
||||
|
||||
// Simple case insensitive comparison convenience utils
|
||||
namespace ircd
|
||||
{
|
||||
struct iless;
|
||||
struct igreater;
|
||||
struct iequals;
|
||||
}
|
||||
|
||||
/// Case insensitive string comparison deciding if two strings are equal
|
||||
struct ircd::iequals
|
||||
{
|
||||
using is_transparent = std::true_type;
|
||||
|
||||
bool s;
|
||||
|
||||
operator const bool &() const
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
bool operator()(const string_view &a, const string_view &b) const;
|
||||
|
||||
template<class A,
|
||||
class B>
|
||||
iequals(A&& a, B&& b)
|
||||
:s{operator()(std::forward<A>(a), std::forward<B>(b))}
|
||||
{}
|
||||
|
||||
iequals() = default;
|
||||
};
|
||||
|
||||
inline bool
|
||||
ircd::iequals::operator()(const string_view &a,
|
||||
const string_view &b)
|
||||
const
|
||||
{
|
||||
return std::equal(begin(a), end(a), begin(b), end(b), []
|
||||
(const char &a, const char &b)
|
||||
{
|
||||
return tolower(a) == tolower(b);
|
||||
});
|
||||
}
|
||||
|
||||
/// Case insensitive string comparison deciding which string compares 'less'
|
||||
/// than the other.
|
||||
struct ircd::iless
|
||||
{
|
||||
using is_transparent = std::true_type;
|
||||
|
||||
bool s;
|
||||
|
||||
operator const bool &() const
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
bool operator()(const string_view &a, const string_view &b) const;
|
||||
|
||||
template<class A,
|
||||
class B>
|
||||
iless(A&& a, B&& b)
|
||||
:s{operator()(std::forward<A>(a), std::forward<B>(b))}
|
||||
{}
|
||||
|
||||
iless() = default;
|
||||
};
|
||||
|
||||
inline bool
|
||||
ircd::iless::operator()(const string_view &a,
|
||||
const string_view &b)
|
||||
const
|
||||
{
|
||||
return std::lexicographical_compare(begin(a), end(a), begin(b), end(b), []
|
||||
(const char &a, const char &b)
|
||||
{
|
||||
return tolower(a) < tolower(b);
|
||||
});
|
||||
}
|
||||
|
||||
/// Case insensitive string comparison deciding which string compares 'greater'
|
||||
/// than the other.
|
||||
struct ircd::igreater
|
||||
{
|
||||
using is_transparent = std::true_type;
|
||||
|
||||
bool s;
|
||||
|
||||
operator const bool &() const
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
bool operator()(const string_view &a, const string_view &b) const;
|
||||
|
||||
template<class A,
|
||||
class B>
|
||||
igreater(A&& a, B&& b)
|
||||
:s{operator()(std::forward<A>(a), std::forward<B>(b))}
|
||||
{}
|
||||
|
||||
igreater() = default;
|
||||
};
|
||||
|
||||
inline bool
|
||||
ircd::igreater::operator()(const string_view &a,
|
||||
const string_view &b)
|
||||
const
|
||||
{
|
||||
return std::lexicographical_compare(begin(a), end(a), begin(b), end(b), []
|
||||
(const char &a, const char &b)
|
||||
{
|
||||
return tolower(a) > tolower(b);
|
||||
});
|
||||
}
|
74
include/ircd/globular.h
Normal file
74
include/ircd/globular.h
Normal file
|
@ -0,0 +1,74 @@
|
|||
// Matrix Construct
|
||||
//
|
||||
// Copyright (C) Matrix Construct Developers, Authors & Contributors
|
||||
// Copyright (C) 2016-2019 Jason Volk <jason@zemos.net>
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice is present in all copies. The
|
||||
// full license for this software is available in the LICENSE file.
|
||||
|
||||
#pragma once
|
||||
#define HAVE_IRCD_GLOBULAR_H
|
||||
|
||||
namespace ircd
|
||||
{
|
||||
// Globular ('*' and '?') expression utils.
|
||||
struct globular_match;
|
||||
struct globular_equals;
|
||||
}
|
||||
|
||||
/// Globular equals. This allows either side of the comparison to include '*'
|
||||
/// and '?' characters and equality of the string expressions will be
|
||||
/// determined.
|
||||
struct ircd::globular_equals
|
||||
{
|
||||
using is_transparent = std::true_type;
|
||||
|
||||
bool s;
|
||||
|
||||
operator const bool &() const
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
bool operator()(const string_view &a, const string_view &b) const;
|
||||
|
||||
template<class A,
|
||||
class B>
|
||||
globular_equals(A&& a, B&& b)
|
||||
:s{operator()(std::forward<A>(a), std::forward<B>(b))}
|
||||
{}
|
||||
|
||||
globular_equals() = default;
|
||||
};
|
||||
|
||||
/// Globular match. Similar to globular_equals but only one side of the
|
||||
/// comparison is considered to be the expression with '*' and '?' characters.
|
||||
/// The expression string is passed at construction. The comparison inputs are
|
||||
/// treated as non-expression strings. This allows for greater optimization
|
||||
/// than globular_equals.
|
||||
struct ircd::globular_match
|
||||
{
|
||||
string_view expr;
|
||||
bool s;
|
||||
|
||||
operator const bool &() const
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
bool operator()(const string_view &a) const;
|
||||
|
||||
globular_match(const string_view &expr)
|
||||
:expr{expr}
|
||||
{}
|
||||
|
||||
template<class A>
|
||||
globular_match(const string_view &expr, A&& a)
|
||||
:expr{expr}
|
||||
,s{operator()(std::forward<A>(a))}
|
||||
{}
|
||||
|
||||
globular_match() = default;
|
||||
};
|
|
@ -36,6 +36,9 @@
|
|||
#include "lex_cast.h"
|
||||
#include "base.h"
|
||||
#include "stringops.h"
|
||||
#include "strl.h"
|
||||
#include "cmp.h"
|
||||
#include "globular.h"
|
||||
#include "tokens.h"
|
||||
#include "iov.h"
|
||||
#include "grammar.h"
|
||||
|
|
|
@ -16,19 +16,6 @@
|
|||
//
|
||||
namespace ircd
|
||||
{
|
||||
// Simple case insensitive comparison convenience utils
|
||||
struct iless;
|
||||
struct igreater;
|
||||
struct iequals;
|
||||
|
||||
// Globular ('*' and '?') expression utils.
|
||||
struct globular_match;
|
||||
struct globular_equals;
|
||||
|
||||
// Vintage
|
||||
struct strlcpy;
|
||||
struct strlcat;
|
||||
|
||||
// wrapper to find(T) != npos
|
||||
template<class T> bool has(const string_view &, const T &);
|
||||
inline bool ihas(const string_view &s, const string_view &t);
|
||||
|
@ -108,259 +95,6 @@ namespace ircd
|
|||
string_view trunc(const string_view &, const size_t &max);
|
||||
}
|
||||
|
||||
/// This is a function. It works the same as the standard strlcpy() but it has
|
||||
/// some useful modernizations and may be informally referred to as strlcpy++.
|
||||
///
|
||||
/// - It optionally works with string_view inputs and ircd::buffer outputs.
|
||||
/// This allows for implicit size parameters and increases its safety while
|
||||
/// simplifying its usage (no more sizeof(buf) where buf coderots into char*).
|
||||
///
|
||||
/// - Its objectification allows for a configurable return type. The old
|
||||
/// strlcpy() returned a size integer type. When using string_view's and
|
||||
/// buffers this would generally lead to the pattern { dst, strlcpy(dst, src) }
|
||||
/// and this is no longer necessary.
|
||||
///
|
||||
struct ircd::strlcpy
|
||||
{
|
||||
mutable_buffer ret;
|
||||
|
||||
public:
|
||||
operator string_view() const
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
operator size_t() const
|
||||
{
|
||||
return size(ret);
|
||||
}
|
||||
|
||||
strlcpy(char *const &dst, const string_view &src, const size_t &max)
|
||||
:ret{[&]() -> mutable_buffer
|
||||
{
|
||||
if(!max)
|
||||
return {};
|
||||
|
||||
const auto len{std::min(src.size(), max - 1)};
|
||||
memcpy(dst, src.data(), len);
|
||||
dst[len] = '\0';
|
||||
return { dst, len };
|
||||
}()}
|
||||
{}
|
||||
|
||||
#ifndef HAVE_STRLCPY
|
||||
strlcpy(char *const &dst, const char *const &src, const size_t &max)
|
||||
:strlcpy{dst, string_view{src, strnlen(src, max)}, max}
|
||||
{}
|
||||
#endif
|
||||
|
||||
strlcpy(const mutable_buffer &dst, const string_view &src)
|
||||
:strlcpy{data(dst), src, size(dst)}
|
||||
{}
|
||||
};
|
||||
|
||||
/// This is a function. It works the same as the standard strlcat() but it has
|
||||
/// some useful modernizations and may be informally referred to as strlcat++.
|
||||
/// see: ircd::strlcpy().
|
||||
///
|
||||
struct ircd::strlcat
|
||||
{
|
||||
mutable_buffer ret;
|
||||
|
||||
public:
|
||||
operator string_view() const
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
operator size_t() const
|
||||
{
|
||||
return size(ret);
|
||||
}
|
||||
|
||||
strlcat(char *const &dst, const string_view &src, const size_t &max)
|
||||
:ret{[&]() -> mutable_buffer
|
||||
{
|
||||
const auto pos{strnlen(dst, max)};
|
||||
const auto remain{max - pos};
|
||||
strlcpy(dst + pos, src, remain);
|
||||
return { dst, pos + src.size() };
|
||||
}()}
|
||||
{}
|
||||
|
||||
#ifndef HAVE_STRLCAT
|
||||
strlcat(char *const &dst, const char *const &src, const size_t &max)
|
||||
:strlcat{dst, string_view{src, ::strnlen(src, max)}, max}
|
||||
{}
|
||||
#endif
|
||||
|
||||
strlcat(const mutable_buffer &dst, const string_view &src)
|
||||
:strlcat{data(dst), src, size(dst)}
|
||||
{}
|
||||
};
|
||||
|
||||
/// Case insensitive string comparison deciding if two strings are equal
|
||||
struct ircd::iequals
|
||||
{
|
||||
using is_transparent = std::true_type;
|
||||
|
||||
bool s;
|
||||
|
||||
operator const bool &() const
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
bool operator()(const string_view &a, const string_view &b) const;
|
||||
|
||||
template<class A,
|
||||
class B>
|
||||
iequals(A&& a, B&& b)
|
||||
:s{operator()(std::forward<A>(a), std::forward<B>(b))}
|
||||
{}
|
||||
|
||||
iequals() = default;
|
||||
};
|
||||
|
||||
inline bool
|
||||
ircd::iequals::operator()(const string_view &a,
|
||||
const string_view &b)
|
||||
const
|
||||
{
|
||||
return std::equal(begin(a), end(a), begin(b), end(b), []
|
||||
(const char &a, const char &b)
|
||||
{
|
||||
return tolower(a) == tolower(b);
|
||||
});
|
||||
}
|
||||
|
||||
/// Case insensitive string comparison deciding which string compares 'less'
|
||||
/// than the other.
|
||||
struct ircd::iless
|
||||
{
|
||||
using is_transparent = std::true_type;
|
||||
|
||||
bool s;
|
||||
|
||||
operator const bool &() const
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
bool operator()(const string_view &a, const string_view &b) const;
|
||||
|
||||
template<class A,
|
||||
class B>
|
||||
iless(A&& a, B&& b)
|
||||
:s{operator()(std::forward<A>(a), std::forward<B>(b))}
|
||||
{}
|
||||
|
||||
iless() = default;
|
||||
};
|
||||
|
||||
inline bool
|
||||
ircd::iless::operator()(const string_view &a,
|
||||
const string_view &b)
|
||||
const
|
||||
{
|
||||
return std::lexicographical_compare(begin(a), end(a), begin(b), end(b), []
|
||||
(const char &a, const char &b)
|
||||
{
|
||||
return tolower(a) < tolower(b);
|
||||
});
|
||||
}
|
||||
|
||||
/// Case insensitive string comparison deciding which string compares 'greater'
|
||||
/// than the other.
|
||||
struct ircd::igreater
|
||||
{
|
||||
using is_transparent = std::true_type;
|
||||
|
||||
bool s;
|
||||
|
||||
operator const bool &() const
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
bool operator()(const string_view &a, const string_view &b) const;
|
||||
|
||||
template<class A,
|
||||
class B>
|
||||
igreater(A&& a, B&& b)
|
||||
:s{operator()(std::forward<A>(a), std::forward<B>(b))}
|
||||
{}
|
||||
|
||||
igreater() = default;
|
||||
};
|
||||
|
||||
inline bool
|
||||
ircd::igreater::operator()(const string_view &a,
|
||||
const string_view &b)
|
||||
const
|
||||
{
|
||||
return std::lexicographical_compare(begin(a), end(a), begin(b), end(b), []
|
||||
(const char &a, const char &b)
|
||||
{
|
||||
return tolower(a) > tolower(b);
|
||||
});
|
||||
}
|
||||
|
||||
/// Globular equals. This allows either side of the comparison to include '*'
|
||||
/// and '?' characters and equality of the string expressions will be
|
||||
/// determined.
|
||||
struct ircd::globular_equals
|
||||
{
|
||||
using is_transparent = std::true_type;
|
||||
|
||||
bool s;
|
||||
|
||||
operator const bool &() const
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
bool operator()(const string_view &a, const string_view &b) const;
|
||||
|
||||
template<class A,
|
||||
class B>
|
||||
globular_equals(A&& a, B&& b)
|
||||
:s{operator()(std::forward<A>(a), std::forward<B>(b))}
|
||||
{}
|
||||
|
||||
globular_equals() = default;
|
||||
};
|
||||
|
||||
/// Globular match. Similar to globular_equals but only one side of the
|
||||
/// comparison is considered to be the expression with '*' and '?' characters.
|
||||
/// The expression string is passed at construction. The comparison inputs are
|
||||
/// treated as non-expression strings. This allows for greater optimization
|
||||
/// than globular_equals.
|
||||
struct ircd::globular_match
|
||||
{
|
||||
string_view expr;
|
||||
bool s;
|
||||
|
||||
operator const bool &() const
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
bool operator()(const string_view &a) const;
|
||||
|
||||
globular_match(const string_view &expr)
|
||||
:expr{expr}
|
||||
{}
|
||||
|
||||
template<class A>
|
||||
globular_match(const string_view &expr, A&& a)
|
||||
:expr{expr}
|
||||
,s{operator()(std::forward<A>(a))}
|
||||
{}
|
||||
|
||||
globular_match() = default;
|
||||
};
|
||||
|
||||
inline ircd::string_view
|
||||
ircd::trunc(const string_view &s,
|
||||
const size_t &max)
|
||||
|
|
110
include/ircd/strl.h
Normal file
110
include/ircd/strl.h
Normal file
|
@ -0,0 +1,110 @@
|
|||
// Matrix Construct
|
||||
//
|
||||
// Copyright (C) Matrix Construct Developers, Authors & Contributors
|
||||
// Copyright (C) 2016-2019 Jason Volk <jason@zemos.net>
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice is present in all copies. The
|
||||
// full license for this software is available in the LICENSE file.
|
||||
|
||||
#pragma once
|
||||
#define HAVE_IRCD_STRL_H
|
||||
|
||||
// Vintage
|
||||
namespace ircd
|
||||
{
|
||||
struct strlcpy;
|
||||
struct strlcat;
|
||||
}
|
||||
|
||||
/// This is a function. It works the same as the standard strlcpy() but it has
|
||||
/// some useful modernizations and may be informally referred to as strlcpy++.
|
||||
///
|
||||
/// - It optionally works with string_view inputs and ircd::buffer outputs.
|
||||
/// This allows for implicit size parameters and increases its safety while
|
||||
/// simplifying its usage (no more sizeof(buf) where buf coderots into char*).
|
||||
///
|
||||
/// - Its objectification allows for a configurable return type. The old
|
||||
/// strlcpy() returned a size integer type. When using string_view's and
|
||||
/// buffers this would generally lead to the pattern { dst, strlcpy(dst, src) }
|
||||
/// and this is no longer necessary.
|
||||
///
|
||||
struct ircd::strlcpy
|
||||
{
|
||||
mutable_buffer ret;
|
||||
|
||||
public:
|
||||
operator string_view() const
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
operator size_t() const
|
||||
{
|
||||
return size(ret);
|
||||
}
|
||||
|
||||
strlcpy(char *const &dst, const string_view &src, const size_t &max)
|
||||
:ret{[&]() -> mutable_buffer
|
||||
{
|
||||
if(!max)
|
||||
return {};
|
||||
|
||||
const auto len{std::min(src.size(), max - 1)};
|
||||
memcpy(dst, src.data(), len);
|
||||
dst[len] = '\0';
|
||||
return { dst, len };
|
||||
}()}
|
||||
{}
|
||||
|
||||
#ifndef HAVE_STRLCPY
|
||||
strlcpy(char *const &dst, const char *const &src, const size_t &max)
|
||||
:strlcpy{dst, string_view{src, strnlen(src, max)}, max}
|
||||
{}
|
||||
#endif
|
||||
|
||||
strlcpy(const mutable_buffer &dst, const string_view &src)
|
||||
:strlcpy{data(dst), src, size(dst)}
|
||||
{}
|
||||
};
|
||||
|
||||
/// This is a function. It works the same as the standard strlcat() but it has
|
||||
/// some useful modernizations and may be informally referred to as strlcat++.
|
||||
/// see: ircd::strlcpy().
|
||||
///
|
||||
struct ircd::strlcat
|
||||
{
|
||||
mutable_buffer ret;
|
||||
|
||||
public:
|
||||
operator string_view() const
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
operator size_t() const
|
||||
{
|
||||
return size(ret);
|
||||
}
|
||||
|
||||
strlcat(char *const &dst, const string_view &src, const size_t &max)
|
||||
:ret{[&]() -> mutable_buffer
|
||||
{
|
||||
const auto pos{strnlen(dst, max)};
|
||||
const auto remain{max - pos};
|
||||
strlcpy(dst + pos, src, remain);
|
||||
return { dst, pos + src.size() };
|
||||
}()}
|
||||
{}
|
||||
|
||||
#ifndef HAVE_STRLCAT
|
||||
strlcat(char *const &dst, const char *const &src, const size_t &max)
|
||||
:strlcat{dst, string_view{src, ::strnlen(src, max)}, max}
|
||||
{}
|
||||
#endif
|
||||
|
||||
strlcat(const mutable_buffer &dst, const string_view &src)
|
||||
:strlcat{data(dst), src, size(dst)}
|
||||
{}
|
||||
};
|
|
@ -125,6 +125,7 @@ libircd_la_SOURCES += demangle.cc
|
|||
libircd_la_SOURCES += locale.cc
|
||||
libircd_la_SOURCES += lex_cast.cc
|
||||
libircd_la_SOURCES += stringops.cc
|
||||
libircd_la_SOURCES += globular.cc
|
||||
libircd_la_SOURCES += tokens.cc
|
||||
libircd_la_SOURCES += parse.cc
|
||||
libircd_la_SOURCES += rand.cc
|
||||
|
|
68
ircd/globular.cc
Normal file
68
ircd/globular.cc
Normal file
|
@ -0,0 +1,68 @@
|
|||
// Matrix Construct
|
||||
//
|
||||
// Copyright (C) Matrix Construct Developers, Authors & Contributors
|
||||
// Copyright (C) 2016-2019 Jason Volk <jason@zemos.net>
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice is present in all copies. The
|
||||
// full license for this software is available in the LICENSE file.
|
||||
|
||||
//
|
||||
// globular_equals
|
||||
//
|
||||
|
||||
bool
|
||||
ircd::globular_equals::operator()(const string_view &a, const string_view &b)
|
||||
const
|
||||
{
|
||||
size_t ap(0), bp(0);
|
||||
while(ap < a.size() && bp < b.size())
|
||||
{
|
||||
const auto ca(tolower(a.at(ap))), cb(tolower(b.at(bp)));
|
||||
const auto globa(ca == '*'), globb(cb == '*');
|
||||
const auto wilda(ca == '?'), wildb(cb == '?');
|
||||
|
||||
if(!globa && !globb && !wilda && !wildb && ca != cb)
|
||||
return false;
|
||||
|
||||
if((globa && ap + 1 >= a.size()) || (globb && bp + 1 >= b.size()))
|
||||
break;
|
||||
|
||||
if(globa && cb == tolower(a.at(ap + 1)))
|
||||
ap += 2;
|
||||
|
||||
if(globb && ca == tolower(b.at(bp + 1)))
|
||||
bp += 2;
|
||||
|
||||
if(globa && globb)
|
||||
++ap, ++bp;
|
||||
|
||||
if(!globa)
|
||||
++ap;
|
||||
|
||||
if(!globb)
|
||||
++bp;
|
||||
}
|
||||
|
||||
if(ap < a.size() && !b.empty() && b.back() == '*')
|
||||
return true;
|
||||
|
||||
if(bp < b.size() && !a.empty() && a.back() == '*')
|
||||
return true;
|
||||
|
||||
return iequals(a.substr(ap), b.substr(bp));
|
||||
}
|
||||
|
||||
//
|
||||
// globular_match
|
||||
//
|
||||
|
||||
bool
|
||||
ircd::globular_match::operator()(const string_view &a)
|
||||
const
|
||||
{
|
||||
//TODO: optimize.
|
||||
const globular_equals globular_equals(expr, a);
|
||||
return bool(globular_equals);
|
||||
}
|
|
@ -42,62 +42,3 @@ ircd::replace(const string_view &s,
|
|||
return std::distance(begin(buf), p);
|
||||
});
|
||||
}
|
||||
|
||||
//
|
||||
// globular_equals
|
||||
//
|
||||
|
||||
bool
|
||||
ircd::globular_equals::operator()(const string_view &a, const string_view &b)
|
||||
const
|
||||
{
|
||||
size_t ap(0), bp(0);
|
||||
while(ap < a.size() && bp < b.size())
|
||||
{
|
||||
const auto ca(tolower(a.at(ap))), cb(tolower(b.at(bp)));
|
||||
const auto globa(ca == '*'), globb(cb == '*');
|
||||
const auto wilda(ca == '?'), wildb(cb == '?');
|
||||
|
||||
if(!globa && !globb && !wilda && !wildb && ca != cb)
|
||||
return false;
|
||||
|
||||
if((globa && ap + 1 >= a.size()) || (globb && bp + 1 >= b.size()))
|
||||
break;
|
||||
|
||||
if(globa && cb == tolower(a.at(ap + 1)))
|
||||
ap += 2;
|
||||
|
||||
if(globb && ca == tolower(b.at(bp + 1)))
|
||||
bp += 2;
|
||||
|
||||
if(globa && globb)
|
||||
++ap, ++bp;
|
||||
|
||||
if(!globa)
|
||||
++ap;
|
||||
|
||||
if(!globb)
|
||||
++bp;
|
||||
}
|
||||
|
||||
if(ap < a.size() && !b.empty() && b.back() == '*')
|
||||
return true;
|
||||
|
||||
if(bp < b.size() && !a.empty() && a.back() == '*')
|
||||
return true;
|
||||
|
||||
return iequals(a.substr(ap), b.substr(bp));
|
||||
}
|
||||
|
||||
//
|
||||
// globular_match
|
||||
//
|
||||
|
||||
bool
|
||||
ircd::globular_match::operator()(const string_view &a)
|
||||
const
|
||||
{
|
||||
//TODO: optimize.
|
||||
const globular_equals globular_equals(expr, a);
|
||||
return bool(globular_equals);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue