diff --git a/include/rexy/cx/string.hpp b/include/rexy/cx/string.hpp index 9a90cb4..2aeccd7 100644 --- a/include/rexy/cx/string.hpp +++ b/include/rexy/cx/string.hpp @@ -27,7 +27,9 @@ namespace rexy::cx{ #include "../string_base.hpp" #include "../utility.hpp" #include -#include //ptrdiff_t +#include //ptrdiff_t, size_t + +#include "../detail/cpp20.hpp" //This is different from rexy::static_string in that this doesn't hold a pointer to a constant string array. //This holds a mutable array of data which can be modified during compile time. static_string is @@ -98,7 +100,7 @@ namespace rexy::cx{ constexpr string(const string&)noexcept = default; constexpr string(string&&)noexcept = default; - ~string(void)noexcept = default; + REXY_CPP20_CONSTEXPR ~string(void)noexcept = default; constexpr string& operator=(const_pointer c)noexcept{ m_length = strlen(c); diff --git a/include/rexy/detail/cpp20.hpp b/include/rexy/detail/cpp20.hpp new file mode 100644 index 0000000..66786fb --- /dev/null +++ b/include/rexy/detail/cpp20.hpp @@ -0,0 +1,30 @@ +/** + This file is a part of rexy's general purpose library + Copyright (C) 2020 rexy712 + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef REXY_CPP20_HPP +#define REXY_CPP20_HPP + + #if __cplusplus > 201703L + #define REXY_CPP20_CONSTEXPR constexpr + #define REXY_CPP20_CONSTEVAL consteval + #else + #define REXY_CPP20_CONSTEXPR + #define REXY_CPP20_CONSTEVAL constexpr + #endif + +#endif diff --git a/include/rexy/string_base.hpp b/include/rexy/string_base.hpp index c64f349..3f4e9ca 100644 --- a/include/rexy/string_base.hpp +++ b/include/rexy/string_base.hpp @@ -34,6 +34,8 @@ #include "detail/hasallocator.hpp" #include "rexy.hpp" +#include "detail/cpp20.hpp" + namespace rexy{ //Base of all RAII strings. Its use is allowing passing of rexy strings to functions without knowing the exact type @@ -161,8 +163,7 @@ namespace rexy{ { s.set_islong_flag(false); } - ~string_base(void)noexcept = default; - + REXY_CPP20_CONSTEXPR ~string_base(void)noexcept = default; constexpr string_base& operator=(string_base&& s)noexcept{ std::swap(m_data, s.m_data); if(this->islong()) @@ -254,9 +255,9 @@ namespace rexy{ using allocator_type = Allocator; private: - void _copy_construct_string(const_pointer data, size_type len, size_type cap) + REXY_CPP20_CONSTEXPR void _copy_construct_string(const_pointer data, size_type len, size_type cap) noexcept(noexcept(this->allocate(0))); - basic_string& _copy_string(const_pointer s, size_type len) + REXY_CPP20_CONSTEXPR basic_string& _copy_string(const_pointer s, size_type len) noexcept(noexcept(this->allocate(0)) && noexcept(this->deallocate(nullptr,0))); @@ -265,52 +266,57 @@ namespace rexy{ 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; - basic_string(const_pointer data, size_type len)noexcept(noexcept(this->allocate(0))); - basic_string(const_pointer data, size_type len, size_type cap)noexcept(noexcept(this->allocate(0))); - basic_string(const_pointer data)noexcept(noexcept(this->allocate(0))); - explicit basic_string(size_type len)noexcept(noexcept(this->allocate(0))); - basic_string(size_type len, size_type cap)noexcept(noexcept(this->allocate(0))); - + REXY_CPP20_CONSTEXPR basic_string(const_pointer data, size_type len)noexcept(noexcept(this->allocate(0))); + REXY_CPP20_CONSTEXPR basic_string(const_pointer data, size_type len, size_type cap)noexcept(noexcept(this->allocate(0))); + REXY_CPP20_CONSTEXPR basic_string(const_pointer data)noexcept(noexcept(this->allocate(0))); + REXY_CPP20_CONSTEXPR explicit basic_string(size_type len)noexcept(noexcept(this->allocate(0))); + REXY_CPP20_CONSTEXPR basic_string(size_type len, size_type cap)noexcept(noexcept(this->allocate(0))); + template + REXY_CPP20_CONSTEXPR basic_string(InputIt start, InputIt fin)noexcept(noexcept(this->allocate(0))); //normal copy and move ctors - basic_string(const basic_string& b)noexcept(noexcept(this->allocate(0))); + REXY_CPP20_CONSTEXPR basic_string(const basic_string& b)noexcept(noexcept(this->allocate(0))); constexpr basic_string(basic_string&& s)noexcept; - basic_string(const string_base&)noexcept(noexcept(this->allocate(0))); + REXY_CPP20_CONSTEXPR basic_string(const string_base&)noexcept(noexcept(this->allocate(0))); //dtor - ~basic_string(void)noexcept(noexcept(this->deallocate(nullptr, 0))); + REXY_CPP20_CONSTEXPR ~basic_string(void)noexcept(noexcept(this->deallocate(nullptr, 0))); - basic_string& operator=(const basic_string& s) + REXY_CPP20_CONSTEXPR basic_string& operator=(const basic_string& s) noexcept(noexcept(this->allocate(0)) && noexcept(this->deallocate(nullptr,0))); constexpr basic_string& operator=(basic_string&& s)noexcept; - basic_string& operator=(const string_base& s) + REXY_CPP20_CONSTEXPR basic_string& operator=(const string_base& s) noexcept(noexcept(this->allocate(0)) && noexcept(this->deallocate(nullptr,0))); //Copy from c string - basic_string& operator=(const_pointer c) + REXY_CPP20_CONSTEXPR basic_string& operator=(const_pointer c) noexcept(noexcept(this->allocate(0)) && noexcept(this->deallocate(nullptr,0))); //Replace managed pointer. Frees existing value - void reset(pointer val = nullptr)noexcept(noexcept(this->deallocate(nullptr,0))); - void reset(pointer val, size_type len)noexcept(noexcept(this->deallocate(nullptr,0))); - bool resize(size_type newsize) + REXY_CPP20_CONSTEXPR void reset(pointer val = nullptr)noexcept(noexcept(this->deallocate(nullptr,0))); + REXY_CPP20_CONSTEXPR void reset(pointer val, size_type len)noexcept(noexcept(this->deallocate(nullptr,0))); + REXY_CPP20_CONSTEXPR bool resize(size_type newsize) noexcept(noexcept(this->allocate(0)) && noexcept(this->deallocate(nullptr,0))); - void append(const_pointer data, size_type len) + REXY_CPP20_CONSTEXPR void append(const_pointer data, size_type len) noexcept(noexcept(this->allocate(0)) && noexcept(this->deallocate(nullptr,0))); - void append(const_pointer data) + REXY_CPP20_CONSTEXPR void append(const_pointer data) noexcept(noexcept(this->allocate(0)) && noexcept(this->deallocate(nullptr,0))); + template + REXY_CPP20_CONSTEXPR void append(InputIt start, InputIt fin) + noexcept(noexcept(this->allocate(0)) && + noexcept(this->deallocate(nullptr,0))); template - basic_string substring(size_type start, size_type end)const; + REXY_CPP20_CONSTEXPR basic_string substring(size_type start, size_type end)const; - pointer release(void)noexcept(noexcept(this->allocate(0))); + REXY_CPP20_CONSTEXPR pointer release(void)noexcept(noexcept(this->allocate(0))); using detail::hasallocator::allocator; }; @@ -341,7 +347,7 @@ namespace rexy{ constexpr size_type length(void)const noexcept; template - operator basic_string(void) + 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); }; @@ -368,7 +374,7 @@ namespace rexy{ constexpr string_view(const_pointer c)noexcept; constexpr string_view(const string_view& s)noexcept; constexpr string_view(string_view&& s)noexcept; - ~string_view(void)noexcept = default; + REXY_CPP20_CONSTEXPR ~string_view(void)noexcept = default; constexpr string_view& operator=(const_pointer c)noexcept; constexpr string_view& operator=(const string_view& s)noexcept; @@ -441,13 +447,13 @@ namespace rexy{ } template = 0, detail::enable_if_string = 0> - decltype(auto) operator+=(Left& l, Right&& r) + REXY_CPP20_CONSTEXPR decltype(auto) operator+=(Left& l, Right&& r) noexcept(noexcept(l + std::forward(r)) && std::is_nothrow_assignable(r))>::value) { return l = (l + std::forward(r)); } template = 0> - decltype(auto) operator+=(Left& l, typename std::decay_t::const_pointer r) + REXY_CPP20_CONSTEXPR decltype(auto) operator+=(Left& l, typename std::decay_t::const_pointer r) noexcept(noexcept(l + r) && std::is_nothrow_assignable::value) { return l = (l + r); diff --git a/include/rexy/string_base.tpp b/include/rexy/string_base.tpp index 00fa8b5..23ba3b9 100644 --- a/include/rexy/string_base.tpp +++ b/include/rexy/string_base.tpp @@ -75,7 +75,7 @@ namespace rexy{ //allocate string if longer than small string capacity, copy otherwise template - void basic_string::_copy_construct_string(const_pointer data, size_type len, size_type cap) + REXY_CPP20_CONSTEXPR void basic_string::_copy_construct_string(const_pointer data, size_type len, size_type cap) noexcept(noexcept(this->allocate(0))) { if(cap > this->get_short_capacity()){ @@ -109,33 +109,45 @@ namespace rexy{ constexpr basic_string::basic_string(rexy::steal data, size_type len, size_type cap)noexcept: string_base(data.value(), len, cap){} template - basic_string::basic_string(const_pointer data, size_type len, size_type cap) + REXY_CPP20_CONSTEXPR basic_string::basic_string(const_pointer data, size_type len, size_type cap) noexcept(noexcept(this->allocate(0))) { _copy_construct_string(data, len, cap); } template - basic_string::basic_string(const_pointer data, size_type len) + REXY_CPP20_CONSTEXPR basic_string::basic_string(const_pointer data, size_type len) noexcept(noexcept(this->allocate(0))): basic_string(data, len, len){} template - basic_string::basic_string(const_pointer data) + REXY_CPP20_CONSTEXPR basic_string::basic_string(const_pointer data) noexcept(noexcept(this->allocate(0))): basic_string(data, data ? strlen(data) : 0){} template - basic_string::basic_string(size_type cap) + REXY_CPP20_CONSTEXPR basic_string::basic_string(size_type cap) noexcept(noexcept(this->allocate(0))): basic_string(size_type{0}, cap){} template - basic_string::basic_string(size_type len, size_type cap) + REXY_CPP20_CONSTEXPR basic_string::basic_string(size_type len, size_type cap) noexcept(noexcept(this->allocate(0))) { _copy_construct_string(nullptr, len, cap); } - + template + template + REXY_CPP20_CONSTEXPR basic_string::basic_string(InputIt start, InputIt fin) + noexcept(noexcept(this->allocate(0))): + basic_string(nullptr, size_type{fin - start}) + { + auto raw = this->get_pointer(); + size_type i = 0; + for(auto it = start;it != fin;++it,++i){ + raw[i] = *it; + } + raw[i] = 0; + } //normal copy and move ctors template - basic_string::basic_string(const basic_string& b) + REXY_CPP20_CONSTEXPR basic_string::basic_string(const basic_string& b) noexcept(noexcept(this->allocate(0))): detail::hasallocator(b) { @@ -146,7 +158,7 @@ namespace rexy{ detail::hasallocator(std::move(s)), string_base(std::move(s)){} template - basic_string::basic_string(const string_base& b) + REXY_CPP20_CONSTEXPR basic_string::basic_string(const string_base& b) noexcept(noexcept(this->allocate(0))) { _copy_construct_string(b.get(), b.length(), b.capacity()); @@ -154,7 +166,7 @@ namespace rexy{ //dtor template - basic_string::~basic_string(void) + REXY_CPP20_CONSTEXPR basic_string::~basic_string(void) noexcept(noexcept(this->deallocate(nullptr, 0))) { if(this->islong()) @@ -162,7 +174,7 @@ namespace rexy{ } template - basic_string& basic_string::operator=(const basic_string& s) + REXY_CPP20_CONSTEXPR basic_string& basic_string::operator=(const basic_string& s) noexcept(noexcept(this->allocate(0)) && noexcept(this->deallocate(nullptr, 0))) { @@ -180,7 +192,7 @@ namespace rexy{ return *this; } template - basic_string& basic_string::operator=(const string_base& s) + REXY_CPP20_CONSTEXPR basic_string& basic_string::operator=(const string_base& s) noexcept(noexcept(this->allocate(0)) && noexcept(this->deallocate(nullptr,0))) { @@ -188,7 +200,7 @@ namespace rexy{ } //Copy from c string template - basic_string& basic_string::operator=(const_pointer c) + REXY_CPP20_CONSTEXPR basic_string& basic_string::operator=(const_pointer c) noexcept(noexcept(this->allocate(0)) && noexcept(this->deallocate(nullptr,0))) { @@ -197,13 +209,13 @@ namespace rexy{ //Replace managed pointer. Frees existing value template - void basic_string::reset(pointer val) + REXY_CPP20_CONSTEXPR void basic_string::reset(pointer val) noexcept(noexcept(this->deallocate(nullptr,0))) { reset(val, val ? strlen(val) : 0); } template - void basic_string::reset(pointer val, size_type len) + REXY_CPP20_CONSTEXPR void basic_string::reset(pointer val, size_type len) noexcept(noexcept(this->deallocate(nullptr,0))) { if(this->islong()) @@ -214,7 +226,7 @@ namespace rexy{ this->set_long_capacity(len); } template - bool basic_string::resize(size_type newsize) + REXY_CPP20_CONSTEXPR bool basic_string::resize(size_type newsize) noexcept(noexcept(this->allocate(0)) && noexcept(this->deallocate(nullptr,0))) { @@ -225,7 +237,7 @@ namespace rexy{ return (*this = basic_string(this->get_pointer(), newsize)); } template - void basic_string::append(const_pointer data, size_type len) + REXY_CPP20_CONSTEXPR void basic_string::append(const_pointer data, size_type len) noexcept(noexcept(this->allocate(0)) && noexcept(this->deallocate(nullptr,0))) { @@ -246,17 +258,43 @@ namespace rexy{ } } template - void basic_string::append(const_pointer data) + REXY_CPP20_CONSTEXPR void basic_string::append(const_pointer data) noexcept(noexcept(this->allocate(0)) && noexcept(this->deallocate(nullptr,0))) { if(data) append(data, strlen(data)); } + template + template + REXY_CPP20_CONSTEXPR void basic_string::append(InputIt start, InputIt fin) + noexcept(noexcept(this->allocate(0)) && + noexcept(this->deallocate(nullptr,0))) + { + size_type append_len = fin - start; + + size_type my_len = this->length(); + size_type my_cap = this->capacity(); + pointer raw = this->get_pointer(); + + if(my_len + append_len > my_cap){ + *this = basic_string(raw, my_len, max(my_len+append_len, my_cap*2)); + raw = this->get_pointer(); + my_cap *= 2; + } + + size_type i = 0; + for(auto it = start;it != fin;++it,++i){ + raw[my_len + i] = *it; + } + this->set_length(my_len + append_len); + raw[my_len + i] = 0; + } + template template - 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 -> basic_string{ if(start > end || end > this->length()) return {}; const size_type newlen = end - start; @@ -265,7 +303,7 @@ namespace rexy{ return tmp; } template - auto basic_string::release(void)noexcept(noexcept(this->allocate(0))) -> pointer{ + REXY_CPP20_CONSTEXPR auto basic_string::release(void)noexcept(noexcept(this->allocate(0))) -> pointer{ if(this->islong()){ pointer raw = this->get_long_ptr(); this->set_islong_flag(false); @@ -284,7 +322,7 @@ namespace rexy{ } template - basic_string& basic_string::_copy_string(const_pointer s, size_type len) + REXY_CPP20_CONSTEXPR basic_string& basic_string::_copy_string(const_pointer s, size_type len) noexcept(noexcept(this->allocate(0)) && noexcept(this->deallocate(nullptr,0))) { @@ -307,7 +345,7 @@ namespace rexy{ } template template - string_cat_expr::operator basic_string(void) + REXY_CPP20_CONSTEXPR string_cat_expr::operator basic_string(void) noexcept(std::is_nothrow_constructible, typename basic_string::size_type>::value && std::is_nothrow_invocable>,decltype(*this)>::value) {