Add compile time vector, array, and hashmap

This commit is contained in:
rexy712 2020-05-01 23:49:25 -07:00
parent d415af2bdd
commit c99abad226
14 changed files with 725 additions and 95 deletions

View File

@ -30,7 +30,6 @@ if(ENABLE_PROFILING)
endif() endif()
set(LIBREXY_PUBLIC_HEADERS "include/rexy/steal.hpp" "include/rexy/binary.hpp" "include/rexy/string_base.hpp" "include/rexy/string.hpp" "include/rexy/filerd.hpp" "include/rexy/string_base.tpp") set(LIBREXY_PUBLIC_HEADERS "include/rexy/steal.hpp" "include/rexy/binary.hpp" "include/rexy/string_base.hpp" "include/rexy/string.hpp" "include/rexy/filerd.hpp" "include/rexy/string_base.tpp")
set(LIBREXY_DETAIL_HEADERS "include/rexy/detail/binary_string_conv.hpp" "include/rexy/detail/default_allocator.hpp" "include/rexy/detail/util.hpp")
target_compile_options(rexy PRIVATE -Wall -Wextra -pedantic -std=c++17) target_compile_options(rexy PRIVATE -Wall -Wextra -pedantic -std=c++17)
install(TARGETS rexy install(TARGETS rexy
@ -41,7 +40,8 @@ install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/pc/librexy.pc"
DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig"
) )
install(FILES ${LIBREXY_PUBLIC_HEADERS} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/rexy/") install(FILES ${LIBREXY_PUBLIC_HEADERS} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/rexy/")
install(FILES ${LIBREXY_DETAIL_HEADERS} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/rexy/detail/") install(DIRECTORY "include/rexy/detail" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/rexy")
install(DIRECTORY "include/rexy/cx" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/rexy")
configure_file( configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/pc/librexy.pc.cmake.in" "${CMAKE_CURRENT_SOURCE_DIR}/pc/librexy.pc.cmake.in"

View File

@ -23,7 +23,7 @@
#include <utility> //move #include <utility> //move
#include <cstring> //memcpy #include <cstring> //memcpy
#include <type_traits> #include <type_traits>
#include "detail/util.hpp" //max #include "cx/utility.hpp" //max
#include "detail/default_allocator.hpp" #include "detail/default_allocator.hpp"
#include "steal.hpp" #include "steal.hpp"
@ -130,7 +130,7 @@ namespace rexy{
} }
void append(const char* data, size_t len){ void append(const char* data, size_t len){
if(m_size + len > m_cap) if(m_size + len > m_cap)
resize(detail::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);
m_size += len; m_size += len;
} }

View File

@ -0,0 +1,56 @@
/**
This file is a part of rexy's general purpose library
Copyright (C) 2020 rexy712
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef REXY_CX_ALGORITHM_HPP
#define REXY_CX_ALGORITHM_HPP
#include "utility.hpp" //swap
namespace rexy::cx{
template<class Iter, class Compare>
constexpr Iter qs_partition(Iter left, Iter right, const Compare& cmp){
auto range = right - left;
auto pivot = left + (range / 2);
auto value = *pivot;
//move pivot value all the way to the right side to preserve it
swap(*pivot, *right);
for(auto it = left;it != right;++it){
if(cmp(*it, value)){
swap(*left, *it);
++left;
}
}
//move pivot value back to proper position
swap(*left, *right);
return left;
}
template<class Iter, class Compare>
constexpr void quicksort(Iter left, Iter right, const Compare& cmp){
while(left < right){
auto real_right = right-1;
auto pivot = qs_partition(left, real_right, cmp);
quicksort(left, pivot, cmp);
left = ++pivot;
}
}
}
#endif

126
include/rexy/cx/array.hpp Normal file
View File

@ -0,0 +1,126 @@
/**
This file is a part of rexy's general purpose library
Copyright (C) 2020 rexy712
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef REXY_CX_ARRAY_HPP
#define REXY_CX_ARRAY_HPP
#include <cstddef> //size_t
#include "utility.hpp" //swap
namespace rexy::cx{
template<class T, size_t N>
class array
{
public:
using value_type = T;
using size_type = size_t;
using difference_type = ptrdiff_t;
using reference = T&;
using const_reference = const T&;
using pointer = T*;
using const_pointer = const T*;
using iterator = T*;
using const_iterator = const T*;
static constexpr size_type max_elements = N;
private:
T m_elements[N] = {};
public:
constexpr reference at(size_type pos){
return m_elements[pos];
}
constexpr const_reference at(size_type pos)const{
return m_elements[pos];
}
constexpr reference operator[](size_type pos){
return m_elements[pos];
}
constexpr const_reference operator[](size_type pos)const{
return m_elements[pos];
}
constexpr reference front(void){
return m_elements[0];
}
constexpr const_reference front(void)const{
return m_elements[0];
}
constexpr reference back(void){
return m_elements[max_elements-1];
}
constexpr const_reference back(void)const{
return m_elements[max_elements-1];
}
constexpr pointer data(void){
return m_elements;
}
constexpr const_pointer data(void)const{
return m_elements;
}
constexpr iterator begin(void){
return m_elements;
}
constexpr const_iterator begin(void)const{
return m_elements;
}
constexpr const_iterator cbegin(void)const{
return m_elements;
}
constexpr iterator end(void){
return m_elements+max_elements;
}
constexpr const_iterator end(void)const{
return m_elements+max_elements;
}
constexpr const_iterator cend(void)const{
return m_elements+max_elements;
}
constexpr bool empty(void)const{
if constexpr(max_elements == 0){
return true;
}else{
return false;
}
}
constexpr size_type size(void)const{
return max_elements;
}
constexpr size_type max_size(void)const{
return max_elements;
}
constexpr void fill(const T& value){
for(auto it = begin();it != end();++it){
*it = value;
}
}
constexpr void swap(array& other){
for(size_type i = 0;i < max_size();++i){
swap(m_elements[i], other.m_elements[i]);
}
}
};
template<class T, class... Us>
array(T, Us...) -> array<T, 1 + sizeof...(Us)>;
}
#endif

42
include/rexy/cx/hash.hpp Normal file
View File

@ -0,0 +1,42 @@
/**
This file is a part of rexy's general purpose library
Copyright (C) 2020 rexy712
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef REXY_CX_HASH_HPP
#define REXY_CX_HASH_HPP
#include <climits> //CHAR_BIT
namespace rexy::cx{
template<class T>
struct hash{
constexpr size_t operator()(const T& t, size_t salt = 0){
constexpr size_t bytes = sizeof(size_t);
size_t val = static_cast<size_t>(t);
size_t hash = 5381 + salt; //magic hash number
for(size_t i = 0;i < bytes;++i){
unsigned char c = static_cast<unsigned char>(val >> (i * CHAR_BIT));
hash = ((hash << 5) + hash) ^ c;
}
return hash;
}
};
}
#endif

148
include/rexy/cx/hashmap.hpp Normal file
View File

@ -0,0 +1,148 @@
/**
This file is a part of rexy's general purpose library
Copyright (C) 2020 rexy712
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef REXY_CX_HASHMAP_HPP
#define REXY_CX_HASHMAP_HPP
#include "vector.hpp"
#include "array.hpp"
#include "algorithm.hpp"
#include "hash.hpp"
#include <climits> //CHAR_BIT
#include <initializer_list>
namespace rexy::cx{
template<class Key, class Value>
struct element
{
Key key;
Value value;
};
template<class Key, class Value, size_t N, class Hash = hash<Key>>
class hashmap
{
public:
static constexpr size_t single_bucket_bit = size_t{1} << ((sizeof(size_t)*CHAR_BIT) - 1);
static constexpr size_t max_size = N;
static_assert((max_size & single_bucket_bit) == 0);
using key_type = Key;
using value_type = Value;
using hash_type = Hash;
private:
array<Value,N> m_values; //perfect hash table
array<size_t,N> m_g; //'salt' values for indexing into the perfect hash table
public:
constexpr hashmap(const element<Key,Value>(&elements)[N]){
array<vector<element<Key,Value>,N>,N> buckets;
array<bool,N> slots_used;
size_t current_bucket = 0;
//place all keys into buckets
for(auto& element : elements){
buckets[Hash{}(element.key) % max_size].push_back(element);
}
//sort the buckets based on size, largest first
quicksort(buckets.begin(), buckets.end(), [](auto&& left, auto&& right) -> bool{
return left.size() > right.size();
});
//for each bucket, try different values of 'd' to try to find a hash that doesn't collide
for(current_bucket = 0;current_bucket < buckets.size();++current_bucket){
auto& bucket = buckets[current_bucket];
//only handle buckets containing collisions
if(bucket.size() <= 1)
break;
array<bool,N> pass_slots_used;
vector<size_t,N> pass_slots;
size_t d = 1;
for(size_t i = 0;i < bucket.size();){
size_t slot = Hash{}(bucket[i].key, d) % max_size;
if(pass_slots_used[slot] || slots_used[slot]){
//slot already in use, try another value for 'd'
++d;
i = 0;
pass_slots_used.fill(false);
pass_slots.clear();
}else{
//slot is good to go
pass_slots_used[slot] = true;
pass_slots.push_back(slot);
++i;
}
}
//store the successful value of 'd' at index of the first hash for this bucket
m_g[Hash{}(bucket[0].key) % max_size] = d;
//take the value from the temporary bucket into the permanent slot
for(size_t i = 0;i < bucket.size();++i){
m_values[pass_slots[i]] = std::move(bucket[i].value);
slots_used[pass_slots[i]] = true;
}
}
//Handle remaining single value buckets
size_t next_free_slot = 0;
for(;current_bucket < buckets.size();++current_bucket){
auto& bucket = buckets[current_bucket];
if(bucket.size() == 0)
break;
for(;slots_used[next_free_slot];++next_free_slot);
m_g[Hash{}(bucket[0].key) % max_size] = (next_free_slot | single_bucket_bit);
m_values[next_free_slot] = std::move(bucket[0].value);
slots_used[next_free_slot] = true;
}
}
//no key checks. give a correct key or get a random answer :)
constexpr value_type& operator[](const Key& key){
size_t d = m_g[Hash{}(key) % max_size];
if(d & single_bucket_bit)
return m_values[d & ~single_bucket_bit];
return m_values[Hash{}(key, d) % max_size];
}
constexpr const value_type& operator[](const Key& key)const{
size_t d = m_g[Hash{}(key) % max_size];
if(d & single_bucket_bit)
return m_values[d & ~single_bucket_bit];
return m_values[Hash{}(key, d) % max_size];
}
};
template<class Key, class Value, size_t N, class Hash = hash<Key>>
constexpr auto make_hashmap(const element<Key,Value>(&list)[N]){
return hashmap<Key,Value,N,Hash>(list);
}
}
#ifdef REXY_STRING_BASE_HPP
#include "string_hash.hpp"
#endif
#endif

View File

@ -0,0 +1,40 @@
/**
This file is a part of rexy's general purpose library
Copyright (C) 2020 rexy712
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef REXY_CX_STRING_HASH_HPP
#define REXY_CX_STRING_HASH_HPP
#include "hash.hpp"
#include "../string_base.hpp"
namespace rexy::cx{
template<>
struct hash<rexy::static_string>{
constexpr size_t operator()(const rexy::static_string& t, size_t salt = 0){
size_t hash = 5381 + salt;
for(size_t i = 0;i < t.length();++i){
hash = ((hash << 5) + hash) ^ t[i];
}
return hash;
}
};
}
#endif

View File

@ -0,0 +1,70 @@
/**
This file is a part of rexy's general purpose library
Copyright (C) 2020 rexy712
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef REXY_CX_UTILITY_HPP
#define REXY_CX_UTILITY_HPP
#include <utility> //forward, move
namespace rexy::cx{
namespace{
template<class T>
constexpr void swap(T& l, T& r){
T tmp = l;
l = r;
r = tmp;
}
template<class T, class U = T>
constexpr T exchange(T& l, U&& r){
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){
return l < r ? l : r;
}
template<class T, class Compare>
constexpr const T& min(const T& l, const T& r, Compare cmp){
return cmp(l, r) ? l : r;
}
template<class T>
constexpr const T& max(const T& l, const T& r){
return l > r ? l : r;
}
template<class T, class Compare>
constexpr const T& max(const T& l, const T& r, Compare cmp){
return cmp(l, r) ? l : r;
}
constexpr size_t strlen(const char* c){
size_t i = 0;
for(;c[i];++i);
return i;
}
constexpr int strcmp(const char* l, const char* r){
using uchar = unsigned char;
for(;*l == *r && *l;++l, ++r);
return (static_cast<uchar>(*l)) - (static_cast<uchar>(*r));
}
}
}
#endif

213
include/rexy/cx/vector.hpp Normal file
View File

@ -0,0 +1,213 @@
/**
This file is a part of rexy's general purpose library
Copyright (C) 2020 rexy712
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef REXY_CX_VECTOR_HPP
#define REXY_CX_VECTOR_HPP
#include <cstddef> //size_t
#include <utility> //move, forward
#include "utility.hpp" //swap
namespace rexy::cx{
template<class T, size_t N>
class vector
{
public:
using value_type = T;
using size_type = size_t;
using difference_type = ptrdiff_t;
using iterator = T*;
using const_iterator = const T*;
using reference = T&;
using const_reference = const T&;
using pointer = T*;
using const_pointer = const T*;
static constexpr size_type max_elements = N;
private:
T m_elements[N] = {};
size_type m_size = 0;
public:
constexpr vector(void) = default;
constexpr vector(const vector&) = default;
constexpr vector(vector&&) = default;
constexpr vector(size_type count, const T& value){
for(size_type i = 0;i < min(count, max_elements);++i){
m_elements[i] = value;
}
}
~vector(void) = default;
constexpr vector& operator=(const vector&) = default;
constexpr vector& operator=(vector&&) = default;
constexpr reference at(size_type pos){
return m_elements[pos];
}
constexpr const_reference at(size_type pos)const{
return m_elements[pos];
}
constexpr reference operator[](size_type pos){
return m_elements[pos];
}
constexpr const_reference operator[](size_type pos)const{
return m_elements[pos];
}
constexpr reference front(void){
return m_elements[0];
}
constexpr const_reference front(void)const{
return m_elements[0];
}
constexpr reference back(void){
return m_elements[m_size-1];
}
constexpr const_reference back(void)const{
return m_elements[m_size-1];
}
constexpr const_pointer data(void)const{
return m_elements;
}
constexpr iterator begin(void){
return m_elements;
}
constexpr const_iterator begin(void)const{
return m_elements;
}
constexpr const_iterator cbegin(void)const{
return m_elements;
}
constexpr iterator end(void){
return m_elements+max_elements;
}
constexpr const_iterator end(void)const{
return m_elements+max_elements;
}
constexpr const_iterator cend(void)const{
return m_elements+max_elements;
}
constexpr bool empty(void)const{
return m_size == 0;
}
constexpr size_type size(void)const{
return m_size;
}
constexpr size_type max_size(void)const{
return max_elements;
}
constexpr size_type capacity(void)const{
return max_elements;
}
constexpr void clear(void){
m_size = 0;
}
constexpr iterator insert(iterator pos, const T& value){
auto start = pos;
auto it = pos;
++pos;
for(;pos != end();++it,++pos){
*pos = std::move(*it);
}
*start = value;
return start;
}
constexpr iterator insert(const_iterator pos, T&& value){
auto start = pos;
auto it = pos;
++pos;
for(;pos != end();++it,++pos){
*pos = std::move(*it);
}
*start = std::move(value);
return start;
}
template<class... Args>
constexpr iterator emplace(const_iterator pos, Args&&... args){
auto start = pos;
auto it = pos;
++pos;
for(;pos != end();++it,++pos){
*pos = std::move(*it);
}
*start = T{std::forward<Args>(args)...};
return start;
}
constexpr iterator erase(const_iterator pos){
auto start = pos;
auto it = pos;
++pos;
for(;pos != end();++it,++pos){
*it = std::move(*pos);
}
return start;
}
constexpr iterator push_back(const T& value){
m_elements[m_size] = value;
return m_elements+(m_size++);
}
template<class... Args>
constexpr iterator emplace_back(Args&&... args){
m_elements[m_size++] = T{std::forward<Args>(args)...};
return m_elements+(m_size++);
}
constexpr void pop_back(void){
--m_size;
}
constexpr void resize(size_type count){
if(count <= max_size())
m_size = count;
}
constexpr void resize(size_type count, const value_type& value){
if(count > m_size){
if(count <= max_size()){
for(size_type i = m_size;i < count;++i){
m_elements[i] = value;
}
}
}else{
m_size = count;
}
}
constexpr void fill(const T& value){
for(auto it = begin();it != end();++it){
*it = value;
}
}
constexpr void swap(vector& other){
size_type i = 0;
for(;i < m_size;++i){
swap(m_elements[i], other.m_elements[i]);
}
for(;i < other.m_size;++i){
swap(m_elements[i], other.m_elements[i]);
}
swap(m_size, other.m_size);
}
};
}
#endif

View File

@ -1,78 +0,0 @@
/**
This file is a part of rexy's general purpose library
Copyright (C) 2020 rexy712
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef REXY_DETAIL_UTIL_HPP
#define REXY_DETAIL_UTIL_HPP
#include <cstddef> //size_t
namespace rexy::detail{
namespace{
//including <algorithm> causes long compile times. so just make my own max instead
template<class T>
constexpr const T& max(const T& a, const T& b){
return (a < b) ? b : a;
}
template<class T>
constexpr const T& min(const T& a, const T& b){
return (a > b) ? b : a;
}
constexpr size_t cx_strlen(const char* c){
size_t i = 0;
for(;c[i];++i);
return i;
}
constexpr int cx_strcmp(const char* l, const char* r){
using uchar = unsigned char;
for(;*l == *r && *l;++l, ++r);
return (uchar{*l}) - (uchar{*r});
}
} //anonymous namespace
} //namespace detail
//std::swap and std::exchange aren't constexpr until c++20
#if __cplusplus > 201703L
#include <utility>
#define rexy_cx_swap(...) std::swap(__VA_ARGS__)
#define rexy_cx_exchange(...) std::exchange(__VA_ARGS__)
#else
#include <type_traits>
namespace rexy::detail{
namespace{
template<class T>
constexpr void cx_swap(T& a, T& b)noexcept(std::is_nothrow_move_constructible<T>::value &&
std::is_nothrow_move_assignable<T>::value)
{
T tmp = std::move(a);
a = std::move(b);
b = std::move(tmp);
}
template<class T, class U = T>
constexpr T cx_exchange(T& t, U&& u){
T old = std::move(t);
t = std::forward<U>(u);
return old;
}
}
} //namespace detail
#define rexy_cx_swap(...) detail::cx_swap(__VA_ARGS__)
#define rexy_cx_exchange(...) detail::cx_exchange(__VA_ARGS__)
#endif
#endif

View File

@ -24,6 +24,7 @@
#include "string.hpp" #include "string.hpp"
#include "binary.hpp" #include "binary.hpp"
#include "cx/utility.hpp"
namespace rexy{ namespace rexy{
@ -38,11 +39,11 @@ namespace rexy{
filerd(const char* f, const char* mode = "r"); filerd(const char* f, const char* mode = "r");
filerd(const filerd&) = delete; filerd(const filerd&) = delete;
constexpr filerd(filerd&& f): constexpr filerd(filerd&& f):
m_fp(rexy_cx_exchange(f.m_fp, nullptr)){} m_fp(cx::exchange(f.m_fp, nullptr)){}
~filerd(void); ~filerd(void);
filerd& operator=(const filerd&) = delete; filerd& operator=(const filerd&) = delete;
constexpr filerd& operator=(filerd&& f){ constexpr filerd& operator=(filerd&& f){
rexy_cx_swap(m_fp, f.m_fp); cx::swap(m_fp, f.m_fp);
return *this; return *this;
} }

View File

@ -24,7 +24,7 @@
#include <cstdlib> //size_t #include <cstdlib> //size_t
#include "steal.hpp" #include "steal.hpp"
#include "detail/util.hpp" #include "cx/utility.hpp"
namespace rexy{ namespace rexy{
@ -53,7 +53,7 @@ namespace rexy{
public: public:
//Stop managing stored pointer. Does not free. //Stop managing stored pointer. Does not free.
constexpr char* release(void){return rexy_cx_exchange(m_data, nullptr);} constexpr char* release(void){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{return m_length;}
@ -198,7 +198,7 @@ namespace rexy{
} //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){
return left.valid() && right.valid() && left.length() == right.length() && !detail::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){
@ -241,4 +241,8 @@ namespace{
#include "detail/binary_string_conv.hpp" #include "detail/binary_string_conv.hpp"
#endif #endif
#ifdef REXY_CX_HASH_HPP
#include "cx/string_hash.hpp"
#endif
#endif #endif

View File

@ -23,7 +23,7 @@
#include <cstdlib> //memcpy #include <cstdlib> //memcpy
#include <cstring> //strlen, strcpy #include <cstring> //strlen, strcpy
#include "detail/util.hpp" //max #include "cx/utility.hpp" //max
namespace rexy{ namespace rexy{
@ -58,7 +58,7 @@ namespace rexy{
} }
template<class Allocator> template<class Allocator>
constexpr string_intermediary<Allocator>::string_intermediary(rexy::steal<char*> data): constexpr string_intermediary<Allocator>::string_intermediary(rexy::steal<char*> data):
string_base(data.value() ? detail::cx_strlen(data.value()) : 0) string_base(data.value() ? cx::strlen(data.value()) : 0)
{ {
m_data = data.value(); m_data = data.value();
m_length = m_cap; m_length = m_cap;
@ -82,7 +82,7 @@ namespace rexy{
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):
string_base(rexy_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):
@ -106,7 +106,7 @@ namespace rexy{
} }
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){
rexy_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;
return *this; return *this;
@ -156,7 +156,7 @@ namespace rexy{
m_length += len; m_length += len;
m_data[m_length] = 0; m_data[m_length] = 0;
}else{ }else{
string_intermediary tmp(detail::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(tmp.m_data, m_data, m_length); memcpy(tmp.m_data, m_data, m_length);
memcpy(tmp.m_data+m_length, data, len); memcpy(tmp.m_data+m_length, data, len);
@ -187,7 +187,7 @@ namespace rexy{
strcpy(m_data, s); strcpy(m_data, s);
}else{ }else{
Allocator::free(m_data); Allocator::free(m_data);
m_cap = detail::max(len, m_cap*2); m_cap = cx::max(len, m_cap*2);
m_data = reinterpret_cast<char*>(Allocator::copy(s, m_cap+1)); m_data = reinterpret_cast<char*>(Allocator::copy(s, m_cap+1));
if(!m_data){ if(!m_data){
m_length = 0; m_length = 0;
@ -245,10 +245,10 @@ namespace rexy{
return *this; return *this;
} }
constexpr static_string::static_string(const char* c): constexpr static_string::static_string(const char* c):
static_string(const_cast<char*>(c), detail::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){
m_data = const_cast<char*>(c); m_data = const_cast<char*>(c);
m_length = detail::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){

View File

@ -3,3 +3,11 @@
#include "rexy/string.hpp" #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/cx/algorithm.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"