From eafe6f5a213d385351cdf191a3142b66d75c62d4 Mon Sep 17 00:00:00 2001 From: rexy712 Date: Wed, 20 Jul 2022 19:13:21 -0700 Subject: [PATCH] Add missing exception specs to basic_string and basic_string_view. Also implement some missing std functionality to them --- include/rexy/compat/cpp17/string_base.hpp | 49 +- include/rexy/compat/cpp20/string_base.hpp | 49 +- include/rexy/string_base.hpp | 419 ++++++++++++----- include/rexy/string_base.tpp | 525 +++++++++++++++++----- include/rexy/string_view.hpp | 79 ++-- include/rexy/string_view.tpp | 92 +++- 6 files changed, 927 insertions(+), 286 deletions(-) diff --git a/include/rexy/compat/cpp17/string_base.hpp b/include/rexy/compat/cpp17/string_base.hpp index 8c39dac..ad1966c 100644 --- a/include/rexy/compat/cpp17/string_base.hpp +++ b/include/rexy/compat/cpp17/string_base.hpp @@ -253,7 +253,7 @@ namespace rexy{ } template::value, int> = 0> - constexpr std::size_t find_first_of(T&& t, const Char* c, std::size_t start, std::size_t size){ + constexpr std::size_t find_first_of(T&& t, const Char* c, std::size_t start, std::size_t size)noexcept{ if(start > t.length()){ return rexy::npos; } @@ -268,7 +268,27 @@ namespace rexy{ } template::value, int> = 0> - constexpr std::size_t find_last_of(T&& t, const Char* c, std::size_t start, std::size_t size){ + constexpr std::size_t find_first_not_of(T&& t, const Char* c, std::size_t start, std::size_t size)noexcept{ + if(start > t.length()){ + return rexy::npos; + } + for(auto it = t.cbegin() + start;it != t.cend();++it){ + bool found = false; + for(std::size_t i = 0;i < size;++i){ + if(*it == c[i]){ + found = true; + break; + } + } + if(!found){ + return it - t.cbegin(); + } + } + return rexy::npos; + } + + template::value, int> = 0> + constexpr std::size_t find_last_of(T&& t, const Char* c, std::size_t start, std::size_t size)noexcept{ if(start > t.length()){ return rexy::npos; } @@ -286,6 +306,31 @@ namespace rexy{ return rexy::npos; } + template::value, int> = 0> + constexpr std::size_t find_last_not_of(T&& t, const Char* c, std::size_t start, std::size_t size)noexcept{ + 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){ + bool found = false; + for(std::size_t i = 0;i < size;++i){ + if(*it == c[i]){ + found = true; + break; + } + } + if(!found){ + return it - t.cbegin(); + } + } + return rexy::npos; + } + } #endif diff --git a/include/rexy/compat/cpp20/string_base.hpp b/include/rexy/compat/cpp20/string_base.hpp index 196380a..55837d2 100644 --- a/include/rexy/compat/cpp20/string_base.hpp +++ b/include/rexy/compat/cpp20/string_base.hpp @@ -174,7 +174,7 @@ namespace rexy{ } template - constexpr std::size_t find_first_of(T&& t, const Char* c, std::size_t start, std::size_t size){ + constexpr std::size_t find_first_of(T&& t, const Char* c, std::size_t start, std::size_t size)noexcept{ if(start > t.length()){ return rexy::npos; } @@ -189,7 +189,27 @@ namespace rexy{ } template - constexpr std::size_t find_last_of(T&& t, const Char* c, std::size_t start, std::size_t size){ + constexpr std::size_t find_first_not_of(T&& t, const Char* c, std::size_t start, std::size_t size)noexcept{ + if(start > t.length()){ + return rexy::npos; + } + for(auto it = t.cbegin() + start;it != t.cend();++it){ + bool found = false; + for(std::size_t i = 0;i < size;++i){ + if(*it == c[i]){ + found = true; + break; + } + } + if(!found){ + return it - t.cbegin(); + } + } + return rexy::npos; + } + + template + constexpr std::size_t find_last_of(T&& t, const Char* c, std::size_t start, std::size_t size)noexcept{ if(start > t.length()){ return rexy::npos; } @@ -207,6 +227,31 @@ namespace rexy{ return rexy::npos; } + template + constexpr std::size_t find_last_not_of(T&& t, const Char* c, std::size_t start, std::size_t size)noexcept{ + 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){ + bool found = false; + for(std::size_t i = 0;i < size;++i){ + if(*it == c[i]){ + found = true; + break; + } + } + if(!found){ + return it - t.cbegin(); + } + } + return rexy::npos; + } + } #endif diff --git a/include/rexy/string_base.hpp b/include/rexy/string_base.hpp index 272abde..d36a4a9 100644 --- a/include/rexy/string_base.hpp +++ b/include/rexy/string_base.hpp @@ -278,23 +278,27 @@ namespace rexy{ constexpr reference at(size_type i)noexcept{return get_pointer()[i];} constexpr const_reference at(size_type i)const noexcept{return get_pointer()[i];} - constexpr const_iterator search(basic_string_view sv)const; - constexpr iterator search(basic_string_view sv); - constexpr const_iterator search(const_pointer c)const; - constexpr iterator search(const_pointer c); + constexpr const_iterator search(basic_string_view sv)const noexcept; + constexpr iterator search(basic_string_view sv)noexcept; + constexpr const_iterator search(const_pointer c)const noexcept; + constexpr iterator search(const_pointer c)noexcept; template - constexpr const_iterator search(const_pointer c, const Searcher& searcher)const; + constexpr const_iterator search(const_pointer c, const Searcher& searcher)const noexcept( + std::is_nothrow_invocable_v); template - constexpr iterator search(const_pointer c, const Searcher& searcher); + constexpr iterator search(const_pointer c, const Searcher& searcher)noexcept( + std::is_nothrow_invocable_v); - constexpr const_iterator rsearch(basic_string_view sv)const; - constexpr iterator rsearch(basic_string_view sv); - constexpr const_iterator rsearch(const_pointer c)const; - constexpr iterator rsearch(const_pointer c); + constexpr const_iterator rsearch(basic_string_view sv)const noexcept; + constexpr iterator rsearch(basic_string_view sv)noexcept; + constexpr const_iterator rsearch(const_pointer c)const noexcept; + constexpr iterator rsearch(const_pointer c)noexcept; template - constexpr const_iterator rsearch(const_pointer c, const Searcher& searcher)const; + constexpr const_iterator rsearch(const_pointer c, const Searcher& searcher)const noexcept( + std::is_nothrow_invocable_v); template - constexpr iterator rsearch(const_pointer c, const Searcher& searcher); + constexpr iterator rsearch(const_pointer c, const Searcher& searcher)noexcept( + std::is_nothrow_invocable_v); constexpr bool starts_with(basic_string_view sv)const noexcept; constexpr bool starts_with(value_type v)const noexcept; @@ -309,41 +313,75 @@ namespace rexy{ constexpr bool contains(const_pointer str)const noexcept; //TODO more compares - constexpr bool compare(const string_base& s)const{return *this == s;} - constexpr bool compare(basic_string_view s)const{return *this == s;} - constexpr bool compare(const_pointer c)const{return *this == c;} + constexpr bool compare(const string_base& s)const noexcept{return *this == s;} + constexpr bool compare(basic_string_view s)const noexcept{return *this == s;} + constexpr bool compare(const_pointer c)const noexcept{return *this == c;} - constexpr size_type find_first_of(value_type v, size_type start = 0)const; - constexpr size_type find_first_of(const_pointer c, size_type pos = 0)const; - constexpr size_type find_first_of(const_pointer c, size_type pos, size_type size)const; - constexpr size_type find_last_of(value_type v, size_type start = 0)const; - 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; + constexpr size_type find_first_of(value_type v, size_type start = 0)const noexcept; + constexpr size_type find_first_of(const_pointer c, size_type start = 0)const noexcept; + constexpr size_type find_first_of(const_pointer c, size_type start, size_type size)const noexcept; + template + constexpr auto find_first_of(const StringView& str, size_type start = 0)const noexcept( + std::is_nothrow_convertible_v>) -> + std::enable_if_t< + std::is_convertible_v>, + size_type>; + + constexpr size_type find_last_of(value_type v, size_type start = 0)const noexcept; + constexpr size_type find_last_of(const_pointer c, size_type start = 0)const noexcept; + constexpr size_type find_last_of(const_pointer c, size_type start, size_type size)const noexcept; + template + constexpr auto find_last_of(const StringView& str, size_type start = 0)const noexcept( + std::is_nothrow_convertible_v>) -> + std::enable_if_t< + std::is_convertible_v>, + size_type>; + + constexpr size_type find_first_not_of(const_pointer str, size_type start, size_type count)const noexcept; + constexpr size_type find_first_not_of(const_pointer str, size_type start = 0)const noexcept; + constexpr size_type find_first_not_of(value_type v, size_type start = 0)const noexcept; + template + constexpr auto find_first_not_of(const StringView& str, size_type start = 0)const noexcept( + std::is_nothrow_convertible_v>) -> + std::enable_if_t< + std::is_convertible_v>, + size_type>; + + constexpr size_type find_last_not_of(const_pointer str, size_type start, size_type count)const noexcept; + constexpr size_type find_last_not_of(const_pointer str, size_type start = 0)const noexcept; + constexpr size_type find_last_not_of(value_type v, size_type start = 0)const noexcept; + template + constexpr auto find_last_not_of(const StringView& str, size_type start = 0)const noexcept( + std::is_nothrow_convertible_v>) -> + std::enable_if_t< + std::is_convertible_v>, + size_type>; constexpr reference front(void)noexcept{return *get_pointer();} constexpr const_reference front(void)const noexcept{return *get_pointer();} constexpr reference back(void)noexcept{return *(get_pointer() + length() - 1);} constexpr const_reference back(void)const noexcept{return *(get_pointer() + length() - 1);} - constexpr iterator begin(void){return get_pointer();} - constexpr const_iterator begin(void)const{return get_pointer();} - constexpr iterator end(void){return get_pointer()+length();} - constexpr const_iterator end(void)const{return get_pointer()+length();} - constexpr const_iterator cbegin(void)const{return begin();} - constexpr const_iterator cend(void)const{return end();} + constexpr iterator begin(void)noexcept{return get_pointer();} + constexpr const_iterator begin(void)const noexcept{return get_pointer();} + constexpr iterator end(void)noexcept{return get_pointer()+length();} + constexpr const_iterator end(void)const noexcept{return get_pointer()+length();} + constexpr const_iterator cbegin(void)const noexcept{return begin();} + constexpr const_iterator cend(void)const noexcept{return end();} - constexpr reverse_iterator rbegin(void){return reverse_iterator(get_pointer()+length());} - constexpr const_reverse_iterator rbegin(void)const{return const_reverse_iterator(get_pointer()+length());} - constexpr reverse_iterator rend(void){return reverse_iterator(get_pointer());} - constexpr const_reverse_iterator rend(void)const{return const_reverse_iterator(get_pointer());} - constexpr const_reverse_iterator crbegin(void)const{return rbegin();} - constexpr const_reverse_iterator crend(void)const{return rend();} + constexpr reverse_iterator rbegin(void)noexcept{return reverse_iterator(get_pointer()+length());} + constexpr const_reverse_iterator rbegin(void)const noexcept{return const_reverse_iterator(get_pointer()+length());} + constexpr reverse_iterator rend(void)noexcept{return reverse_iterator(get_pointer());} + constexpr const_reverse_iterator rend(void)const noexcept{return const_reverse_iterator(get_pointer());} + constexpr const_reverse_iterator crbegin(void)const noexcept{return rbegin();} + constexpr const_reverse_iterator crend(void)const noexcept{return rend();} constexpr void clear(void)noexcept; constexpr basic_string_view create_view(void)const noexcept; constexpr basic_string_view create_view(const_iterator start, const_iterator fin)const noexcept; - }; + + }; //class string_base //Supplies all functions that string_base can't implement @@ -367,125 +405,279 @@ namespace rexy{ 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); - REXY_CPP20_CONSTEXPR basic_string& _copy_string(const_pointer s, size_type len) - noexcept(is_nothrow_allocator_v); + + REXY_CPP20_CONSTEXPR + void _copy_construct_string(const_pointer data, size_type len, size_type cap)noexcept( + is_nothrow_allocator_v); + + REXY_CPP20_CONSTEXPR + basic_string& _copy_string(const_pointer s, size_type len)noexcept( + is_nothrow_allocator_v); + template - REXY_CPP20_CONSTEXPR basic_string& _insert_impl(size_type pos, InputIt start, size_type insert_count)noexcept(is_nothrow_allocator_v); + REXY_CPP20_CONSTEXPR + basic_string& _insert_impl(size_type pos, InputIt start, size_type insert_count)noexcept( + is_nothrow_allocator_v); + template - constexpr basic_string& _replace_impl(size_type pos, size_type count, InputIt src, size_type count2); + constexpr basic_string& _replace_impl(size_type pos, size_type count, InputIt src, size_type count2)noexcept; public: constexpr basic_string(void)noexcept; constexpr basic_string(rexy::steal data, size_type len)noexcept; constexpr basic_string(rexy::steal data, size_type len, size_type cap)noexcept; constexpr basic_string(rexy::steal data)noexcept; - REXY_CPP20_CONSTEXPR basic_string(const_pointer data, size_type len)noexcept(is_nothrow_allocator_v); - REXY_CPP20_CONSTEXPR basic_string(const_pointer data, size_type len, size_type cap)noexcept(is_nothrow_allocator_v); - REXY_CPP20_CONSTEXPR basic_string(const_pointer data)noexcept(is_nothrow_allocator_v); - REXY_CPP20_CONSTEXPR explicit basic_string(size_type len)noexcept(is_nothrow_allocator_v); - REXY_CPP20_CONSTEXPR basic_string(size_type len, size_type cap)noexcept(is_nothrow_allocator_v); + + REXY_CPP20_CONSTEXPR + basic_string(const_pointer data, size_type len)noexcept( + is_nothrow_allocator_v); + + REXY_CPP20_CONSTEXPR + basic_string(const_pointer data, size_type len, size_type cap)noexcept( + is_nothrow_allocator_v); + + REXY_CPP20_CONSTEXPR + basic_string(const_pointer data)noexcept( + is_nothrow_allocator_v); + + REXY_CPP20_CONSTEXPR + explicit basic_string(size_type len)noexcept( + is_nothrow_allocator_v); + + REXY_CPP20_CONSTEXPR + basic_string(size_type len, size_type cap)noexcept( + is_nothrow_allocator_v); + template,int>> - REXY_CPP20_CONSTEXPR basic_string(InputIt start, InputIt fin)noexcept(is_nothrow_allocator_v); - REXY_CPP20_CONSTEXPR basic_string(const basic_string_view& sv)noexcept(is_nothrow_allocator_v); + REXY_CPP20_CONSTEXPR + basic_string(InputIt start, InputIt fin)noexcept( + is_nothrow_allocator_v); + + REXY_CPP20_CONSTEXPR + basic_string(const basic_string_view& sv)noexcept( + is_nothrow_allocator_v); + //normal copy and move ctors - REXY_CPP20_CONSTEXPR basic_string(const basic_string& b)noexcept(is_nothrow_allocator_v); + REXY_CPP20_CONSTEXPR + basic_string(const basic_string& b)noexcept( + is_nothrow_allocator_v); + constexpr basic_string(basic_string&& s)noexcept; - REXY_CPP20_CONSTEXPR basic_string(const string_base&)noexcept(is_nothrow_allocator_v); + + REXY_CPP20_CONSTEXPR + basic_string(const string_base&)noexcept( + is_nothrow_allocator_v); + //dtor - REXY_CPP20_CONSTEXPR ~basic_string(void)noexcept(is_nothrow_allocator_v); + REXY_CPP20_CONSTEXPR + ~basic_string(void)noexcept( + is_nothrow_allocator_v); - REXY_CPP20_CONSTEXPR basic_string& operator=(const basic_string& s) - noexcept(is_nothrow_allocator_v); + + REXY_CPP20_CONSTEXPR + basic_string& operator=(const basic_string& s)noexcept( + is_nothrow_allocator_v); constexpr basic_string& operator=(basic_string&& s)noexcept; - REXY_CPP20_CONSTEXPR basic_string& operator=(const string_base& s) - noexcept(is_nothrow_allocator_v); - REXY_CPP20_CONSTEXPR basic_string& operator=(const basic_string_view& sv) - noexcept(is_nothrow_allocator_v); + REXY_CPP20_CONSTEXPR + basic_string& operator=(const string_base& s)noexcept( + is_nothrow_allocator_v); + + REXY_CPP20_CONSTEXPR + basic_string& operator=(const basic_string_view& sv)noexcept( + is_nothrow_allocator_v); + //Copy from c string - REXY_CPP20_CONSTEXPR basic_string& operator=(const_pointer c) - noexcept(is_nothrow_allocator_v); + REXY_CPP20_CONSTEXPR + basic_string& operator=(const_pointer c)noexcept( + is_nothrow_allocator_v); + + + //These can't be put in base because they require us to know the type of Alloc + constexpr size_type find_first_of(const basic_string& str, size_type start = 0)const noexcept; + constexpr size_type find_last_of(const basic_string& str, size_type start = 0)const noexcept; + constexpr size_type find_first_not_of(const basic_string& str, size_type start = 0)const noexcept; + constexpr size_type find_last_not_of(const basic_string& str, size_type start = 0)const noexcept; //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 reserve(size_type newsize)noexcept(is_nothrow_allocator_v); - REXY_CPP20_CONSTEXPR void shrink_to_fit(void)noexcept(is_nothrow_allocator_v); + REXY_CPP20_CONSTEXPR + void reset(pointer val = nullptr)noexcept( + is_nothrow_allocator_v); - REXY_CPP20_CONSTEXPR void resize(size_type newsize, value_type v = value_type())noexcept(is_nothrow_allocator_v); + REXY_CPP20_CONSTEXPR + void reset(pointer val, size_type len)noexcept( + is_nothrow_allocator_v); + + REXY_CPP20_CONSTEXPR + bool reserve(size_type newsize)noexcept( + is_nothrow_allocator_v); + + REXY_CPP20_CONSTEXPR + void shrink_to_fit(void)noexcept( + is_nothrow_allocator_v); + + REXY_CPP20_CONSTEXPR + void resize(size_type newsize, value_type v = value_type())noexcept( + is_nothrow_allocator_v); + + + + 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); - 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 auto insert(const_iterator pos, InputIt start, InputIt last)noexcept(is_nothrow_allocator_v) -> + REXY_CPP20_CONSTEXPR + auto insert(const_iterator pos, InputIt start, InputIt last)noexcept( + is_nothrow_allocator_v) -> std::enable_if_t,basic_string&>; + template - REXY_CPP20_CONSTEXPR auto insert(size_type pos, InputIt start, InputIt last)noexcept(is_nothrow_allocator_v) -> + REXY_CPP20_CONSTEXPR + auto insert(size_type pos, InputIt start, InputIt last)noexcept( + is_nothrow_allocator_v) -> std::enable_if_t,basic_string&>; - REXY_CPP20_CONSTEXPR basic_string& insert(const_iterator pos, std::initializer_list list)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,basic_string&>; + REXY_CPP20_CONSTEXPR + auto insert(size_type pos, const StringView& sv)noexcept( + is_nothrow_allocator_v) -> + std::enable_if_t< + std::is_convertible_v> && + !std::is_convertible_v, + basic_string&>; + 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,basic_string&>; + 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> && + !std::is_convertible_v, + basic_string&>; + + template - REXY_CPP20_CONSTEXPR auto append(InputIt start, InputIt fin)noexcept(is_nothrow_allocator_v) -> - std::enable_if_t,basic_string&>; - REXY_CPP20_CONSTEXPR basic_string& append(const_pointer data, size_type len)noexcept(is_nothrow_allocator_v); - REXY_CPP20_CONSTEXPR basic_string& append(const_pointer data)noexcept(is_nothrow_allocator_v); - REXY_CPP20_CONSTEXPR basic_string& append(const basic_string& other)noexcept(is_nothrow_allocator_v); + REXY_CPP20_CONSTEXPR + auto append(InputIt start, InputIt fin)noexcept( + is_nothrow_allocator_v) -> + std::enable_if_t,basic_string&>; + + REXY_CPP20_CONSTEXPR + basic_string& append(const_pointer data, size_type len)noexcept( + is_nothrow_allocator_v); + + REXY_CPP20_CONSTEXPR + basic_string& append(const_pointer data)noexcept( + is_nothrow_allocator_v); + + REXY_CPP20_CONSTEXPR + basic_string& append(const basic_string& other)noexcept( + is_nothrow_allocator_v); + + + + REXY_CPP20_CONSTEXPR + void push_back(value_type data)noexcept( + is_nothrow_allocator_v); - REXY_CPP20_CONSTEXPR void push_back(value_type data)noexcept(is_nothrow_allocator_v); 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); + constexpr basic_string& replace(size_type pos, size_type count, const basic_string& str)noexcept; + constexpr basic_string& replace(const_iterator pos, const_iterator last, const basic_string& str)noexcept; + constexpr basic_string& replace(size_type pos, size_type count, const basic_string& str, size_type pos2, size_type count2 = npos)noexcept; + template - constexpr auto replace(const_iterator first, const_iterator last, InputIt first2, InputIt last2) -> - std::enable_if_t,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 list); + constexpr auto replace(const_iterator first, const_iterator last, InputIt first2, InputIt last2)noexcept -> + std::enable_if_t,basic_string&>; + + constexpr basic_string& replace(size_type pos, size_type count, const_pointer cstr, size_type count2)noexcept; + constexpr basic_string& replace(const_iterator first, const_iterator last, const_pointer cstr, size_type count)noexcept; + constexpr basic_string& replace(size_type pos, size_type count, const_pointer cstr)noexcept; + constexpr basic_string& replace(const_iterator first, const_iterator last, const_pointer cstr)noexcept; + constexpr basic_string& replace(size_type pos, size_type count, size_type count2, value_type v)noexcept; + constexpr basic_string& replace(const_iterator first, const_iterator last, size_type count2, value_type v)noexcept; + constexpr basic_string& replace(const_iterator first, const_iterator last, std::initializer_list list)noexcept; + template - constexpr auto replace(size_type pos, size_type count, const StringView& sv) -> - std::enable_if_t> && !std::is_convertible_v,basic_string&>; + constexpr auto replace(size_type pos, size_type count, const StringView& sv)noexcept -> + std::enable_if_t< + std::is_convertible_v> && + !std::is_convertible_v, + basic_string&>; + template - constexpr auto replace(const_iterator first, const_iterator last, const StringView& sv) -> - std::enable_if_t> && !std::is_convertible_v,basic_string&>; + constexpr auto replace(const_iterator first, const_iterator last, const StringView& sv)noexcept -> + std::enable_if_t< + std::is_convertible_v> && + !std::is_convertible_v, + basic_string&>; + template - 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,basic_string&>; + constexpr auto replace(size_type pos, size_type count, const StringView& sv, size_type pos2, size_type count2 = npos)noexcept -> + std::enable_if_t< + std::is_convertible_v> && + !std::is_convertible_v, + 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; - 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); + template + REXY_CPP20_CONSTEXPR + basic_string substring(size_type start, size_type end)const noexcept( + is_nothrow_allocator_v); + + REXY_CPP20_CONSTEXPR + basic_string substr(size_type start, size_type end)const noexcept( + is_nothrow_allocator_v); + + REXY_CPP20_CONSTEXPR + pointer release(void)noexcept( + is_nothrow_allocator_v); + using detail::hasallocator::allocator; - }; + }; //class basic_string //Like an expression template but not really template @@ -514,14 +706,19 @@ namespace rexy{ constexpr size_type length(void)const noexcept; template - REXY_CPP20_CONSTEXPR operator basic_string(void) - noexcept(std::is_nothrow_constructible, typename basic_string::size_type>::value && - std::is_nothrow_invocable>,decltype(*this)>::value); + REXY_CPP20_CONSTEXPR + operator basic_string(void)noexcept( + std::is_nothrow_constructible_v< + basic_string, + typename basic_string::size_type> && + std::is_nothrow_invocable_v< + detail::string_appender>, + decltype(*this)>); }; template string_cat_expr(Left&&,Right&&) -> string_cat_expr; -} +} //namespace rexy #include "string_base.tpp" diff --git a/include/rexy/string_base.tpp b/include/rexy/string_base.tpp index 2718de8..7c471c9 100644 --- a/include/rexy/string_base.tpp +++ b/include/rexy/string_base.tpp @@ -34,75 +34,83 @@ namespace rexy{ template - constexpr auto string_base::search(basic_string_view sv)const -> const_iterator{ + constexpr auto string_base::search(basic_string_view sv)const noexcept -> const_iterator{ if(sv.length() > length()){ return cend(); } return two_way_search(cbegin(), cend(), sv.cbegin(), sv.cend()); } template - constexpr auto string_base::search(basic_string_view sv) -> iterator{ + constexpr auto string_base::search(basic_string_view sv)noexcept -> iterator{ if(sv.length() > length()){ return end(); } return two_way_search(begin(), end(), sv.cbegin(), sv.cend()); } template - constexpr auto string_base::search(const_pointer c)const -> const_iterator{ + constexpr auto string_base::search(const_pointer c)const noexcept -> const_iterator{ const auto len = rexy::strlen(c); return two_way_search(cbegin(), cend(), c, c + len); } template - constexpr auto string_base::search(const_pointer c) -> iterator{ + constexpr auto string_base::search(const_pointer c)noexcept -> iterator{ const auto len = rexy::strlen(c); return two_way_search(begin(), end(), c, c + len); } template template - constexpr auto string_base::search(const_pointer c, const Searcher& searcher)const -> const_iterator{ + constexpr auto string_base::search(const_pointer c, const Searcher& searcher)const noexcept( + std::is_nothrow_invocable_v) -> const_iterator + { const auto len = rexy::strlen(c); return searcher(cbegin(), cend(), c, c + len); } template template - constexpr auto string_base::search(const_pointer c, const Searcher& searcher) -> iterator{ + constexpr auto string_base::search(const_pointer c, const Searcher& searcher)noexcept( + std::is_nothrow_invocable_v) -> iterator + { const auto len = rexy::strlen(c); return searcher(begin(), end(), c, c + len); } template - constexpr auto string_base::rsearch(basic_string_view sv)const -> const_iterator{ + constexpr auto string_base::rsearch(basic_string_view sv)const noexcept-> const_iterator{ if(sv.length() > length()){ return cend(); } return two_way_search(crbegin(), crend(), sv.crbegin(), sv.crend()).base(); } template - constexpr auto string_base::rsearch(basic_string_view sv) -> iterator{ + constexpr auto string_base::rsearch(basic_string_view sv)noexcept -> iterator{ if(sv.length() > length()){ return end(); } return two_way_search(rbegin(), rend(), sv.crbegin(), sv.crend()).base() - sv.length(); } template - constexpr auto string_base::rsearch(const_pointer c)const -> const_iterator{ + constexpr auto string_base::rsearch(const_pointer c)const noexcept -> const_iterator{ const auto len = rexy::strlen(c); return two_way_search(crbegin(), crend(), std::reverse_iterator(c + len), std::reverse_iterator(c)).base() - len; } template - constexpr auto string_base::rsearch(const_pointer c) -> iterator{ + constexpr auto string_base::rsearch(const_pointer c)noexcept -> iterator{ const auto len = rexy::strlen(c); return two_way_search(rbegin(), rend(), std::reverse_iterator(c + len), std::reverse_iterator(c)).base() - len; } template template - constexpr auto string_base::rsearch(const_pointer c, const Searcher& searcher)const -> const_iterator{ + constexpr auto string_base::rsearch(const_pointer c, const Searcher& searcher)const noexcept( + std::is_nothrow_invocable_v) -> const_iterator + { const auto len = rexy::strlen(c); return searcher(crbegin(), crend(), std::reverse_iterator(c + len), std::reverse_iterator(c)).base() - len; } template template - constexpr auto string_base::rsearch(const_pointer c, const Searcher& searcher) -> iterator{ + constexpr auto string_base::rsearch(const_pointer c, const Searcher& searcher)noexcept( + std::is_nothrow_invocable_v) -> iterator + { const auto len = rexy::strlen(c); return searcher(rbegin(), rend(), std::reverse_iterator(c + len), std::reverse_iterator(c)).base() - len; } @@ -146,28 +154,101 @@ namespace rexy{ } template - constexpr auto string_base::find_first_of(value_type v, size_type start)const -> size_type{ + constexpr auto string_base::find_first_of(value_type v, size_type start)const noexcept-> size_type{ return rexy::find_first_of(*this, &v, start, 1); } template - constexpr auto string_base::find_first_of(const_pointer c, size_type pos)const -> size_type{ - return rexy::find_first_of(*this, c, pos, rexy::strlen(c)); + constexpr auto string_base::find_first_of(const_pointer c, size_type start)const noexcept -> size_type{ + return rexy::find_first_of(*this, c, start, rexy::strlen(c)); } template - constexpr auto string_base::find_first_of(const_pointer c, size_type pos, size_type size)const -> size_type{ - return rexy::find_first_of(*this, c, pos, size); + constexpr auto string_base::find_first_of(const_pointer c, size_type start, size_type size)const noexcept -> size_type{ + return rexy::find_first_of(*this, c, start, size); } template - constexpr auto string_base::find_last_of(value_type v, size_type start)const -> size_type{ + template + constexpr auto string_base::find_first_of(const StringView& str, size_type start)const noexcept( + std::is_nothrow_convertible_v>) -> + std::enable_if_t< + std::is_convertible_v>, + size_type> + { + const basic_string_view tmp(str); + return rexy::find_first_of(*this, tmp.c_str(), start, tmp.length()); + } + + + template + constexpr auto string_base::find_last_of(value_type v, size_type start)const noexcept -> size_type{ return rexy::find_last_of(*this, &v, start, 1); } template - constexpr auto string_base::find_last_of(const_pointer c, size_type pos)const -> size_type{ - return rexy::find_last_of(*this, c, pos, rexy::strlen(c)); + constexpr auto string_base::find_last_of(const_pointer c, size_type start)const noexcept -> size_type{ + return rexy::find_last_of(*this, c, start, rexy::strlen(c)); } template - constexpr auto string_base::find_last_of(const_pointer c, size_type pos, size_type size)const -> size_type{ - return rexy::find_last_of(*this, c, pos, size); + constexpr auto string_base::find_last_of(const_pointer c, size_type start, size_type size)const noexcept -> size_type{ + return rexy::find_last_of(*this, c, start, size); + } + template + template + constexpr auto string_base::find_last_of(const StringView& str, size_type start)const noexcept( + std::is_nothrow_convertible_v>) -> + std::enable_if_t< + std::is_convertible_v>, + size_type> + { + const rexy::basic_string_view tmp(str); + return rexy::find_last_of(*this, tmp.c_str(), start, tmp.length()); + } + + + template + constexpr auto string_base::find_first_not_of(const_pointer str, size_type start, size_type count)const noexcept -> size_type{ + return rexy::find_first_not_of(*this, str, start, count); + } + template + constexpr auto string_base::find_first_not_of(const_pointer str, size_type start)const noexcept -> size_type{ + return rexy::find_first_not_of(*this, str, start, rexy::strlen(str)); + } + template + constexpr auto string_base::find_first_not_of(value_type v, size_type start)const noexcept -> size_type{ + return rexy::find_first_not_of(*this, &v, start, 1); + } + template + template + constexpr auto string_base::find_first_not_of(const StringView& str, size_type start)const noexcept( + std::is_nothrow_convertible_v>) -> + std::enable_if_t< + std::is_convertible_v>, + size_type> + { + const basic_string_view tmp(str); + return rexy::find_first_not_of(*this, tmp.c_str(), start, tmp.length()); + } + + template + constexpr auto string_base::find_last_not_of(const_pointer str, size_type start, size_type count)const noexcept -> size_type{ + return rexy::find_last_not_of(*this, str, start, count); + } + template + constexpr auto string_base::find_last_not_of(const_pointer str, size_type start)const noexcept -> size_type{ + return rexy::find_last_not_of(*this, str, start, rexy::strlen(str)); + } + template + constexpr auto string_base::find_last_not_of(value_type v, size_type start)const noexcept -> size_type{ + return rexy::find_last_not_of(*this, &v, start, 1); + } + template + template + constexpr auto string_base::find_last_not_of(const StringView& str, size_type start)const noexcept( + std::is_nothrow_convertible_v>) -> + std::enable_if_t< + std::is_convertible_v>, + size_type> + { + const basic_string_view tmp(str); + return rexy::find_last_not_of(*this, tmp.c_str(), start, tmp.length()); } @@ -191,8 +272,9 @@ namespace rexy{ //allocate string if longer than small string capacity, copy otherwise template - REXY_CPP20_CONSTEXPR void basic_string::_copy_construct_string(const_pointer data, size_type len, size_type cap) - noexcept(is_nothrow_allocator_v) + REXY_CPP20_CONSTEXPR + void basic_string::_copy_construct_string(const_pointer data, size_type len, size_type cap)noexcept( + is_nothrow_allocator_v) { if constexpr(string_base::uses_sso()){ if(cap > string_base::short_string_size()){ @@ -228,50 +310,66 @@ namespace rexy{ template constexpr basic_string::basic_string(void)noexcept{} + template constexpr basic_string::basic_string(rexy::steal data)noexcept: basic_string(data.value(), data.value() ? rexy::strlen(data.value()) : 0){} + template constexpr basic_string::basic_string(rexy::steal data, size_type len)noexcept: string_base(data.value(), len, len){} + template constexpr basic_string::basic_string(rexy::steal data, size_type len, size_type cap)noexcept: string_base(data.value(), len, cap){} + template - REXY_CPP20_CONSTEXPR basic_string::basic_string(const_pointer data, size_type len, size_type cap) - noexcept(is_nothrow_allocator_v) + REXY_CPP20_CONSTEXPR + basic_string::basic_string(const_pointer data, size_type len, size_type cap)noexcept( + is_nothrow_allocator_v) { _copy_construct_string(data, len, cap); } + template - REXY_CPP20_CONSTEXPR basic_string::basic_string(const_pointer data, size_type len) - noexcept(is_nothrow_allocator_v): + REXY_CPP20_CONSTEXPR + basic_string::basic_string(const_pointer data, size_type len)noexcept( + is_nothrow_allocator_v): basic_string(data, len, len){} + template - REXY_CPP20_CONSTEXPR basic_string::basic_string(const_pointer data) - noexcept(is_nothrow_allocator_v): + REXY_CPP20_CONSTEXPR + basic_string::basic_string(const_pointer data)noexcept( + is_nothrow_allocator_v): basic_string(data, data ? rexy::strlen(data) : 0){} + template - REXY_CPP20_CONSTEXPR basic_string::basic_string(size_type cap) - noexcept(is_nothrow_allocator_v): + REXY_CPP20_CONSTEXPR + basic_string::basic_string(size_type cap)noexcept( + is_nothrow_allocator_v): basic_string(size_type(0), cap){} + template - REXY_CPP20_CONSTEXPR basic_string::basic_string(size_type len, size_type cap) - noexcept(is_nothrow_allocator_v) + REXY_CPP20_CONSTEXPR + basic_string::basic_string(size_type len, size_type cap)noexcept( + is_nothrow_allocator_v) { _copy_construct_string(nullptr, len, cap); } + template - REXY_CPP20_CONSTEXPR basic_string::basic_string(const basic_string_view& sv) - noexcept(is_nothrow_allocator_v) + REXY_CPP20_CONSTEXPR + basic_string::basic_string(const basic_string_view& sv)noexcept( + is_nothrow_allocator_v) { _copy_construct_string(sv.c_str(), sv.length(), sv.length()); } template template - REXY_CPP20_CONSTEXPR basic_string::basic_string(InputIt start, InputIt fin) - noexcept(is_nothrow_allocator_v): + REXY_CPP20_CONSTEXPR + basic_string::basic_string(InputIt start, InputIt fin)noexcept( + is_nothrow_allocator_v): basic_string(nullptr, size_type(fin - start)) { auto raw = this->get_pointer(); @@ -281,38 +379,47 @@ namespace rexy{ } raw[i] = 0; } + //normal copy and move ctors template - REXY_CPP20_CONSTEXPR basic_string::basic_string(const basic_string& b) - noexcept(is_nothrow_allocator_v): + REXY_CPP20_CONSTEXPR + basic_string::basic_string(const basic_string& b)noexcept( + is_nothrow_allocator_v): detail::hasallocator(b) { _copy_construct_string(b.data(), b.length(), b.length()); } + template constexpr basic_string::basic_string(basic_string&& s)noexcept: detail::hasallocator(std::move(s)), string_base(std::move(s)){} + template - REXY_CPP20_CONSTEXPR basic_string::basic_string(const string_base& b) - noexcept(is_nothrow_allocator_v) + REXY_CPP20_CONSTEXPR + basic_string::basic_string(const string_base& b)noexcept( + is_nothrow_allocator_v) { _copy_construct_string(b.data(), b.length(), b.length()); } + //dtor template - REXY_CPP20_CONSTEXPR basic_string::~basic_string(void) - noexcept(is_nothrow_allocator_v) + REXY_CPP20_CONSTEXPR + basic_string::~basic_string(void)noexcept( + is_nothrow_allocator_v) { if(this->islong()){ this->deallocate(this->get_pointer(), sizeof(value_type)*(this->capacity()+1)); } } + template - REXY_CPP20_CONSTEXPR basic_string& basic_string::operator=(const basic_string& s) - noexcept(is_nothrow_allocator_v) + REXY_CPP20_CONSTEXPR + basic_string& basic_string::operator=(const basic_string& s)noexcept( + is_nothrow_allocator_v) { if(s.length() < this->capacity()){ rexy::memcpy(this->get_pointer(), s.get_pointer(), sizeof(value_type)*(s.length()+1)); @@ -323,42 +430,69 @@ namespace rexy{ return (*this = std::move(tmp)); } } + template constexpr basic_string& basic_string::operator=(basic_string&& s)noexcept{ string_base::operator=(std::move(s)); return *this; } + template - REXY_CPP20_CONSTEXPR basic_string& basic_string::operator=(const string_base& s) - noexcept(is_nothrow_allocator_v) + REXY_CPP20_CONSTEXPR + basic_string& basic_string::operator=(const string_base& s)noexcept( + is_nothrow_allocator_v) { return (*this = basic_string(s)); } + //Copy from c string template - REXY_CPP20_CONSTEXPR basic_string& basic_string::operator=(const basic_string_view& sv) - noexcept(is_nothrow_allocator_v) + REXY_CPP20_CONSTEXPR + basic_string& basic_string::operator=(const basic_string_view& sv)noexcept( + is_nothrow_allocator_v) { return _copy_string(sv.c_str(), sv.length()); } template - REXY_CPP20_CONSTEXPR basic_string& basic_string::operator=(const_pointer c) - noexcept(is_nothrow_allocator_v) + REXY_CPP20_CONSTEXPR + basic_string& basic_string::operator=(const_pointer c)noexcept( + is_nothrow_allocator_v) { return _copy_string(c, rexy::strlen(c)); } + template + constexpr auto basic_string::find_first_of(const basic_string& str, size_type start)const noexcept -> size_type{ + return rexy::find_first_of(*this, str.c_str(), start, str.length()); + } + template + constexpr auto basic_string::find_last_of(const basic_string& str, size_type start)const noexcept -> size_type{ + return rexy::find_last_of(*this, str.c_str(), start, str.length()); + } + template + constexpr auto basic_string::find_first_not_of(const basic_string& str, size_type start)const noexcept -> size_type{ + return rexy::find_first_not_of(*this, str.c_str(), start, str.length()); + } + template + constexpr auto basic_string::find_last_not_of(const basic_string& str, size_type start)const noexcept -> size_type{ + return rexy::find_last_not_of(*this, str.c_str(), start, str.length()); + } + + //Replace managed pointer. Frees existing value template - REXY_CPP20_CONSTEXPR void basic_string::reset(pointer val) - noexcept(is_nothrow_allocator_v) + REXY_CPP20_CONSTEXPR + void basic_string::reset(pointer val)noexcept( + is_nothrow_allocator_v) { reset(val, val ? rexy::strlen(val) : 0); } + template - REXY_CPP20_CONSTEXPR void basic_string::reset(pointer val, size_type len) - noexcept(is_nothrow_allocator_v) + REXY_CPP20_CONSTEXPR + void basic_string::reset(pointer val, size_type len)noexcept( + is_nothrow_allocator_v) { if(this->islong()) this->deallocate(this->get_pointer(),sizeof(value_type)*(this->capacity()+1)); @@ -371,23 +505,35 @@ namespace rexy{ this->set_capacity(len); } } + template - REXY_CPP20_CONSTEXPR bool basic_string::reserve(size_type newsize)noexcept(is_nothrow_allocator_v){ + REXY_CPP20_CONSTEXPR + bool basic_string::reserve(size_type newsize)noexcept( + is_nothrow_allocator_v) + { if(newsize < this->capacity()) return false; if(!this->islong() && newsize < string_base::short_string_size()) return false; return (*this = basic_string(this->get_pointer(), newsize)).valid(); } + template - REXY_CPP20_CONSTEXPR void basic_string::shrink_to_fit(void)noexcept(is_nothrow_allocator_v){ + REXY_CPP20_CONSTEXPR + void basic_string::shrink_to_fit(void)noexcept( + is_nothrow_allocator_v) + { if(this->length() == this->capacity()){ return; } *this = basic_string(this->get_pointer(), this->length(), this->length()); } + template - REXY_CPP20_CONSTEXPR void basic_string::resize(size_type newsize, value_type v)noexcept(is_nothrow_allocator_v){ + REXY_CPP20_CONSTEXPR + void basic_string::resize(size_type newsize, value_type v)noexcept( + is_nothrow_allocator_v) + { const auto len = this->length(); const auto copy_count = std::min(newsize, len); const auto insert_count = newsize > len ? newsize - len : 0; @@ -409,122 +555,204 @@ namespace rexy{ 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&{ + REXY_CPP20_CONSTEXPR + auto basic_string::insert(size_type pos, size_type insert_count, value_type v)noexcept( + is_nothrow_allocator_v) -> basic_string& + { return _insert_impl(pos, constant_iterator{v}, insert_count); } template - REXY_CPP20_CONSTEXPR auto basic_string::insert(size_type pos, value_type v)noexcept(is_nothrow_allocator_v) -> basic_string&{ + REXY_CPP20_CONSTEXPR + auto basic_string::insert(size_type pos, value_type v)noexcept( + is_nothrow_allocator_v) -> basic_string& + { return _insert_impl(pos, &v, 1); } + template - REXY_CPP20_CONSTEXPR auto basic_string::insert(size_type pos, const_pointer str)noexcept(is_nothrow_allocator_v) -> basic_string&{ + REXY_CPP20_CONSTEXPR + auto basic_string::insert(size_type pos, const_pointer str)noexcept( + is_nothrow_allocator_v) -> basic_string& + { return _insert_impl(pos, str, rexy::strlen(str)); } + 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&{ + 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_impl(pos, 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&{ + REXY_CPP20_CONSTEXPR + auto basic_string::insert(size_type pos, const basic_string& other)noexcept( + is_nothrow_allocator_v) -> basic_string& + { return _insert_impl(pos, other.begin(), other.length()); } + 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&{ + 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_impl(pos, 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&{ + REXY_CPP20_CONSTEXPR + auto basic_string::insert(const_iterator pos, value_type v)noexcept( + is_nothrow_allocator_v) -> basic_string& + { return _insert_impl(pos - this->begin(), &v, 1); } + template - REXY_CPP20_CONSTEXPR auto basic_string::insert(const_iterator pos, size_type count, value_type v)noexcept(is_nothrow_allocator_v) -> basic_string&{ + 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, InputIt start, InputIt last)noexcept(is_nothrow_allocator_v) -> - std::enable_if_t,basic_string&> + REXY_CPP20_CONSTEXPR + auto basic_string::insert(const_iterator pos, InputIt start, InputIt last)noexcept( + is_nothrow_allocator_v) -> + std::enable_if_t,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&{ + 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,basic_string&> + 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> && + !std::is_convertible_v, + basic_string&> { 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,basic_string&> + 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> && + !std::is_convertible_v, + basic_string&> { return insert(pos, sv.begin() + index_str, sv.begin() + index_str + count); } template template - REXY_CPP20_CONSTEXPR auto basic_string::insert(size_type pos, InputIt start, InputIt last)noexcept(is_nothrow_allocator_v) -> - std::enable_if_t,basic_string&> + REXY_CPP20_CONSTEXPR + auto basic_string::insert(size_type pos, InputIt start, InputIt last)noexcept( + is_nothrow_allocator_v) -> + std::enable_if_t,basic_string&> { size_type insert_count = 0; for(auto it = start;it != last;++it, ++insert_count){} return _insert_impl(pos, start, insert_count); } + + + template - REXY_CPP20_CONSTEXPR auto basic_string::append(const_pointer data, size_type len)noexcept(is_nothrow_allocator_v) -> basic_string&{ + REXY_CPP20_CONSTEXPR + auto basic_string::append(const_pointer data, size_type len)noexcept( + is_nothrow_allocator_v) -> basic_string& + { return _insert_impl(this->length(), data, len); } + template - REXY_CPP20_CONSTEXPR auto basic_string::append(const_pointer data)noexcept(is_nothrow_allocator_v) -> basic_string&{ + REXY_CPP20_CONSTEXPR + auto basic_string::append(const_pointer data)noexcept( + is_nothrow_allocator_v) -> basic_string& + { if(data){ append(data, rexy::strlen(data)); } return *this; } + template - REXY_CPP20_CONSTEXPR auto basic_string::append(const basic_string& other)noexcept(is_nothrow_allocator_v) -> basic_string&{ + REXY_CPP20_CONSTEXPR + auto basic_string::append(const basic_string& other)noexcept( + is_nothrow_allocator_v) -> basic_string& + { return _insert_impl(this->length(), other.data(), other.length()); } + template template - REXY_CPP20_CONSTEXPR auto basic_string::append(InputIt start, InputIt fin)noexcept(is_nothrow_allocator_v) -> - std::enable_if_t,basic_string&> + REXY_CPP20_CONSTEXPR + auto basic_string::append(InputIt start, InputIt fin)noexcept( + is_nothrow_allocator_v) -> + std::enable_if_t,basic_string&> { return insert(this->length(), start, fin); } template - REXY_CPP20_CONSTEXPR void basic_string::push_back(value_type data) - noexcept(is_nothrow_allocator_v) + REXY_CPP20_CONSTEXPR + void basic_string::push_back(value_type data)noexcept( + is_nothrow_allocator_v) { append(&data, 1); } + + template constexpr void basic_string::pop_back(void)noexcept{ erase(this->end() - 1); } + + template - constexpr auto basic_string::replace(size_type pos, size_type count, const basic_string& str) -> basic_string&{ + constexpr auto basic_string::replace(size_type pos, size_type count, const basic_string& str)noexcept -> basic_string&{ return replace(pos, count, str.create_view()); } + template - constexpr auto basic_string::replace(const_iterator first, const_iterator last, const basic_string& str) -> basic_string&{ + constexpr auto basic_string::replace( + const_iterator first, const_iterator last, + const basic_string& str)noexcept -> basic_string& + { return replace(first, last, str.create_view()); } + template - constexpr auto basic_string::replace(size_type pos, size_type count, const basic_string& str, size_type pos2, size_type count2) -> basic_string&{ + constexpr auto basic_string::replace( + size_type pos, size_type count, + const basic_string& str, size_type pos2, size_type count2)noexcept -> basic_string& + { return replace(pos, count, str.create_view(), pos2, count2); } + template template - constexpr auto basic_string::replace(const_iterator first, const_iterator last, InputIt first2, InputIt last2) -> + constexpr auto basic_string::replace(const_iterator first, const_iterator last, InputIt first2, InputIt last2)noexcept -> std::enable_if_t,basic_string&> { const size_type len = last - first; @@ -532,52 +760,88 @@ namespace rexy{ for(auto it = first2;count < len && it != last2;++count,++it); return _replace_impl(size_type(first - this->begin()), len, first2, count); } + template - constexpr auto basic_string::replace(size_type pos, size_type count, const_pointer cstr, size_type count2) -> basic_string&{ + constexpr auto basic_string::replace( + size_type pos, size_type count, + const_pointer cstr, size_type count2)noexcept -> basic_string& + { return _replace_impl(pos, count, cstr, count2); } + template - constexpr auto basic_string::replace(const_iterator first, const_iterator last, const_pointer cstr, size_type count) -> basic_string&{ + constexpr auto basic_string::replace( + const_iterator first, const_iterator last, + const_pointer cstr, size_type count)noexcept -> basic_string& + { return _replace_impl(size_type(first - this->begin()), size_type(last - first), cstr, count); } + template - constexpr auto basic_string::replace(size_type pos, size_type count, const_pointer cstr) -> basic_string&{ + constexpr auto basic_string::replace(size_type pos, size_type count, const_pointer cstr)noexcept -> basic_string&{ return _replace_impl(pos, count, cstr, rexy::strlen(cstr)); } + template - constexpr auto basic_string::replace(const_iterator first, const_iterator last, const_pointer cstr) -> basic_string&{ + constexpr auto basic_string::replace(const_iterator first, const_iterator last, const_pointer cstr)noexcept -> basic_string&{ return _replace_impl(size_type(first - this->begin()), size_type(last - first), cstr, rexy::strlen(cstr)); } + template - constexpr auto basic_string::replace(size_type pos, size_type count, size_type count2, value_type v) -> basic_string&{ + constexpr auto basic_string::replace( + size_type pos, size_type count, + size_type count2, value_type v)noexcept -> basic_string& + { return _replace_impl(pos, count, constant_iterator{v}, count2); } + template - constexpr auto basic_string::replace(const_iterator first, const_iterator last, size_type count2, value_type v) -> basic_string&{ + constexpr auto basic_string::replace( + const_iterator first, const_iterator last, + size_type count2, value_type v)noexcept -> basic_string& + { return _replace_impl(size_type(first - this->begin()), size_type(last - first), constant_iterator{v}, count2); } + template - constexpr auto basic_string::replace(const_iterator first, const_iterator last, std::initializer_list list) -> basic_string&{ + constexpr auto basic_string::replace( + const_iterator first, const_iterator last, + std::initializer_list list)noexcept -> basic_string& + { return _replace_impl(size_type(first - this->begin()), size_type(last - first), list.begin(), list.size()); } + template template - constexpr auto basic_string::replace(size_type pos, size_type count, const StringView& sv) -> - std::enable_if_t> && !std::is_convertible_v,basic_string&> + constexpr auto basic_string::replace(size_type pos, size_type count, const StringView& sv)noexcept -> + std::enable_if_t< + std::is_convertible_v> && + !std::is_convertible_v, + basic_string&> { return _replace_impl(pos, count, sv.begin(), sv.length()); } + template template - constexpr auto basic_string::replace(const_iterator first, const_iterator last, const StringView& sv) -> - std::enable_if_t> && !std::is_convertible_v,basic_string&> + constexpr auto basic_string::replace(const_iterator first, const_iterator last, const StringView& sv)noexcept -> + std::enable_if_t< + std::is_convertible_v> && + !std::is_convertible_v, + basic_string&> { return _replace_impl(size_type(first - this->begin()), size_type(last - first), sv.begin(), sv.length()); } + template template - constexpr auto basic_string::replace(size_type pos, size_type count, const StringView& sv, size_type pos2, size_type count2) -> - std::enable_if_t> && !std::is_convertible_v,basic_string&> + constexpr auto basic_string::replace( + size_type pos, size_type count, + const StringView& sv, size_type pos2, size_type count2)noexcept -> + std::enable_if_t< + std::is_convertible_v> && + !std::is_convertible_v, + basic_string&> { if(pos2 > sv.length()){ pos2 = sv.length(); @@ -590,6 +854,8 @@ namespace rexy{ return _replace_impl(pos, count, sv.begin() + pos2, maxlen2); } + + template constexpr auto basic_string::erase(size_type index, size_type count)noexcept -> basic_string&{ const auto len = this->length(); @@ -597,22 +863,22 @@ namespace rexy{ const auto end_pos = index + rem_count; const auto relocate_count = len - end_pos + 1; //include terminator - { - auto* src = this->get_pointer() + end_pos; - auto* dst = this->get_pointer() + index; - for(size_type i = 0;i < relocate_count;++i){ - *dst++ = *src++; - } + auto* src = this->get_pointer() + end_pos; + auto* dst = this->get_pointer() + index; + for(size_type i = 0;i < relocate_count;++i){ + *dst++ = *src++; } this->set_length(len - rem_count); return *this; } + template constexpr auto basic_string::erase(const_iterator pos)noexcept -> iterator{ const auto pos_index = pos - this->begin(); erase(pos - this->begin(), 1); return this->begin() + pos_index; } + template constexpr auto basic_string::erase(const_iterator first, const_iterator last)noexcept -> iterator{ const auto distance = last - first; @@ -622,9 +888,13 @@ namespace rexy{ } + template template - REXY_CPP20_CONSTEXPR auto basic_string::substring(size_type start, size_type end)const -> basic_string{ + REXY_CPP20_CONSTEXPR + auto basic_string::substring(size_type start, size_type end)const noexcept( + is_nothrow_allocator_v) -> basic_string + { if(start > end || end > this->length()) return {}; const size_type newlen = end - start; @@ -632,13 +902,22 @@ namespace rexy{ tmp.append(this->data() + start, newlen); return tmp; } + template - REXY_CPP20_CONSTEXPR auto basic_string::substr(size_type start, size_type end)const -> basic_string{ + REXY_CPP20_CONSTEXPR + auto basic_string::substr(size_type start, size_type end)const noexcept( + is_nothrow_allocator_v) -> basic_string + { return substring(start, end); } + + template - REXY_CPP20_CONSTEXPR auto basic_string::release(void)noexcept(is_nothrow_allocator_v) -> pointer{ + REXY_CPP20_CONSTEXPR + auto basic_string::release(void)noexcept( + is_nothrow_allocator_v) -> pointer + { if(this->islong()){ pointer raw = this->get_pointer(); this->set_short_ptr(); @@ -659,10 +938,13 @@ namespace rexy{ } } + + template - REXY_CPP20_CONSTEXPR basic_string& basic_string::_copy_string(const_pointer s, size_type len) - noexcept(is_nothrow_allocator_v) - { + REXY_CPP20_CONSTEXPR + basic_string& basic_string::_copy_string(const_pointer s, size_type len)noexcept( + is_nothrow_allocator_v) + { if(!s || !len) return (*this = basic_string(rexy::steal(nullptr), 0, 0)); if(len <= this->length()){ @@ -674,9 +956,13 @@ namespace rexy{ } return (*this = basic_string(s, len)); } + template template - REXY_CPP20_CONSTEXPR auto basic_string::_insert_impl(size_type pos, InputIt start, size_type insert_count)noexcept(is_nothrow_allocator_v) -> basic_string&{ + REXY_CPP20_CONSTEXPR + auto basic_string::_insert_impl(size_type pos, InputIt start, size_type insert_count)noexcept( + is_nothrow_allocator_v) -> basic_string& + { const size_type len = this->length(); const size_type cap = this->capacity(); //add one for null terminator @@ -719,7 +1005,7 @@ namespace rexy{ } template template - constexpr auto basic_string::_replace_impl(size_type pos, size_type count, InputIt src, size_type count2) -> basic_string&{ + constexpr auto basic_string::_replace_impl(size_type pos, size_type count, InputIt src, size_type count2)noexcept -> basic_string&{ const auto len = this->length(); if(pos > len){ pos = len; @@ -745,9 +1031,14 @@ namespace rexy{ } template template - REXY_CPP20_CONSTEXPR string_cat_expr::operator basic_string::value_type,Alloc>(void) - noexcept(std::is_nothrow_constructible, typename basic_string::size_type>::value && - std::is_nothrow_invocable>,decltype(*this)>::value) + REXY_CPP20_CONSTEXPR + string_cat_expr::operator basic_string::value_type,Alloc>(void)noexcept( + std::is_nothrow_constructible_v< + basic_string, + typename basic_string::size_type> && + std::is_nothrow_invocable_v< + detail::string_appender>, + decltype(*this)>) { size_type len = length(); basic_string ret(len); diff --git a/include/rexy/string_view.hpp b/include/rexy/string_view.hpp index 2f15f4b..6ff1d44 100644 --- a/include/rexy/string_view.hpp +++ b/include/rexy/string_view.hpp @@ -83,49 +83,64 @@ namespace rexy{ constexpr const_reference back(void)const noexcept{return m_data[m_length-1];} constexpr const_iterator it_at(size_type i)const noexcept{return m_data + i;} - constexpr const_iterator search(basic_string_view s)const; - constexpr const_iterator search(const_pointer c)const; + constexpr const_iterator search(basic_string_view s)const noexcept; + constexpr const_iterator search(const_pointer c)const noexcept; template - constexpr const_iterator search(basic_string_view s, const Searcher& searcher)const; + constexpr const_iterator search(basic_string_view s, const Searcher& searcher)const noexcept( + std::is_nothrow_invocable_v); template - constexpr const_iterator search(const_pointer c, const Searcher& searcher)const; + constexpr const_iterator search(const_pointer c, const Searcher& searcher)const noexcept( + std::is_nothrow_invocable_v); - constexpr bool starts_with(basic_string_view sv)const; - constexpr bool starts_with(value_type v)const; - constexpr bool starts_with(const_pointer str)const; + constexpr bool starts_with(basic_string_view sv)const noexcept; + constexpr bool starts_with(value_type v)const noexcept; + constexpr bool starts_with(const_pointer str)const noexcept; - constexpr bool ends_with(basic_string_view sv)const; - constexpr bool ends_with(value_type v)const; - constexpr bool ends_with(const_pointer str)const; + constexpr bool ends_with(basic_string_view sv)const noexcept; + constexpr bool ends_with(value_type v)const noexcept; + constexpr bool ends_with(const_pointer str)const noexcept; - constexpr bool contains(basic_string_view sv)const; - constexpr bool contains(value_type sv)const; - constexpr bool contains(const_pointer str)const; + constexpr bool contains(basic_string_view sv)const noexcept; + constexpr bool contains(value_type sv)const noexcept; + constexpr bool contains(const_pointer str)const noexcept; - constexpr bool compare(const basic_string_view& s)const{return *this == s;} - constexpr bool compare(const_pointer c)const{return *this == c;} + constexpr bool compare(const basic_string_view& s)const noexcept{return *this == s;} + constexpr bool compare(const_pointer c)const noexcept{return *this == c;} - constexpr const_iterator begin(void)const{return m_data;} - constexpr const_iterator end(void)const{return m_data+m_length;} - constexpr const_iterator cbegin(void)const{return begin();} - constexpr const_iterator cend(void)const{return end();} + constexpr const_iterator begin(void)const noexcept{return m_data;} + constexpr const_iterator end(void)const noexcept{return m_data+m_length;} + constexpr const_iterator cbegin(void)const noexcept{return begin();} + constexpr const_iterator cend(void)const noexcept{return end();} - constexpr const_reverse_iterator rbegin(void)const{return const_reverse_iterator(m_data+m_length);} - constexpr const_reverse_iterator rend(void)const{return const_reverse_iterator(m_data);} - constexpr const_reverse_iterator crbegin(void)const{return rbegin();} - constexpr const_reverse_iterator crend(void)const{return rend();} + constexpr const_reverse_iterator rbegin(void)const noexcept{return const_reverse_iterator(m_data+m_length);} + constexpr const_reverse_iterator rend(void)const noexcept{return const_reverse_iterator(m_data);} + constexpr const_reverse_iterator crbegin(void)const noexcept{return rbegin();} + constexpr const_reverse_iterator crend(void)const noexcept{return rend();} - constexpr void remove_prefix(size_type i); - constexpr void remove_suffix(size_type i); + constexpr void remove_prefix(size_type i)noexcept; + constexpr void remove_suffix(size_type i)noexcept; - constexpr basic_string_view substr(size_type pos, size_type count = npos)const; + constexpr basic_string_view substr(size_type pos, size_type count = npos)const noexcept; - constexpr size_type find_first_of(value_type v, size_type start = 0)const; - constexpr size_type find_first_of(const_pointer c, size_type pos = 0)const; - constexpr size_type find_first_of(const_pointer c, size_type pos, size_type size)const; - constexpr size_type find_last_of(value_type v, size_type start = 0)const; - 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; + constexpr size_type find_first_of(basic_string_view str, size_type pos = 0)const noexcept; + constexpr size_type find_first_of(value_type v, size_type start = 0)const noexcept; + constexpr size_type find_first_of(const_pointer c, size_type pos = 0)const noexcept; + constexpr size_type find_first_of(const_pointer c, size_type pos, size_type size)const noexcept; + + constexpr size_type find_first_not_of(basic_string_view str, size_type pos = 0)const noexcept; + constexpr size_type find_first_not_of(value_type v, size_type start = 0)const noexcept; + constexpr size_type find_first_not_of(const_pointer c, size_type pos = 0)const noexcept; + constexpr size_type find_first_not_of(const_pointer c, size_type pos, size_type size)const noexcept; + + constexpr size_type find_last_of(basic_string_view str, size_type pos = 0)const noexcept; + constexpr size_type find_last_of(value_type v, size_type start = 0)const noexcept; + constexpr size_type find_last_of(const_pointer c, size_type pos = 0)const noexcept; + constexpr size_type find_last_of(const_pointer c, size_type pos, size_type size)const noexcept; + + constexpr size_type find_last_not_of(basic_string_view str, size_type pos = 0)const noexcept; + constexpr size_type find_last_not_of(value_type v, size_type start = 0)const noexcept; + constexpr size_type find_last_not_of(const_pointer c, size_type pos = 0)const noexcept; + constexpr size_type find_last_not_of(const_pointer c, size_type pos, size_type size)const noexcept; }; diff --git a/include/rexy/string_view.tpp b/include/rexy/string_view.tpp index 69d6910..b8be6e6 100644 --- a/include/rexy/string_view.tpp +++ b/include/rexy/string_view.tpp @@ -50,20 +50,22 @@ namespace rexy{ } template - constexpr auto basic_string_view::search(basic_string_view s)const -> const_iterator{ + constexpr auto basic_string_view::search(basic_string_view s)const noexcept -> const_iterator{ if(s.length() > m_length){ return cend(); } return two_way_search(cbegin(), cend(), s.cbegin(), s.cend()); } template - constexpr auto basic_string_view::search(const_pointer c)const -> const_iterator{ + constexpr auto basic_string_view::search(const_pointer c)const noexcept -> const_iterator{ basic_string_view tmp(c); return search(tmp); } template template - constexpr auto basic_string_view::search(basic_string_view s, const Searcher& searcher)const -> const_iterator{ + constexpr auto basic_string_view::search(basic_string_view s, const Searcher& searcher)const noexcept( + std::is_nothrow_invocable_v) -> const_iterator + { if(s.length() > m_length){ return cend(); } @@ -71,13 +73,15 @@ namespace rexy{ } template template - constexpr auto basic_string_view::search(const_pointer c, const Searcher& searcher)const -> const_iterator{ + constexpr auto basic_string_view::search(const_pointer c, const Searcher& searcher)const noexcept( + std::is_nothrow_invocable_v) -> const_iterator + { basic_string_view tmp(c); return search(tmp, searcher); } template - constexpr bool basic_string_view::starts_with(basic_string_view sv)const{ + constexpr bool basic_string_view::starts_with(basic_string_view sv)const noexcept{ if(sv.length() > length()){ return false; } @@ -88,16 +92,16 @@ namespace rexy{ return false; } template - constexpr bool basic_string_view::starts_with(value_type v)const{ + constexpr bool basic_string_view::starts_with(value_type v)const noexcept{ return front() == v; } template - constexpr bool basic_string_view::starts_with(const_pointer s)const{ + constexpr bool basic_string_view::starts_with(const_pointer s)const noexcept{ return starts_with(basic_string_view(s)); } template - constexpr bool basic_string_view::ends_with(basic_string_view sv)const{ + constexpr bool basic_string_view::ends_with(basic_string_view sv)const noexcept{ if(sv.length() > length()){ return false; } @@ -109,16 +113,16 @@ namespace rexy{ return false; } template - constexpr bool basic_string_view::ends_with(value_type v)const{ + constexpr bool basic_string_view::ends_with(value_type v)const noexcept{ return back() == v; } template - constexpr bool basic_string_view::ends_with(const_pointer s)const{ + constexpr bool basic_string_view::ends_with(const_pointer s)const noexcept{ return ends_with(basic_string_view(s)); } template - constexpr bool basic_string_view::contains(basic_string_view sv)const{ + constexpr bool basic_string_view::contains(basic_string_view sv)const noexcept{ const auto it = two_way_search(cbegin(), cend(), sv.cbegin(), sv.cend()); if(it != cend()){ return true; @@ -126,7 +130,7 @@ namespace rexy{ return false; } template - constexpr bool basic_string_view::contains(value_type v)const{ + constexpr bool basic_string_view::contains(value_type v)const noexcept{ for(size_type i = 0;i < length();++i){ if(m_data[i] == v){ return true; @@ -135,19 +139,19 @@ namespace rexy{ return false; } template - constexpr bool basic_string_view::contains(const_pointer str)const{ + constexpr bool basic_string_view::contains(const_pointer str)const noexcept{ return contains(basic_string_view(str)); } template - constexpr basic_string_view basic_string_view::substr(size_type pos, size_type count)const{ + constexpr basic_string_view basic_string_view::substr(size_type pos, size_type count)const noexcept{ const size_type real_count = rexy::min(count, length() - pos); return basic_string_view{m_data + pos, real_count}; } template - constexpr void basic_string_view::remove_prefix(size_type i){ + constexpr void basic_string_view::remove_prefix(size_type i) noexcept{ if(i > m_length){ m_data = end(); m_length = 0; @@ -157,38 +161,82 @@ namespace rexy{ } } template - constexpr void basic_string_view::remove_suffix(size_type i){ + constexpr void basic_string_view::remove_suffix(size_type i) noexcept{ if(i > m_length){ m_length = 0; }else{ m_length -= i; } } + template - constexpr auto basic_string_view::find_first_of(value_type v, size_type start)const -> size_type{ + constexpr auto basic_string_view::find_first_of(basic_string_view str, size_type pos)const noexcept -> size_type{ + return rexy::find_first_of(*this, str.c_str(), pos, str.length()); + } + template + constexpr auto basic_string_view::find_first_of(value_type v, size_type start)const noexcept -> size_type{ return rexy::find_first_of(*this, &v, start, 1); } template - constexpr auto basic_string_view::find_first_of(const_pointer c, size_type start)const -> size_type{ + constexpr auto basic_string_view::find_first_of(const_pointer c, size_type start)const noexcept -> size_type{ return rexy::find_first_of(*this, c, start, rexy::strlen(c)); } template - constexpr auto basic_string_view::find_first_of(const_pointer c, size_type start, size_type size)const -> size_type{ + constexpr auto basic_string_view::find_first_of(const_pointer c, size_type start, size_type size)const noexcept -> size_type{ return rexy::find_first_of(*this, c, start, size); } + template - constexpr auto basic_string_view::find_last_of(value_type v, size_type start)const -> size_type{ + constexpr auto basic_string_view::find_first_not_of(basic_string_view str, size_type pos)const noexcept -> size_type{ + return rexy::find_first_not_of(*this, str.c_str(), pos, str.length()); + } + template + constexpr auto basic_string_view::find_first_not_of(value_type v, size_type start)const noexcept -> size_type{ + return rexy::find_first_not_of(*this, &v, start, 1); + } + template + constexpr auto basic_string_view::find_first_not_of(const_pointer c, size_type start)const noexcept -> size_type{ + return rexy::find_first_not_of(*this, c, start, rexy::strlen(c)); + } + template + constexpr auto basic_string_view::find_first_not_of(const_pointer c, size_type start, size_type size)const noexcept -> size_type{ + return rexy::find_first_not_of(*this, c, start, size); + } + + template + constexpr auto basic_string_view::find_last_of(basic_string_view str, size_type pos)const noexcept -> size_type{ + return rexy::find_last_of(*this, str.c_str(), pos, str.length()); + } + template + constexpr auto basic_string_view::find_last_of(value_type v, size_type start)const noexcept -> size_type{ return rexy::find_last_of(*this, &v, start, 1); } template - constexpr auto basic_string_view::find_last_of(const_pointer c, size_type start)const -> size_type{ + constexpr auto basic_string_view::find_last_of(const_pointer c, size_type start)const noexcept -> size_type{ return rexy::find_last_of(*this, c, start, rexy::strlen(c)); } template - constexpr auto basic_string_view::find_last_of(const_pointer c, size_type start, size_type size)const -> size_type{ + constexpr auto basic_string_view::find_last_of(const_pointer c, size_type start, size_type size)const noexcept -> size_type{ return rexy::find_last_of(*this, c, start, size); } + template + constexpr auto basic_string_view::find_last_not_of(basic_string_view str, size_type pos)const noexcept -> size_type{ + return rexy::find_last_not_of(*this, str.c_str(), pos, str.length()); + } + template + constexpr auto basic_string_view::find_last_not_of(value_type v, size_type start)const noexcept -> size_type{ + return rexy::find_last_not_of(*this, &v, start, 1); + } + template + constexpr auto basic_string_view::find_last_not_of(const_pointer c, size_type start)const noexcept -> size_type{ + return rexy::find_last_not_of(*this, c, start, rexy::strlen(c)); + } + template + constexpr auto basic_string_view::find_last_not_of(const_pointer c, size_type start, size_type size)const noexcept -> size_type{ + return rexy::find_last_not_of(*this, c, start, size); + } + } #endif