/** 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