/**
This file is a part of rexy's general purpose library
Copyright (C) 2022 rexy712
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
#ifndef REXY_COMPAT_CPP20_STRING_BASE_HPP
#define REXY_COMPAT_CPP20_STRING_BASE_HPP
#include "../../string_base.hpp"
#include //convertible_to
#include //forward, as_const
#include //decay, is_nothrow_assignable
namespace rexy{
template
concept BasicString = requires(const T& a){
{std::as_const(a).length()} -> std::convertible_to::size_type>;
{std::as_const(a).c_str()} -> std::convertible_to::const_pointer>;
{std::as_const(a)[0]} -> std::convertible_to::const_reference>;
{std::as_const(a).begin()} -> std::convertible_to::const_iterator>;
{std::as_const(a).end()} -> std::convertible_to::const_iterator>;
};
template
concept StringExpr = rexy::is_template_type::value;
template
concept String = BasicString || StringExpr;
template
struct is_string{
static constexpr bool value = BasicString;
};
template
static constexpr bool is_string_v = is_string::value;
template
struct are_strings{
static constexpr bool value = (BasicString && ...);
};
template
static constexpr bool are_strings_v = are_strings::value;
template
struct is_string_expr{
static constexpr bool value = StringExpr;
};
template
static constexpr bool is_string_expr_v = is_string_expr::value;
template
struct are_string_expr{
static constexpr bool value = (StringExpr && ...);
};
template
static constexpr bool are_string_expr_v = are_string_expr::value;
//Compare
template
constexpr bool operator==(Str1&& left, Str2&& right){
if(left.length() != right.length()){
return false;
}
return !detail::string_compare(std::forward(left), std::forward(right), left.length());
}
template
constexpr bool operator==(Str1&& left, typename std::decay_t::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
constexpr bool operator==(typename std::decay_t::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
constexpr bool operator!=(Str1&& left, Str2&& right){
return !(std::forward(left) == std::forward(right));
}
template
constexpr bool operator!=(Str1&& left, typename std::decay_t::const_pointer right){
return !(std::forward(left) == right);
}
template
constexpr bool operator!=(typename std::decay_t::const_pointer left, Str1&& right){
return !(left == std::forward(right));
}
//String + string concat
template
constexpr auto operator+(Left&& l, Right&& r)
//uses deduction guide whereas std::is_nothrow_constructible couldn't
noexcept(noexcept(::new (nullptr) string_cat_expr(std::forward(l), std::forward(r))))
{
return string_cat_expr(std::forward(l), std::forward(r));
}
template
constexpr auto operator+(typename std::decay_t::const_pointer left, Right&& right)
noexcept(noexcept(::new (nullptr) string_cat_expr(rexy::basic_string_view(left), std::forward(right))))
{
return string_cat_expr(rexy::basic_string_view(left), std::forward(right));
}
template
constexpr auto operator+(Left&& left, typename std::decay_t::const_pointer right)
noexcept(noexcept(::new (nullptr) string_cat_expr(std::forward(left), rexy::basic_string_view(right))))
{
return rexy::string_cat_expr(std::forward(left), rexy::basic_string_view(right));
}
//String concat assign
template
constexpr decltype(auto) operator+=(Left& l, Right&& r)
noexcept(noexcept(l + std::forward(r)) && std::is_nothrow_assignable(r))>::value)
{
return l = (l + std::forward(r));
}
template
constexpr decltype(auto) operator+=(Left& l, typename std::decay_t::const_pointer r)
noexcept(noexcept(l + r) && std::is_nothrow_assignable::value)
{
return l = (l + r);
}
}
#endif