Add noexcept specs to all the things

This commit is contained in:
rexy712 2020-05-06 15:23:58 -07:00
parent b97e7d7c1b
commit daac14dddf
18 changed files with 501 additions and 329 deletions

View File

@ -39,18 +39,14 @@ namespace rexy{
size_t m_cap = 0;
public:
protected:
constexpr binary_base(void) = default;
constexpr binary_base(char* data, size_t size):
constexpr binary_base(void)noexcept = default;
constexpr binary_base(char* data, size_t size)noexcept:
m_data(data), m_cap(size){}
constexpr binary_base(char* data, size_t cap, size_t size):
constexpr binary_base(char* data, size_t cap, size_t size)noexcept:
m_data(data), m_size(size), m_cap(cap){}
template<class Allocator>
binary_base(const binary_base& b):
m_data(Allocator::copy(b.m_data, b.m_cap)),
m_size(b.m_size),
m_cap(b.m_cap){}
binary_base(binary_base&&);
~binary_base(void) = default;
binary_base(const binary_base& b)noexcept{}
~binary_base(void)noexcept = default;
public:
char* release(void);
@ -71,64 +67,83 @@ namespace rexy{
public:
using allocator_type = Allocator;
public:
constexpr binary_data(void) = default;
[[deprecated]] binary_data(char* data, size_t size):
constexpr binary_data(void)noexcept = default;
[[deprecated]] binary_data(char* data, size_t size)noexcept:
binary_base(data, size){}
binary_data(rexy::steal<char*> data, size_t size):
binary_base(data.value(), size){}
binary_data(const char* data, size_t size):
binary_base(reinterpret_cast<char*>(Allocator::copy(data, size)), size){}
[[deprecated]] binary_data(char* data, size_t cap, size_t size):
[[deprecated]] binary_data(char* data, size_t cap, size_t size)noexcept:
binary_base(data, cap, size){}
binary_data(rexy::steal<char*> data, size_t cap, size_t size):
binary_data(const char* data, size_t size)
noexcept(noexcept(Allocator::copy(data, size))):
binary_base(reinterpret_cast<char*>(Allocator::copy(data, size)), size){}
constexpr binary_data(rexy::steal<char*> data, size_t size)noexcept:
binary_base(data.value(), size){}
constexpr binary_data(rexy::steal<char*> data, size_t cap, size_t size)noexcept:
binary_base(data.value(), cap, size){}
binary_data(const char* data, size_t cap, size_t size):
binary_data(const char* data, size_t cap, size_t size)
noexcept(noexcept(Allocator::copy(data, size))):
binary_base(reinterpret_cast<char*>(Allocator::copy(data, size)), cap, size){}
binary_data(size_t size):
binary_data(size_t size)
noexcept(noexcept(Allocator::allocate(size))):
binary_base(reinterpret_cast<char*>(Allocator::allocate(size)), size){}
binary_data(const binary_data& b):
binary_base(b)
binary_data(const binary_data& b)
noexcept(noexcept(Allocator::copy(b.m_data, b.m_cap))):
binary_base(b.m_data, b.m_cap, b.m_size)
{
m_data = Allocator::copy(b.m_data, b.m_cap);
}
binary_data(binary_data&& b):
binary_base(std::move(b)){}
~binary_data(void){
constexpr binary_data(binary_data&& b)noexcept:
binary_base(cx::exchange(b.m_data, nullptr), b.m_cap, b.m_size){}
~binary_data(void)
noexcept(noexcept(Allocator::free(m_data)))
{
Allocator::free(m_data);
}
binary_data& operator=(const binary_data& b){
binary_data& operator=(const binary_data& b)
noexcept(std::is_nothrow_copy_constructible<binary_data<Allocator>>::value &&
std::is_nothrow_move_assignable<binary_data<Allocator>>::value)
{
binary_data<allocator_type> tmp(b);
return (*this = std::move(tmp));
}
binary_data& operator=(binary_data&& b){
constexpr binary_data& operator=(binary_data&& b)
noexcept(noexcept(cx::swap(m_data, b.m_data)))
{
m_size = b.m_size;
m_cap = b.m_cap;
std::swap(m_data, b.m_data);
cx::swap(m_data, b.m_data);
return *this;
}
void reset(void){
void reset(void)
noexcept(noexcept(Allocator::free(m_data)))
{
Allocator::free(m_data);
m_data = nullptr;
m_cap = m_size = 0;
}
void reset(char* val, size_t cap, size_t size = 0){
void reset(char* val, size_t cap, size_t size = 0)
noexcept(noexcept(Allocator::free(m_data)))
{
Allocator::free(m_data);
m_data = val;
m_cap = cap;
m_size = size;
}
bool resize(size_t newsize){
bool resize(size_t newsize)
noexcept(std::is_nothrow_constructible<binary_data<Allocator>,size_t>::value)
{
if(newsize < m_cap)
return false;
binary_data<allocator_type> tmp(newsize);
if(!tmp)
return false;
memcpy(STOP_STRICT_ALIAS_WARNING(tmp).m_data, m_data, m_size);
std::swap(m_data, STOP_STRICT_ALIAS_WARNING(tmp).m_data);
cx::swap(m_data, STOP_STRICT_ALIAS_WARNING(tmp).m_data);
m_cap = STOP_STRICT_ALIAS_WARNING(tmp).m_cap;
return true;
}
void append(const char* data, size_t len){
void append(const char* data, size_t len)
noexcept(noexcept(resize(len)))
{
if(m_size + len > m_cap)
resize(cx::max(m_cap*2, m_size+len));
memcpy(m_data+m_size, data, len);
@ -151,22 +166,26 @@ namespace rexy{
}
template<class Left, class Right, detail::enable_if_binary<Left,Right> = 0>
bool operator==(Left&& l, Right&& r){
bool operator==(Left&& l, Right&& r)noexcept{
return l && r && l.size() == r.size() && l.capacity() == r.capacity() && !memcmp(l.get(), r.get(), l.size());
}
template<class Left, class Right, detail::enable_if_binary<Left,Right> = 0>
bool operator!=(Left&& l, Right&& r){
bool operator!=(Left&& l, Right&& r)noexcept{
return !(std::forward<Left>(l) == std::forward<Right>(r));
}
template<class All, class Alr>
auto operator+(const rexy::binary_data<All>& l, const rexy::binary_data<Alr>& r){
auto operator+(const rexy::binary_data<All>& l, const rexy::binary_data<Alr>& r)
noexcept(std::is_nothrow_constructible<binary_data<All>, size_t>::value)
{
rexy::binary_data<All> retval(l.size() + r.size());
memcpy(retval.get(), l.get(), l.size());
memcpy(retval.get()+l.size(), r.get(), r.size());
return retval;
}
template<class All, class Alr>
decltype(auto) operator+=(rexy::binary_data<All>& l, const rexy::binary_data<Alr>& r){
decltype(auto) operator+=(rexy::binary_data<All>& l, const rexy::binary_data<Alr>& r)
noexcept(noexcept(l.resize(0)))
{
l.resize(l.size() + r.size());
memcpy(l.get()+l.size(), r.get(), r.size());
return l;

View File

@ -21,10 +21,15 @@
#include "utility.hpp" //swap
#include <type_traits>
namespace rexy::cx{
template<class Iter, class Compare>
constexpr Iter qs_partition(Iter left, Iter right, const Compare& cmp){
constexpr Iter qs_partition(Iter left, Iter right, const Compare& cmp)
noexcept(std::is_nothrow_invocable<Compare,decltype(*left),decltype(*right)>::value &&
noexcept(cx::swap(*left,*right)))
{
auto range = right - left;
auto pivot = left + (range / 2);
auto value = *pivot;
@ -42,7 +47,9 @@ namespace rexy::cx{
return left;
}
template<class Iter, class Compare>
constexpr void quicksort(Iter left, Iter right, const Compare& cmp){
constexpr void quicksort(Iter left, Iter right, const Compare& cmp)
noexcept(noexcept(cx::qs_partition(left, right, cmp)))
{
while(left < right){
auto real_right = right-1;
auto pivot = qs_partition(left, real_right, cmp);

View File

@ -22,6 +22,8 @@
#include <cstddef> //size_t
#include "utility.hpp" //swap
#include <type_traits>
namespace rexy::cx{
template<class T, size_t N>
@ -44,76 +46,80 @@ namespace rexy::cx{
T m_elements[N] = {};
public:
constexpr reference at(size_type pos){
constexpr reference at(size_type pos)noexcept{
return m_elements[pos];
}
constexpr const_reference at(size_type pos)const{
constexpr const_reference at(size_type pos)const noexcept{
return m_elements[pos];
}
constexpr reference operator[](size_type pos){
constexpr reference operator[](size_type pos)noexcept{
return m_elements[pos];
}
constexpr const_reference operator[](size_type pos)const{
constexpr const_reference operator[](size_type pos)const noexcept{
return m_elements[pos];
}
constexpr reference front(void){
constexpr reference front(void)noexcept{
return m_elements[0];
}
constexpr const_reference front(void)const{
constexpr const_reference front(void)const noexcept{
return m_elements[0];
}
constexpr reference back(void){
constexpr reference back(void)noexcept{
return m_elements[max_elements-1];
}
constexpr const_reference back(void)const{
constexpr const_reference back(void)const noexcept{
return m_elements[max_elements-1];
}
constexpr pointer data(void){
constexpr pointer data(void)noexcept{
return m_elements;
}
constexpr const_pointer data(void)const{
constexpr const_pointer data(void)const noexcept{
return m_elements;
}
constexpr iterator begin(void){
constexpr iterator begin(void)noexcept{
return m_elements;
}
constexpr const_iterator begin(void)const{
constexpr const_iterator begin(void)const noexcept{
return m_elements;
}
constexpr const_iterator cbegin(void)const{
constexpr const_iterator cbegin(void)const noexcept{
return m_elements;
}
constexpr iterator end(void){
constexpr iterator end(void)noexcept{
return m_elements+max_elements;
}
constexpr const_iterator end(void)const{
constexpr const_iterator end(void)const noexcept{
return m_elements+max_elements;
}
constexpr const_iterator cend(void)const{
constexpr const_iterator cend(void)const noexcept{
return m_elements+max_elements;
}
constexpr bool empty(void)const{
constexpr bool empty(void)const noexcept{
if constexpr(max_elements == 0){
return true;
}else{
return false;
}
}
constexpr size_type size(void)const{
constexpr size_type size(void)const noexcept{
return max_elements;
}
constexpr size_type max_size(void)const{
constexpr size_type max_size(void)const noexcept{
return max_elements;
}
constexpr void fill(const T& value){
constexpr void fill(const T& value)
noexcept(std::is_nothrow_copy_assignable<T>::value)
{
for(auto it = begin();it != end();++it){
*it = value;
}
}
constexpr void swap(array& other){
constexpr void swap(array& other)
noexcept(noexcept(cx::swap(m_elements[0], other.m_elements[0])))
{
for(size_type i = 0;i < max_size();++i){
swap(m_elements[i], other.m_elements[i]);
cx::swap(m_elements[i], other.m_elements[i]);
}
}
};

View File

@ -25,7 +25,7 @@ namespace rexy::cx{
template<class T>
struct hash{
constexpr size_t operator()(const T& t, size_t salt = 0){
constexpr size_t operator()(const T& t, size_t salt = 0)const noexcept{
constexpr size_t bytes = sizeof(size_t);
size_t val = static_cast<size_t>(t);
size_t hash = 5381 + salt; //magic hash number

View File

@ -73,9 +73,9 @@ namespace rexy::cx{
//no key checks. give a correct key or get a random answer :)
template<class U, class UHash = hash<std::decay_t<U>>>
constexpr reference operator[](U&& u);
constexpr reference operator[](U&& u)noexcept;
template<class U, class UHash = hash<std::decay_t<U>>>
constexpr const_reference operator[](U&& u)const;
constexpr const_reference operator[](U&& u)const noexcept;
};
template<class Key, class Value, size_t N, class Hash>
@ -90,7 +90,7 @@ namespace rexy::cx{
}
//sort the buckets based on size, largest first
quicksort(buckets.begin(), buckets.end(), [](auto&& left, auto&& right) -> bool{
cx::quicksort(buckets.begin(), buckets.end(), [](auto&& left, auto&& right) -> bool{
return left.size() > right.size();
});
@ -148,7 +148,7 @@ namespace rexy::cx{
//no key checks. give a correct key or get a random answer :)
template<class Key, class Value, size_t N, class Hash>
template<class U, class UHash>
constexpr auto hashmap<Key,Value,N,Hash>::operator[](U&& key) -> reference{
constexpr auto hashmap<Key,Value,N,Hash>::operator[](U&& key)noexcept -> reference{
auto d = m_g[UHash{}(std::forward<U>(key)) % max_size];
if(d & single_bucket_bit)
return m_values[d & ~single_bucket_bit];
@ -156,7 +156,7 @@ namespace rexy::cx{
}
template<class Key, class Value, size_t N, class Hash>
template<class U, class UHash>
constexpr auto hashmap<Key,Value,N,Hash>::operator[](U&& key)const -> const_reference{
constexpr auto hashmap<Key,Value,N,Hash>::operator[](U&& key)const noexcept -> const_reference{
auto d = m_g[UHash{}(std::forward<U>(key)) % max_size];
if(d & single_bucket_bit)
return m_values[d & ~single_bucket_bit];

View File

@ -26,7 +26,7 @@ namespace rexy::cx{
#include "../string_base.hpp"
#include "utility.hpp"
#include <type_traits>
//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
@ -46,7 +46,7 @@ namespace rexy::cx{
public:
constexpr string(void) = default;
template<size_t M>
constexpr string(const char(&data)[M]):
constexpr string(const char(&data)[M])noexcept:
m_length(M)
{
static_assert(M <= N);
@ -54,14 +54,14 @@ namespace rexy::cx{
m_data[i] = data[i];
}
}
constexpr string(const char* data):
constexpr string(const char* data)noexcept:
m_length(cx::strlen(data))
{
for(size_t i = 0;i < m_length;++i){
m_data[i] = data[i];
}
}
constexpr string(const char* data, size_t len):
constexpr string(const char* data, size_t len)noexcept:
m_length(len)
{
for(size_t i = 0;i < m_length;++i){
@ -69,7 +69,7 @@ namespace rexy::cx{
}
}
constexpr string(const rexy::static_string& str):
constexpr string(const rexy::static_string& str)noexcept:
m_length(str.length())
{
for(size_t i = 0;i < m_length;++i){
@ -77,56 +77,58 @@ namespace rexy::cx{
}
}
template<class Left, class Right>
constexpr string(const rexy::string_cat_expr<Left,Right>& expr){
constexpr string(const rexy::string_cat_expr<Left,Right>& expr)
noexcept(std::is_nothrow_invocable<rexy::detail::string_appender<cx::string<N>>, decltype(expr)>::value)
{
rexy::detail::string_appender<cx::string<N>> append(*this);
append(expr);
}
constexpr string(const string&) = default;
constexpr string(string&&) = default;
~string(void) = default;
constexpr string(const string&)noexcept = default;
constexpr string(string&&)noexcept = default;
~string(void)noexcept = default;
constexpr string& operator=(const char* c){
constexpr string& operator=(const char* c)noexcept{
m_length = cx::strlen(c);
for(size_t i = 0;i < m_length;++i){
m_data[i] = c[i];
}
return *this;
}
constexpr string& operator=(const string&) = default;
constexpr string& operator=(string&&) = default;
constexpr string& operator=(const string&)noexcept = default;
constexpr string& operator=(string&&)noexcept = default;
constexpr size_t length(void)const{
constexpr size_t length(void)const noexcept{
return m_length;
}
constexpr size_t capacity(void)const{
constexpr size_t capacity(void)const noexcept{
return max_size;
}
constexpr char* get(void){
constexpr char* get(void)noexcept{
return m_data;
}
constexpr const char* get(void)const{
constexpr const char* get(void)const noexcept{
return m_data;
}
constexpr operator char*(void){
constexpr operator char*(void)noexcept{
return m_data;
}
constexpr operator const char*(void)const{
constexpr operator const char*(void)const noexcept{
return m_data;
}
constexpr bool valid(void)const{
constexpr bool valid(void)const noexcept{
return m_length > 0;
}
constexpr char& operator[](size_t i){
constexpr char& operator[](size_t i)noexcept{
return m_data[i];
}
constexpr const char& operator[](size_t i)const{
constexpr const char& operator[](size_t i)const noexcept{
return m_data[i];
}
constexpr bool resize(size_t i){
constexpr bool resize(size_t i)noexcept{
if(i >= capacity())
return false;
m_length = i;
@ -134,18 +136,18 @@ namespace rexy::cx{
return true;
}
constexpr void append(const char* data, size_t len){
constexpr void append(const char* data, size_t len)noexcept{
for(size_t i = 0;i < len;++i){
m_data[m_length++] = data[i];
}
}
constexpr void append(const char* data){
constexpr void append(const char* data)noexcept{
append(data, cx::strlen(data));
}
constexpr void append(const string& s){
constexpr void append(const string& s)noexcept{
append(s.get(), s.length());
}
constexpr void append(const rexy::static_string& s){
constexpr void append(const rexy::static_string& s)noexcept{
append(s.get(), s.length());
}
};
@ -166,15 +168,15 @@ namespace rexy::cx{
}
template<class Str1, class Str2, std::enable_if_t<detail::is_cx_string<Str1,Str2>::value,int> = 0>
constexpr auto operator+(Str1&& l, Str2&& r){
constexpr auto operator+(Str1&& l, Str2&& r)noexcept{
return string_cat_expr(std::forward<Str1>(l), std::forward<Str2>(r));
}
template<class Str1, std::enable_if_t<detail::is_cx_string<Str1>::value,int> = 0>
constexpr auto operator+(Str1&& l, const char* r){
constexpr auto operator+(Str1&& l, const char* r)noexcept{
return string_cat_expr(std::forward<Str1>(l), rexy::static_string(r));
}
template<class Str1, std::enable_if_t<detail::is_cx_string<Str1>::value,int> = 0>
constexpr auto operator+(const char* l, Str1&& r){
constexpr auto operator+(const char* l, Str1&& r)noexcept{
return string_cat_expr(rexy::static_string(l), std::forward<Str1>(r));
}
}

View File

@ -28,7 +28,7 @@ namespace rexy::cx{
//jenkns one at a time hash
template<class Str>
struct string_hash{
constexpr size_t operator()(const Str& s, size_t salt = 0){
constexpr size_t operator()(const Str& s, size_t salt = 0)const noexcept{
size_t hash = salt;
for(size_t i = 0;i < s.length();++i){
hash += s[i];

View File

@ -20,45 +20,55 @@
#define REXY_CX_UTILITY_HPP
#include <utility> //forward, move
#include <type_traits>
namespace rexy::cx{
namespace{
template<class T>
constexpr void swap(T& l, T& r){
constexpr void swap(T& l, T& r)
noexcept(std::is_nothrow_copy_assignable<T>::value)
{
T tmp = l;
l = r;
r = tmp;
}
template<class T, class U = T>
constexpr T exchange(T& l, U&& r){
constexpr T exchange(T& l, U&& r)
noexcept(std::is_nothrow_assignable<T,U&&>::value &&
std::is_nothrow_move_assignable<T>::value)
{
T old = std::move(l);
l = std::forward<U>(r);
return old;
}
template<class T>
constexpr const T& min(const T& l, const T& r){
constexpr const T& min(const T& l, const T& r)noexcept{
return l < r ? l : r;
}
template<class T, class Compare>
constexpr const T& min(const T& l, const T& r, Compare cmp){
constexpr const T& min(const T& l, const T& r, Compare cmp)
noexcept(std::is_nothrow_invocable<Compare,const T&,const T&>::value)
{
return cmp(l, r) ? l : r;
}
template<class T>
constexpr const T& max(const T& l, const T& r){
constexpr const T& max(const T& l, const T& r)noexcept{
return l > r ? l : r;
}
template<class T, class Compare>
constexpr const T& max(const T& l, const T& r, Compare cmp){
constexpr const T& max(const T& l, const T& r, Compare cmp)
noexcept(std::is_nothrow_invocable<Compare,const T&,const T&>::value)
{
return cmp(l, r) ? l : r;
}
constexpr size_t strlen(const char* c){
constexpr size_t strlen(const char* c)noexcept{
size_t i = 0;
for(;c[i];++i);
return i;
}
constexpr int strcmp(const char* l, const char* r){
constexpr int strcmp(const char* l, const char* r)noexcept{
using uchar = unsigned char;
for(;*l == *r && *l;++l, ++r);
return (static_cast<uchar>(*l)) - (static_cast<uchar>(*r));

View File

@ -24,6 +24,8 @@
#include "utility.hpp" //swap
#include <type_traits>
namespace rexy::cx{
template<class T, size_t N>
@ -47,83 +49,88 @@ namespace rexy::cx{
size_type m_size = 0;
public:
constexpr vector(void) = default;
constexpr vector(const vector&) = default;
constexpr vector(vector&&) = default;
constexpr vector(void)noexcept(std::is_nothrow_default_constructible<T>::value) = default;
constexpr vector(const vector&)noexcept(std::is_nothrow_copy_constructible<T>::value) = default;
constexpr vector(vector&&)noexcept(std::is_nothrow_move_constructible<T>::value) = default;
constexpr vector(size_type count, const T& value){
constexpr vector(size_type count, const T& value)
noexcept(std::is_nothrow_copy_assignable<T>::value)
{
for(size_type i = 0;i < min(count, max_elements);++i){
m_elements[i] = value;
}
}
~vector(void) = default;
~vector(void)noexcept = default;
constexpr vector& operator=(const vector&) = default;
constexpr vector& operator=(vector&&) = default;
constexpr vector& operator=(const vector&)noexcept(std::is_nothrow_copy_assignable<T>::value) = default;
constexpr vector& operator=(vector&&)noexcept(std::is_nothrow_move_assignable<T>::value) = default;
constexpr reference at(size_type pos){
constexpr reference at(size_type pos)noexcept{
return m_elements[pos];
}
constexpr const_reference at(size_type pos)const{
constexpr const_reference at(size_type pos)const noexcept{
return m_elements[pos];
}
constexpr reference operator[](size_type pos){
constexpr reference operator[](size_type pos)noexcept{
return m_elements[pos];
}
constexpr const_reference operator[](size_type pos)const{
constexpr const_reference operator[](size_type pos)const noexcept{
return m_elements[pos];
}
constexpr reference front(void){
constexpr reference front(void)noexcept{
return m_elements[0];
}
constexpr const_reference front(void)const{
constexpr const_reference front(void)const noexcept{
return m_elements[0];
}
constexpr reference back(void){
constexpr reference back(void)noexcept{
return m_elements[m_size-1];
}
constexpr const_reference back(void)const{
constexpr const_reference back(void)const noexcept{
return m_elements[m_size-1];
}
constexpr const_pointer data(void)const{
constexpr const_pointer data(void)const noexcept{
return m_elements;
}
constexpr iterator begin(void){
constexpr iterator begin(void)noexcept{
return m_elements;
}
constexpr const_iterator begin(void)const{
constexpr const_iterator begin(void)const noexcept{
return m_elements;
}
constexpr const_iterator cbegin(void)const{
constexpr const_iterator cbegin(void)const noexcept{
return m_elements;
}
constexpr iterator end(void){
constexpr iterator end(void)noexcept{
return m_elements+max_elements;
}
constexpr const_iterator end(void)const{
constexpr const_iterator end(void)const noexcept{
return m_elements+max_elements;
}
constexpr const_iterator cend(void)const{
constexpr const_iterator cend(void)const noexcept{
return m_elements+max_elements;
}
constexpr bool empty(void)const{
constexpr bool empty(void)const noexcept{
return m_size == 0;
}
constexpr size_type size(void)const{
constexpr size_type size(void)const noexcept{
return m_size;
}
constexpr size_type max_size(void)const{
constexpr size_type max_size(void)const noexcept{
return max_elements;
}
constexpr size_type capacity(void)const{
constexpr size_type capacity(void)const noexcept{
return max_elements;
}
constexpr void clear(void){
constexpr void clear(void)noexcept{
m_size = 0;
}
constexpr iterator insert(iterator pos, const T& value){
constexpr iterator insert(iterator pos, const T& value)
noexcept(std::is_nothrow_move_assignable<T>::value &&
std::is_nothrow_copy_assignable<T>::value)
{
auto start = pos;
auto it = pos;
++pos;
@ -133,7 +140,9 @@ namespace rexy::cx{
*start = value;
return start;
}
constexpr iterator insert(const_iterator pos, T&& value){
constexpr iterator insert(const_iterator pos, T&& value)
noexcept(std::is_nothrow_move_assignable<T>::value)
{
auto start = pos;
auto it = pos;
++pos;
@ -144,7 +153,10 @@ namespace rexy::cx{
return start;
}
template<class... Args>
constexpr iterator emplace(const_iterator pos, Args&&... args){
constexpr iterator emplace(const_iterator pos, Args&&... args)
noexcept(std::is_nothrow_move_assignable<T>::value &&
std::is_nothrow_constructible<T,Args&&...>::value)
{
auto start = pos;
auto it = pos;
++pos;
@ -154,7 +166,9 @@ namespace rexy::cx{
*start = T{std::forward<Args>(args)...};
return start;
}
constexpr iterator erase(const_iterator pos){
constexpr iterator erase(const_iterator pos)
noexcept(std::is_nothrow_move_assignable<T>::value)
{
auto start = pos;
auto it = pos;
++pos;
@ -163,23 +177,27 @@ namespace rexy::cx{
}
return start;
}
constexpr iterator push_back(const T& value){
constexpr iterator push_back(const T& value)
noexcept(std::is_nothrow_copy_assignable<T>::value)
{
m_elements[m_size] = value;
return m_elements+(m_size++);
}
template<class... Args>
constexpr iterator emplace_back(Args&&... args){
constexpr iterator emplace_back(Args&&... args)
noexcept(std::is_nothrow_constructible<T,Args&&...>::value)
{
m_elements[m_size++] = T{std::forward<Args>(args)...};
return m_elements+(m_size++);
}
constexpr void pop_back(void){
constexpr void pop_back(void)noexcept{
--m_size;
}
constexpr void resize(size_type count){
constexpr void resize(size_type count)noexcept{
if(count <= max_size())
m_size = count;
}
constexpr void resize(size_type count, const value_type& value){
constexpr void resize(size_type count, const value_type& value)noexcept{
if(count > m_size){
if(count <= max_size()){
for(size_type i = m_size;i < count;++i){
@ -190,20 +208,24 @@ namespace rexy::cx{
m_size = count;
}
}
constexpr void fill(const T& value){
constexpr void fill(const T& value)
noexcept(std::is_nothrow_copy_assignable<T>::value)
{
for(auto it = begin();it != end();++it){
*it = value;
}
}
constexpr void swap(vector& other){
constexpr void swap(vector& other)
noexcept(noexcept(cx::swap(m_elements[0], other.m_elements[0])))
{
size_type i = 0;
for(;i < m_size;++i){
swap(m_elements[i], other.m_elements[i]);
cx::swap(m_elements[i], other.m_elements[i]);
}
for(;i < other.m_size;++i){
swap(m_elements[i], other.m_elements[i]);
cx::swap(m_elements[i], other.m_elements[i]);
}
swap(m_size, other.m_size);
cx::swap(m_size, other.m_size);
}
};

View File

@ -25,44 +25,64 @@
namespace rexy{
template<class Al, class Str = rexy::string, detail::enable_if_concrete_string<Str> = 0>
auto binary_to_string(const binary_data<Al>& b){
auto binary_to_string(const binary_data<Al>& b)
noexcept(std::is_nothrow_constructible<Str, decltype(b.size())>::value)
{
Str s(b.size()+1);
memcpy(s.get(), b.get(), b.size());
s[b.size()] = 0;
return s;
}
template<class Al, class Str = rexy::string, detail::enable_if_concrete_string<Str> = 0, std::enable_if_t<std::is_same<std::decay_t<Al>,typename Str::allocator_type>::value,int> = 0>
auto binary_to_string(binary_data<Al>&& b){
auto binary_to_string(binary_data<Al>&& b)
noexcept(std::is_nothrow_default_constructible<Str>::value &&
noexcept(std::declval<Str>().reset(nullptr, 0)) &&
noexcept(b.release()))
{
Str s;
s.reset(b.get(), b.size());
b.release();
return s;
}
template<class Bin = rexy::binary, detail::enable_if_binary<Bin> = 0>
auto string_to_binary(const string_base& s){
auto string_to_binary(const string_base& s)
noexcept(std::is_nothrow_constructible<Bin, decltype(s.length())>::value &&
noexcept(std::declval<Bin>().append(nullptr, 0)))
{
Bin b(s.length()+1);
b.append(s.get(), s.length()+1);
return b;
}
template<class Al, class Bin = rexy::binary, detail::enable_if_binary<Bin> = 0, std::enable_if_t<std::is_same<std::decay_t<Al>,typename Bin::allocator_type>::value,int> = 0>
auto string_to_binary(string_intermediary<Al>&& s){
auto string_to_binary(string_intermediary<Al>&& s)
noexcept(std::is_nothrow_default_constructible<Bin>::value &&
noexcept(std::declval<Bin>().reset(nullptr, 0)) &&
noexcept(s.release()))
{
Bin b;
b.reset(s.get(), s.length()+1);
s.release();
return b;
}
template<class L, class R, detail::enable_if_binary<L> = 0, detail::enable_if_concrete_string<R> = 0>
decltype(auto) operator+=(L& l, R&& r){
decltype(auto) operator+=(L& l, R&& r)
noexcept(noexcept(l.append(nullptr, 0)))
{
l.append(r.get(), r.length()+1);
return l;
}
template<class L, class R, detail::enable_if_binary<L> = 0, detail::enable_if_string<R> = 0, std::enable_if_t<!detail::is_concrete_string<R>::value,int> = 0>
decltype(auto) operator+=(L& l, R&& r){
decltype(auto) operator+=(L& l, R&& r)
noexcept(std::is_nothrow_constructible<rexy::string,R&&>::value &&
std::is_nothrow_assignable<L,rexy::string>::value)
{
rexy::string concrete = r;
return (l = concrete);
}
template<class L, class R, detail::enable_if_concrete_string<L> = 0, detail::enable_if_binary<R> = 0>
decltype(auto) operator+=(L& l, R&& r){
decltype(auto) operator+=(L& l, R&& r)
noexcept(noexcept(l.resize(0, 0)))
{
l.resize(l.length(), r.size() + 1);
memcpy(l.get()+l.length()+1, r.get(), r.size());
return l;

View File

@ -25,6 +25,7 @@
#include "string.hpp"
#include "binary.hpp"
#include "cx/utility.hpp"
#include <type_traits>
namespace rexy{
@ -35,37 +36,37 @@ namespace rexy{
FILE* m_fp = nullptr;
public:
constexpr filerd(void) = default;
filerd(const char* f, const char* mode = "r");
constexpr filerd(void)noexcept = default;
filerd(const char* f, const char* mode = "r")noexcept;
filerd(const filerd&) = delete;
constexpr filerd(filerd&& f):
constexpr filerd(filerd&& f)noexcept:
m_fp(cx::exchange(f.m_fp, nullptr)){}
~filerd(void);
~filerd(void)noexcept;
filerd& operator=(const filerd&) = delete;
constexpr filerd& operator=(filerd&& f){
constexpr filerd& operator=(filerd&& f)noexcept{
cx::swap(m_fp, f.m_fp);
return *this;
}
void reset(FILE* fp = nullptr);
FILE* release(void);
size_t length(void);
size_t position(void)const;
void rewind(size_t pos = 0);
void reset(FILE* fp = nullptr)noexcept;
FILE* release(void)noexcept;
size_t length(void)noexcept;
size_t position(void)const noexcept;
void rewind(size_t pos = 0)noexcept;
operator FILE*(void);
operator const FILE*(void)const;
FILE* get(void);
const FILE* get(void)const;
operator bool(void)const;
operator FILE*(void)noexcept;
operator const FILE*(void)const noexcept;
FILE* get(void)noexcept;
const FILE* get(void)const noexcept;
operator bool(void)const noexcept;
size_t read(char* dest, size_t bytes);
rexy::string read(size_t bytes);
rexy::string readln(size_t max = 0);
rexy::binary read_bin(size_t bytes);
size_t read(char* dest, size_t bytes)noexcept;
rexy::string read(size_t bytes)noexcept;
rexy::string readln(size_t max = 0)noexcept;
rexy::binary read_bin(size_t bytes)noexcept(std::is_nothrow_constructible<rexy::binary, rexy::steal<char*>, size_t, size_t>::value);
size_t write(const char* c, size_t bytes);
size_t write(const rexy::string_base&);
size_t write(const char* c, size_t bytes)noexcept;
size_t write(const rexy::string_base&)noexcept;
};
}

View File

@ -21,6 +21,8 @@
#include <utility> //forward
#include <type_traits>
namespace rexy{
template<class T>
@ -31,7 +33,8 @@ namespace rexy{
public:
template<class U>
constexpr steal(U&& u):
constexpr steal(U&& u)
noexcept(std::is_nothrow_constructible<T,U&&>::value):
m_val(std::forward<U>(u)){}
steal(const steal&) = delete;
@ -39,10 +42,10 @@ namespace rexy{
steal& operator=(const steal&) = delete;
steal& operator=(steal&&) = delete;
constexpr T&& value(void){
constexpr T&& value(void)noexcept{
return std::forward<T>(m_val);
}
constexpr const T& value(void)const{
constexpr const T& value(void)const noexcept{
return m_val;
}
};

View File

@ -29,4 +29,8 @@ namespace rexy{
}
#ifdef REXY_BINARY_HPP
#include "detail/binary_string_conv.hpp"
#endif
#endif

View File

@ -22,6 +22,7 @@
#include <type_traits> //is_same, integral_contant, enable_if, etc
#include <utility> //forward
#include <cstdlib> //size_t
#include <cstring> //strlen
#include "steal.hpp"
#include "cx/utility.hpp"
@ -40,35 +41,36 @@ namespace rexy{
char* m_data = nullptr;
protected:
constexpr string_base(void) = default;
constexpr string_base(size_t len):
constexpr string_base(void)noexcept = default;
constexpr string_base(size_t len)noexcept:
m_cap(len){}
//Initialize without copying
constexpr string_base(char* data, size_t len):
constexpr string_base(char* data, size_t len)noexcept:
m_cap(len), m_data(data){}
constexpr string_base(char* data, size_t len, size_t cap):
constexpr string_base(char* data, size_t len, size_t cap)noexcept:
m_length(len), m_cap(cap), m_data(data){}
//Copy ctor (do nothing)
constexpr string_base(const string_base&){}
~string_base(void) = default;
constexpr string_base(const string_base&)noexcept{}
~string_base(void)noexcept = default;
public:
//Stop managing stored pointer. Does not free.
constexpr char* release(void){return cx::exchange(m_data, nullptr);}
constexpr char* release(void)noexcept(noexcept(cx::exchange(m_data, nullptr)))
{return cx::exchange(m_data, nullptr);}
//Length of string not including null terminator
constexpr size_t length(void)const{return m_length;}
constexpr size_t capacity(void)const{return m_cap;}
constexpr size_t length(void)const noexcept{return m_length;}
constexpr size_t capacity(void)const noexcept{return m_cap;}
//direct access to managed pointer
constexpr char* get(void){return m_data;}
constexpr const char* get(void)const{return m_data;}
constexpr operator char*(void){return m_data;}
constexpr operator const char*(void)const{return m_data;}
constexpr char* get(void)noexcept{return m_data;}
constexpr const char* get(void)const noexcept{return m_data;}
constexpr operator char*(void)noexcept{return m_data;}
constexpr operator const char*(void)const noexcept{return m_data;}
//true if m_data is not null
constexpr bool valid(void)const{return m_data;}
constexpr bool valid(void)const noexcept{return m_data;}
constexpr char& operator[](size_t i){return m_data[i];}
constexpr const char& operator[](size_t i)const{return m_data[i];}
constexpr char& operator[](size_t i)noexcept{return m_data[i];}
constexpr const char& operator[](size_t i)const noexcept{return m_data[i];}
};
@ -79,46 +81,56 @@ namespace rexy{
public:
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)));
public:
constexpr string_intermediary(void);
constexpr string_intermediary(rexy::steal<char*> data, size_t len);
constexpr string_intermediary(rexy::steal<char*> data, size_t len, size_t cap);
[[deprecated]] constexpr string_intermediary(char* data, size_t len);
string_intermediary(const char* data, size_t len);
[[deprecated]] constexpr string_intermediary(char* data, size_t len, size_t cap);
string_intermediary(const char* data);
constexpr string_intermediary(rexy::steal<char*>);
string_intermediary(size_t len);
string_intermediary(size_t len, size_t cap);
constexpr string_intermediary(void)noexcept;
constexpr string_intermediary(rexy::steal<char*> data, size_t len)noexcept;
constexpr string_intermediary(rexy::steal<char*> data, size_t len, size_t cap)noexcept;
constexpr string_intermediary(rexy::steal<char*> 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(size_t len)noexcept(noexcept(Allocator::allocate(len)));
string_intermediary(size_t len, size_t cap)noexcept(noexcept(Allocator::allocate(len)));
//normal copy and move ctors
string_intermediary(const string_intermediary& b);
constexpr string_intermediary(string_intermediary&& s);
string_intermediary(const string_intermediary& b)noexcept(noexcept(Allocator::copy(b.m_data, b.m_length)));
constexpr string_intermediary(string_intermediary&& s)noexcept(noexcept(cx::exchange(s.m_data, nullptr)));
string_intermediary(const string_base& b);
string_intermediary(const string_base& b)noexcept(noexcept(Allocator::copy(b.get(), b.length())));
//dtor
~string_intermediary(void);
~string_intermediary(void)noexcept(noexcept(Allocator::free(m_data)));
string_intermediary& operator=(const string_intermediary& s);
constexpr string_intermediary& operator=(string_intermediary&& s);
string_intermediary& operator=(const string_intermediary& s)
noexcept(std::is_nothrow_copy_constructible<string_intermediary<Allocator>>::value &&
std::is_nothrow_move_assignable<string_intermediary<Allocator>>::value);
constexpr string_intermediary& operator=(string_intermediary&& s)noexcept(noexcept(cx::swap(m_data, s.m_data)));
//Copy from c string
string_intermediary& operator=(const char* c);
string_intermediary& operator=(const char* c)noexcept(noexcept(_copy_string(c, 0)));
//Copy from other string_base
string_intermediary& operator=(const string_base& s);
string_intermediary& operator=(const string_base& s)noexcept(noexcept(_copy_string(s.get(), 0)));
//Replace managed pointer. Frees existing value
void reset(char* val = nullptr);
void reset(char* val, size_t len);
bool resize(size_t newsize);
void append(const char* data, size_t len);
void append(const char* data);
void append(const string_base& s);
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<string_intermediary<Allocator>>::value &&
std::is_nothrow_move_assignable<string_intermediary<Allocator>>::value);
void append(const char* data, size_t len)noexcept(std::is_nothrow_constructible<string_intermediary<Allocator>,decltype(m_length)>::value);
void append(const char* data)noexcept(std::is_nothrow_constructible<string_intermediary<Allocator>,decltype(m_length)>::value);
void append(const string_base& s)noexcept(std::is_nothrow_constructible<string_intermediary<Allocator>,decltype(m_length)>::value);
private:
string_intermediary& _copy_string(const char* s, size_t len);
};
namespace detail{
template<class T>
struct string_appender;
}
//Like an expression template but not really
template<class Left, class Right>
class string_cat_expr : public string_expr
@ -129,14 +141,18 @@ namespace rexy{
public:
template<class T, class U>
constexpr string_cat_expr(T&& l, U&& r);
constexpr string_cat_expr(string_cat_expr&& s);
constexpr string_cat_expr(T&& l, U&& r)noexcept(std::is_nothrow_constructible<Left,T&&>::value &&
std::is_nothrow_constructible<Right,U&&>::value);
constexpr string_cat_expr(string_cat_expr&& s)noexcept(std::is_nothrow_constructible<Left,decltype(s.m_l)>::value &&
std::is_nothrow_constructible<Right,decltype(s.m_r)>::value);
constexpr size_t length(void)const;
constexpr size_t length(void)const noexcept(noexcept(m_l.length()) && noexcept(m_r.length()));
template<class Alloc>
operator string_intermediary<Alloc>(void);
constexpr const Left& left(void)const;
constexpr const Right& right(void)const;
operator string_intermediary<Alloc>(void)
noexcept(std::is_nothrow_constructible<string_intermediary<Alloc>, size_t>::value &&
std::is_nothrow_invocable<detail::string_appender<string_intermediary<Alloc>>,decltype(*this)>::value);
constexpr const Left& left(void)const noexcept;
constexpr const Right& right(void)const noexcept;
};
template<class Left, class Right>
string_cat_expr(Left&, Right&) -> string_cat_expr<Left&,Right&>;
@ -153,16 +169,16 @@ namespace rexy{
class static_string : public string_base
{
public:
constexpr static_string(void) = default;
constexpr static_string(const char* str, size_t len);
constexpr static_string(const char* c);
constexpr static_string(const static_string& s);
constexpr static_string(static_string&& s);
~static_string(void) = default;
constexpr static_string(void)noexcept = default;
constexpr static_string(const char* str, size_t len)noexcept;
constexpr static_string(const char* c)noexcept;
constexpr static_string(const static_string& s)noexcept;
constexpr static_string(static_string&& s)noexcept;
~static_string(void)noexcept = default;
constexpr static_string& operator=(const char* c);
constexpr static_string& operator=(const static_string& s);
constexpr static_string& operator=(static_string&&);
constexpr static_string& operator=(const char* c)noexcept;
constexpr static_string& operator=(const static_string& s)noexcept;
constexpr static_string& operator=(static_string&&)noexcept;
};
@ -189,43 +205,55 @@ namespace rexy{
private:
Targ& m_targ;
public:
constexpr string_appender(Targ& t);
constexpr string_appender(Targ& t)noexcept;
template<class L, class R>
constexpr void operator()(const string_cat_expr<L,R>& str);
constexpr void operator()(const string_cat_expr<L,R>& str)
noexcept(noexcept((*this)(str.left())) && noexcept((*this)(str.right())));
template<class Str, std::enable_if_t<!rexy::is_template_type<Str,string_cat_expr>::value,int> = 0>
constexpr void operator()(Str&& str);
constexpr void operator()(Str&& str)noexcept(noexcept(m_targ.append(str.get(), str.length())));
};
} //namespace detail
template<class Str1, class Str2, detail::enable_if_concrete_string<Str1,Str2> = 0>
constexpr bool operator==(Str1&& left, Str2&& right){
constexpr bool operator==(Str1&& left, Str2&& right)noexcept{
return left.valid() && right.valid() && left.length() == right.length() && !cx::strcmp(left.get(), right.get());
}
template<class Str1, class Str2, detail::enable_if_concrete_string<Str1,Str2> = 0>
constexpr bool operator!=(Str1&& left, Str2&& right){
constexpr bool operator!=(Str1&& left, Str2&& right)noexcept{
return !(left == right);
}
template<class Left, class Right, detail::enable_if_string<Left,Right> = 0>
constexpr auto operator+(Left&& l, Right&& r){
constexpr auto operator+(Left&& l, Right&& r)
//uses deduction guide whereas std::is_nothrow_constructible couldn't
noexcept(noexcept(::new (nullptr) string_cat_expr(std::forward<Left>(l), std::forward<Right>(r))))
{
return string_cat_expr(std::forward<Left>(l), std::forward<Right>(r));
}
template<class Right, detail::enable_if_string<Right> = 0>
constexpr auto operator+(const char* left, Right&& right){
constexpr auto operator+(const char* left, Right&& right)
noexcept(noexcept(::new (nullptr) string_cat_expr(rexy::static_string(left), std::forward<Right>(right))))
{
return string_cat_expr(rexy::static_string(left), std::forward<Right>(right));
}
template<class Left, detail::enable_if_string<Left> = 0>
constexpr auto operator+(Left&& left, const char* right){
constexpr auto operator+(Left&& left, const char* right)
noexcept(noexcept(::new (nullptr) string_cat_expr(std::forward<Left>(left), rexy::static_string(right))))
{
return rexy::string_cat_expr(std::forward<Left>(left), rexy::static_string(right));
}
template<class Left, class Right, detail::enable_if_concrete_string<Left> = 0, detail::enable_if_string<Right> = 0>
decltype(auto) operator+=(Left& l, Right&& r){
decltype(auto) operator+=(Left& l, Right&& r)
noexcept(noexcept(l + std::forward<Right>(r)) && std::is_nothrow_assignable<Left, decltype(l + std::forward<Right>(r))>::value)
{
return l = (l + std::forward<Right>(r));
}
template<class Left, detail::enable_if_concrete_string<Left> = 0>
decltype(auto) operator+=(Left& l, const char* r){
decltype(auto) operator+=(Left& l, const char* r)
noexcept(noexcept(l + r) && std::is_nothrow_assignable<Left, decltype(l + r)>::value)
{
return l = (l + r);
}
}
@ -233,15 +261,11 @@ namespace rexy{
#include "string_base.tpp"
namespace{
constexpr inline rexy::static_string operator"" _ss(const char* str, size_t len){
constexpr inline rexy::static_string operator"" _ss(const char* str, size_t len)noexcept{
return rexy::static_string(str, len);
}
}
#ifdef REXY_BINARY_HPP
#include "detail/binary_string_conv.hpp"
#endif
#ifdef REXY_CX_HASH_HPP
#include "cx/string_hash.hpp"
#endif

View File

@ -30,27 +30,37 @@
namespace rexy{
template<class Allocator>
constexpr string_intermediary<Allocator>::string_intermediary(void){}
constexpr string_intermediary<Allocator>::string_intermediary(void)noexcept{}
template<class Allocator>
/*deprecated*/ constexpr string_intermediary<Allocator>::string_intermediary(char* data, size_t len):
string_base(data, len){}
constexpr string_intermediary<Allocator>::string_intermediary(rexy::steal<char*> data)noexcept:
string_base(data.value() ? cx::strlen(data.value()) : 0)
{
m_data = data.value();
m_length = m_cap;
}
template<class Allocator>
constexpr string_intermediary<Allocator>::string_intermediary(rexy::steal<char*> data, size_t len):
constexpr string_intermediary<Allocator>::string_intermediary(rexy::steal<char*> data, size_t len)noexcept:
string_base(data.value(), len){}
template<class Allocator>
/*deprecated*/ constexpr string_intermediary<Allocator>::string_intermediary(char* data, size_t len, size_t cap):
string_base(data, len, cap){}
template<class Allocator>
constexpr string_intermediary<Allocator>::string_intermediary(rexy::steal<char*> data, size_t len, size_t cap):
constexpr string_intermediary<Allocator>::string_intermediary(rexy::steal<char*> data, size_t len, size_t cap)noexcept:
string_base(data.value(), len, cap){}
template<class Allocator>
string_intermediary<Allocator>::string_intermediary(const char* data, size_t len):
/*deprecated*/ constexpr string_intermediary<Allocator>::string_intermediary(char* data, size_t len)noexcept:
string_base(data, len){}
template<class Allocator>
/*deprecated*/ constexpr string_intermediary<Allocator>::string_intermediary(char* data, size_t len, size_t cap)noexcept:
string_base(data, len, cap){}
template<class Allocator>
string_intermediary<Allocator>::string_intermediary(const char* data, size_t len)
noexcept(noexcept(Allocator::copy(data,len))):
string_base(reinterpret_cast<char*>(len ? Allocator::copy(data, len+1) : nullptr), len)
{
m_data[len] = 0;
}
template<class Allocator>
string_intermediary<Allocator>::string_intermediary(const char* data):
string_intermediary<Allocator>::string_intermediary(const char* data)
noexcept(noexcept(strlen(data)) &&
noexcept(Allocator::copy(data, m_cap))):
string_base(data ? strlen(data) : 0)
{
if(m_cap){
@ -59,20 +69,15 @@ namespace rexy{
}
}
template<class Allocator>
constexpr string_intermediary<Allocator>::string_intermediary(rexy::steal<char*> data):
string_base(data.value() ? cx::strlen(data.value()) : 0)
{
m_data = data.value();
m_length = m_cap;
}
template<class Allocator>
string_intermediary<Allocator>::string_intermediary(size_t len):
string_intermediary<Allocator>::string_intermediary(size_t len)
noexcept(noexcept(Allocator::allocate(len))):
string_base(reinterpret_cast<char*>(len ? Allocator::allocate(len+1) : nullptr), len)
{
m_data[len] = 0;
}
template<class Allocator>
string_intermediary<Allocator>::string_intermediary(size_t len, size_t cap):
string_intermediary<Allocator>::string_intermediary(size_t len, size_t cap)
noexcept(noexcept(Allocator::allocate(len))):
string_base(reinterpret_cast<char*>(len ? Allocator::allocate(len+1) : nullptr), len, cap)
{
m_data[len] = 0;
@ -80,24 +85,32 @@ namespace rexy{
//normal copy and move ctors
template<class Allocator>
string_intermediary<Allocator>::string_intermediary(const string_intermediary& b):
string_intermediary<Allocator>::string_intermediary(const string_intermediary& b)
noexcept(noexcept(Allocator::copy(b.m_data, b.m_length))):
string_base(reinterpret_cast<char*>(b.m_length ? Allocator::copy(b.m_data, b.m_length+1) : nullptr), b.m_length, b.m_cap){}
template<class Allocator>
constexpr string_intermediary<Allocator>::string_intermediary(string_intermediary&& s):
constexpr string_intermediary<Allocator>::string_intermediary(string_intermediary&& s)
noexcept(noexcept(cx::exchange(s.m_data, nullptr))):
string_base(cx::exchange(s.m_data, nullptr), s.m_length, s.m_cap){}
template<class Allocator>
string_intermediary<Allocator>::string_intermediary(const string_base& b):
string_intermediary<Allocator>::string_intermediary(const string_base& b)
noexcept(noexcept(Allocator::copy(b.get(), b.length()))):
string_base(reinterpret_cast<char*>(b.length() ? Allocator::copy(b.get(), b.length()+1) : nullptr), b.length(), b.capacity()){}
//dtor
template<class Allocator>
string_intermediary<Allocator>::~string_intermediary(void){
string_intermediary<Allocator>::~string_intermediary(void)
noexcept(noexcept(Allocator::free(m_data)))
{
Allocator::free(m_data);
}
template<class Allocator>
string_intermediary<Allocator>& string_intermediary<Allocator>::operator=(const string_intermediary& s){
string_intermediary<Allocator>& string_intermediary<Allocator>::operator=(const string_intermediary& s)
noexcept(std::is_nothrow_copy_constructible<string_intermediary<Allocator>>::value &&
std::is_nothrow_move_assignable<string_intermediary<Allocator>>::value)
{
if(s.m_length < m_length){
memcpy(m_data, s.m_data, s.m_length+1);
m_length = s.m_length;
@ -107,7 +120,9 @@ namespace rexy{
return (*this = std::move(tmp));
}
template<class Allocator>
constexpr string_intermediary<Allocator>& string_intermediary<Allocator>::operator=(string_intermediary&& s){
constexpr string_intermediary<Allocator>& string_intermediary<Allocator>::operator=(string_intermediary&& s)
noexcept(noexcept(cx::swap(m_data, s.m_data)))
{
cx::swap(m_data, s.m_data);
m_length = s.m_length;
m_cap = s.m_cap;
@ -115,32 +130,43 @@ namespace rexy{
}
//Copy from c string
template<class Allocator>
string_intermediary<Allocator>& string_intermediary<Allocator>::operator=(const char* c){
string_intermediary<Allocator>& string_intermediary<Allocator>::operator=(const char* c)
noexcept(noexcept(_copy_string(c, 0)))
{
return _copy_string(c, strlen(c));
}
//Copy from other string_base
template<class Allocator>
string_intermediary<Allocator>& string_intermediary<Allocator>::operator=(const string_base& s){
string_intermediary<Allocator>& string_intermediary<Allocator>::operator=(const string_base& s)
noexcept(noexcept(_copy_string(s.get(), 0)))
{
return _copy_string(s.get(), s.length());
}
//Replace managed pointer. Frees existing value
template<class Allocator>
void string_intermediary<Allocator>::reset(char* val){
void string_intermediary<Allocator>::reset(char* val)
noexcept(noexcept(Allocator::free(m_data)))
{
Allocator::free(m_data);
m_data = val;
m_length = val ? strlen(val) : 0;
m_cap = m_length;
}
template<class Allocator>
void string_intermediary<Allocator>::reset(char* val, size_t len){
void string_intermediary<Allocator>::reset(char* val, size_t len)
noexcept(noexcept(Allocator::free(m_data)))
{
Allocator::free(m_data);
m_data = val;
m_length = len;
m_cap = len;
}
template<class Allocator>
bool string_intermediary<Allocator>::resize(size_t newsize){
bool string_intermediary<Allocator>::resize(size_t newsize)
noexcept(std::is_nothrow_copy_constructible<string_intermediary<Allocator>>::value &&
std::is_nothrow_move_assignable<string_intermediary<Allocator>>::value)
{
if(newsize < m_cap)
return false;
string_intermediary tmp(newsize);
@ -152,7 +178,9 @@ namespace rexy{
return true;
}
template<class Allocator>
void string_intermediary<Allocator>::append(const char* data, size_t len){
void string_intermediary<Allocator>::append(const char* data, size_t len)
noexcept(std::is_nothrow_constructible<string_intermediary<Allocator>,decltype(m_length)>::value)
{
if(len+m_length <= m_cap){
memcpy(m_data+m_length, data, len);
m_length += len;
@ -160,25 +188,32 @@ namespace rexy{
}else{
string_intermediary tmp(cx::max(m_length + len, m_cap*2));
if(m_data)
memcpy(STOP_STRING_ALIASING_WARNING(tmp).m_data, m_data, m_length);
memcpy(STOP_STRING_ALIASING_WARNING(tmp).m_data+m_length, data, len);
STOP_STRING_ALIASING_WARNING(tmp).m_length = len+m_length;
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;
*this = std::move(tmp);
}
}
template<class Allocator>
void string_intermediary<Allocator>::append(const char* data){
void string_intermediary<Allocator>::append(const char* data)
noexcept(std::is_nothrow_constructible<string_intermediary<Allocator>,decltype(m_length)>::value)
{
if(data)
append(data, strlen(data));
}
template<class Allocator>
void string_intermediary<Allocator>::append(const string_base& s){
void string_intermediary<Allocator>::append(const string_base& s)
noexcept(std::is_nothrow_constructible<string_intermediary<Allocator>,decltype(m_length)>::value)
{
append(s.get(), s.length());
}
template<class Allocator>
string_intermediary<Allocator>& string_intermediary<Allocator>::_copy_string(const char* s, size_t len){
string_intermediary<Allocator>& string_intermediary<Allocator>::_copy_string(const char* s, size_t len)
noexcept(noexcept(Allocator::free(m_data)) &&
noexcept(Allocator::copy(s, len)))
{
if(!len){
Allocator::free(m_data);
m_length = 0;
@ -204,21 +239,30 @@ namespace rexy{
template<class Left, class Right>
template<class T, class U>
constexpr string_cat_expr<Left,Right>::string_cat_expr(T&& l, U&& r):
constexpr string_cat_expr<Left,Right>::string_cat_expr(T&& l, U&& r)
noexcept(std::is_nothrow_constructible<Left,T&&>::value &&
std::is_nothrow_constructible<Right,U&&>::value):
m_l(std::forward<T>(l)),
m_r(std::forward<U>(r)){}
template<class Left, class Right>
constexpr string_cat_expr<Left,Right>::string_cat_expr(string_cat_expr&& s):
constexpr string_cat_expr<Left,Right>::string_cat_expr(string_cat_expr&& s)
noexcept(std::is_nothrow_constructible<Left,decltype(s.m_l)>::value &&
std::is_nothrow_constructible<Right,decltype(s.m_r)>::value):
m_l(std::forward<Left>(s.m_l)),
m_r(std::forward<Right>(s.m_r)){}
template<class Left, class Right>
constexpr size_t string_cat_expr<Left,Right>::length(void)const{
constexpr size_t string_cat_expr<Left,Right>::length(void)const
noexcept(noexcept(m_l.length()) && noexcept(m_r.length()))
{
return m_l.length() + m_r.length();
}
template<class Left, class Right>
template<class Alloc>
string_cat_expr<Left,Right>::operator string_intermediary<Alloc>(void){
string_cat_expr<Left,Right>::operator string_intermediary<Alloc>(void)
noexcept(std::is_nothrow_constructible<string_intermediary<Alloc>, size_t>::value &&
std::is_nothrow_invocable<detail::string_appender<string_intermediary<Alloc>>,decltype(*this)>::value)
{
size_t len = length();
string_intermediary<Alloc> ret(len);
detail::string_appender<string_intermediary<Alloc>> append(ret);
@ -226,34 +270,34 @@ namespace rexy{
return ret;
}
template<class Left, class Right>
constexpr const Left& string_cat_expr<Left,Right>::left(void)const{
constexpr const Left& string_cat_expr<Left,Right>::left(void)const noexcept{
return m_l;
}
template<class Left, class Right>
constexpr const Right& string_cat_expr<Left,Right>::right(void)const{
constexpr const Right& string_cat_expr<Left,Right>::right(void)const noexcept{
return m_r;
}
constexpr static_string::static_string(const char* str, size_t len):
constexpr static_string::static_string(const char* str, size_t len)noexcept:
string_base(const_cast<char*>(str), len, len){}
constexpr static_string::static_string(const static_string& s):
constexpr static_string::static_string(const static_string& s)noexcept:
string_base(s.m_data, s.m_length, s.m_length){}
constexpr static_string::static_string(static_string&& s):
constexpr static_string::static_string(static_string&& s)noexcept:
string_base(s.m_data, s.m_length, s.m_length){}
constexpr static_string& static_string::operator=(const static_string& s){
constexpr static_string& static_string::operator=(const static_string& s)noexcept{
m_data = s.m_data;
m_length = s.m_length;
return *this;
}
constexpr static_string::static_string(const char* c):
constexpr static_string::static_string(const char* c)noexcept:
static_string(const_cast<char*>(c), cx::strlen(c)){}
constexpr static_string& static_string::operator=(const char* c){
constexpr static_string& static_string::operator=(const char* c)noexcept{
m_data = const_cast<char*>(c);
m_length = cx::strlen(c);
return *this;
}
constexpr static_string& static_string::operator=(static_string&& s){
constexpr static_string& static_string::operator=(static_string&& s)noexcept{
m_data = s.m_data;
m_length = s.m_length;
return *this;
@ -261,16 +305,20 @@ namespace rexy{
namespace detail{
template<class Targ>
constexpr string_appender<Targ>::string_appender(Targ& t): m_targ(t){}
constexpr string_appender<Targ>::string_appender(Targ& t)noexcept: m_targ(t){}
template<class Targ>
template<class L, class R>
constexpr void string_appender<Targ>::operator()(const string_cat_expr<L,R>& str){
constexpr void string_appender<Targ>::operator()(const string_cat_expr<L,R>& str)
noexcept(noexcept((*this)(str.left())) && noexcept((*this)(str.right())))
{
(*this)(str.left());
(*this)(str.right());
}
template<class Targ>
template<class Str, std::enable_if_t<!rexy::is_template_type<Str,string_cat_expr>::value,int>>
constexpr void string_appender<Targ>::operator()(Str&& str){
constexpr void string_appender<Targ>::operator()(Str&& str)
noexcept(noexcept(m_targ.append(str.get(), str.length())))
{
m_targ.append(str.get(), str.length());
}
}

View File

@ -20,11 +20,6 @@
namespace rexy{
binary_base::binary_base(binary_base&& b):
m_data(std::exchange(b.m_data, nullptr)),
m_size(b.m_size),
m_cap(b.m_cap){}
char* binary_base::release(void){
return std::exchange(m_data, nullptr);
}

View File

@ -1,13 +1,21 @@
//Never actually used in the project. This just ensures that all syntax is correct during builds.
#include "rexy/string.hpp"
#include "rexy/binary.hpp"
#include "rexy/filerd.hpp"
#include "rexy/steal.hpp"
#include "rexy/string_base.hpp"
#include "rexy/string_base.tpp"
#include "rexy/string.hpp"
#include "rexy/traits.hpp"
#include "rexy/detail/binary_string_conv.hpp"
#include "rexy/detail/default_allocator.hpp"
#include "rexy/cx/algorithm.hpp"
#include "rexy/cx/array.hpp"
#include "rexy/cx/hash.hpp"
#include "rexy/cx/hashmap.hpp"
#include "rexy/cx/string_hash.hpp"
#include "rexy/cx/string.hpp"
#include "rexy/cx/utility.hpp"
#include "rexy/cx/vector.hpp"
#include "rexy/cx/array.hpp"
#include "rexy/cx/hashmap.hpp"
#include "rexy/cx/array.hpp"
#include "rexy/cx/vector.hpp"

View File

@ -20,25 +20,26 @@
#include <cstdio> //fopen, fclose
#include <utility> //exchange, swap
#include <type_traits>
namespace rexy{
filerd::filerd(const char* f, const char* mode):
filerd::filerd(const char* f, const char* mode)noexcept:
m_fp(fopen(f, mode)){}
filerd::~filerd(void){
filerd::~filerd(void)noexcept{
if(m_fp)
fclose(m_fp);
}
void filerd::reset(FILE* fp){
void filerd::reset(FILE* fp)noexcept{
if(m_fp)
fclose(m_fp);
m_fp = fp;
}
FILE* filerd::release(void){
FILE* filerd::release(void)noexcept{
return std::exchange(m_fp, nullptr);
}
size_t filerd::length(void){
size_t filerd::length(void)noexcept{
if(!m_fp)
return 0;
size_t tmp, ret;
@ -48,38 +49,38 @@ namespace rexy{
fseek(m_fp, tmp, SEEK_SET);
return ret;
}
size_t filerd::position(void)const{
size_t filerd::position(void)const noexcept{
return ftell(m_fp);
}
void filerd::rewind(size_t pos){
void filerd::rewind(size_t pos)noexcept{
fseek(m_fp, pos, SEEK_SET);
}
filerd::operator FILE*(void){
filerd::operator FILE*(void)noexcept{
return m_fp;
}
filerd::operator const FILE*(void)const{
filerd::operator const FILE*(void)const noexcept{
return m_fp;
}
FILE* filerd::get(void){
FILE* filerd::get(void)noexcept{
return m_fp;
}
const FILE* filerd::get(void)const{
const FILE* filerd::get(void)const noexcept{
return m_fp;
}
filerd::operator bool(void)const{
filerd::operator bool(void)const noexcept{
return m_fp;
}
size_t filerd::read(char* dest, size_t bytes){
size_t filerd::read(char* dest, size_t bytes)noexcept{
return fread(dest, 1, bytes, m_fp);
}
rexy::string filerd::read(size_t bytes){
rexy::string filerd::read(size_t bytes)noexcept{
char* tmp = reinterpret_cast<char*>(rexy::string::allocator_type::allocate(bytes));
size_t written = read(tmp, bytes);
return rexy::string(rexy::steal(tmp), written);
}
rexy::string filerd::readln(size_t max){
rexy::string filerd::readln(size_t max)noexcept{
rexy::string ret;
char c;
size_t count = 0;
@ -90,15 +91,17 @@ namespace rexy{
}
return ret;
}
rexy::binary filerd::read_bin(size_t bytes){
rexy::binary filerd::read_bin(size_t bytes)
noexcept(std::is_nothrow_constructible<rexy::binary, rexy::steal<char*>, size_t, size_t>::value)
{
char* tmp = reinterpret_cast<char*>(rexy::binary::allocator_type::allocate(bytes));
size_t written = read(tmp, bytes);
return rexy::binary(rexy::steal(tmp), written, written);
}
size_t filerd::write(const char* c, size_t bytes){
size_t filerd::write(const char* c, size_t bytes)noexcept{
return fwrite(c, 1, bytes, m_fp);
}
size_t filerd::write(const rexy::string_base& c){
size_t filerd::write(const rexy::string_base& c)noexcept{
return write(c.get(), c.length());
}