diff --git a/include/rexy/detail/format/format_error.hpp b/include/rexy/detail/format/format_error.hpp index 480c213..98377fb 100644 --- a/include/rexy/detail/format/format_error.hpp +++ b/include/rexy/detail/format/format_error.hpp @@ -37,7 +37,7 @@ namespace rexy::fmt{ string_view errstr; constexpr const char* what(void)const{ - return errstr; + return errstr.c_str(); } }; diff --git a/include/rexy/detail/format/formatter.hpp b/include/rexy/detail/format/formatter.hpp index 7f2a257..a24c1f1 100644 --- a/include/rexy/detail/format/formatter.hpp +++ b/include/rexy/detail/format/formatter.hpp @@ -49,10 +49,15 @@ namespace rexy::fmt{ requires(!UTF8_String) constexpr OutIt perform_standard_format(const Char* c, OutIt out, const format_specs& specs, const std::locale& loc); template + requires(UTF8_String) constexpr OutIt perform_standard_format(const Char* c, OutIt out, const format_specs& specs, const std::locale& loc); template constexpr OutIt perform_standard_format(const Char* c, OutIt out); template + constexpr OutIt perform_standard_format(basic_string_view> str, OutIt out, const format_specs& specs, const std::locale& loc); + template + constexpr OutIt perform_standard_format(basic_string_view> str, OutIt out); + template constexpr OutIt perform_standard_format(Char b, OutIt out, const format_specs& specs, const std::locale& loc); template constexpr OutIt perform_standard_format(Char b, OutIt out); diff --git a/include/rexy/detail/format/formatter.tpp b/include/rexy/detail/format/formatter.tpp index 94b68c6..4259fe4 100644 --- a/include/rexy/detail/format/formatter.tpp +++ b/include/rexy/detail/format/formatter.tpp @@ -204,6 +204,7 @@ namespace rexy::fmt::detail{ } return width; } + template requires(!UTF8_String) 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 + requires(UTF8_String) constexpr OutIt perform_standard_format(const Char* c, OutIt out, const format_specs& specs, const std::locale& loc){ const basic_string_view str{c}; std::size_t est_width = 0; @@ -263,6 +265,14 @@ namespace rexy::fmt::detail{ } return std::move(out); } + template + constexpr OutIt perform_standard_format(basic_string_view> str, OutIt out, const format_specs& specs, const std::locale& loc){ + return perform_standard_format(str.c_str(), std::move(out), specs, loc); + } + template + constexpr OutIt perform_standard_format(basic_string_view> str, OutIt out){ + return perform_standard_format(str.c_str(), std::move(out)); + } template constexpr OutIt perform_standard_format(Char b, OutIt out, const format_specs& specs, const std::locale& loc){ diff --git a/include/rexy/detail/format/output_buffer.tpp b/include/rexy/detail/format/output_buffer.tpp index 2fb251c..33cf483 100644 --- a/include/rexy/detail/format/output_buffer.tpp +++ b/include/rexy/detail/format/output_buffer.tpp @@ -63,22 +63,22 @@ namespace rexy::fmt::detail{ template 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 - struct container_traits : public It, public container_traits_helper{ - template - static std::false_type check(int); - static std::true_type check(...); + struct something : public It{ + template + static std::true_type check(int); + static std::false_type check(...); + + static constexpr bool value = decltype(check(0))::value; }; + template OutIt real_write_out(const Char* start, std::size_t write_count, OutIt out){ - static constexpr bool has_container = decltype(container_traits::check(0))::value; + static constexpr bool has_container = something::value;//decltype(container_traits::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 diff --git a/include/rexy/string_base.hpp b/include/rexy/string_base.hpp index 37ed3d9..d073ac6 100644 --- a/include/rexy/string_base.hpp +++ b/include/rexy/string_base.hpp @@ -336,18 +336,6 @@ namespace rexy{ constexpr basic_string_view create_view(void)const noexcept; constexpr basic_string_view 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 - [[deprecated]] constexpr const_iterator search(const string_base& s, const Searcher& searcher)const; - template - [[deprecated]] constexpr iterator search(const string_base& s, const Searcher& searcher); }; @@ -378,6 +366,8 @@ namespace rexy{ 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); + template + 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); 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 + 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); //normal copy and move ctors @@ -419,6 +409,8 @@ namespace rexy{ 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); @@ -428,20 +420,22 @@ namespace rexy{ 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, 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 basic_string& 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); 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>; + std::enable_if_t> && !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>; + std::enable_if_t> && !std::is_convertible_v,basic_string&>; + template - REXY_CPP20_CONSTEXPR basic_string& append(InputIt start, InputIt fin)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); @@ -449,6 +443,30 @@ namespace rexy{ 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); + 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); + template + constexpr auto replace(size_type pos, size_type count, const StringView& sv) -> + std::enable_if_t> && !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&>; + 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 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); using detail::hasallocator::allocator; - - [[deprecated]] REXY_CPP20_CONSTEXPR bool resize(size_type newsize)noexcept(is_nothrow_allocator_v); }; //Like an expression template but not really diff --git a/include/rexy/string_base.tpp b/include/rexy/string_base.tpp index c17ba82..7f46181 100644 --- a/include/rexy/string_base.tpp +++ b/include/rexy/string_base.tpp @@ -32,6 +32,23 @@ namespace rexy{ + namespace detail{ + template + 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 + value_iterator_adapter(T) -> value_iterator_adapter; + } + template constexpr auto string_base::search(basic_string_view sv)const -> const_iterator{ if(sv.length() > length()){ @@ -138,6 +155,8 @@ namespace rexy{ set_length(0); get_pointer()[0] = 0; } + + template constexpr auto string_base::create_view(void)const noexcept -> basic_string_view{ return basic_string_view(data(), length()); @@ -229,7 +248,7 @@ namespace rexy{ } template - template + template REXY_CPP20_CONSTEXPR basic_string::basic_string(InputIt start, InputIt fin) noexcept(is_nothrow_allocator_v): basic_string(nullptr, size_type{fin - start}) @@ -247,7 +266,7 @@ namespace rexy{ noexcept(is_nothrow_allocator_v): detail::hasallocator(b) { - _copy_construct_string(b.get(), b.length(), b.length()); + _copy_construct_string(b.data(), b.length(), b.length()); } template constexpr basic_string::basic_string(basic_string&& s)noexcept: @@ -257,7 +276,7 @@ namespace rexy{ REXY_CPP20_CONSTEXPR basic_string::basic_string(const string_base& b) noexcept(is_nothrow_allocator_v) { - _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::short_string_size()) return false; - return (*this = basic_string(this->get_pointer(), newsize)); + 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){ @@ -346,23 +365,31 @@ namespace rexy{ } *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){ + 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 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{ - 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 @@ -395,7 +422,9 @@ namespace rexy{ } template template - REXY_CPP20_CONSTEXPR auto basic_string::insert(const_iterator pos, InputIt start, InputIt last)noexcept(is_nothrow_allocator_v) -> 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 @@ -405,21 +434,23 @@ namespace rexy{ 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> + std::enable_if_t> && !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> + std::enable_if_t> && !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) -> 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); @@ -441,7 +472,9 @@ namespace rexy{ } template template - REXY_CPP20_CONSTEXPR auto basic_string::append(InputIt start, InputIt fin)noexcept(is_nothrow_allocator_v) -> 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); } @@ -456,6 +489,85 @@ namespace rexy{ erase(this->end() - 1); } + template + constexpr auto basic_string::replace(size_type pos, size_type count, const basic_string& str) -> 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&{ + 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&{ + 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) -> + std::enable_if_t,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 + constexpr auto basic_string::replace(size_type pos, size_type count, const_pointer cstr, size_type count2) -> 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&{ + 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&{ + 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&{ + 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&{ + return _replace_impl(pos, count, detail::value_iterator_adapter{v}, count2); + } + template + constexpr auto basic_string::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 + constexpr auto basic_string::replace(const_iterator first, const_iterator last, std::initializer_list list) -> 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&> + { + 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&> + { + 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&> + { + 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 constexpr auto basic_string::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 tmp(newlen); - tmp.append(this->get() + start, newlen); + tmp.append(this->data() + start, newlen); return tmp; } template @@ -545,24 +657,66 @@ namespace rexy{ 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&{ 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 + template + constexpr auto basic_string::_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 @@ -582,31 +736,6 @@ namespace rexy{ return ret; } - - template - [[deprecated]] constexpr auto string_base::search(const string_base& s)const -> const_iterator{ - return two_way_search(cbegin(), cend(), s.begin(), s.end()); - } - template - [[deprecated]] constexpr auto string_base::search(const string_base& s) -> iterator{ - return two_way_search(begin(), end(), s.begin(), s.end()); - } - template - template - [[deprecated]] constexpr auto string_base::search(const string_base& s, const Searcher& searcher)const -> const_iterator{ - return searcher(cbegin(), cend(), s.begin(), s.end()); - } - template - template - [[deprecated]] constexpr auto string_base::search(const string_base& s, const Searcher& searcher) -> iterator{ - return searcher(begin(), end(), s.begin(), s.end()); - } - template - [[deprecated]] REXY_CPP20_CONSTEXPR bool basic_string::resize(size_type newsize)noexcept(is_nothrow_allocator_v){ - return reserve(newsize); - } - - } //namespace rexy #endif diff --git a/include/rexy/string_view.hpp b/include/rexy/string_view.hpp index 1877ff0..ba77cbc 100644 --- a/include/rexy/string_view.hpp +++ b/include/rexy/string_view.hpp @@ -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 diff --git a/include/rexy/traits.hpp b/include/rexy/traits.hpp index c8736f6..55843aa 100644 --- a/include/rexy/traits.hpp +++ b/include/rexy/traits.hpp @@ -20,6 +20,7 @@ #define REXY_TRAITS_HPP #include //is_same, decay, integral_constant, declval +#include //iterator_traits #include "rexy.hpp" @@ -53,6 +54,85 @@ namespace rexy{ static constexpr bool value = std::is_same*>(nullptr)))>::value; }; + template + struct is_dereferencable : public std::false_type{}; + template + struct is_dereferencable()))>> : public std::true_type{}; + template + static constexpr bool is_dereferencable_v = is_dereferencable::value; + + template + struct is_pointer_dereferencable : public std::false_type{}; + template + struct is_pointer_dereferencable().operator->())>> : public std::true_type{}; + template + struct is_pointer_dereferencable> : public std::true_type{}; + template + static constexpr bool is_pointer_dereferencable_v = is_pointer_dereferencable::value; + + template + struct is_prefix_incrementable : public std::false_type{}; + template + struct is_prefix_incrementable>>()))>> : public std::true_type{}; + template + static constexpr bool is_prefix_incrementable_v = is_prefix_incrementable::value; + + template + struct is_postfix_incrementable : public std::false_type{}; + template + struct is_postfix_incrementable>>())++)>> : public std::true_type{}; + template + static constexpr bool is_postfix_incrementable_v = is_postfix_incrementable::value; + + template + struct is_equality_comparable : public std::false_type{}; + template + struct is_equality_comparable() == std::declval())>> : public std::true_type{}; + template + static constexpr bool is_equality_comparable_v = is_equality_comparable::value; + + template + struct is_inequality_comparable : public std::false_type{}; + template + struct is_inequality_comparable() != std::declval())>> : public std::true_type{}; + template + static constexpr bool is_inequality_comparable_v = is_inequality_comparable::value; + + template + struct is_legacy_iterator{ + static constexpr bool value = is_prefix_incrementable_v && is_dereferencable_v; + }; + template + static constexpr bool is_legacy_iterator_v = is_legacy_iterator::value; + + template && + is_inequality_comparable_v && + is_pointer_dereferencable_v && + is_postfix_incrementable_v> + struct is_legacy_input_iterator : public std::false_type{}; + + template + struct is_legacy_input_iterator{ + static constexpr bool value = std::is_convertible_v() == std::declval()),bool> && + std::is_same_v())),typename std::iterator_traits::reference> && + std::is_same_v>>()),std::add_lvalue_reference_t> && + std::is_convertible_v>>()++), typename std::iterator_traits::value_type>; + }; + template + static constexpr bool is_legacy_input_iterator_v = is_legacy_input_iterator::value; + + template && + is_postfix_incrementable_v> + struct is_legacy_output_iterator : public std::false_type{}; + + template + struct is_legacy_output_iterator{ + static constexpr bool value = + std::is_same_v>>()),std::add_lvalue_reference_t> && + std::is_convertible_v>>()++), std::add_lvalue_reference_t>>; + }; + template + static constexpr bool is_legacy_output_iterator_v = is_legacy_output_iterator::value; } diff --git a/include/rexy/utility.hpp b/include/rexy/utility.hpp index eac98fe..43bcc34 100644 --- a/include/rexy/utility.hpp +++ b/include/rexy/utility.hpp @@ -92,14 +92,14 @@ namespace rexy{ return val > 0 ? val : -val; } -#ifdef REXY_if_constexpr +#ifdef REXY_if_consteval template constexpr size_t strlen(const T* c)noexcept{ return std::char_traits::length(c); } template constexpr int strcmp(const T* l, const T* r)noexcept{ - REXY_if_constexpr{ + REXY_if_consteval{ if constexpr(std::is_same_v,char>){ return std::strcmp(l, r); }else if constexpr(std::is_same_v,wchar_t>){ @@ -111,7 +111,7 @@ namespace rexy{ } template 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,char>){ return std::strncmp(l, r, max); }else if constexpr (std::is_same_v,wchar_t>){ @@ -123,7 +123,7 @@ namespace rexy{ } template 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,char>){ return std::strncmp(l, r, max); }else if constexpr (std::is_same_v,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(l); @@ -150,7 +150,7 @@ namespace rexy{ } } } -#else // REXY_if_constexpr +#else // REXY_if_consteval template 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 } diff --git a/tests/basic_string.cpp b/tests/basic_string.cpp index 16534a4..240114e 100644 --- a/tests/basic_string.cpp +++ b/tests/basic_string.cpp @@ -12,6 +12,8 @@ exit(1); } +using namespace rexy::str_literals; + using test_str = rexy::basic_string>; 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 + 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(); }