148 lines
4.7 KiB
C++
148 lines
4.7 KiB
C++
/**
|
|
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 <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#ifndef REXY_COMPAT_CPP20_STRING_BASE_HPP
|
|
#define REXY_COMPAT_CPP20_STRING_BASE_HPP
|
|
|
|
#include "../../string_base.hpp"
|
|
|
|
#include <utility> //forward
|
|
#include <type_traits> //decay, is_nothrow_assignable
|
|
|
|
#include "../../concepts/string.hpp"
|
|
|
|
namespace rexy{
|
|
|
|
//Compare
|
|
template<BasicString Str1, BasicString Str2>
|
|
constexpr bool operator==(Str1&& left, Str2&& right){
|
|
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>
|
|
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<Left>(l), std::forward<Right>(r))))
|
|
{
|
|
return string_cat_expr(std::forward<Left>(l), std::forward<Right>(r));
|
|
}
|
|
template<String Right>
|
|
constexpr auto operator+(typename std::decay_t<Right>::const_pointer left, Right&& right)
|
|
noexcept(noexcept(::new (nullptr) string_cat_expr(rexy::basic_string_view(left), std::forward<Right>(right))))
|
|
{
|
|
return string_cat_expr(rexy::basic_string_view(left), std::forward<Right>(right));
|
|
}
|
|
template<String Left>
|
|
constexpr auto operator+(Left&& left, typename std::decay_t<Left>::const_pointer right)
|
|
noexcept(noexcept(::new (nullptr) string_cat_expr(std::forward<Left>(left), rexy::basic_string_view(right))))
|
|
{
|
|
return rexy::string_cat_expr(std::forward<Left>(left), rexy::basic_string_view(right));
|
|
}
|
|
|
|
//String concat assign
|
|
template<BasicString Left, String Right>
|
|
constexpr decltype(auto) operator+=(Left& l, Right&& r)
|
|
noexcept(noexcept(l + std::forward<Right>(r)) && std::is_nothrow_assignable<Left, decltype(l + std::forward<Right>(r))>::value)
|
|
{
|
|
return l = (l + std::forward<Right>(r));
|
|
}
|
|
template<BasicString Left>
|
|
constexpr decltype(auto) operator+=(Left& l, typename std::decay_t<Left>::const_pointer r)
|
|
noexcept(noexcept(l + r) && std::is_nothrow_assignable<Left, decltype(l + r)>::value)
|
|
{
|
|
return l = (l + r);
|
|
}
|
|
|
|
template<BasicString T, class Char>
|
|
constexpr std::size_t find_first_of(T&& t, const Char* c, std::size_t start, std::size_t size){
|
|
if(start > t.length()){
|
|
return rexy::npos;
|
|
}
|
|
for(auto it = t.cbegin() + start;it != t.cend();++it){
|
|
for(std::size_t i = 0;i < size;++i){
|
|
if(*it == c[i]){
|
|
return it - t.cbegin();
|
|
}
|
|
}
|
|
}
|
|
return rexy::npos;
|
|
}
|
|
|
|
template<BasicString T, class Char>
|
|
constexpr std::size_t find_last_of(T&& t, const Char* c, std::size_t start, std::size_t size){
|
|
if(start > t.length()){
|
|
return rexy::npos;
|
|
}
|
|
|
|
const auto b = t.cend() - 1;
|
|
const auto e = t.cbegin() - 1 - start;
|
|
|
|
for(auto it = b;it != e;--it){
|
|
for(std::size_t i = 0;i < size;++i){
|
|
if(*it == c[i]){
|
|
return it - t.cbegin();
|
|
}
|
|
}
|
|
}
|
|
return rexy::npos;
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|