diff --git a/include/rexy/string_base.hpp b/include/rexy/string_base.hpp index 9fa3ed5..50347cf 100644 --- a/include/rexy/string_base.hpp +++ b/include/rexy/string_base.hpp @@ -55,8 +55,7 @@ namespace rexy{ public: //Stop managing stored pointer. Does not free. - constexpr char* release(void)noexcept(noexcept(cx::exchange(m_data, nullptr))) - {return cx::exchange(m_data, nullptr);} + constexpr char* release(void)noexcept{return cx::exchange(m_data, nullptr);} //Length of string not including null terminator constexpr size_t length(void)const noexcept{return m_length;} @@ -82,18 +81,17 @@ namespace rexy{ using allocator_type = Allocator; private: - string_intermediary& _copy_string(const char* s, size_t len)noexcept(noexcept(Allocator::free(m_data)) && - noexcept(Allocator::copy(s, len))); + string_intermediary& _copy_string(const char* s, size_t len) + noexcept(noexcept(Allocator::copy(nullptr,0)) && + noexcept(Allocator::free(nullptr))); public: constexpr string_intermediary(void)noexcept; constexpr string_intermediary(rexy::steal data, size_t len)noexcept; constexpr string_intermediary(rexy::steal data, size_t len, size_t cap)noexcept; constexpr string_intermediary(rexy::steal data)noexcept; - [[deprecated]] constexpr string_intermediary(char* data, size_t len)noexcept; - [[deprecated]] constexpr string_intermediary(char* data, size_t len, size_t cap)noexcept; string_intermediary(const char* data, size_t len)noexcept(noexcept(Allocator::copy(data,len))); - string_intermediary(const char* data)noexcept(noexcept(strlen(data)) && noexcept(Allocator::copy(data, m_cap))); + string_intermediary(const char* data)noexcept(noexcept(Allocator::copy(data, m_cap))); string_intermediary(size_t len)noexcept(noexcept(Allocator::allocate(len))); string_intermediary(size_t len, size_t cap)noexcept(noexcept(Allocator::allocate(len))); @@ -107,22 +105,35 @@ namespace rexy{ ~string_intermediary(void)noexcept(noexcept(Allocator::free(m_data))); string_intermediary& operator=(const string_intermediary& s) - noexcept(std::is_nothrow_copy_constructible>::value && - std::is_nothrow_move_assignable>::value); - constexpr string_intermediary& operator=(string_intermediary&& s)noexcept(noexcept(cx::swap(m_data, s.m_data))); + noexcept(noexcept(Allocator::copy(nullptr,0)) && + noexcept(Allocator::free(nullptr))); + + constexpr string_intermediary& operator=(string_intermediary&& s)noexcept; //Copy from c string - string_intermediary& operator=(const char* c)noexcept(noexcept(_copy_string(c, 0))); + string_intermediary& operator=(const char* c) + noexcept(noexcept(Allocator::copy(nullptr,0)) && + noexcept(Allocator::free(nullptr))); //Copy from other string_base - string_intermediary& operator=(const string_base& s)noexcept(noexcept(_copy_string(s.get(), 0))); + string_intermediary& operator=(const string_base& s) + noexcept(noexcept(Allocator::copy(nullptr,0)) && + noexcept(Allocator::free(nullptr))); //Replace managed pointer. Frees existing value void reset(char* val = nullptr)noexcept(noexcept(Allocator::free(m_data))); void reset(char* val, size_t len)noexcept(noexcept(Allocator::free(m_data))); - bool resize(size_t newsize)noexcept(std::is_nothrow_copy_constructible>::value && - std::is_nothrow_move_assignable>::value); - void append(const char* data, size_t len)noexcept(std::is_nothrow_constructible,decltype(m_length)>::value); - void append(const char* data)noexcept(std::is_nothrow_constructible,decltype(m_length)>::value); - void append(const string_base& s)noexcept(std::is_nothrow_constructible,decltype(m_length)>::value); + bool resize(size_t newsize) + noexcept(noexcept(Allocator::copy(nullptr,0)) && + noexcept(Allocator::free(nullptr))); + + void append(const char* data, size_t len) + noexcept(noexcept(Allocator::allocate(0)) && + noexcept(Allocator::free(nullptr))); + void append(const char* data) + noexcept(noexcept(Allocator::allocate(0)) && + noexcept(Allocator::free(nullptr))); + void append(const string_base& s) + noexcept(noexcept(Allocator::allocate(0)) && + noexcept(Allocator::free(nullptr))); }; @@ -146,7 +157,7 @@ namespace rexy{ constexpr string_cat_expr(string_cat_expr&& s)noexcept(std::is_nothrow_constructible::value && std::is_nothrow_constructible::value); - constexpr size_t length(void)const noexcept(noexcept(m_l.length()) && noexcept(m_r.length())); + constexpr size_t length(void)const noexcept; template operator string_intermediary(void) noexcept(std::is_nothrow_constructible, size_t>::value && diff --git a/include/rexy/string_base.tpp b/include/rexy/string_base.tpp index 19994aa..97c038f 100644 --- a/include/rexy/string_base.tpp +++ b/include/rexy/string_base.tpp @@ -40,27 +40,20 @@ namespace rexy{ } template constexpr string_intermediary::string_intermediary(rexy::steal data, size_t len)noexcept: - string_base(data.value(), len){} + string_base(data.value(), len, len){} template constexpr string_intermediary::string_intermediary(rexy::steal data, size_t len, size_t cap)noexcept: string_base(data.value(), len, cap){} template - /*deprecated*/ constexpr string_intermediary::string_intermediary(char* data, size_t len)noexcept: - string_base(data, len){} - template - /*deprecated*/ constexpr string_intermediary::string_intermediary(char* data, size_t len, size_t cap)noexcept: - string_base(data, len, cap){} - template string_intermediary::string_intermediary(const char* data, size_t len) noexcept(noexcept(Allocator::copy(data,len))): - string_base(reinterpret_cast(len ? Allocator::copy(data, len+1) : nullptr), len) + string_base(reinterpret_cast(len ? Allocator::copy(data, len+1) : nullptr), len, len) { m_data[len] = 0; } template string_intermediary::string_intermediary(const char* data) - noexcept(noexcept(strlen(data)) && - noexcept(Allocator::copy(data, m_cap))): + noexcept(noexcept(Allocator::copy(data, m_cap))): string_base(data ? strlen(data) : 0) { if(m_cap){ @@ -108,10 +101,10 @@ namespace rexy{ template string_intermediary& string_intermediary::operator=(const string_intermediary& s) - noexcept(std::is_nothrow_copy_constructible>::value && - std::is_nothrow_move_assignable>::value) + noexcept(noexcept(Allocator::copy(nullptr,0)) && + noexcept(Allocator::free(nullptr))) { - if(s.m_length < m_length){ + if(s.m_length < m_cap){ memcpy(m_data, s.m_data, s.m_length+1); m_length = s.m_length; return *this; @@ -120,9 +113,7 @@ namespace rexy{ return (*this = std::move(tmp)); } template - constexpr string_intermediary& string_intermediary::operator=(string_intermediary&& s) - noexcept(noexcept(cx::swap(m_data, s.m_data))) - { + constexpr string_intermediary& string_intermediary::operator=(string_intermediary&& s)noexcept{ cx::swap(m_data, s.m_data); m_length = s.m_length; m_cap = s.m_cap; @@ -131,14 +122,16 @@ namespace rexy{ //Copy from c string template string_intermediary& string_intermediary::operator=(const char* c) - noexcept(noexcept(_copy_string(c, 0))) + noexcept(noexcept(Allocator::copy(nullptr,0)) && + noexcept(Allocator::free(nullptr))) { return _copy_string(c, strlen(c)); } //Copy from other string_base template string_intermediary& string_intermediary::operator=(const string_base& s) - noexcept(noexcept(_copy_string(s.get(), 0))) + noexcept(noexcept(Allocator::copy(nullptr,0)) && + noexcept(Allocator::free(nullptr))) { return _copy_string(s.get(), s.length()); } @@ -164,76 +157,61 @@ namespace rexy{ } template bool string_intermediary::resize(size_t newsize) - noexcept(std::is_nothrow_copy_constructible>::value && - std::is_nothrow_move_assignable>::value) + noexcept(noexcept(Allocator::copy(nullptr,0)) && + noexcept(Allocator::free(nullptr))) { if(newsize < m_cap) return false; - string_intermediary tmp(newsize); - if(m_data){ - memcpy(tmp.get(), m_data, m_length); - tmp[m_length] = 0; - } - *this = std::move(tmp); - return true; + return (*this = string_intermediary(m_data, newsize)); } template void string_intermediary::append(const char* data, size_t len) - noexcept(std::is_nothrow_constructible,decltype(m_length)>::value) + noexcept(noexcept(Allocator::allocate(0)) && + noexcept(Allocator::free(nullptr))) { if(len+m_length <= m_cap){ memcpy(m_data+m_length, data, len); m_length += len; m_data[m_length] = 0; + }else if(!m_data){ + *this = string_intermediary(len, len); + memcpy(m_data, data, len+1); }else{ - string_intermediary tmp(cx::max(m_length + len, m_cap*2)); - if(m_data) - memcpy(STOP_STRICT_ALIAS_WARNING(tmp).m_data, m_data, m_length); - memcpy(STOP_STRICT_ALIAS_WARNING(tmp).m_data+m_length, data, len); - STOP_STRICT_ALIAS_WARNING(tmp).m_length = len+m_length; - tmp[m_length+len] = 0; + auto newsize = cx::max(m_length+len, m_cap*2); + string_intermediary tmp(newsize); + tmp.append(m_data, m_length); + tmp.append(data, len); *this = std::move(tmp); } } template void string_intermediary::append(const char* data) - noexcept(std::is_nothrow_constructible,decltype(m_length)>::value) + noexcept(noexcept(Allocator::allocate(0)) && + noexcept(Allocator::free(nullptr))) { if(data) append(data, strlen(data)); } template void string_intermediary::append(const string_base& s) - noexcept(std::is_nothrow_constructible,decltype(m_length)>::value) + noexcept(noexcept(Allocator::allocate(0)) && + noexcept(Allocator::free(nullptr))) { append(s.get(), s.length()); } template string_intermediary& string_intermediary::_copy_string(const char* s, size_t len) - noexcept(noexcept(Allocator::free(m_data)) && - noexcept(Allocator::copy(s, len))) + noexcept(noexcept(Allocator::copy(nullptr,0)) && + noexcept(Allocator::free(nullptr))) { - if(!len){ - Allocator::free(m_data); - m_length = 0; - m_cap = 0; + if(len <= m_length){ + m_length = len; + memcpy(m_data, s, len); + m_data[len] = 0; return *this; } - if(len <= m_length){ - strcpy(m_data, s); - }else{ - Allocator::free(m_data); - m_cap = cx::max(len, m_cap*2); - m_data = reinterpret_cast(Allocator::copy(s, m_cap+1)); - if(!m_data){ - m_length = 0; - m_cap = 0; - return *this; - } - } - m_length = len; - return *this; + return (*this = string_intermediary(s, len)); } @@ -252,9 +230,7 @@ namespace rexy{ m_r(std::forward(s.m_r)){} template - constexpr size_t string_cat_expr::length(void)const - noexcept(noexcept(m_l.length()) && noexcept(m_r.length())) - { + constexpr size_t string_cat_expr::length(void)const noexcept{ return m_l.length() + m_r.length(); } template