Fix missing string comparisons

This commit is contained in:
rexy712 2022-05-21 22:42:21 -07:00
parent 1ece6dccca
commit d9f44cfeda

View File

@ -441,15 +441,41 @@ namespace rexy{
template<class Left, class Right>
string_cat_expr(Left&&,Right&&) -> string_cat_expr<Left&&,Right&&>;
namespace detail{
template<class Left, class Right>
constexpr int string_compare(Left&& left, Right&& right, size_t maxlen){
for(size_t i = 0;i < maxlen;++i){
const auto diff = left[i] - right[i];
if(diff != 0){
return diff;
}
if(left[i] == 0 || right[i] == 0){
return diff;
}
}
return 0;
}
template<class Str>
constexpr size_t string_len(const Str* str){
if(!str){
return 0;
}
size_t i;
for(i = 0;str[i] != 0;++i);
return i;
}
}
#if __cplusplus >= 202002L
template<class T>
concept BasicString = requires(T a){
{a.length()} -> std::same_as<typename std::decay_t<T>::size_type>;
{a.c_str()} -> std::same_as<typename std::decay_t<T>::const_pointer>;
{a[0]} -> std::same_as<typename std::decay_t<T>::const_reference>;
{a.begin()} -> std::same_as<typename std::decay_t<T>::const_iterator>;
{a.end()} -> std::same_as<typename std::decay_t<T>::const_iterator>;
concept BasicString = requires(const T& a){
{std::as_const(a).length()} -> std::convertible_to<typename std::decay_t<T>::size_type>;
{std::as_const(a).c_str()} -> std::convertible_to<typename std::decay_t<T>::const_pointer>;
{std::as_const(a)[0]} -> std::convertible_to<typename std::decay_t<T>::const_reference>;
{std::as_const(a).begin()} -> std::convertible_to<typename std::decay_t<T>::const_iterator>;
{std::as_const(a).end()} -> std::convertible_to<typename std::decay_t<T>::const_iterator>;
};
template<class T>
concept StringExpr = rexy::is_template_type<T,string_cat_expr>::value;
@ -484,12 +510,47 @@ namespace rexy{
//Compare
template<BasicString Str1, BasicString Str2>
constexpr bool operator==(Str1&& left, Str2&& right){
return left.length() == right.length() && !strcmp(left.c_str(), right.c_str());
if(left.length() != right.length()){
return false;
}
return !detail::string_compare(std::forward<Str1>(left), std::forward<Str2>(right), left.length());
}
template<BasicString Str1>
constexpr bool operator==(Str1&& left, typename std::decay_t<Str1>::const_pointer right){
if(right == nullptr){
return false;
}
const auto rlen = detail::string_len(right);
if(rlen != left.length()){
return false;
}
const auto minlen = min(left.length(), rlen);
return !detail::string_compare(left.c_str(), right, minlen+1);
}
template<BasicString Str1>
constexpr bool operator==(typename std::decay_t<Str1>::const_pointer left, Str1&& right){
if(left == nullptr){
return false;
}
const auto llen = detail::string_len(left);
if(llen != right.length()){
return false;
}
const auto minlen = min(right.length(), llen);
return !detail::string_compare(right.c_str(), left, minlen+1);
}
template<BasicString Str1, BasicString Str2>
constexpr bool operator!=(Str1&& left, Str2&& right){
return !(std::forward<Str1>(left) == std::forward<Str2>(right));
}
template<BasicString Str1>
constexpr bool operator!=(Str1&& left, typename std::decay_t<Str1>::const_pointer right){
return !(std::forward<Str1>(left) == right);
}
template<BasicString Str1>
constexpr bool operator!=(typename std::decay_t<Str1>::const_pointer left, Str1&& right){
return !(left == std::forward<Str1>(right));
}
//String + string concat
template<String Left, String Right>
@ -533,7 +594,7 @@ namespace rexy{
struct has_##fun##_f{ \
std::false_type check(...); \
template<class type> \
auto check(type* u) -> std::enable_if<std::is_same_v<std::declval<type>().fun(__VA_ARGS__),ret>,std::true_type>; \
auto check(type* u) -> std::enable_if<std::is_convertible_v<std::declval<type>().fun(__VA_ARGS__),ret>,std::true_type>; \
\
static constexpr bool value = decltype(check(std::declval<T*>()))::value; \
}; \
@ -545,7 +606,7 @@ namespace rexy{
struct has_##opname##_f{ \
std::false_type check(...); \
template<class type> \
auto check(type* u) -> std::enable_if<std::is_same_v<std::declval<type>().operator op(__VA_ARGS__),ret>,std::true_type>; \
auto check(type* u) -> std::enable_if<std::is_convertible_v<std::declval<type>().operator op(__VA_ARGS__),ret>,std::true_type>; \
\
static constexpr bool value = decltype(check(std::declval<T*>()))::value; \
}; \
@ -590,12 +651,47 @@ namespace rexy{
//Compare
template<class Str1, class Str2, std::enable_if_t<are_strings<Str1, Str2>::value,int> = 0>
constexpr bool operator==(Str1&& left, Str2&& right){
return left.length() == right.length() && !strcmp(left.c_str(), right.c_str());
if(left.length() != right.length()){
return false;
}
return !detail::string_compare(std::forward<Str1>(left), std::forward<Str2>(right), left.length());
}
template<class Str1, std::enable_if_t<are_strings<Str1>::value,int> = 0>
constexpr bool operator==(Str1&& left, typename std::decay_t<Str1>::const_pointer right){
if(right == nullptr){
return false;
}
const auto rlen = detail::string_len(right);
if(rlen != left.length()){
return false;
}
const auto minlen = min(left.length(), rlen);
return !detail::string_compare(left.c_str(), right, minlen+1);
}
template<class Str1, std::enable_if_t<are_strings<Str1>::value,int> = 0>
constexpr bool operator==(typename std::decay_t<Str1>::const_pointer left, Str1&& right){
if(left == nullptr){
return false;
}
const auto llen = detail::string_len(left);
if(llen != right.length()){
return false;
}
const auto minlen = min(right.length(), llen);
return !detail::string_compare(right.c_str(), left, minlen+1);
}
template<class Str1, class Str2, std::enable_if_t<are_strings<Str1, Str2>::value,int> = 0>
constexpr bool operator!=(Str1&& left, Str2&& right)noexcept{
return !(std::forward<Str1>(left) == std::forward<Str2>(right));
}
template<class Str1, std::enable_if_t<are_strings<Str1>::value,int> = 0>
constexpr bool operator!=(Str1&& left, typename std::decay_t<Str1>::const_pointer right)noexcept{
return !(std::forward<Str1>(left) == right);
}
template<class Str1, std::enable_if_t<are_strings<Str1>::value,int> = 0>
constexpr bool operator!=(typename std::decay_t<Str1>::const_pointer left, Str1&& right)noexcept{
return !(left == std::forward<Str1>(right));
}
//String + string concat
template<class Left, class Right, std::enable_if_t<are_strings<Left, Right>::value,int> = 0>