Remove deprecated string functions. Add replace functions to basic_string.
This commit is contained in:
parent
2a69be29a6
commit
cdd51a6e3a
@ -37,7 +37,7 @@ namespace rexy::fmt{
|
||||
string_view errstr;
|
||||
|
||||
constexpr const char* what(void)const{
|
||||
return errstr;
|
||||
return errstr.c_str();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@ -49,10 +49,15 @@ namespace rexy::fmt{
|
||||
requires(!UTF8_String<Char>)
|
||||
constexpr OutIt perform_standard_format(const Char* c, OutIt out, const format_specs& specs, const std::locale& loc);
|
||||
template<UTF8_String Char, class OutIt>
|
||||
requires(UTF8_String<Char>)
|
||||
constexpr OutIt perform_standard_format(const Char* c, OutIt out, const format_specs& specs, const std::locale& loc);
|
||||
template<class Char, class OutIt>
|
||||
constexpr OutIt perform_standard_format(const Char* c, OutIt out);
|
||||
template<class Char, class OutIt>
|
||||
constexpr OutIt perform_standard_format(basic_string_view<std::type_identity_t<Char>> str, OutIt out, const format_specs& specs, const std::locale& loc);
|
||||
template<class Char, class OutIt>
|
||||
constexpr OutIt perform_standard_format(basic_string_view<std::type_identity_t<Char>> str, OutIt out);
|
||||
template<class Char, class OutIt>
|
||||
constexpr OutIt perform_standard_format(Char b, OutIt out, const format_specs& specs, const std::locale& loc);
|
||||
template<class Char, class OutIt>
|
||||
constexpr OutIt perform_standard_format(Char b, OutIt out);
|
||||
|
||||
@ -204,6 +204,7 @@ namespace rexy::fmt::detail{
|
||||
}
|
||||
return width;
|
||||
}
|
||||
|
||||
template<class Char, class OutIt>
|
||||
requires(!UTF8_String<Char>)
|
||||
constexpr OutIt perform_standard_format(const Char* c, OutIt out, const format_specs& specs, const std::locale& loc){
|
||||
@ -228,6 +229,7 @@ namespace rexy::fmt::detail{
|
||||
return perform_format_write_aligned(std::move(out), est_width, specs, alignment::left, outputter);
|
||||
}
|
||||
template<UTF8_String Char, class OutIt>
|
||||
requires(UTF8_String<Char>)
|
||||
constexpr OutIt perform_standard_format(const Char* c, OutIt out, const format_specs& specs, const std::locale& loc){
|
||||
const basic_string_view<Char> str{c};
|
||||
std::size_t est_width = 0;
|
||||
@ -263,6 +265,14 @@ namespace rexy::fmt::detail{
|
||||
}
|
||||
return std::move(out);
|
||||
}
|
||||
template<class Char, class OutIt>
|
||||
constexpr OutIt perform_standard_format(basic_string_view<std::type_identity_t<Char>> str, OutIt out, const format_specs& specs, const std::locale& loc){
|
||||
return perform_standard_format<Char>(str.c_str(), std::move(out), specs, loc);
|
||||
}
|
||||
template<class Char, class OutIt>
|
||||
constexpr OutIt perform_standard_format(basic_string_view<std::type_identity_t<Char>> str, OutIt out){
|
||||
return perform_standard_format(str.c_str(), std::move(out));
|
||||
}
|
||||
|
||||
template<class Char, class OutIt>
|
||||
constexpr OutIt perform_standard_format(Char b, OutIt out, const format_specs& specs, const std::locale& loc){
|
||||
|
||||
@ -63,22 +63,22 @@ namespace rexy::fmt::detail{
|
||||
|
||||
template<class T, class It>
|
||||
concept HasInsertMethod = requires(T t, It i){
|
||||
{t.insert(0, i, i)};
|
||||
{t.insert(1, i, i)}; //don't use 0 index because pointer conversion causes ambiguous call
|
||||
{t.size()};
|
||||
};
|
||||
|
||||
struct container_traits_helper{
|
||||
using container = int;
|
||||
};
|
||||
template<class It>
|
||||
struct container_traits : public It, public container_traits_helper{
|
||||
template<class T = container_traits, class U = typename T::container>
|
||||
static std::false_type check(int);
|
||||
static std::true_type check(...);
|
||||
struct something : public It{
|
||||
template<class U = something, class C = decltype(U::container)>
|
||||
static std::true_type check(int);
|
||||
static std::false_type check(...);
|
||||
|
||||
static constexpr bool value = decltype(check(0))::value;
|
||||
};
|
||||
|
||||
template<class Char, class OutIt>
|
||||
OutIt real_write_out(const Char* start, std::size_t write_count, OutIt out){
|
||||
static constexpr bool has_container = decltype(container_traits<OutIt>::check(0))::value;
|
||||
static constexpr bool has_container = something<OutIt>::value;//decltype(container_traits<OutIt>::check(0))::value;
|
||||
|
||||
//optimize for types where direct access to the underlying container is available
|
||||
//check for a container member and a 'container_type' typedef in OutIt
|
||||
|
||||
@ -336,18 +336,6 @@ namespace rexy{
|
||||
|
||||
constexpr basic_string_view<value_type> create_view(void)const noexcept;
|
||||
constexpr basic_string_view<value_type> create_view(const_iterator start, const_iterator fin)const noexcept;
|
||||
|
||||
|
||||
[[deprecated]] constexpr pointer get(void)noexcept{return get_pointer();}
|
||||
[[deprecated]] constexpr const_pointer get(void)const noexcept{return get_pointer();}
|
||||
[[deprecated]] constexpr operator pointer(void)noexcept{return get_pointer();}
|
||||
[[deprecated]] constexpr operator const_pointer(void)const noexcept{return get_pointer();}
|
||||
[[deprecated]] constexpr const_iterator search(const string_base& s)const;
|
||||
[[deprecated]] constexpr iterator search(const string_base& s);
|
||||
template<class Searcher>
|
||||
[[deprecated]] constexpr const_iterator search(const string_base& s, const Searcher& searcher)const;
|
||||
template<class Searcher>
|
||||
[[deprecated]] constexpr iterator search(const string_base& s, const Searcher& searcher);
|
||||
};
|
||||
|
||||
|
||||
@ -378,6 +366,8 @@ namespace rexy{
|
||||
noexcept(is_nothrow_allocator_v<Alloc>);
|
||||
template<class InputIt>
|
||||
REXY_CPP20_CONSTEXPR basic_string& _insert_impl(size_type pos, InputIt start, size_type insert_count)noexcept(is_nothrow_allocator_v<Alloc>);
|
||||
template<class InputIt>
|
||||
constexpr basic_string& _replace_impl(size_type pos, size_type count, InputIt src, size_type count2);
|
||||
|
||||
public:
|
||||
constexpr basic_string(void)noexcept;
|
||||
@ -389,7 +379,7 @@ namespace rexy{
|
||||
REXY_CPP20_CONSTEXPR basic_string(const_pointer data)noexcept(is_nothrow_allocator_v<Alloc>);
|
||||
REXY_CPP20_CONSTEXPR explicit basic_string(size_type len)noexcept(is_nothrow_allocator_v<Alloc>);
|
||||
REXY_CPP20_CONSTEXPR basic_string(size_type len, size_type cap)noexcept(is_nothrow_allocator_v<Alloc>);
|
||||
template<class InputIt>
|
||||
template<class InputIt, class Enable = std::enable_if_t<is_legacy_input_iterator_v<InputIt>,int>>
|
||||
REXY_CPP20_CONSTEXPR basic_string(InputIt start, InputIt fin)noexcept(is_nothrow_allocator_v<Alloc>);
|
||||
REXY_CPP20_CONSTEXPR basic_string(const basic_string_view<Char>& sv)noexcept(is_nothrow_allocator_v<Alloc>);
|
||||
//normal copy and move ctors
|
||||
@ -419,6 +409,8 @@ namespace rexy{
|
||||
REXY_CPP20_CONSTEXPR bool reserve(size_type newsize)noexcept(is_nothrow_allocator_v<Alloc>);
|
||||
REXY_CPP20_CONSTEXPR void shrink_to_fit(void)noexcept(is_nothrow_allocator_v<Alloc>);
|
||||
|
||||
REXY_CPP20_CONSTEXPR void resize(size_type newsize, value_type v = value_type())noexcept(is_nothrow_allocator_v<Alloc>);
|
||||
|
||||
REXY_CPP20_CONSTEXPR basic_string& insert(size_type pos, size_type insert_count, value_type v)noexcept(is_nothrow_allocator_v<Alloc>);
|
||||
REXY_CPP20_CONSTEXPR basic_string& insert(size_type pos, value_type v)noexcept(is_nothrow_allocator_v<Alloc>);
|
||||
REXY_CPP20_CONSTEXPR basic_string& insert(size_type pos, const_pointer str)noexcept(is_nothrow_allocator_v<Alloc>);
|
||||
@ -428,20 +420,22 @@ namespace rexy{
|
||||
REXY_CPP20_CONSTEXPR basic_string& insert(const_iterator pos, value_type v)noexcept(is_nothrow_allocator_v<Alloc>);
|
||||
REXY_CPP20_CONSTEXPR basic_string& insert(const_iterator pos, size_type count, value_type v)noexcept(is_nothrow_allocator_v<Alloc>);
|
||||
template<class InputIt>
|
||||
REXY_CPP20_CONSTEXPR basic_string& insert(const_iterator pos, InputIt start, InputIt last)noexcept(is_nothrow_allocator_v<Alloc>);
|
||||
REXY_CPP20_CONSTEXPR auto insert(const_iterator pos, InputIt start, InputIt last)noexcept(is_nothrow_allocator_v<Alloc>) ->
|
||||
std::enable_if_t<is_legacy_input_iterator_v<InputIt>,basic_string&>;
|
||||
template<class InputIt>
|
||||
REXY_CPP20_CONSTEXPR basic_string& insert(size_type pos, InputIt start, InputIt last)noexcept(is_nothrow_allocator_v<Alloc>);
|
||||
REXY_CPP20_CONSTEXPR auto insert(size_type pos, InputIt start, InputIt last)noexcept(is_nothrow_allocator_v<Alloc>) ->
|
||||
std::enable_if_t<is_legacy_input_iterator_v<InputIt>,basic_string&>;
|
||||
REXY_CPP20_CONSTEXPR basic_string& insert(const_iterator pos, std::initializer_list<value_type> list)noexcept(is_nothrow_allocator_v<Alloc>);
|
||||
template<class StringView>
|
||||
REXY_CPP20_CONSTEXPR auto insert(size_type pos, const StringView& sv)noexcept(is_nothrow_allocator_v<Alloc>) ->
|
||||
std::enable_if_t<std::is_convertible_v<const StringView&, basic_string_view<value_type>> && !std::is_convertible_v<const StringView&,const_pointer>>;
|
||||
std::enable_if_t<std::is_convertible_v<const StringView&, basic_string_view<value_type>> && !std::is_convertible_v<const StringView&,const_pointer>,basic_string&>;
|
||||
template<class StringView>
|
||||
REXY_CPP20_CONSTEXPR auto insert(size_type pos, const StringView& sv, size_type index_str, size_type count = npos)noexcept(is_nothrow_allocator_v<Alloc>) ->
|
||||
std::enable_if_t<std::is_convertible_v<const StringView&, basic_string_view<value_type>> && !std::is_convertible_v<const StringView&,const_pointer>>;
|
||||
std::enable_if_t<std::is_convertible_v<const StringView&, basic_string_view<value_type>> && !std::is_convertible_v<const StringView&,const_pointer>,basic_string&>;
|
||||
|
||||
template<class InputIt>
|
||||
REXY_CPP20_CONSTEXPR basic_string& append(InputIt start, InputIt fin)noexcept(is_nothrow_allocator_v<Alloc>);
|
||||
|
||||
|
||||
REXY_CPP20_CONSTEXPR auto append(InputIt start, InputIt fin)noexcept(is_nothrow_allocator_v<Alloc>) ->
|
||||
std::enable_if_t<is_legacy_input_iterator_v<InputIt>,basic_string&>;
|
||||
REXY_CPP20_CONSTEXPR basic_string& append(const_pointer data, size_type len)noexcept(is_nothrow_allocator_v<Alloc>);
|
||||
REXY_CPP20_CONSTEXPR basic_string& append(const_pointer data)noexcept(is_nothrow_allocator_v<Alloc>);
|
||||
REXY_CPP20_CONSTEXPR basic_string& append(const basic_string& other)noexcept(is_nothrow_allocator_v<Alloc>);
|
||||
@ -449,6 +443,30 @@ namespace rexy{
|
||||
REXY_CPP20_CONSTEXPR void push_back(value_type data)noexcept(is_nothrow_allocator_v<Alloc>);
|
||||
constexpr void pop_back(void)noexcept;
|
||||
|
||||
|
||||
constexpr basic_string& replace(size_type pos, size_type count, const basic_string& str);
|
||||
constexpr basic_string& replace(const_iterator pos, const_iterator last, const basic_string& str);
|
||||
constexpr basic_string& replace(size_type pos, size_type count, const basic_string& str, size_type pos2, size_type count2 = npos);
|
||||
template<class InputIt>
|
||||
constexpr auto replace(const_iterator first, const_iterator last, InputIt first2, InputIt last2) ->
|
||||
std::enable_if_t<is_legacy_input_iterator_v<InputIt>,basic_string&>;
|
||||
constexpr basic_string& replace(size_type pos, size_type count, const_pointer cstr, size_type count2);
|
||||
constexpr basic_string& replace(const_iterator first, const_iterator last, const_pointer cstr, size_type count);
|
||||
constexpr basic_string& replace(size_type pos, size_type count, const_pointer cstr);
|
||||
constexpr basic_string& replace(const_iterator first, const_iterator last, const_pointer cstr);
|
||||
constexpr basic_string& replace(size_type pos, size_type count, size_type count2, value_type v);
|
||||
constexpr basic_string& replace(const_iterator first, const_iterator last, size_type count2, value_type v);
|
||||
constexpr basic_string& replace(const_iterator first, const_iterator last, std::initializer_list<value_type> list);
|
||||
template<class StringView>
|
||||
constexpr auto replace(size_type pos, size_type count, const StringView& sv) ->
|
||||
std::enable_if_t<std::is_convertible_v<const StringView&, basic_string_view<value_type>> && !std::is_convertible_v<const StringView&,const_pointer>,basic_string&>;
|
||||
template<class StringView>
|
||||
constexpr auto replace(const_iterator first, const_iterator last, const StringView& sv) ->
|
||||
std::enable_if_t<std::is_convertible_v<const StringView&, basic_string_view<value_type>> && !std::is_convertible_v<const StringView&,const_pointer>,basic_string&>;
|
||||
template<class StringView>
|
||||
constexpr auto replace(size_type pos, size_type count, const StringView& sv, size_type pos2, size_type count2 = npos) ->
|
||||
std::enable_if_t<std::is_convertible_v<const StringView&, basic_string_view<value_type>> && !std::is_convertible_v<const StringView&,const_pointer>,basic_string&>;
|
||||
|
||||
constexpr basic_string& erase(size_type index = 0, size_type count = npos)noexcept;
|
||||
constexpr iterator erase(const_iterator pos)noexcept;
|
||||
constexpr iterator erase(const_iterator first, const_iterator last)noexcept;
|
||||
@ -460,8 +478,6 @@ namespace rexy{
|
||||
REXY_CPP20_CONSTEXPR pointer release(void)noexcept(is_nothrow_allocator_v<Alloc>);
|
||||
using detail::hasallocator<Alloc>::allocator;
|
||||
|
||||
|
||||
[[deprecated]] REXY_CPP20_CONSTEXPR bool resize(size_type newsize)noexcept(is_nothrow_allocator_v<Alloc>);
|
||||
};
|
||||
|
||||
//Like an expression template but not really
|
||||
|
||||
@ -32,6 +32,23 @@
|
||||
|
||||
namespace rexy{
|
||||
|
||||
namespace detail{
|
||||
template<class T>
|
||||
struct value_iterator_adapter{
|
||||
T val;
|
||||
|
||||
constexpr value_iterator_adapter& operator++(void)noexcept{return *this;}
|
||||
constexpr value_iterator_adapter operator++(int)noexcept{return *this;}
|
||||
constexpr T operator*(void)const noexcept{return val;}
|
||||
|
||||
constexpr bool operator==(const value_iterator_adapter& other)const{return val == other.val;}
|
||||
constexpr bool operator!=(const value_iterator_adapter& other)const{return val == other.val;}
|
||||
|
||||
};
|
||||
template<class T>
|
||||
value_iterator_adapter(T) -> value_iterator_adapter<T>;
|
||||
}
|
||||
|
||||
template<class Char>
|
||||
constexpr auto string_base<Char>::search(basic_string_view<value_type> sv)const -> const_iterator{
|
||||
if(sv.length() > length()){
|
||||
@ -138,6 +155,8 @@ namespace rexy{
|
||||
set_length(0);
|
||||
get_pointer()[0] = 0;
|
||||
}
|
||||
|
||||
|
||||
template<class Char>
|
||||
constexpr auto string_base<Char>::create_view(void)const noexcept -> basic_string_view<value_type>{
|
||||
return basic_string_view<value_type>(data(), length());
|
||||
@ -229,7 +248,7 @@ namespace rexy{
|
||||
}
|
||||
|
||||
template<class Char, REXY_ALLOCATOR_CONCEPT Alloc>
|
||||
template<class InputIt>
|
||||
template<class InputIt, class Enable>
|
||||
REXY_CPP20_CONSTEXPR basic_string<Char,Alloc>::basic_string(InputIt start, InputIt fin)
|
||||
noexcept(is_nothrow_allocator_v<Alloc>):
|
||||
basic_string(nullptr, size_type{fin - start})
|
||||
@ -247,7 +266,7 @@ namespace rexy{
|
||||
noexcept(is_nothrow_allocator_v<Alloc>):
|
||||
detail::hasallocator<Alloc>(b)
|
||||
{
|
||||
_copy_construct_string(b.get(), b.length(), b.length());
|
||||
_copy_construct_string(b.data(), b.length(), b.length());
|
||||
}
|
||||
template<class Char, REXY_ALLOCATOR_CONCEPT Alloc>
|
||||
constexpr basic_string<Char,Alloc>::basic_string(basic_string&& s)noexcept:
|
||||
@ -257,7 +276,7 @@ namespace rexy{
|
||||
REXY_CPP20_CONSTEXPR basic_string<Char,Alloc>::basic_string(const string_base<Char>& b)
|
||||
noexcept(is_nothrow_allocator_v<Alloc>)
|
||||
{
|
||||
_copy_construct_string(b.get(), b.length(), b.length());
|
||||
_copy_construct_string(b.data(), b.length(), b.length());
|
||||
}
|
||||
|
||||
//dtor
|
||||
@ -337,7 +356,7 @@ namespace rexy{
|
||||
return false;
|
||||
if(!this->islong() && newsize < string_base<Char>::short_string_size())
|
||||
return false;
|
||||
return (*this = basic_string(this->get_pointer(), newsize));
|
||||
return (*this = basic_string(this->get_pointer(), newsize)).valid();
|
||||
}
|
||||
template<class Char, REXY_ALLOCATOR_CONCEPT Alloc>
|
||||
REXY_CPP20_CONSTEXPR void basic_string<Char,Alloc>::shrink_to_fit(void)noexcept(is_nothrow_allocator_v<Alloc>){
|
||||
@ -346,23 +365,31 @@ namespace rexy{
|
||||
}
|
||||
*this = basic_string(this->get_pointer(), this->length(), this->length());
|
||||
}
|
||||
template<class Char, REXY_ALLOCATOR_CONCEPT Alloc>
|
||||
REXY_CPP20_CONSTEXPR void basic_string<Char,Alloc>::resize(size_type newsize, value_type v)noexcept(is_nothrow_allocator_v<Alloc>){
|
||||
const auto len = this->length();
|
||||
const auto copy_count = std::min(newsize, len);
|
||||
const auto insert_count = newsize > len ? newsize - len : 0;
|
||||
|
||||
basic_string newstr(newsize);
|
||||
auto* ptr = newstr.data();
|
||||
|
||||
rexy::memcpy(ptr, this->data(), copy_count * sizeof(value_type));
|
||||
ptr += copy_count;
|
||||
|
||||
for(size_type i = 0;i < insert_count;++i){
|
||||
*ptr++ = v;
|
||||
}
|
||||
*ptr = 0;
|
||||
newstr.set_length(newsize);
|
||||
|
||||
*this = std::move(newstr);
|
||||
}
|
||||
|
||||
|
||||
template<class Char, REXY_ALLOCATOR_CONCEPT Alloc>
|
||||
REXY_CPP20_CONSTEXPR auto basic_string<Char,Alloc>::insert(size_type pos, size_type insert_count, value_type v)noexcept(is_nothrow_allocator_v<Alloc>) -> basic_string&{
|
||||
struct insert_adapter{
|
||||
value_type val;
|
||||
|
||||
constexpr insert_adapter& operator++(void)noexcept{return *this;}
|
||||
constexpr insert_adapter operator++(int)noexcept{return *this;}
|
||||
constexpr value_type operator*(void)const noexcept{return val;}
|
||||
|
||||
constexpr bool operator==(const insert_adapter& other)const{return val == other.val;}
|
||||
constexpr bool operator!=(const insert_adapter& other)const{return val == other.val;}
|
||||
|
||||
};
|
||||
|
||||
return _insert_impl(pos, insert_adapter{v}, insert_count);
|
||||
return _insert_impl(pos, detail::value_iterator_adapter{v}, insert_count);
|
||||
}
|
||||
|
||||
template<class Char, REXY_ALLOCATOR_CONCEPT Alloc>
|
||||
@ -395,7 +422,9 @@ namespace rexy{
|
||||
}
|
||||
template<class Char, REXY_ALLOCATOR_CONCEPT Alloc>
|
||||
template<class InputIt>
|
||||
REXY_CPP20_CONSTEXPR auto basic_string<Char,Alloc>::insert(const_iterator pos, InputIt start, InputIt last)noexcept(is_nothrow_allocator_v<Alloc>) -> basic_string&{
|
||||
REXY_CPP20_CONSTEXPR auto basic_string<Char,Alloc>::insert(const_iterator pos, InputIt start, InputIt last)noexcept(is_nothrow_allocator_v<Alloc>) ->
|
||||
std::enable_if_t<is_legacy_input_iterator_v<InputIt>,basic_string&>
|
||||
{
|
||||
return insert(pos - this->begin(), std::move(start), std::move(last));
|
||||
}
|
||||
template<class Char, REXY_ALLOCATOR_CONCEPT Alloc>
|
||||
@ -405,21 +434,23 @@ namespace rexy{
|
||||
template<class Char, REXY_ALLOCATOR_CONCEPT Alloc>
|
||||
template<class StringView>
|
||||
REXY_CPP20_CONSTEXPR auto basic_string<Char,Alloc>::insert(size_type pos, const StringView& sv)noexcept(is_nothrow_allocator_v<Alloc>) ->
|
||||
std::enable_if_t<std::is_convertible_v<const StringView&, basic_string_view<value_type>> && !std::is_convertible_v<const StringView&,const_pointer>>
|
||||
std::enable_if_t<std::is_convertible_v<const StringView&, basic_string_view<value_type>> && !std::is_convertible_v<const StringView&,const_pointer>,basic_string&>
|
||||
{
|
||||
return insert(pos, sv.begin(), sv.end());
|
||||
}
|
||||
template<class Char, REXY_ALLOCATOR_CONCEPT Alloc>
|
||||
template<class StringView>
|
||||
REXY_CPP20_CONSTEXPR auto basic_string<Char,Alloc>::insert(size_type pos, const StringView& sv, size_type index_str, size_type count)noexcept(is_nothrow_allocator_v<Alloc>) ->
|
||||
std::enable_if_t<std::is_convertible_v<const StringView&, basic_string_view<value_type>> && !std::is_convertible_v<const StringView&,const_pointer>>
|
||||
std::enable_if_t<std::is_convertible_v<const StringView&, basic_string_view<value_type>> && !std::is_convertible_v<const StringView&,const_pointer>,basic_string&>
|
||||
{
|
||||
return insert(pos, sv.begin() + index_str, sv.begin() + index_str + count);
|
||||
}
|
||||
|
||||
template<class Char, REXY_ALLOCATOR_CONCEPT Alloc>
|
||||
template<class InputIt>
|
||||
REXY_CPP20_CONSTEXPR auto basic_string<Char,Alloc>::insert(size_type pos, InputIt start, InputIt last)noexcept(is_nothrow_allocator_v<Alloc>) -> basic_string&{
|
||||
REXY_CPP20_CONSTEXPR auto basic_string<Char,Alloc>::insert(size_type pos, InputIt start, InputIt last)noexcept(is_nothrow_allocator_v<Alloc>) ->
|
||||
std::enable_if_t<is_legacy_input_iterator_v<InputIt>,basic_string&>
|
||||
{
|
||||
size_type insert_count = 0;
|
||||
for(auto it = start;it != last;++it, ++insert_count){}
|
||||
return _insert_impl(pos, start, insert_count);
|
||||
@ -441,7 +472,9 @@ namespace rexy{
|
||||
}
|
||||
template<class Char, REXY_ALLOCATOR_CONCEPT Alloc>
|
||||
template<class InputIt>
|
||||
REXY_CPP20_CONSTEXPR auto basic_string<Char,Alloc>::append(InputIt start, InputIt fin)noexcept(is_nothrow_allocator_v<Alloc>) -> basic_string&{
|
||||
REXY_CPP20_CONSTEXPR auto basic_string<Char,Alloc>::append(InputIt start, InputIt fin)noexcept(is_nothrow_allocator_v<Alloc>) ->
|
||||
std::enable_if_t<is_legacy_input_iterator_v<InputIt>,basic_string&>
|
||||
{
|
||||
return insert(this->length(), start, fin);
|
||||
}
|
||||
|
||||
@ -456,6 +489,85 @@ namespace rexy{
|
||||
erase(this->end() - 1);
|
||||
}
|
||||
|
||||
template<class Char, REXY_ALLOCATOR_CONCEPT Alloc>
|
||||
constexpr auto basic_string<Char,Alloc>::replace(size_type pos, size_type count, const basic_string& str) -> basic_string&{
|
||||
return replace(pos, count, str.create_view());
|
||||
}
|
||||
template<class Char, REXY_ALLOCATOR_CONCEPT Alloc>
|
||||
constexpr auto basic_string<Char,Alloc>::replace(const_iterator first, const_iterator last, const basic_string& str) -> basic_string&{
|
||||
return replace(first, last, str.create_view());
|
||||
}
|
||||
template<class Char, REXY_ALLOCATOR_CONCEPT Alloc>
|
||||
constexpr auto basic_string<Char,Alloc>::replace(size_type pos, size_type count, const basic_string& str, size_type pos2, size_type count2) -> basic_string&{
|
||||
return replace(pos, count, str.create_view(), pos2, count2);
|
||||
}
|
||||
template<class Char, REXY_ALLOCATOR_CONCEPT Alloc>
|
||||
template<class InputIt>
|
||||
constexpr auto basic_string<Char,Alloc>::replace(const_iterator first, const_iterator last, InputIt first2, InputIt last2) ->
|
||||
std::enable_if_t<is_legacy_input_iterator_v<InputIt>,basic_string&>
|
||||
{
|
||||
const size_type len = last - first;
|
||||
size_type count = 0;
|
||||
for(auto it = first2;count < len && it != last2;++count,++it);
|
||||
return _replace_impl(size_type{first - this->begin()}, len, first2, count);
|
||||
}
|
||||
template<class Char, REXY_ALLOCATOR_CONCEPT Alloc>
|
||||
constexpr auto basic_string<Char,Alloc>::replace(size_type pos, size_type count, const_pointer cstr, size_type count2) -> basic_string&{
|
||||
return _replace_impl(pos, count, cstr, count2);
|
||||
}
|
||||
template<class Char, REXY_ALLOCATOR_CONCEPT Alloc>
|
||||
constexpr auto basic_string<Char,Alloc>::replace(const_iterator first, const_iterator last, const_pointer cstr, size_type count) -> basic_string&{
|
||||
return _replace_impl(size_type{first - this->begin()}, size_type{last - first}, cstr, count);
|
||||
}
|
||||
template<class Char, REXY_ALLOCATOR_CONCEPT Alloc>
|
||||
constexpr auto basic_string<Char,Alloc>::replace(size_type pos, size_type count, const_pointer cstr) -> basic_string&{
|
||||
return _replace_impl(pos, count, cstr, rexy::strlen(cstr));
|
||||
}
|
||||
template<class Char, REXY_ALLOCATOR_CONCEPT Alloc>
|
||||
constexpr auto basic_string<Char,Alloc>::replace(const_iterator first, const_iterator last, const_pointer cstr) -> basic_string&{
|
||||
return _replace_impl(size_type{first - this->begin()}, size_type{last - first}, cstr, rexy::strlen(cstr));
|
||||
}
|
||||
template<class Char, REXY_ALLOCATOR_CONCEPT Alloc>
|
||||
constexpr auto basic_string<Char,Alloc>::replace(size_type pos, size_type count, size_type count2, value_type v) -> basic_string&{
|
||||
return _replace_impl(pos, count, detail::value_iterator_adapter{v}, count2);
|
||||
}
|
||||
template<class Char, REXY_ALLOCATOR_CONCEPT Alloc>
|
||||
constexpr auto basic_string<Char,Alloc>::replace(const_iterator first, const_iterator last, size_type count2, value_type v) -> basic_string&{
|
||||
return _replace_impl(size_type{first - this->begin()}, size_type{last - first}, detail::value_iterator_adapter{v}, count2);
|
||||
}
|
||||
template<class Char, REXY_ALLOCATOR_CONCEPT Alloc>
|
||||
constexpr auto basic_string<Char,Alloc>::replace(const_iterator first, const_iterator last, std::initializer_list<value_type> list) -> basic_string&{
|
||||
return _replace_impl(size_type{first - this->begin()}, size_type{last - first}, list.begin(), list.size());
|
||||
}
|
||||
template<class Char, REXY_ALLOCATOR_CONCEPT Alloc>
|
||||
template<class StringView>
|
||||
constexpr auto basic_string<Char,Alloc>::replace(size_type pos, size_type count, const StringView& sv) ->
|
||||
std::enable_if_t<std::is_convertible_v<const StringView&, basic_string_view<value_type>> && !std::is_convertible_v<const StringView&,const_pointer>,basic_string&>
|
||||
{
|
||||
return _replace_impl(pos, count, sv.begin(), sv.length());
|
||||
}
|
||||
template<class Char, REXY_ALLOCATOR_CONCEPT Alloc>
|
||||
template<class StringView>
|
||||
constexpr auto basic_string<Char,Alloc>::replace(const_iterator first, const_iterator last, const StringView& sv) ->
|
||||
std::enable_if_t<std::is_convertible_v<const StringView&, basic_string_view<value_type>> && !std::is_convertible_v<const StringView&,const_pointer>,basic_string&>
|
||||
{
|
||||
return _replace_impl(size_type{first - this->begin()}, size_type{last - first}, sv.begin(), sv.length());
|
||||
}
|
||||
template<class Char, REXY_ALLOCATOR_CONCEPT Alloc>
|
||||
template<class StringView>
|
||||
constexpr auto basic_string<Char,Alloc>::replace(size_type pos, size_type count, const StringView& sv, size_type pos2, size_type count2) ->
|
||||
std::enable_if_t<std::is_convertible_v<const StringView&, basic_string_view<value_type>> && !std::is_convertible_v<const StringView&,const_pointer>,basic_string&>
|
||||
{
|
||||
if(pos2 > sv.length()){
|
||||
pos2 = sv.length();
|
||||
}
|
||||
const auto maxlen2 = sv.length() - pos2;
|
||||
if(count2 > maxlen2){
|
||||
count2 = maxlen2;
|
||||
}
|
||||
|
||||
return _replace_impl(pos, count, sv.begin() + pos2, maxlen2);
|
||||
}
|
||||
|
||||
template<class Char, REXY_ALLOCATOR_CONCEPT Alloc>
|
||||
constexpr auto basic_string<Char,Alloc>::erase(size_type index, size_type count)noexcept -> basic_string&{
|
||||
@ -496,7 +608,7 @@ namespace rexy{
|
||||
return {};
|
||||
const size_type newlen = end - start;
|
||||
basic_string<value_type,Alloc> tmp(newlen);
|
||||
tmp.append(this->get() + start, newlen);
|
||||
tmp.append(this->data() + start, newlen);
|
||||
return tmp;
|
||||
}
|
||||
template<class Char, REXY_ALLOCATOR_CONCEPT Alloc>
|
||||
@ -545,24 +657,66 @@ namespace rexy{
|
||||
template<class InputIt>
|
||||
REXY_CPP20_CONSTEXPR auto basic_string<Char,Alloc>::_insert_impl(size_type pos, InputIt start, size_type insert_count)noexcept(is_nothrow_allocator_v<Alloc>) -> basic_string&{
|
||||
const size_type len = this->length();
|
||||
const size_type cap = this->capacity();
|
||||
const size_type after_pos_count = len > pos ? len - pos : 0;
|
||||
|
||||
basic_string newstr(rexy::max(pos + insert_count, len + insert_count));
|
||||
auto* ptr = newstr.get_pointer();
|
||||
if(insert_count + len <= cap){
|
||||
|
||||
rexy::memcpy(ptr, this->get_pointer(), sizeof(value_type) * pos);
|
||||
ptr += pos;
|
||||
auto* dest_ptr = this->data() + pos + insert_count;
|
||||
const auto* src_ptr = this->data() + pos;
|
||||
for(size_type i = 0;i < after_pos_count;++i){
|
||||
*dest_ptr++ = *src_ptr++;
|
||||
}
|
||||
dest_ptr = this->data() + pos;
|
||||
for(size_type i = 0;i < insert_count;++i){
|
||||
*dest_ptr++ = *start++;
|
||||
}
|
||||
this->data()[len + insert_count] = 0; //null terminator
|
||||
this->set_length(len + insert_count);
|
||||
|
||||
for(size_type i = 0;i < insert_count;++i){
|
||||
*ptr++ = *start++;
|
||||
return *this;
|
||||
|
||||
}else{
|
||||
|
||||
basic_string newstr(rexy::max(pos + insert_count, len + insert_count));
|
||||
auto* ptr = newstr.get_pointer();
|
||||
|
||||
rexy::memcpy(ptr, this->get_pointer(), sizeof(value_type) * pos);
|
||||
ptr += pos;
|
||||
|
||||
for(size_type i = 0;i < insert_count;++i){
|
||||
*ptr++ = *start++;
|
||||
}
|
||||
|
||||
rexy::memcpy(ptr, this->get_pointer() + pos, sizeof(value_type) * after_pos_count);
|
||||
ptr += after_pos_count;
|
||||
*ptr = 0; //null terminator
|
||||
newstr.set_length(len + insert_count);
|
||||
|
||||
return (*this = std::move(newstr));
|
||||
|
||||
}
|
||||
}
|
||||
template<class Char, REXY_ALLOCATOR_CONCEPT Alloc>
|
||||
template<class InputIt>
|
||||
constexpr auto basic_string<Char,Alloc>::_replace_impl(size_type pos, size_type count, InputIt src, size_type count2) -> basic_string&{
|
||||
const auto len = this->length();
|
||||
if(pos > len){
|
||||
pos = len;
|
||||
}
|
||||
const auto maxlen = len - pos;
|
||||
if(count > maxlen){
|
||||
count = maxlen;
|
||||
}
|
||||
|
||||
rexy::memcpy(ptr, this->get_pointer() + pos, sizeof(value_type) * after_pos_count);
|
||||
ptr += after_pos_count;
|
||||
*ptr = 0; //null terminator
|
||||
newstr.set_length(len + insert_count);
|
||||
const auto real_count = std::min(count, count2);
|
||||
|
||||
return (*this = std::move(newstr));
|
||||
auto* dest_ptr = this->get_pointer() + pos;
|
||||
for(size_type i = 0;i < real_count;++i){
|
||||
*dest_ptr++ = *src++;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class Left, class Right>
|
||||
@ -582,31 +736,6 @@ namespace rexy{
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
template<class Char>
|
||||
[[deprecated]] constexpr auto string_base<Char>::search(const string_base& s)const -> const_iterator{
|
||||
return two_way_search(cbegin(), cend(), s.begin(), s.end());
|
||||
}
|
||||
template<class Char>
|
||||
[[deprecated]] constexpr auto string_base<Char>::search(const string_base& s) -> iterator{
|
||||
return two_way_search(begin(), end(), s.begin(), s.end());
|
||||
}
|
||||
template<class Char>
|
||||
template<class Searcher>
|
||||
[[deprecated]] constexpr auto string_base<Char>::search(const string_base& s, const Searcher& searcher)const -> const_iterator{
|
||||
return searcher(cbegin(), cend(), s.begin(), s.end());
|
||||
}
|
||||
template<class Char>
|
||||
template<class Searcher>
|
||||
[[deprecated]] constexpr auto string_base<Char>::search(const string_base& s, const Searcher& searcher) -> iterator{
|
||||
return searcher(begin(), end(), s.begin(), s.end());
|
||||
}
|
||||
template<class Char, REXY_ALLOCATOR_CONCEPT Alloc>
|
||||
[[deprecated]] REXY_CPP20_CONSTEXPR bool basic_string<Char,Alloc>::resize(size_type newsize)noexcept(is_nothrow_allocator_v<Alloc>){
|
||||
return reserve(newsize);
|
||||
}
|
||||
|
||||
|
||||
} //namespace rexy
|
||||
|
||||
#endif
|
||||
|
||||
@ -127,9 +127,6 @@ namespace rexy{
|
||||
constexpr size_type find_last_of(const_pointer c, size_type pos = 0)const;
|
||||
constexpr size_type find_last_of(const_pointer c, size_type pos, size_type size)const;
|
||||
|
||||
|
||||
[[deprecated]] constexpr const_pointer get(void)const noexcept{return m_data;}
|
||||
[[deprecated]] constexpr operator const_pointer(void)const noexcept{return m_data;}
|
||||
};
|
||||
|
||||
template<class T>
|
||||
|
||||
@ -20,6 +20,7 @@
|
||||
#define REXY_TRAITS_HPP
|
||||
|
||||
#include <type_traits> //is_same, decay, integral_constant, declval
|
||||
#include <iterator> //iterator_traits
|
||||
|
||||
#include "rexy.hpp"
|
||||
|
||||
@ -53,6 +54,85 @@ namespace rexy{
|
||||
static constexpr bool value = std::is_same<std::true_type,decltype(test(static_cast<std::decay_t<T>*>(nullptr)))>::value;
|
||||
};
|
||||
|
||||
template<class T, class = void>
|
||||
struct is_dereferencable : public std::false_type{};
|
||||
template<class T>
|
||||
struct is_dereferencable<T,std::void_t<decltype(*(std::declval<T>()))>> : public std::true_type{};
|
||||
template<class T>
|
||||
static constexpr bool is_dereferencable_v = is_dereferencable<T>::value;
|
||||
|
||||
template<class T, class = void>
|
||||
struct is_pointer_dereferencable : public std::false_type{};
|
||||
template<class T>
|
||||
struct is_pointer_dereferencable<T,std::void_t<decltype(std::declval<T>().operator->())>> : public std::true_type{};
|
||||
template<class T>
|
||||
struct is_pointer_dereferencable<T*,std::void_t<T*>> : public std::true_type{};
|
||||
template<class T>
|
||||
static constexpr bool is_pointer_dereferencable_v = is_pointer_dereferencable<T>::value;
|
||||
|
||||
template<class T, class = void>
|
||||
struct is_prefix_incrementable : public std::false_type{};
|
||||
template<class T>
|
||||
struct is_prefix_incrementable<T,std::void_t<decltype(++(std::declval<std::add_lvalue_reference_t<std::remove_cvref_t<T>>>()))>> : public std::true_type{};
|
||||
template<class T>
|
||||
static constexpr bool is_prefix_incrementable_v = is_prefix_incrementable<T>::value;
|
||||
|
||||
template<class T, class = void>
|
||||
struct is_postfix_incrementable : public std::false_type{};
|
||||
template<class T>
|
||||
struct is_postfix_incrementable<T,std::void_t<decltype((std::declval<std::add_lvalue_reference_t<std::remove_cvref_t<T>>>())++)>> : public std::true_type{};
|
||||
template<class T>
|
||||
static constexpr bool is_postfix_incrementable_v = is_postfix_incrementable<T>::value;
|
||||
|
||||
template<class T, class = void>
|
||||
struct is_equality_comparable : public std::false_type{};
|
||||
template<class T>
|
||||
struct is_equality_comparable<T,std::void_t<decltype(std::declval<T>() == std::declval<T>())>> : public std::true_type{};
|
||||
template<class T>
|
||||
static constexpr bool is_equality_comparable_v = is_equality_comparable<T>::value;
|
||||
|
||||
template<class T, class = void>
|
||||
struct is_inequality_comparable : public std::false_type{};
|
||||
template<class T>
|
||||
struct is_inequality_comparable<T,std::void_t<decltype(std::declval<T>() != std::declval<T>())>> : public std::true_type{};
|
||||
template<class T>
|
||||
static constexpr bool is_inequality_comparable_v = is_inequality_comparable<T>::value;
|
||||
|
||||
template<class T>
|
||||
struct is_legacy_iterator{
|
||||
static constexpr bool value = is_prefix_incrementable_v<T> && is_dereferencable_v<T>;
|
||||
};
|
||||
template<class T>
|
||||
static constexpr bool is_legacy_iterator_v = is_legacy_iterator<T>::value;
|
||||
|
||||
template<class T, bool = is_legacy_iterator_v<T> &&
|
||||
is_inequality_comparable_v<T> &&
|
||||
is_pointer_dereferencable_v<T> &&
|
||||
is_postfix_incrementable_v<T>>
|
||||
struct is_legacy_input_iterator : public std::false_type{};
|
||||
|
||||
template<class T>
|
||||
struct is_legacy_input_iterator<T,true>{
|
||||
static constexpr bool value = std::is_convertible_v<decltype(std::declval<T>() == std::declval<T>()),bool> &&
|
||||
std::is_same_v<decltype(*(std::declval<T>())),typename std::iterator_traits<T>::reference> &&
|
||||
std::is_same_v<decltype(++std::declval<std::add_lvalue_reference_t<std::remove_cvref_t<T>>>()),std::add_lvalue_reference_t<T>> &&
|
||||
std::is_convertible_v<decltype(*std::declval<std::add_lvalue_reference_t<std::remove_cvref_t<T>>>()++), typename std::iterator_traits<T>::value_type>;
|
||||
};
|
||||
template<class T>
|
||||
static constexpr bool is_legacy_input_iterator_v = is_legacy_input_iterator<T>::value;
|
||||
|
||||
template<class T, class Value, bool = is_legacy_iterator_v<T> &&
|
||||
is_postfix_incrementable_v<T>>
|
||||
struct is_legacy_output_iterator : public std::false_type{};
|
||||
|
||||
template<class T, class Value>
|
||||
struct is_legacy_output_iterator<T,Value,true>{
|
||||
static constexpr bool value =
|
||||
std::is_same_v<decltype(++std::declval<std::add_lvalue_reference_t<std::remove_cvref_t<T>>>()),std::add_lvalue_reference_t<T>> &&
|
||||
std::is_convertible_v<decltype(std::declval<std::add_lvalue_reference_t<std::remove_cvref_t<T>>>()++), std::add_lvalue_reference_t<std::add_const_t<T>>>;
|
||||
};
|
||||
template<class T, class Value>
|
||||
static constexpr bool is_legacy_output_iterator_v = is_legacy_output_iterator<T,Value>::value;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -92,14 +92,14 @@ namespace rexy{
|
||||
return val > 0 ? val : -val;
|
||||
}
|
||||
|
||||
#ifdef REXY_if_constexpr
|
||||
#ifdef REXY_if_consteval
|
||||
template<class T>
|
||||
constexpr size_t strlen(const T* c)noexcept{
|
||||
return std::char_traits<T>::length(c);
|
||||
}
|
||||
template<class T>
|
||||
constexpr int strcmp(const T* l, const T* r)noexcept{
|
||||
REXY_if_constexpr{
|
||||
REXY_if_consteval{
|
||||
if constexpr(std::is_same_v<std::remove_cvref_t<T>,char>){
|
||||
return std::strcmp(l, r);
|
||||
}else if constexpr(std::is_same_v<std::remove_cvref_t<T>,wchar_t>){
|
||||
@ -111,7 +111,7 @@ namespace rexy{
|
||||
}
|
||||
template<class T>
|
||||
constexpr int strncmp(const T* l, const T* r, std::size_t max)noexcept{
|
||||
REXY_if_constexpr{
|
||||
REXY_if_consteval{
|
||||
if constexpr(std::is_same_v<std::remove_cvref_t<T>,char>){
|
||||
return std::strncmp(l, r, max);
|
||||
}else if constexpr (std::is_same_v<std::remove_cvref_t<T>,wchar_t>){
|
||||
@ -123,7 +123,7 @@ namespace rexy{
|
||||
}
|
||||
template<class T, class Compare>
|
||||
constexpr int strncmp(const T* l, const T* r, std::size_t max, Compare cmp)noexcept{
|
||||
REXY_if_constexpr{
|
||||
REXY_if_consteval{
|
||||
if constexpr(std::is_same_v<std::remove_cvref_t<T>,char>){
|
||||
return std::strncmp(l, r, max);
|
||||
}else if constexpr (std::is_same_v<std::remove_cvref_t<T>,wchar_t>){
|
||||
@ -139,7 +139,7 @@ namespace rexy{
|
||||
return *l - *r;
|
||||
}
|
||||
constexpr void memcpy(void* l, const void* r, size_t n){
|
||||
REXY_if_constexpr{
|
||||
REXY_if_consteval{
|
||||
std::memcpy(l, r, n);
|
||||
}else{
|
||||
char* ld = static_cast<char*>(l);
|
||||
@ -150,7 +150,7 @@ namespace rexy{
|
||||
}
|
||||
}
|
||||
}
|
||||
#else // REXY_if_constexpr
|
||||
#else // REXY_if_consteval
|
||||
template<class T>
|
||||
constexpr size_t strlen(const T* c)noexcept{
|
||||
size_t i = 0;
|
||||
@ -180,7 +180,7 @@ namespace rexy{
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // REXY_if_constexpr
|
||||
#endif // REXY_if_consteval
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -12,6 +12,8 @@
|
||||
exit(1);
|
||||
}
|
||||
|
||||
using namespace rexy::str_literals;
|
||||
|
||||
using test_str = rexy::basic_string<char,rexy::allocator<char>>;
|
||||
|
||||
void check_empty_construction(){
|
||||
@ -295,6 +297,42 @@ void check_string_erase(){
|
||||
}
|
||||
}
|
||||
|
||||
void check_string_replace(){
|
||||
rexy::string test = "test string";
|
||||
test.replace(0, 4, "yolo");
|
||||
if(test != "yolo string"){
|
||||
error("string replace operation 1 did not result in a correct result\n");
|
||||
}
|
||||
|
||||
test = "this is a long string version"_sv;
|
||||
auto it = test.search("long"_sv);
|
||||
if(it == test.end()){
|
||||
error("string search failed in replace test\n");
|
||||
}
|
||||
test.replace(it, it+4, "thic");
|
||||
if(test != "this is a thic string version"){
|
||||
error("string replace operation 2 did not result in a correct result\n");
|
||||
}
|
||||
|
||||
test.replace(test.end() - 7, test.end(), "vrisiod");
|
||||
if(test != "this is a thic string vrisiod"){
|
||||
error("string replace operation 3 did not result in a correct result\n");
|
||||
}
|
||||
|
||||
test.replace(test.begin(), test.end(), "change");
|
||||
if(test != "changes a thic string vrisiod"){
|
||||
error("string replace operation 4 did not result in a correct result\n");
|
||||
}
|
||||
test = "short"_sv;
|
||||
|
||||
test.replace(test.begin(), test.end(), "a longer string");
|
||||
if(test != "a lon"){
|
||||
error("string replace operation 5 did not result in a correct result\n");
|
||||
}
|
||||
}
|
||||
|
||||
#include <iterator>
|
||||
|
||||
int main(){
|
||||
check_empty_construction();
|
||||
check_short_construction();
|
||||
@ -307,4 +345,5 @@ int main(){
|
||||
check_string_search();
|
||||
check_string_insert();
|
||||
check_string_erase();
|
||||
check_string_replace();
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user