diff --git a/include/rexy/string_base.hpp b/include/rexy/string_base.hpp index 6b13a1a..e0fd748 100644 --- a/include/rexy/string_base.hpp +++ b/include/rexy/string_base.hpp @@ -26,6 +26,7 @@ #include //CHAR_BIT #include //reverse_iterator #include //ostream +#include #include "steal.hpp" #include "utility.hpp" @@ -188,6 +189,9 @@ namespace rexy{ else return get_short_length(); } + constexpr size_type size(void)const noexcept{ + return length(); + } constexpr size_type capacity(void)const noexcept{ if(islong()) return get_long_capacity(); @@ -259,6 +263,8 @@ namespace rexy{ using const_reverse_iterator = typename string_base::const_reverse_iterator; using allocator_type = Alloc; + static constexpr size_type npos = size_type{-1}; + private: REXY_CPP20_CONSTEXPR void _copy_construct_string(const_pointer data, size_type len, size_type cap) noexcept(is_nothrow_allocator_v); @@ -302,8 +308,28 @@ namespace rexy{ //Replace managed pointer. Frees existing value REXY_CPP20_CONSTEXPR void reset(pointer val = nullptr)noexcept(is_nothrow_allocator_v); REXY_CPP20_CONSTEXPR void reset(pointer val, size_type len)noexcept(is_nothrow_allocator_v); - REXY_CPP20_CONSTEXPR bool resize(size_type newsize) - noexcept(is_nothrow_allocator_v); + REXY_CPP20_CONSTEXPR bool resize(size_type newsize)noexcept(is_nothrow_allocator_v); + + //TODO more insert + REXY_CPP20_CONSTEXPR basic_string& insert(size_type pos, size_type insert_count, value_type v)noexcept(is_nothrow_allocator_v); + REXY_CPP20_CONSTEXPR basic_string& insert(size_type pos, value_type v)noexcept(is_nothrow_allocator_v); + REXY_CPP20_CONSTEXPR basic_string& insert(size_type pos, const_pointer str)noexcept(is_nothrow_allocator_v); + REXY_CPP20_CONSTEXPR basic_string& insert(size_type pos, const_pointer str, size_type insert_count)noexcept(is_nothrow_allocator_v); + REXY_CPP20_CONSTEXPR basic_string& insert(size_type pos, const basic_string& other)noexcept(is_nothrow_allocator_v); + REXY_CPP20_CONSTEXPR basic_string& insert(size_type pos, const basic_string& other, size_type index_str, size_type count = npos)noexcept(is_nothrow_allocator_v); + REXY_CPP20_CONSTEXPR basic_string& insert(const_iterator pos, value_type v)noexcept(is_nothrow_allocator_v); + REXY_CPP20_CONSTEXPR basic_string& insert(const_iterator pos, size_type count, value_type v)noexcept(is_nothrow_allocator_v); + template + REXY_CPP20_CONSTEXPR basic_string& insert(const_iterator pos, InIt start, InIt last)noexcept(is_nothrow_allocator_v); + template + REXY_CPP20_CONSTEXPR basic_string& insert(size_type pos, InIt start, InIt last)noexcept(is_nothrow_allocator_v); + REXY_CPP20_CONSTEXPR basic_string& insert(const_iterator pos, std::initializer_list list)noexcept(is_nothrow_allocator_v); + template + REXY_CPP20_CONSTEXPR auto insert(size_type pos, const StringView& sv)noexcept(is_nothrow_allocator_v) -> + std::enable_if_t> && !std::is_convertible_v>; + template + REXY_CPP20_CONSTEXPR auto insert(size_type pos, const StringView& sv, size_type index_str, size_type count = npos)noexcept(is_nothrow_allocator_v) -> + std::enable_if_t> && !std::is_convertible_v>; REXY_CPP20_CONSTEXPR void push_back(value_type data) noexcept(is_nothrow_allocator_v); @@ -317,6 +343,7 @@ namespace rexy{ template REXY_CPP20_CONSTEXPR basic_string substring(size_type start, size_type end)const; + REXY_CPP20_CONSTEXPR basic_string substr(size_type start, size_type end)const; REXY_CPP20_CONSTEXPR pointer release(void)noexcept(is_nothrow_allocator_v); using detail::hasallocator::allocator; diff --git a/include/rexy/string_base.tpp b/include/rexy/string_base.tpp index 279936c..b86237a 100644 --- a/include/rexy/string_base.tpp +++ b/include/rexy/string_base.tpp @@ -250,6 +250,106 @@ namespace rexy{ return (*this = basic_string(this->get_pointer(), newsize)); } + + template + REXY_CPP20_CONSTEXPR auto basic_string::insert(size_type pos, size_type insert_count, value_type v)noexcept(is_nothrow_allocator_v) -> basic_string&{ + struct insert_adapter{ + size_type max; + value_type val; + + constexpr insert_adapter& operator++(void)noexcept{ + --max; + return *this; + } + constexpr value_type operator*(void)const noexcept{ + return val; + } + + constexpr bool operator==(const insert_adapter& other)const = default; + constexpr bool operator!=(const insert_adapter& other)const = default; + }; + + return insert(pos, insert_adapter{insert_count, v}, insert_adapter{0, v}); + } + + template + REXY_CPP20_CONSTEXPR auto basic_string::insert(size_type pos, value_type v)noexcept(is_nothrow_allocator_v) -> basic_string&{ + return insert(pos, size_type{1}, v); + } + template + REXY_CPP20_CONSTEXPR auto basic_string::insert(size_type pos, const_pointer str)noexcept(is_nothrow_allocator_v) -> basic_string&{ + const size_type slen = rexy::strlen(str); + return insert(pos, str, str + slen); + } + template + REXY_CPP20_CONSTEXPR auto basic_string::insert(size_type pos, const_pointer str, size_type insert_count)noexcept(is_nothrow_allocator_v) -> basic_string&{ + return insert(pos, str, str + insert_count); + } + template + REXY_CPP20_CONSTEXPR auto basic_string::insert(size_type pos, const basic_string& other)noexcept(is_nothrow_allocator_v) -> basic_string&{ + return insert(pos, other.begin(), other.end()); + } + template + REXY_CPP20_CONSTEXPR auto basic_string::insert(size_type pos, const basic_string& other, size_type index_str, size_type count)noexcept(is_nothrow_allocator_v) -> basic_string&{ + return insert(pos, other.begin() + index_str, other.begin() + index_str + count); + } + template + REXY_CPP20_CONSTEXPR auto basic_string::insert(const_iterator pos, value_type v)noexcept(is_nothrow_allocator_v) -> basic_string&{ + return insert(pos, size_type{1}, v); + } + template + REXY_CPP20_CONSTEXPR auto basic_string::insert(const_iterator pos, size_type count, value_type v)noexcept(is_nothrow_allocator_v) -> basic_string&{ + return insert(pos - this->begin(), count, v); + } + template + template + REXY_CPP20_CONSTEXPR auto basic_string::insert(const_iterator pos, InIt start, InIt last)noexcept(is_nothrow_allocator_v) -> basic_string&{ + return insert(pos - this->begin(), std::move(start), std::move(last)); + } + template + REXY_CPP20_CONSTEXPR auto basic_string::insert(const_iterator pos, std::initializer_list list)noexcept(is_nothrow_allocator_v) -> basic_string&{ + return insert(pos, list.begin(), list.end()); + } + template + template + REXY_CPP20_CONSTEXPR auto basic_string::insert(size_type pos, const StringView& sv)noexcept(is_nothrow_allocator_v) -> + std::enable_if_t> && !std::is_convertible_v> + { + return insert(pos, sv.begin(), sv.end()); + } + template + template + REXY_CPP20_CONSTEXPR auto basic_string::insert(size_type pos, const StringView& sv, size_type index_str, size_type count)noexcept(is_nothrow_allocator_v) -> + std::enable_if_t> && !std::is_convertible_v> + { + return insert(pos, sv.begin() + index_str, sv.begin() + index_str + count); + } + + template + template + REXY_CPP20_CONSTEXPR auto basic_string::insert(size_type pos, InIt start, InIt last)noexcept(is_nothrow_allocator_v) -> basic_string&{ + const size_type len = this->length(); + size_type insert_count = 0; + for(auto it = start;it != last;++it, ++insert_count){} + resize(rexy::max(pos + insert_count, len + insert_count)); + + const size_type move_count = rexy::min(0, len - pos); + const auto ptr = this->get_pointer(); + + for(size_type i = move_count+1;i > 0;--i){ + const size_type index = i + pos; + ptr[index] = ptr[index-1]; + } + { + size_type i = 0; + for(auto it = start;it != last;++it,++i){ + ptr[pos+i] = *it; + } + } + this->set_length(len + insert_count); + return *this; + } + template REXY_CPP20_CONSTEXPR void basic_string::push_back(value_type data) noexcept(is_nothrow_allocator_v) @@ -320,6 +420,11 @@ namespace rexy{ tmp.append(this->get() + start, newlen); return tmp; } + template + REXY_CPP20_CONSTEXPR auto basic_string::substr(size_type start, size_type end)const -> basic_string{ + return substring(start, end); + } + template REXY_CPP20_CONSTEXPR auto basic_string::release(void)noexcept(is_nothrow_allocator_v) -> pointer{ if(this->islong()){