Add noexcept specs to all the things
This commit is contained in:
parent
b97e7d7c1b
commit
daac14dddf
@ -39,18 +39,14 @@ namespace rexy{
|
|||||||
size_t m_cap = 0;
|
size_t m_cap = 0;
|
||||||
public:
|
public:
|
||||||
protected:
|
protected:
|
||||||
constexpr binary_base(void) = default;
|
constexpr binary_base(void)noexcept = default;
|
||||||
constexpr binary_base(char* data, size_t size):
|
constexpr binary_base(char* data, size_t size)noexcept:
|
||||||
m_data(data), m_cap(size){}
|
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){}
|
m_data(data), m_size(size), m_cap(cap){}
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
binary_base(const binary_base& b):
|
binary_base(const binary_base& b)noexcept{}
|
||||||
m_data(Allocator::copy(b.m_data, b.m_cap)),
|
~binary_base(void)noexcept = default;
|
||||||
m_size(b.m_size),
|
|
||||||
m_cap(b.m_cap){}
|
|
||||||
binary_base(binary_base&&);
|
|
||||||
~binary_base(void) = default;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
char* release(void);
|
char* release(void);
|
||||||
@ -71,64 +67,83 @@ namespace rexy{
|
|||||||
public:
|
public:
|
||||||
using allocator_type = Allocator;
|
using allocator_type = Allocator;
|
||||||
public:
|
public:
|
||||||
constexpr binary_data(void) = default;
|
constexpr binary_data(void)noexcept = default;
|
||||||
[[deprecated]] binary_data(char* data, size_t size):
|
[[deprecated]] binary_data(char* data, size_t size)noexcept:
|
||||||
binary_base(data, size){}
|
binary_base(data, size){}
|
||||||
binary_data(rexy::steal<char*> data, size_t size):
|
[[deprecated]] binary_data(char* data, size_t cap, size_t size)noexcept:
|
||||||
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):
|
|
||||||
binary_base(data, cap, size){}
|
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_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_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_base(reinterpret_cast<char*>(Allocator::allocate(size)), size){}
|
||||||
binary_data(const binary_data& b):
|
binary_data(const binary_data& b)
|
||||||
binary_base(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);
|
m_data = Allocator::copy(b.m_data, b.m_cap);
|
||||||
}
|
}
|
||||||
binary_data(binary_data&& b):
|
constexpr binary_data(binary_data&& b)noexcept:
|
||||||
binary_base(std::move(b)){}
|
binary_base(cx::exchange(b.m_data, nullptr), b.m_cap, b.m_size){}
|
||||||
~binary_data(void){
|
~binary_data(void)
|
||||||
|
noexcept(noexcept(Allocator::free(m_data)))
|
||||||
|
{
|
||||||
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);
|
binary_data<allocator_type> tmp(b);
|
||||||
return (*this = std::move(tmp));
|
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_size = b.m_size;
|
||||||
m_cap = b.m_cap;
|
m_cap = b.m_cap;
|
||||||
std::swap(m_data, b.m_data);
|
cx::swap(m_data, b.m_data);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
void reset(void){
|
void reset(void)
|
||||||
|
noexcept(noexcept(Allocator::free(m_data)))
|
||||||
|
{
|
||||||
Allocator::free(m_data);
|
Allocator::free(m_data);
|
||||||
m_data = nullptr;
|
m_data = nullptr;
|
||||||
m_cap = m_size = 0;
|
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);
|
Allocator::free(m_data);
|
||||||
m_data = val;
|
m_data = val;
|
||||||
m_cap = cap;
|
m_cap = cap;
|
||||||
m_size = size;
|
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)
|
if(newsize < m_cap)
|
||||||
return false;
|
return false;
|
||||||
binary_data<allocator_type> tmp(newsize);
|
binary_data<allocator_type> tmp(newsize);
|
||||||
if(!tmp)
|
if(!tmp)
|
||||||
return false;
|
return false;
|
||||||
memcpy(STOP_STRICT_ALIAS_WARNING(tmp).m_data, m_data, m_size);
|
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;
|
m_cap = STOP_STRICT_ALIAS_WARNING(tmp).m_cap;
|
||||||
return true;
|
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)
|
if(m_size + len > m_cap)
|
||||||
resize(cx::max(m_cap*2, m_size+len));
|
resize(cx::max(m_cap*2, m_size+len));
|
||||||
memcpy(m_data+m_size, data, 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>
|
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());
|
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>
|
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));
|
return !(std::forward<Left>(l) == std::forward<Right>(r));
|
||||||
}
|
}
|
||||||
template<class All, class Alr>
|
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());
|
rexy::binary_data<All> retval(l.size() + r.size());
|
||||||
memcpy(retval.get(), l.get(), l.size());
|
memcpy(retval.get(), l.get(), l.size());
|
||||||
memcpy(retval.get()+l.size(), r.get(), r.size());
|
memcpy(retval.get()+l.size(), r.get(), r.size());
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
template<class All, class Alr>
|
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());
|
l.resize(l.size() + r.size());
|
||||||
memcpy(l.get()+l.size(), r.get(), r.size());
|
memcpy(l.get()+l.size(), r.get(), r.size());
|
||||||
return l;
|
return l;
|
||||||
|
|||||||
@ -21,10 +21,15 @@
|
|||||||
|
|
||||||
#include "utility.hpp" //swap
|
#include "utility.hpp" //swap
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
namespace rexy::cx{
|
namespace rexy::cx{
|
||||||
|
|
||||||
template<class Iter, class Compare>
|
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 range = right - left;
|
||||||
auto pivot = left + (range / 2);
|
auto pivot = left + (range / 2);
|
||||||
auto value = *pivot;
|
auto value = *pivot;
|
||||||
@ -42,7 +47,9 @@ namespace rexy::cx{
|
|||||||
return left;
|
return left;
|
||||||
}
|
}
|
||||||
template<class Iter, class Compare>
|
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){
|
while(left < right){
|
||||||
auto real_right = right-1;
|
auto real_right = right-1;
|
||||||
auto pivot = qs_partition(left, real_right, cmp);
|
auto pivot = qs_partition(left, real_right, cmp);
|
||||||
|
|||||||
@ -22,6 +22,8 @@
|
|||||||
#include <cstddef> //size_t
|
#include <cstddef> //size_t
|
||||||
#include "utility.hpp" //swap
|
#include "utility.hpp" //swap
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
namespace rexy::cx{
|
namespace rexy::cx{
|
||||||
|
|
||||||
template<class T, size_t N>
|
template<class T, size_t N>
|
||||||
@ -44,76 +46,80 @@ namespace rexy::cx{
|
|||||||
T m_elements[N] = {};
|
T m_elements[N] = {};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
constexpr reference at(size_type pos){
|
constexpr reference at(size_type pos)noexcept{
|
||||||
return m_elements[pos];
|
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];
|
return m_elements[pos];
|
||||||
}
|
}
|
||||||
constexpr reference operator[](size_type pos){
|
constexpr reference operator[](size_type pos)noexcept{
|
||||||
return m_elements[pos];
|
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];
|
return m_elements[pos];
|
||||||
}
|
}
|
||||||
constexpr reference front(void){
|
constexpr reference front(void)noexcept{
|
||||||
return m_elements[0];
|
return m_elements[0];
|
||||||
}
|
}
|
||||||
constexpr const_reference front(void)const{
|
constexpr const_reference front(void)const noexcept{
|
||||||
return m_elements[0];
|
return m_elements[0];
|
||||||
}
|
}
|
||||||
constexpr reference back(void){
|
constexpr reference back(void)noexcept{
|
||||||
return m_elements[max_elements-1];
|
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];
|
return m_elements[max_elements-1];
|
||||||
}
|
}
|
||||||
constexpr pointer data(void){
|
constexpr pointer data(void)noexcept{
|
||||||
return m_elements;
|
return m_elements;
|
||||||
}
|
}
|
||||||
constexpr const_pointer data(void)const{
|
constexpr const_pointer data(void)const noexcept{
|
||||||
return m_elements;
|
return m_elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr iterator begin(void){
|
constexpr iterator begin(void)noexcept{
|
||||||
return m_elements;
|
return m_elements;
|
||||||
}
|
}
|
||||||
constexpr const_iterator begin(void)const{
|
constexpr const_iterator begin(void)const noexcept{
|
||||||
return m_elements;
|
return m_elements;
|
||||||
}
|
}
|
||||||
constexpr const_iterator cbegin(void)const{
|
constexpr const_iterator cbegin(void)const noexcept{
|
||||||
return m_elements;
|
return m_elements;
|
||||||
}
|
}
|
||||||
constexpr iterator end(void){
|
constexpr iterator end(void)noexcept{
|
||||||
return m_elements+max_elements;
|
return m_elements+max_elements;
|
||||||
}
|
}
|
||||||
constexpr const_iterator end(void)const{
|
constexpr const_iterator end(void)const noexcept{
|
||||||
return m_elements+max_elements;
|
return m_elements+max_elements;
|
||||||
}
|
}
|
||||||
constexpr const_iterator cend(void)const{
|
constexpr const_iterator cend(void)const noexcept{
|
||||||
return m_elements+max_elements;
|
return m_elements+max_elements;
|
||||||
}
|
}
|
||||||
constexpr bool empty(void)const{
|
constexpr bool empty(void)const noexcept{
|
||||||
if constexpr(max_elements == 0){
|
if constexpr(max_elements == 0){
|
||||||
return true;
|
return true;
|
||||||
}else{
|
}else{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
constexpr size_type size(void)const{
|
constexpr size_type size(void)const noexcept{
|
||||||
return max_elements;
|
return max_elements;
|
||||||
}
|
}
|
||||||
constexpr size_type max_size(void)const{
|
constexpr size_type max_size(void)const noexcept{
|
||||||
return max_elements;
|
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){
|
for(auto it = begin();it != end();++it){
|
||||||
*it = value;
|
*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){
|
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]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -25,7 +25,7 @@ namespace rexy::cx{
|
|||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
struct hash{
|
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);
|
constexpr size_t bytes = sizeof(size_t);
|
||||||
size_t val = static_cast<size_t>(t);
|
size_t val = static_cast<size_t>(t);
|
||||||
size_t hash = 5381 + salt; //magic hash number
|
size_t hash = 5381 + salt; //magic hash number
|
||||||
|
|||||||
@ -73,9 +73,9 @@ namespace rexy::cx{
|
|||||||
|
|
||||||
//no key checks. give a correct key or get a random answer :)
|
//no key checks. give a correct key or get a random answer :)
|
||||||
template<class U, class UHash = hash<std::decay_t<U>>>
|
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>>>
|
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>
|
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
|
//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();
|
return left.size() > right.size();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -148,7 +148,7 @@ namespace rexy::cx{
|
|||||||
//no key checks. give a correct key or get a random answer :)
|
//no key checks. give a correct key or get a random answer :)
|
||||||
template<class Key, class Value, size_t N, class Hash>
|
template<class Key, class Value, size_t N, class Hash>
|
||||||
template<class U, class UHash>
|
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];
|
auto d = m_g[UHash{}(std::forward<U>(key)) % max_size];
|
||||||
if(d & single_bucket_bit)
|
if(d & single_bucket_bit)
|
||||||
return m_values[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 Key, class Value, size_t N, class Hash>
|
||||||
template<class U, class UHash>
|
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];
|
auto d = m_g[UHash{}(std::forward<U>(key)) % max_size];
|
||||||
if(d & single_bucket_bit)
|
if(d & single_bucket_bit)
|
||||||
return m_values[d & ~single_bucket_bit];
|
return m_values[d & ~single_bucket_bit];
|
||||||
|
|||||||
@ -26,7 +26,7 @@ namespace rexy::cx{
|
|||||||
|
|
||||||
#include "../string_base.hpp"
|
#include "../string_base.hpp"
|
||||||
#include "utility.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 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
|
//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:
|
public:
|
||||||
constexpr string(void) = default;
|
constexpr string(void) = default;
|
||||||
template<size_t M>
|
template<size_t M>
|
||||||
constexpr string(const char(&data)[M]):
|
constexpr string(const char(&data)[M])noexcept:
|
||||||
m_length(M)
|
m_length(M)
|
||||||
{
|
{
|
||||||
static_assert(M <= N);
|
static_assert(M <= N);
|
||||||
@ -54,14 +54,14 @@ namespace rexy::cx{
|
|||||||
m_data[i] = data[i];
|
m_data[i] = data[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
constexpr string(const char* data):
|
constexpr string(const char* data)noexcept:
|
||||||
m_length(cx::strlen(data))
|
m_length(cx::strlen(data))
|
||||||
{
|
{
|
||||||
for(size_t i = 0;i < m_length;++i){
|
for(size_t i = 0;i < m_length;++i){
|
||||||
m_data[i] = data[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)
|
m_length(len)
|
||||||
{
|
{
|
||||||
for(size_t i = 0;i < m_length;++i){
|
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())
|
m_length(str.length())
|
||||||
{
|
{
|
||||||
for(size_t i = 0;i < m_length;++i){
|
for(size_t i = 0;i < m_length;++i){
|
||||||
@ -77,56 +77,58 @@ namespace rexy::cx{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
template<class Left, class Right>
|
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);
|
rexy::detail::string_appender<cx::string<N>> append(*this);
|
||||||
append(expr);
|
append(expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr string(const string&) = default;
|
constexpr string(const string&)noexcept = default;
|
||||||
constexpr string(string&&) = default;
|
constexpr string(string&&)noexcept = default;
|
||||||
~string(void) = default;
|
~string(void)noexcept = default;
|
||||||
|
|
||||||
constexpr string& operator=(const char* c){
|
constexpr string& operator=(const char* c)noexcept{
|
||||||
m_length = cx::strlen(c);
|
m_length = cx::strlen(c);
|
||||||
for(size_t i = 0;i < m_length;++i){
|
for(size_t i = 0;i < m_length;++i){
|
||||||
m_data[i] = c[i];
|
m_data[i] = c[i];
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
constexpr string& operator=(const string&) = default;
|
constexpr string& operator=(const string&)noexcept = default;
|
||||||
constexpr string& operator=(string&&) = default;
|
constexpr string& operator=(string&&)noexcept = default;
|
||||||
|
|
||||||
|
|
||||||
constexpr size_t length(void)const{
|
constexpr size_t length(void)const noexcept{
|
||||||
return m_length;
|
return m_length;
|
||||||
}
|
}
|
||||||
constexpr size_t capacity(void)const{
|
constexpr size_t capacity(void)const noexcept{
|
||||||
return max_size;
|
return max_size;
|
||||||
}
|
}
|
||||||
constexpr char* get(void){
|
constexpr char* get(void)noexcept{
|
||||||
return m_data;
|
return m_data;
|
||||||
}
|
}
|
||||||
constexpr const char* get(void)const{
|
constexpr const char* get(void)const noexcept{
|
||||||
return m_data;
|
return m_data;
|
||||||
}
|
}
|
||||||
constexpr operator char*(void){
|
constexpr operator char*(void)noexcept{
|
||||||
return m_data;
|
return m_data;
|
||||||
}
|
}
|
||||||
constexpr operator const char*(void)const{
|
constexpr operator const char*(void)const noexcept{
|
||||||
return m_data;
|
return m_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr bool valid(void)const{
|
constexpr bool valid(void)const noexcept{
|
||||||
return m_length > 0;
|
return m_length > 0;
|
||||||
}
|
}
|
||||||
constexpr char& operator[](size_t i){
|
constexpr char& operator[](size_t i)noexcept{
|
||||||
return m_data[i];
|
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];
|
return m_data[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr bool resize(size_t i){
|
constexpr bool resize(size_t i)noexcept{
|
||||||
if(i >= capacity())
|
if(i >= capacity())
|
||||||
return false;
|
return false;
|
||||||
m_length = i;
|
m_length = i;
|
||||||
@ -134,18 +136,18 @@ namespace rexy::cx{
|
|||||||
return true;
|
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){
|
for(size_t i = 0;i < len;++i){
|
||||||
m_data[m_length++] = data[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));
|
append(data, cx::strlen(data));
|
||||||
}
|
}
|
||||||
constexpr void append(const string& s){
|
constexpr void append(const string& s)noexcept{
|
||||||
append(s.get(), s.length());
|
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());
|
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>
|
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));
|
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>
|
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));
|
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>
|
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));
|
return string_cat_expr(rexy::static_string(l), std::forward<Str1>(r));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,7 +28,7 @@ namespace rexy::cx{
|
|||||||
//jenkns one at a time hash
|
//jenkns one at a time hash
|
||||||
template<class Str>
|
template<class Str>
|
||||||
struct string_hash{
|
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;
|
size_t hash = salt;
|
||||||
for(size_t i = 0;i < s.length();++i){
|
for(size_t i = 0;i < s.length();++i){
|
||||||
hash += s[i];
|
hash += s[i];
|
||||||
|
|||||||
@ -20,45 +20,55 @@
|
|||||||
#define REXY_CX_UTILITY_HPP
|
#define REXY_CX_UTILITY_HPP
|
||||||
|
|
||||||
#include <utility> //forward, move
|
#include <utility> //forward, move
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
namespace rexy::cx{
|
namespace rexy::cx{
|
||||||
|
|
||||||
namespace{
|
namespace{
|
||||||
template<class T>
|
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;
|
T tmp = l;
|
||||||
l = r;
|
l = r;
|
||||||
r = tmp;
|
r = tmp;
|
||||||
}
|
}
|
||||||
template<class T, class U = T>
|
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);
|
T old = std::move(l);
|
||||||
l = std::forward<U>(r);
|
l = std::forward<U>(r);
|
||||||
return old;
|
return old;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
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;
|
return l < r ? l : r;
|
||||||
}
|
}
|
||||||
template<class T, class Compare>
|
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;
|
return cmp(l, r) ? l : r;
|
||||||
}
|
}
|
||||||
template<class T>
|
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;
|
return l > r ? l : r;
|
||||||
}
|
}
|
||||||
template<class T, class Compare>
|
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;
|
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;
|
size_t i = 0;
|
||||||
for(;c[i];++i);
|
for(;c[i];++i);
|
||||||
return 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;
|
using uchar = unsigned char;
|
||||||
for(;*l == *r && *l;++l, ++r);
|
for(;*l == *r && *l;++l, ++r);
|
||||||
return (static_cast<uchar>(*l)) - (static_cast<uchar>(*r));
|
return (static_cast<uchar>(*l)) - (static_cast<uchar>(*r));
|
||||||
|
|||||||
@ -24,6 +24,8 @@
|
|||||||
|
|
||||||
#include "utility.hpp" //swap
|
#include "utility.hpp" //swap
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
namespace rexy::cx{
|
namespace rexy::cx{
|
||||||
|
|
||||||
template<class T, size_t N>
|
template<class T, size_t N>
|
||||||
@ -47,83 +49,88 @@ namespace rexy::cx{
|
|||||||
size_type m_size = 0;
|
size_type m_size = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
constexpr vector(void) = default;
|
constexpr vector(void)noexcept(std::is_nothrow_default_constructible<T>::value) = default;
|
||||||
constexpr vector(const vector&) = default;
|
constexpr vector(const vector&)noexcept(std::is_nothrow_copy_constructible<T>::value) = default;
|
||||||
constexpr vector(vector&&) = 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){
|
for(size_type i = 0;i < min(count, max_elements);++i){
|
||||||
m_elements[i] = value;
|
m_elements[i] = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
~vector(void) = default;
|
~vector(void)noexcept = default;
|
||||||
|
|
||||||
constexpr vector& operator=(const vector&) = default;
|
constexpr vector& operator=(const vector&)noexcept(std::is_nothrow_copy_assignable<T>::value) = default;
|
||||||
constexpr vector& operator=(vector&&) = 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];
|
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];
|
return m_elements[pos];
|
||||||
}
|
}
|
||||||
constexpr reference operator[](size_type pos){
|
constexpr reference operator[](size_type pos)noexcept{
|
||||||
return m_elements[pos];
|
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];
|
return m_elements[pos];
|
||||||
}
|
}
|
||||||
constexpr reference front(void){
|
constexpr reference front(void)noexcept{
|
||||||
return m_elements[0];
|
return m_elements[0];
|
||||||
}
|
}
|
||||||
constexpr const_reference front(void)const{
|
constexpr const_reference front(void)const noexcept{
|
||||||
return m_elements[0];
|
return m_elements[0];
|
||||||
}
|
}
|
||||||
constexpr reference back(void){
|
constexpr reference back(void)noexcept{
|
||||||
return m_elements[m_size-1];
|
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];
|
return m_elements[m_size-1];
|
||||||
}
|
}
|
||||||
constexpr const_pointer data(void)const{
|
constexpr const_pointer data(void)const noexcept{
|
||||||
return m_elements;
|
return m_elements;
|
||||||
}
|
}
|
||||||
constexpr iterator begin(void){
|
constexpr iterator begin(void)noexcept{
|
||||||
return m_elements;
|
return m_elements;
|
||||||
}
|
}
|
||||||
constexpr const_iterator begin(void)const{
|
constexpr const_iterator begin(void)const noexcept{
|
||||||
return m_elements;
|
return m_elements;
|
||||||
}
|
}
|
||||||
constexpr const_iterator cbegin(void)const{
|
constexpr const_iterator cbegin(void)const noexcept{
|
||||||
return m_elements;
|
return m_elements;
|
||||||
}
|
}
|
||||||
constexpr iterator end(void){
|
constexpr iterator end(void)noexcept{
|
||||||
return m_elements+max_elements;
|
return m_elements+max_elements;
|
||||||
}
|
}
|
||||||
constexpr const_iterator end(void)const{
|
constexpr const_iterator end(void)const noexcept{
|
||||||
return m_elements+max_elements;
|
return m_elements+max_elements;
|
||||||
}
|
}
|
||||||
constexpr const_iterator cend(void)const{
|
constexpr const_iterator cend(void)const noexcept{
|
||||||
return m_elements+max_elements;
|
return m_elements+max_elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr bool empty(void)const{
|
constexpr bool empty(void)const noexcept{
|
||||||
return m_size == 0;
|
return m_size == 0;
|
||||||
}
|
}
|
||||||
constexpr size_type size(void)const{
|
constexpr size_type size(void)const noexcept{
|
||||||
return m_size;
|
return m_size;
|
||||||
}
|
}
|
||||||
constexpr size_type max_size(void)const{
|
constexpr size_type max_size(void)const noexcept{
|
||||||
return max_elements;
|
return max_elements;
|
||||||
}
|
}
|
||||||
constexpr size_type capacity(void)const{
|
constexpr size_type capacity(void)const noexcept{
|
||||||
return max_elements;
|
return max_elements;
|
||||||
}
|
}
|
||||||
constexpr void clear(void){
|
constexpr void clear(void)noexcept{
|
||||||
m_size = 0;
|
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 start = pos;
|
||||||
auto it = pos;
|
auto it = pos;
|
||||||
++pos;
|
++pos;
|
||||||
@ -133,7 +140,9 @@ namespace rexy::cx{
|
|||||||
*start = value;
|
*start = value;
|
||||||
return start;
|
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 start = pos;
|
||||||
auto it = pos;
|
auto it = pos;
|
||||||
++pos;
|
++pos;
|
||||||
@ -144,7 +153,10 @@ namespace rexy::cx{
|
|||||||
return start;
|
return start;
|
||||||
}
|
}
|
||||||
template<class... Args>
|
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 start = pos;
|
||||||
auto it = pos;
|
auto it = pos;
|
||||||
++pos;
|
++pos;
|
||||||
@ -154,7 +166,9 @@ namespace rexy::cx{
|
|||||||
*start = T{std::forward<Args>(args)...};
|
*start = T{std::forward<Args>(args)...};
|
||||||
return start;
|
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 start = pos;
|
||||||
auto it = pos;
|
auto it = pos;
|
||||||
++pos;
|
++pos;
|
||||||
@ -163,23 +177,27 @@ namespace rexy::cx{
|
|||||||
}
|
}
|
||||||
return start;
|
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;
|
m_elements[m_size] = value;
|
||||||
return m_elements+(m_size++);
|
return m_elements+(m_size++);
|
||||||
}
|
}
|
||||||
template<class... Args>
|
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)...};
|
m_elements[m_size++] = T{std::forward<Args>(args)...};
|
||||||
return m_elements+(m_size++);
|
return m_elements+(m_size++);
|
||||||
}
|
}
|
||||||
constexpr void pop_back(void){
|
constexpr void pop_back(void)noexcept{
|
||||||
--m_size;
|
--m_size;
|
||||||
}
|
}
|
||||||
constexpr void resize(size_type count){
|
constexpr void resize(size_type count)noexcept{
|
||||||
if(count <= max_size())
|
if(count <= max_size())
|
||||||
m_size = count;
|
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 > m_size){
|
||||||
if(count <= max_size()){
|
if(count <= max_size()){
|
||||||
for(size_type i = m_size;i < count;++i){
|
for(size_type i = m_size;i < count;++i){
|
||||||
@ -190,20 +208,24 @@ namespace rexy::cx{
|
|||||||
m_size = count;
|
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){
|
for(auto it = begin();it != end();++it){
|
||||||
*it = value;
|
*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;
|
size_type i = 0;
|
||||||
for(;i < m_size;++i){
|
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){
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@ -25,44 +25,64 @@
|
|||||||
|
|
||||||
namespace rexy{
|
namespace rexy{
|
||||||
template<class Al, class Str = rexy::string, detail::enable_if_concrete_string<Str> = 0>
|
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);
|
Str s(b.size()+1);
|
||||||
memcpy(s.get(), b.get(), b.size());
|
memcpy(s.get(), b.get(), b.size());
|
||||||
s[b.size()] = 0;
|
s[b.size()] = 0;
|
||||||
return s;
|
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>
|
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;
|
Str s;
|
||||||
s.reset(b.get(), b.size());
|
s.reset(b.get(), b.size());
|
||||||
b.release();
|
b.release();
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
template<class Bin = rexy::binary, detail::enable_if_binary<Bin> = 0>
|
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);
|
Bin b(s.length()+1);
|
||||||
b.append(s.get(), s.length()+1);
|
b.append(s.get(), s.length()+1);
|
||||||
return b;
|
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>
|
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;
|
Bin b;
|
||||||
b.reset(s.get(), s.length()+1);
|
b.reset(s.get(), s.length()+1);
|
||||||
s.release();
|
s.release();
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
template<class L, class R, detail::enable_if_binary<L> = 0, detail::enable_if_concrete_string<R> = 0>
|
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);
|
l.append(r.get(), r.length()+1);
|
||||||
return l;
|
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>
|
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;
|
rexy::string concrete = r;
|
||||||
return (l = concrete);
|
return (l = concrete);
|
||||||
}
|
}
|
||||||
template<class L, class R, detail::enable_if_concrete_string<L> = 0, detail::enable_if_binary<R> = 0>
|
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);
|
l.resize(l.length(), r.size() + 1);
|
||||||
memcpy(l.get()+l.length()+1, r.get(), r.size());
|
memcpy(l.get()+l.length()+1, r.get(), r.size());
|
||||||
return l;
|
return l;
|
||||||
|
|||||||
@ -25,6 +25,7 @@
|
|||||||
#include "string.hpp"
|
#include "string.hpp"
|
||||||
#include "binary.hpp"
|
#include "binary.hpp"
|
||||||
#include "cx/utility.hpp"
|
#include "cx/utility.hpp"
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
namespace rexy{
|
namespace rexy{
|
||||||
|
|
||||||
@ -35,37 +36,37 @@ namespace rexy{
|
|||||||
FILE* m_fp = nullptr;
|
FILE* m_fp = nullptr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
constexpr filerd(void) = default;
|
constexpr filerd(void)noexcept = default;
|
||||||
filerd(const char* f, const char* mode = "r");
|
filerd(const char* f, const char* mode = "r")noexcept;
|
||||||
filerd(const filerd&) = delete;
|
filerd(const filerd&) = delete;
|
||||||
constexpr filerd(filerd&& f):
|
constexpr filerd(filerd&& f)noexcept:
|
||||||
m_fp(cx::exchange(f.m_fp, nullptr)){}
|
m_fp(cx::exchange(f.m_fp, nullptr)){}
|
||||||
~filerd(void);
|
~filerd(void)noexcept;
|
||||||
filerd& operator=(const filerd&) = delete;
|
filerd& operator=(const filerd&) = delete;
|
||||||
constexpr filerd& operator=(filerd&& f){
|
constexpr filerd& operator=(filerd&& f)noexcept{
|
||||||
cx::swap(m_fp, f.m_fp);
|
cx::swap(m_fp, f.m_fp);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset(FILE* fp = nullptr);
|
void reset(FILE* fp = nullptr)noexcept;
|
||||||
FILE* release(void);
|
FILE* release(void)noexcept;
|
||||||
size_t length(void);
|
size_t length(void)noexcept;
|
||||||
size_t position(void)const;
|
size_t position(void)const noexcept;
|
||||||
void rewind(size_t pos = 0);
|
void rewind(size_t pos = 0)noexcept;
|
||||||
|
|
||||||
operator FILE*(void);
|
operator FILE*(void)noexcept;
|
||||||
operator const FILE*(void)const;
|
operator const FILE*(void)const noexcept;
|
||||||
FILE* get(void);
|
FILE* get(void)noexcept;
|
||||||
const FILE* get(void)const;
|
const FILE* get(void)const noexcept;
|
||||||
operator bool(void)const;
|
operator bool(void)const noexcept;
|
||||||
|
|
||||||
size_t read(char* dest, size_t bytes);
|
size_t read(char* dest, size_t bytes)noexcept;
|
||||||
rexy::string read(size_t bytes);
|
rexy::string read(size_t bytes)noexcept;
|
||||||
rexy::string readln(size_t max = 0);
|
rexy::string readln(size_t max = 0)noexcept;
|
||||||
rexy::binary read_bin(size_t bytes);
|
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 char* c, size_t bytes)noexcept;
|
||||||
size_t write(const rexy::string_base&);
|
size_t write(const rexy::string_base&)noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,6 +21,8 @@
|
|||||||
|
|
||||||
#include <utility> //forward
|
#include <utility> //forward
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
namespace rexy{
|
namespace rexy{
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
@ -31,7 +33,8 @@ namespace rexy{
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
template<class U>
|
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)){}
|
m_val(std::forward<U>(u)){}
|
||||||
|
|
||||||
steal(const steal&) = delete;
|
steal(const steal&) = delete;
|
||||||
@ -39,10 +42,10 @@ namespace rexy{
|
|||||||
steal& operator=(const steal&) = delete;
|
steal& operator=(const steal&) = delete;
|
||||||
steal& operator=(steal&&) = delete;
|
steal& operator=(steal&&) = delete;
|
||||||
|
|
||||||
constexpr T&& value(void){
|
constexpr T&& value(void)noexcept{
|
||||||
return std::forward<T>(m_val);
|
return std::forward<T>(m_val);
|
||||||
}
|
}
|
||||||
constexpr const T& value(void)const{
|
constexpr const T& value(void)const noexcept{
|
||||||
return m_val;
|
return m_val;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -29,4 +29,8 @@ namespace rexy{
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef REXY_BINARY_HPP
|
||||||
|
#include "detail/binary_string_conv.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -22,6 +22,7 @@
|
|||||||
#include <type_traits> //is_same, integral_contant, enable_if, etc
|
#include <type_traits> //is_same, integral_contant, enable_if, etc
|
||||||
#include <utility> //forward
|
#include <utility> //forward
|
||||||
#include <cstdlib> //size_t
|
#include <cstdlib> //size_t
|
||||||
|
#include <cstring> //strlen
|
||||||
|
|
||||||
#include "steal.hpp"
|
#include "steal.hpp"
|
||||||
#include "cx/utility.hpp"
|
#include "cx/utility.hpp"
|
||||||
@ -40,35 +41,36 @@ namespace rexy{
|
|||||||
char* m_data = nullptr;
|
char* m_data = nullptr;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
constexpr string_base(void) = default;
|
constexpr string_base(void)noexcept = default;
|
||||||
constexpr string_base(size_t len):
|
constexpr string_base(size_t len)noexcept:
|
||||||
m_cap(len){}
|
m_cap(len){}
|
||||||
//Initialize without copying
|
//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){}
|
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){}
|
m_length(len), m_cap(cap), m_data(data){}
|
||||||
//Copy ctor (do nothing)
|
//Copy ctor (do nothing)
|
||||||
constexpr string_base(const string_base&){}
|
constexpr string_base(const string_base&)noexcept{}
|
||||||
~string_base(void) = default;
|
~string_base(void)noexcept = default;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
//Stop managing stored pointer. Does not free.
|
//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
|
//Length of string not including null terminator
|
||||||
constexpr size_t length(void)const{return m_length;}
|
constexpr size_t length(void)const noexcept{return m_length;}
|
||||||
constexpr size_t capacity(void)const{return m_cap;}
|
constexpr size_t capacity(void)const noexcept{return m_cap;}
|
||||||
//direct access to managed pointer
|
//direct access to managed pointer
|
||||||
constexpr char* get(void){return m_data;}
|
constexpr char* get(void)noexcept{return m_data;}
|
||||||
constexpr const char* get(void)const{return m_data;}
|
constexpr const char* get(void)const noexcept{return m_data;}
|
||||||
constexpr operator char*(void){return m_data;}
|
constexpr operator char*(void)noexcept{return m_data;}
|
||||||
constexpr operator const char*(void)const{return m_data;}
|
constexpr operator const char*(void)const noexcept{return m_data;}
|
||||||
//true if m_data is not null
|
//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 char& operator[](size_t i)noexcept{return m_data[i];}
|
||||||
constexpr const char& operator[](size_t i)const{return m_data[i];}
|
constexpr const char& operator[](size_t i)const noexcept{return m_data[i];}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -79,46 +81,56 @@ namespace rexy{
|
|||||||
public:
|
public:
|
||||||
using allocator_type = Allocator;
|
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:
|
public:
|
||||||
constexpr string_intermediary(void);
|
constexpr string_intermediary(void)noexcept;
|
||||||
constexpr string_intermediary(rexy::steal<char*> data, size_t len);
|
constexpr string_intermediary(rexy::steal<char*> data, size_t len)noexcept;
|
||||||
constexpr string_intermediary(rexy::steal<char*> data, size_t len, size_t cap);
|
constexpr string_intermediary(rexy::steal<char*> data, size_t len, size_t cap)noexcept;
|
||||||
[[deprecated]] constexpr string_intermediary(char* data, size_t len);
|
constexpr string_intermediary(rexy::steal<char*> data)noexcept;
|
||||||
string_intermediary(const char* data, size_t len);
|
[[deprecated]] constexpr string_intermediary(char* data, size_t len)noexcept;
|
||||||
[[deprecated]] constexpr string_intermediary(char* data, size_t len, size_t cap);
|
[[deprecated]] constexpr string_intermediary(char* data, size_t len, size_t cap)noexcept;
|
||||||
string_intermediary(const char* data);
|
string_intermediary(const char* data, size_t len)noexcept(noexcept(Allocator::copy(data,len)));
|
||||||
constexpr string_intermediary(rexy::steal<char*>);
|
string_intermediary(const char* data)noexcept(noexcept(strlen(data)) && noexcept(Allocator::copy(data, m_cap)));
|
||||||
string_intermediary(size_t len);
|
string_intermediary(size_t len)noexcept(noexcept(Allocator::allocate(len)));
|
||||||
string_intermediary(size_t len, size_t cap);
|
string_intermediary(size_t len, size_t cap)noexcept(noexcept(Allocator::allocate(len)));
|
||||||
|
|
||||||
//normal copy and move ctors
|
//normal copy and move ctors
|
||||||
string_intermediary(const string_intermediary& b);
|
string_intermediary(const string_intermediary& b)noexcept(noexcept(Allocator::copy(b.m_data, b.m_length)));
|
||||||
constexpr string_intermediary(string_intermediary&& s);
|
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
|
//dtor
|
||||||
~string_intermediary(void);
|
~string_intermediary(void)noexcept(noexcept(Allocator::free(m_data)));
|
||||||
|
|
||||||
string_intermediary& operator=(const string_intermediary& s);
|
string_intermediary& operator=(const string_intermediary& s)
|
||||||
constexpr string_intermediary& operator=(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
|
//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
|
//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
|
//Replace managed pointer. Frees existing value
|
||||||
void reset(char* val = nullptr);
|
void reset(char* val = nullptr)noexcept(noexcept(Allocator::free(m_data)));
|
||||||
void reset(char* val, size_t len);
|
void reset(char* val, size_t len)noexcept(noexcept(Allocator::free(m_data)));
|
||||||
bool resize(size_t newsize);
|
bool resize(size_t newsize)noexcept(std::is_nothrow_copy_constructible<string_intermediary<Allocator>>::value &&
|
||||||
void append(const char* data, size_t len);
|
std::is_nothrow_move_assignable<string_intermediary<Allocator>>::value);
|
||||||
void append(const char* data);
|
void append(const char* data, size_t len)noexcept(std::is_nothrow_constructible<string_intermediary<Allocator>,decltype(m_length)>::value);
|
||||||
void append(const string_base& s);
|
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
|
//Like an expression template but not really
|
||||||
template<class Left, class Right>
|
template<class Left, class Right>
|
||||||
class string_cat_expr : public string_expr
|
class string_cat_expr : public string_expr
|
||||||
@ -129,14 +141,18 @@ namespace rexy{
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
template<class T, class U>
|
template<class T, class U>
|
||||||
constexpr string_cat_expr(T&& l, U&& r);
|
constexpr string_cat_expr(T&& l, U&& r)noexcept(std::is_nothrow_constructible<Left,T&&>::value &&
|
||||||
constexpr string_cat_expr(string_cat_expr&& s);
|
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>
|
template<class Alloc>
|
||||||
operator string_intermediary<Alloc>(void);
|
operator string_intermediary<Alloc>(void)
|
||||||
constexpr const Left& left(void)const;
|
noexcept(std::is_nothrow_constructible<string_intermediary<Alloc>, size_t>::value &&
|
||||||
constexpr const Right& right(void)const;
|
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>
|
template<class Left, class Right>
|
||||||
string_cat_expr(Left&, Right&) -> string_cat_expr<Left&,Right&>;
|
string_cat_expr(Left&, Right&) -> string_cat_expr<Left&,Right&>;
|
||||||
@ -153,16 +169,16 @@ namespace rexy{
|
|||||||
class static_string : public string_base
|
class static_string : public string_base
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
constexpr static_string(void) = default;
|
constexpr static_string(void)noexcept = default;
|
||||||
constexpr static_string(const char* str, size_t len);
|
constexpr static_string(const char* str, size_t len)noexcept;
|
||||||
constexpr static_string(const char* c);
|
constexpr static_string(const char* c)noexcept;
|
||||||
constexpr static_string(const static_string& s);
|
constexpr static_string(const static_string& s)noexcept;
|
||||||
constexpr static_string(static_string&& s);
|
constexpr static_string(static_string&& s)noexcept;
|
||||||
~static_string(void) = default;
|
~static_string(void)noexcept = default;
|
||||||
|
|
||||||
constexpr static_string& operator=(const char* c);
|
constexpr static_string& operator=(const char* c)noexcept;
|
||||||
constexpr static_string& operator=(const static_string& s);
|
constexpr static_string& operator=(const static_string& s)noexcept;
|
||||||
constexpr static_string& operator=(static_string&&);
|
constexpr static_string& operator=(static_string&&)noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -189,43 +205,55 @@ namespace rexy{
|
|||||||
private:
|
private:
|
||||||
Targ& m_targ;
|
Targ& m_targ;
|
||||||
public:
|
public:
|
||||||
constexpr string_appender(Targ& t);
|
constexpr string_appender(Targ& t)noexcept;
|
||||||
template<class L, class R>
|
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>
|
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
|
} //namespace detail
|
||||||
|
|
||||||
template<class Str1, class Str2, detail::enable_if_concrete_string<Str1,Str2> = 0>
|
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());
|
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>
|
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);
|
return !(left == right);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Left, class Right, detail::enable_if_string<Left,Right> = 0>
|
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));
|
return string_cat_expr(std::forward<Left>(l), std::forward<Right>(r));
|
||||||
}
|
}
|
||||||
template<class Right, detail::enable_if_string<Right> = 0>
|
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));
|
return string_cat_expr(rexy::static_string(left), std::forward<Right>(right));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Left, detail::enable_if_string<Left> = 0>
|
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));
|
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>
|
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));
|
return l = (l + std::forward<Right>(r));
|
||||||
}
|
}
|
||||||
template<class Left, detail::enable_if_concrete_string<Left> = 0>
|
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);
|
return l = (l + r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -233,15 +261,11 @@ namespace rexy{
|
|||||||
#include "string_base.tpp"
|
#include "string_base.tpp"
|
||||||
|
|
||||||
namespace{
|
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);
|
return rexy::static_string(str, len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef REXY_BINARY_HPP
|
|
||||||
#include "detail/binary_string_conv.hpp"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef REXY_CX_HASH_HPP
|
#ifdef REXY_CX_HASH_HPP
|
||||||
#include "cx/string_hash.hpp"
|
#include "cx/string_hash.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -30,27 +30,37 @@
|
|||||||
namespace rexy{
|
namespace rexy{
|
||||||
|
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
constexpr string_intermediary<Allocator>::string_intermediary(void){}
|
constexpr string_intermediary<Allocator>::string_intermediary(void)noexcept{}
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
/*deprecated*/ constexpr string_intermediary<Allocator>::string_intermediary(char* data, size_t len):
|
constexpr string_intermediary<Allocator>::string_intermediary(rexy::steal<char*> data)noexcept:
|
||||||
string_base(data, len){}
|
string_base(data.value() ? cx::strlen(data.value()) : 0)
|
||||||
|
{
|
||||||
|
m_data = data.value();
|
||||||
|
m_length = m_cap;
|
||||||
|
}
|
||||||
template<class Allocator>
|
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){}
|
string_base(data.value(), len){}
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
/*deprecated*/ constexpr string_intermediary<Allocator>::string_intermediary(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, len, cap){}
|
|
||||||
template<class Allocator>
|
|
||||||
constexpr string_intermediary<Allocator>::string_intermediary(rexy::steal<char*> data, size_t len, size_t cap):
|
|
||||||
string_base(data.value(), len, cap){}
|
string_base(data.value(), len, cap){}
|
||||||
template<class Allocator>
|
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)
|
string_base(reinterpret_cast<char*>(len ? Allocator::copy(data, len+1) : nullptr), len)
|
||||||
{
|
{
|
||||||
m_data[len] = 0;
|
m_data[len] = 0;
|
||||||
}
|
}
|
||||||
template<class Allocator>
|
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)
|
string_base(data ? strlen(data) : 0)
|
||||||
{
|
{
|
||||||
if(m_cap){
|
if(m_cap){
|
||||||
@ -59,20 +69,15 @@ namespace rexy{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
constexpr string_intermediary<Allocator>::string_intermediary(rexy::steal<char*> data):
|
string_intermediary<Allocator>::string_intermediary(size_t len)
|
||||||
string_base(data.value() ? cx::strlen(data.value()) : 0)
|
noexcept(noexcept(Allocator::allocate(len))):
|
||||||
{
|
|
||||||
m_data = data.value();
|
|
||||||
m_length = m_cap;
|
|
||||||
}
|
|
||||||
template<class Allocator>
|
|
||||||
string_intermediary<Allocator>::string_intermediary(size_t len):
|
|
||||||
string_base(reinterpret_cast<char*>(len ? Allocator::allocate(len+1) : nullptr), len)
|
string_base(reinterpret_cast<char*>(len ? Allocator::allocate(len+1) : nullptr), len)
|
||||||
{
|
{
|
||||||
m_data[len] = 0;
|
m_data[len] = 0;
|
||||||
}
|
}
|
||||||
template<class Allocator>
|
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)
|
string_base(reinterpret_cast<char*>(len ? Allocator::allocate(len+1) : nullptr), len, cap)
|
||||||
{
|
{
|
||||||
m_data[len] = 0;
|
m_data[len] = 0;
|
||||||
@ -80,24 +85,32 @@ namespace rexy{
|
|||||||
|
|
||||||
//normal copy and move ctors
|
//normal copy and move ctors
|
||||||
template<class Allocator>
|
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){}
|
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>
|
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){}
|
string_base(cx::exchange(s.m_data, nullptr), s.m_length, s.m_cap){}
|
||||||
|
|
||||||
template<class Allocator>
|
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()){}
|
string_base(reinterpret_cast<char*>(b.length() ? Allocator::copy(b.get(), b.length()+1) : nullptr), b.length(), b.capacity()){}
|
||||||
|
|
||||||
//dtor
|
//dtor
|
||||||
template<class Allocator>
|
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);
|
Allocator::free(m_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Allocator>
|
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){
|
if(s.m_length < m_length){
|
||||||
memcpy(m_data, s.m_data, s.m_length+1);
|
memcpy(m_data, s.m_data, s.m_length+1);
|
||||||
m_length = s.m_length;
|
m_length = s.m_length;
|
||||||
@ -107,7 +120,9 @@ namespace rexy{
|
|||||||
return (*this = std::move(tmp));
|
return (*this = std::move(tmp));
|
||||||
}
|
}
|
||||||
template<class Allocator>
|
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);
|
cx::swap(m_data, s.m_data);
|
||||||
m_length = s.m_length;
|
m_length = s.m_length;
|
||||||
m_cap = s.m_cap;
|
m_cap = s.m_cap;
|
||||||
@ -115,32 +130,43 @@ namespace rexy{
|
|||||||
}
|
}
|
||||||
//Copy from c string
|
//Copy from c string
|
||||||
template<class Allocator>
|
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));
|
return _copy_string(c, strlen(c));
|
||||||
}
|
}
|
||||||
//Copy from other string_base
|
//Copy from other string_base
|
||||||
template<class Allocator>
|
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());
|
return _copy_string(s.get(), s.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
//Replace managed pointer. Frees existing value
|
//Replace managed pointer. Frees existing value
|
||||||
template<class Allocator>
|
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);
|
Allocator::free(m_data);
|
||||||
m_data = val;
|
m_data = val;
|
||||||
m_length = val ? strlen(val) : 0;
|
m_length = val ? strlen(val) : 0;
|
||||||
m_cap = m_length;
|
m_cap = m_length;
|
||||||
}
|
}
|
||||||
template<class Allocator>
|
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);
|
Allocator::free(m_data);
|
||||||
m_data = val;
|
m_data = val;
|
||||||
m_length = len;
|
m_length = len;
|
||||||
m_cap = len;
|
m_cap = len;
|
||||||
}
|
}
|
||||||
template<class Allocator>
|
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)
|
if(newsize < m_cap)
|
||||||
return false;
|
return false;
|
||||||
string_intermediary tmp(newsize);
|
string_intermediary tmp(newsize);
|
||||||
@ -152,7 +178,9 @@ namespace rexy{
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
template<class Allocator>
|
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){
|
if(len+m_length <= m_cap){
|
||||||
memcpy(m_data+m_length, data, len);
|
memcpy(m_data+m_length, data, len);
|
||||||
m_length += len;
|
m_length += len;
|
||||||
@ -160,25 +188,32 @@ namespace rexy{
|
|||||||
}else{
|
}else{
|
||||||
string_intermediary tmp(cx::max(m_length + len, m_cap*2));
|
string_intermediary tmp(cx::max(m_length + len, m_cap*2));
|
||||||
if(m_data)
|
if(m_data)
|
||||||
memcpy(STOP_STRING_ALIASING_WARNING(tmp).m_data, m_data, m_length);
|
memcpy(STOP_STRICT_ALIAS_WARNING(tmp).m_data, m_data, m_length);
|
||||||
memcpy(STOP_STRING_ALIASING_WARNING(tmp).m_data+m_length, data, len);
|
memcpy(STOP_STRICT_ALIAS_WARNING(tmp).m_data+m_length, data, len);
|
||||||
STOP_STRING_ALIASING_WARNING(tmp).m_length = len+m_length;
|
STOP_STRICT_ALIAS_WARNING(tmp).m_length = len+m_length;
|
||||||
tmp[m_length+len] = 0;
|
tmp[m_length+len] = 0;
|
||||||
*this = std::move(tmp);
|
*this = std::move(tmp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
template<class Allocator>
|
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)
|
if(data)
|
||||||
append(data, strlen(data));
|
append(data, strlen(data));
|
||||||
}
|
}
|
||||||
template<class Allocator>
|
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());
|
append(s.get(), s.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Allocator>
|
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){
|
if(!len){
|
||||||
Allocator::free(m_data);
|
Allocator::free(m_data);
|
||||||
m_length = 0;
|
m_length = 0;
|
||||||
@ -204,21 +239,30 @@ namespace rexy{
|
|||||||
|
|
||||||
template<class Left, class Right>
|
template<class Left, class Right>
|
||||||
template<class T, class U>
|
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_l(std::forward<T>(l)),
|
||||||
m_r(std::forward<U>(r)){}
|
m_r(std::forward<U>(r)){}
|
||||||
template<class Left, class Right>
|
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_l(std::forward<Left>(s.m_l)),
|
||||||
m_r(std::forward<Right>(s.m_r)){}
|
m_r(std::forward<Right>(s.m_r)){}
|
||||||
|
|
||||||
template<class Left, class Right>
|
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();
|
return m_l.length() + m_r.length();
|
||||||
}
|
}
|
||||||
template<class Left, class Right>
|
template<class Left, class Right>
|
||||||
template<class Alloc>
|
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();
|
size_t len = length();
|
||||||
string_intermediary<Alloc> ret(len);
|
string_intermediary<Alloc> ret(len);
|
||||||
detail::string_appender<string_intermediary<Alloc>> append(ret);
|
detail::string_appender<string_intermediary<Alloc>> append(ret);
|
||||||
@ -226,34 +270,34 @@ namespace rexy{
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
template<class Left, class Right>
|
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;
|
return m_l;
|
||||||
}
|
}
|
||||||
template<class Left, class Right>
|
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;
|
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){}
|
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){}
|
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){}
|
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_data = s.m_data;
|
||||||
m_length = s.m_length;
|
m_length = s.m_length;
|
||||||
return *this;
|
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)){}
|
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_data = const_cast<char*>(c);
|
||||||
m_length = cx::strlen(c);
|
m_length = cx::strlen(c);
|
||||||
return *this;
|
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_data = s.m_data;
|
||||||
m_length = s.m_length;
|
m_length = s.m_length;
|
||||||
return *this;
|
return *this;
|
||||||
@ -261,16 +305,20 @@ namespace rexy{
|
|||||||
|
|
||||||
namespace detail{
|
namespace detail{
|
||||||
template<class Targ>
|
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 Targ>
|
||||||
template<class L, class R>
|
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.left());
|
||||||
(*this)(str.right());
|
(*this)(str.right());
|
||||||
}
|
}
|
||||||
template<class Targ>
|
template<class Targ>
|
||||||
template<class Str, std::enable_if_t<!rexy::is_template_type<Str,string_cat_expr>::value,int>>
|
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());
|
m_targ.append(str.get(), str.length());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,11 +20,6 @@
|
|||||||
|
|
||||||
namespace rexy{
|
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){
|
char* binary_base::release(void){
|
||||||
return std::exchange(m_data, nullptr);
|
return std::exchange(m_data, nullptr);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,13 +1,21 @@
|
|||||||
//Never actually used in the project. This just ensures that all syntax is correct during builds.
|
//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/binary.hpp"
|
||||||
#include "rexy/filerd.hpp"
|
#include "rexy/filerd.hpp"
|
||||||
#include "rexy/steal.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/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/utility.hpp"
|
||||||
#include "rexy/cx/vector.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"
|
|
||||||
|
|||||||
@ -20,25 +20,26 @@
|
|||||||
|
|
||||||
#include <cstdio> //fopen, fclose
|
#include <cstdio> //fopen, fclose
|
||||||
#include <utility> //exchange, swap
|
#include <utility> //exchange, swap
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
namespace rexy{
|
namespace rexy{
|
||||||
|
|
||||||
filerd::filerd(const char* f, const char* mode):
|
filerd::filerd(const char* f, const char* mode)noexcept:
|
||||||
m_fp(fopen(f, mode)){}
|
m_fp(fopen(f, mode)){}
|
||||||
filerd::~filerd(void){
|
filerd::~filerd(void)noexcept{
|
||||||
if(m_fp)
|
if(m_fp)
|
||||||
fclose(m_fp);
|
fclose(m_fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void filerd::reset(FILE* fp){
|
void filerd::reset(FILE* fp)noexcept{
|
||||||
if(m_fp)
|
if(m_fp)
|
||||||
fclose(m_fp);
|
fclose(m_fp);
|
||||||
m_fp = fp;
|
m_fp = fp;
|
||||||
}
|
}
|
||||||
FILE* filerd::release(void){
|
FILE* filerd::release(void)noexcept{
|
||||||
return std::exchange(m_fp, nullptr);
|
return std::exchange(m_fp, nullptr);
|
||||||
}
|
}
|
||||||
size_t filerd::length(void){
|
size_t filerd::length(void)noexcept{
|
||||||
if(!m_fp)
|
if(!m_fp)
|
||||||
return 0;
|
return 0;
|
||||||
size_t tmp, ret;
|
size_t tmp, ret;
|
||||||
@ -48,38 +49,38 @@ namespace rexy{
|
|||||||
fseek(m_fp, tmp, SEEK_SET);
|
fseek(m_fp, tmp, SEEK_SET);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
size_t filerd::position(void)const{
|
size_t filerd::position(void)const noexcept{
|
||||||
return ftell(m_fp);
|
return ftell(m_fp);
|
||||||
}
|
}
|
||||||
void filerd::rewind(size_t pos){
|
void filerd::rewind(size_t pos)noexcept{
|
||||||
fseek(m_fp, pos, SEEK_SET);
|
fseek(m_fp, pos, SEEK_SET);
|
||||||
}
|
}
|
||||||
|
|
||||||
filerd::operator FILE*(void){
|
filerd::operator FILE*(void)noexcept{
|
||||||
return m_fp;
|
return m_fp;
|
||||||
}
|
}
|
||||||
filerd::operator const FILE*(void)const{
|
filerd::operator const FILE*(void)const noexcept{
|
||||||
return m_fp;
|
return m_fp;
|
||||||
}
|
}
|
||||||
FILE* filerd::get(void){
|
FILE* filerd::get(void)noexcept{
|
||||||
return m_fp;
|
return m_fp;
|
||||||
}
|
}
|
||||||
const FILE* filerd::get(void)const{
|
const FILE* filerd::get(void)const noexcept{
|
||||||
return m_fp;
|
return m_fp;
|
||||||
}
|
}
|
||||||
filerd::operator bool(void)const{
|
filerd::operator bool(void)const noexcept{
|
||||||
return m_fp;
|
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);
|
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));
|
char* tmp = reinterpret_cast<char*>(rexy::string::allocator_type::allocate(bytes));
|
||||||
size_t written = read(tmp, bytes);
|
size_t written = read(tmp, bytes);
|
||||||
return rexy::string(rexy::steal(tmp), written);
|
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;
|
rexy::string ret;
|
||||||
char c;
|
char c;
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
@ -90,15 +91,17 @@ namespace rexy{
|
|||||||
}
|
}
|
||||||
return ret;
|
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));
|
char* tmp = reinterpret_cast<char*>(rexy::binary::allocator_type::allocate(bytes));
|
||||||
size_t written = read(tmp, bytes);
|
size_t written = read(tmp, bytes);
|
||||||
return rexy::binary(rexy::steal(tmp), written, written);
|
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);
|
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());
|
return write(c.get(), c.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user