Add string searching with default option of two-way algorithm or user specified algorithm. Rearrange file structure to hopefully make things not seem arbitrarily placed in the cx subfolder
This commit is contained in:
parent
2ea8c617f0
commit
28c8caae0a
@ -34,7 +34,7 @@ if(BUILD_TESTS)
|
|||||||
add_subdirectory(tests)
|
add_subdirectory(tests)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(LIBREXY_PUBLIC_HEADERS "include/rexy/traits.hpp" "include/rexy/steal.hpp" "include/rexy/binary.hpp" "include/rexy/expression.hpp" "include/rexy/binary_base.hpp" "include/rexy/binary_base.tpp" "include/rexy/string_base.hpp" "include/rexy/string.hpp" "include/rexy/filerd.hpp" "include/rexy/string_base.tpp" "include/rexy/allocator.hpp")
|
set(LIBREXY_PUBLIC_HEADERS "include/rexy/algorithm.hpp" "include/rexy/utility.hpp" "include/rexy/basic_string_hash.hpp" "include/rexy/hash.hpp" "include/rexy/static_string_hash.hpp" "include/rexy/string_hash.hpp" "include/rexy/traits.hpp" "include/rexy/steal.hpp" "include/rexy/binary.hpp" "include/rexy/expression.hpp" "include/rexy/binary_base.hpp" "include/rexy/binary_base.tpp" "include/rexy/string_base.hpp" "include/rexy/string.hpp" "include/rexy/filerd.hpp" "include/rexy/string_base.tpp" "include/rexy/allocator.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
|
||||||
|
|||||||
109
include/rexy/algorithm.hpp
Normal file
109
include/rexy/algorithm.hpp
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
/**
|
||||||
|
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_ALGORITHM_HPP
|
||||||
|
#define REXY_ALGORITHM_HPP
|
||||||
|
|
||||||
|
#include "utility.hpp" //swap
|
||||||
|
#include <cstdint> //SIZE_MAX
|
||||||
|
#include "detail/algorithm.hpp"
|
||||||
|
#include <cstdlib> //size_t
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
namespace rexy{
|
||||||
|
|
||||||
|
template<class Iter, class Compare>
|
||||||
|
constexpr void quicksort(Iter left, Iter right, const Compare& cmp)
|
||||||
|
noexcept(noexcept(detail::qs_partition(left, right, cmp)))
|
||||||
|
{
|
||||||
|
while(left < right){
|
||||||
|
auto real_right = right-1;
|
||||||
|
auto pivot = detail::qs_partition(left, real_right, cmp);
|
||||||
|
quicksort(left, pivot, cmp);
|
||||||
|
left = ++pivot;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class HIter, class NIter>
|
||||||
|
constexpr HIter two_way_search(const HIter& hstart, const HIter& hend, const NIter& nstart, const NIter& nend){
|
||||||
|
size_t j = 0;
|
||||||
|
size_t i = 0;
|
||||||
|
size_t nlen = nend - nstart;
|
||||||
|
size_t hlen = hend - hstart;
|
||||||
|
auto [max_suffix, period] = detail::critical_factorization(nstart, nend);
|
||||||
|
|
||||||
|
if(detail::iter_compare(nstart, nstart + period, max_suffix)){
|
||||||
|
size_t memory = SIZE_MAX;
|
||||||
|
while(j <= hlen - nlen){
|
||||||
|
i = max(max_suffix, memory) + 1;
|
||||||
|
//right side
|
||||||
|
while(i < nlen && nstart[i] == hstart[i + j]){
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
if(i >= nlen){
|
||||||
|
i = max_suffix;
|
||||||
|
//left side
|
||||||
|
while(i > memory && nstart[i] == hstart[i + j]){
|
||||||
|
--i;
|
||||||
|
}
|
||||||
|
if(i <= memory){
|
||||||
|
return hstart + j; //?
|
||||||
|
}
|
||||||
|
j += period;
|
||||||
|
memory = nlen - period - 1;
|
||||||
|
}else{
|
||||||
|
j += (i - max_suffix);
|
||||||
|
memory = SIZE_MAX;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
period = max(max_suffix + 1, nlen - max_suffix - 1) + 1;
|
||||||
|
j = 0;
|
||||||
|
while(j <= hlen - nlen){
|
||||||
|
i = max_suffix + 1;
|
||||||
|
while(i < nlen && nstart[i] == hstart[i + j]){
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
if(i >= nlen){
|
||||||
|
i = max_suffix;
|
||||||
|
while(i != SIZE_MAX && nstart[i] == hstart[i + j]){
|
||||||
|
--i;
|
||||||
|
}
|
||||||
|
if(i == SIZE_MAX){
|
||||||
|
return hstart + j; //?
|
||||||
|
}
|
||||||
|
j += period;
|
||||||
|
}else{
|
||||||
|
j += (i - max_suffix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hend;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct two_way_searcher{
|
||||||
|
template<class HIter, class NIter>
|
||||||
|
constexpr HIter operator()(const HIter& hstart, const HIter& hend, const NIter& nstart, const NIter& nend)const{
|
||||||
|
return two_way_search(hstart, hend, nstart, nend);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -16,13 +16,13 @@
|
|||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef REXY_CX_BASIC_STRING_HASH_HPP
|
#ifndef REXY_BASIC_STRING_HASH_HPP
|
||||||
#define REXY_CX_BASIC_STRING_HASH_HPP
|
#define REXY_BASIC_STRING_HASH_HPP
|
||||||
|
|
||||||
#include "string_hash.hpp"
|
#include "string_hash.hpp"
|
||||||
#include "../string.hpp"
|
#include "string.hpp"
|
||||||
|
|
||||||
namespace rexy::cx{
|
namespace rexy{
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct hash<rexy::string> : public string_hash<rexy::string>{};
|
struct hash<rexy::string> : public string_hash<rexy::string>{};
|
||||||
@ -26,7 +26,7 @@
|
|||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <iterator> //reverse_iterator
|
#include <iterator> //reverse_iterator
|
||||||
|
|
||||||
#include "cx/utility.hpp" //max
|
#include "utility.hpp" //max
|
||||||
#include "steal.hpp"
|
#include "steal.hpp"
|
||||||
#include "expression.hpp"
|
#include "expression.hpp"
|
||||||
#include "traits.hpp"
|
#include "traits.hpp"
|
||||||
|
|||||||
@ -23,12 +23,10 @@
|
|||||||
#include <utility> //move
|
#include <utility> //move
|
||||||
#include <cstring> //memcpy
|
#include <cstring> //memcpy
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include "cx/utility.hpp" //max
|
#include "utility.hpp" //max
|
||||||
#include "steal.hpp"
|
#include "steal.hpp"
|
||||||
#include "detail/string_appender.hpp"
|
#include "detail/string_appender.hpp"
|
||||||
|
|
||||||
#include "cx/utility.hpp" //strlen
|
|
||||||
|
|
||||||
#define STOP_STRICT_ALIAS_WARNING(x) (x)
|
#define STOP_STRICT_ALIAS_WARNING(x) (x)
|
||||||
|
|
||||||
namespace rexy{
|
namespace rexy{
|
||||||
@ -42,7 +40,7 @@ namespace rexy{
|
|||||||
constexpr binary_base::binary_base(const binary_base&)noexcept{}
|
constexpr binary_base::binary_base(const binary_base&)noexcept{}
|
||||||
|
|
||||||
constexpr auto binary_base::release(void)noexcept -> pointer{
|
constexpr auto binary_base::release(void)noexcept -> pointer{
|
||||||
return cx::exchange(m_data, nullptr);
|
return exchange(m_data, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr auto binary_base::size(void)const -> size_type{
|
constexpr auto binary_base::size(void)const -> size_type{
|
||||||
@ -109,7 +107,7 @@ namespace rexy{
|
|||||||
constexpr basic_binary<Allocator>::basic_binary(void)noexcept{}
|
constexpr basic_binary<Allocator>::basic_binary(void)noexcept{}
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
constexpr basic_binary<Allocator>::basic_binary(rexy::steal<pointer> data)noexcept:
|
constexpr basic_binary<Allocator>::basic_binary(rexy::steal<pointer> data)noexcept:
|
||||||
binary_base(data.value() ? cx::strlen(data.value()) : 0)
|
binary_base(data.value() ? strlen(data.value()) : 0)
|
||||||
{
|
{
|
||||||
m_data = data.value();
|
m_data = data.value();
|
||||||
m_size = m_cap;
|
m_size = m_cap;
|
||||||
@ -132,7 +130,7 @@ namespace rexy{
|
|||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
basic_binary<Allocator>::basic_binary(const_pointer data)
|
basic_binary<Allocator>::basic_binary(const_pointer data)
|
||||||
noexcept(noexcept(this->allocate(0))):
|
noexcept(noexcept(this->allocate(0))):
|
||||||
basic_binary(data ? this->allocate(cx::strlen(data)) : nullptr, cx::strlen(data))
|
basic_binary(data ? this->allocate(strlen(data)) : nullptr, strlen(data))
|
||||||
{
|
{
|
||||||
if(data)
|
if(data)
|
||||||
memcpy(m_data, data, m_cap);
|
memcpy(m_data, data, m_cap);
|
||||||
@ -163,7 +161,7 @@ namespace rexy{
|
|||||||
}
|
}
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
constexpr basic_binary<Allocator>::basic_binary(basic_binary&& b)noexcept:
|
constexpr basic_binary<Allocator>::basic_binary(basic_binary&& b)noexcept:
|
||||||
binary_base(cx::exchange(b.m_data, nullptr), b.m_size, b.m_cap){}
|
binary_base(exchange(b.m_data, nullptr), b.m_size, b.m_cap){}
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
basic_binary<Allocator>::basic_binary(const binary_base& b)
|
basic_binary<Allocator>::basic_binary(const binary_base& b)
|
||||||
noexcept(noexcept(this->allocate(0))):
|
noexcept(noexcept(this->allocate(0))):
|
||||||
@ -188,7 +186,7 @@ namespace rexy{
|
|||||||
constexpr basic_binary<Allocator>& basic_binary<Allocator>::operator=(basic_binary&& b)noexcept{
|
constexpr basic_binary<Allocator>& basic_binary<Allocator>::operator=(basic_binary&& b)noexcept{
|
||||||
m_size = b.m_size;
|
m_size = b.m_size;
|
||||||
m_cap = b.m_cap;
|
m_cap = b.m_cap;
|
||||||
cx::swap(m_data, b.m_data);
|
swap(m_data, b.m_data);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
@ -231,7 +229,7 @@ namespace rexy{
|
|||||||
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);
|
||||||
cx::swap(m_data, STOP_STRICT_ALIAS_WARNING(tmp).m_data);
|
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;
|
||||||
}
|
}
|
||||||
@ -241,7 +239,7 @@ namespace rexy{
|
|||||||
noexcept(this->deallocate(nullptr,0)))
|
noexcept(this->deallocate(nullptr,0)))
|
||||||
{
|
{
|
||||||
if(m_size + len > m_cap)
|
if(m_size + len > m_cap)
|
||||||
resize(cx::max(m_cap*2, m_size+len));
|
resize(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;
|
||||||
}
|
}
|
||||||
@ -263,7 +261,7 @@ namespace rexy{
|
|||||||
constexpr static_binary::static_binary(const_pointer str, size_type len)noexcept:
|
constexpr static_binary::static_binary(const_pointer str, size_type len)noexcept:
|
||||||
binary_base(const_cast<pointer>(str), len, len){}
|
binary_base(const_cast<pointer>(str), len, len){}
|
||||||
constexpr static_binary::static_binary(const_pointer str)noexcept:
|
constexpr static_binary::static_binary(const_pointer str)noexcept:
|
||||||
static_binary(str, cx::strlen(str)){}
|
static_binary(str, strlen(str)){}
|
||||||
constexpr static_binary::static_binary(const static_binary& s)noexcept:
|
constexpr static_binary::static_binary(const static_binary& s)noexcept:
|
||||||
static_binary(s.get(), s.size()){}
|
static_binary(s.get(), s.size()){}
|
||||||
constexpr static_binary::static_binary(static_binary&& s)noexcept:
|
constexpr static_binary::static_binary(static_binary&& s)noexcept:
|
||||||
@ -271,7 +269,7 @@ namespace rexy{
|
|||||||
|
|
||||||
constexpr static_binary& static_binary::operator=(const_pointer str)noexcept{
|
constexpr static_binary& static_binary::operator=(const_pointer str)noexcept{
|
||||||
m_data = const_cast<pointer>(str);
|
m_data = const_cast<pointer>(str);
|
||||||
m_size = cx::strlen(str);
|
m_size = strlen(str);
|
||||||
m_cap = m_size;
|
m_cap = m_size;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,65 +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_CX_ALGORITHM_HPP
|
|
||||||
#define REXY_CX_ALGORITHM_HPP
|
|
||||||
|
|
||||||
#include "utility.hpp" //swap
|
|
||||||
|
|
||||||
#include <type_traits>
|
|
||||||
|
|
||||||
namespace rexy::cx{
|
|
||||||
|
|
||||||
namespace detail{
|
|
||||||
template<class Iter, class Compare>
|
|
||||||
constexpr Iter qs_partition(Iter left, Iter right, const Compare& cmp)
|
|
||||||
noexcept(std::is_nothrow_invocable<Compare,decltype(*left),decltype(*right)>::value &&
|
|
||||||
noexcept(cx::swap(*left,*right)))
|
|
||||||
{
|
|
||||||
auto range = right - left;
|
|
||||||
auto pivot = left + (range / 2);
|
|
||||||
auto value = *pivot;
|
|
||||||
|
|
||||||
//move pivot value all the way to the right side to preserve it
|
|
||||||
cx::swap(*pivot, *right);
|
|
||||||
for(auto it = left;it != right;++it){
|
|
||||||
if(cmp(*it, value)){
|
|
||||||
cx::swap(*left, *it);
|
|
||||||
++left;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//move pivot value back to proper position
|
|
||||||
cx::swap(*left, *right);
|
|
||||||
return left;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
template<class Iter, class Compare>
|
|
||||||
constexpr void quicksort(Iter left, Iter right, const Compare& cmp)
|
|
||||||
noexcept(noexcept(cx::detail::qs_partition(left, right, cmp)))
|
|
||||||
{
|
|
||||||
while(left < right){
|
|
||||||
auto real_right = right-1;
|
|
||||||
auto pivot = detail::qs_partition(left, real_right, cmp);
|
|
||||||
quicksort(left, pivot, cmp);
|
|
||||||
left = ++pivot;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@ -20,7 +20,7 @@
|
|||||||
#define REXY_CX_ARRAY_HPP
|
#define REXY_CX_ARRAY_HPP
|
||||||
|
|
||||||
#include <cstddef> //size_t
|
#include <cstddef> //size_t
|
||||||
#include "utility.hpp" //swap
|
#include "../utility.hpp" //swap
|
||||||
#include "detail/bool_specialize_base.hpp"
|
#include "detail/bool_specialize_base.hpp"
|
||||||
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
@ -117,10 +117,10 @@ namespace rexy::cx{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
constexpr void swap(array& other)
|
constexpr void swap(array& other)
|
||||||
noexcept(noexcept(cx::swap(m_elements[0], other.m_elements[0])))
|
noexcept(noexcept(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){
|
||||||
cx::swap(m_elements[i], other.m_elements[i]);
|
swap(m_elements[i], other.m_elements[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -216,7 +216,7 @@ namespace rexy::cx{
|
|||||||
}
|
}
|
||||||
constexpr void swap(array& other)noexcept{
|
constexpr void swap(array& other)noexcept{
|
||||||
for(size_type i = 0;i < arr_size;++i){
|
for(size_type i = 0;i < arr_size;++i){
|
||||||
cx::swap(m_elements[i], other.m_elements[i]);
|
swap(m_elements[i], other.m_elements[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -19,7 +19,7 @@
|
|||||||
#ifndef REXY_CX_CX_STRING_HASH_HPP
|
#ifndef REXY_CX_CX_STRING_HASH_HPP
|
||||||
#define REXY_CX_CX_STRING_HASH_HPP
|
#define REXY_CX_CX_STRING_HASH_HPP
|
||||||
|
|
||||||
#include "string_hash.hpp"
|
#include "../string_hash.hpp"
|
||||||
#include "string.hpp"
|
#include "string.hpp"
|
||||||
|
|
||||||
namespace rexy::cx{
|
namespace rexy::cx{
|
||||||
|
|||||||
@ -22,7 +22,7 @@
|
|||||||
#include <cstddef> //size_t
|
#include <cstddef> //size_t
|
||||||
#include <utility> //move, forward, pair
|
#include <utility> //move, forward, pair
|
||||||
#include <climits> //CHAR_BIT
|
#include <climits> //CHAR_BIT
|
||||||
#include "../utility.hpp" //swap
|
#include "../../utility.hpp" //swap
|
||||||
|
|
||||||
|
|
||||||
namespace rexy::cx::detail{
|
namespace rexy::cx::detail{
|
||||||
|
|||||||
@ -21,8 +21,8 @@
|
|||||||
|
|
||||||
#include "vector.hpp"
|
#include "vector.hpp"
|
||||||
#include "array.hpp"
|
#include "array.hpp"
|
||||||
#include "algorithm.hpp"
|
#include "../algorithm.hpp"
|
||||||
#include "hash.hpp"
|
#include "../hash.hpp"
|
||||||
|
|
||||||
#include <climits> //CHAR_BIT
|
#include <climits> //CHAR_BIT
|
||||||
#include <cstddef> //size_t, ptrdiff_t
|
#include <cstddef> //size_t, ptrdiff_t
|
||||||
@ -103,7 +103,7 @@ namespace rexy::cx{
|
|||||||
}
|
}
|
||||||
|
|
||||||
//sort the buckets based on size, largest first
|
//sort the buckets based on size, largest first
|
||||||
cx::quicksort(buckets.begin(), buckets.end(), [](auto&& left, auto&& right) -> bool{
|
quicksort(buckets.begin(), buckets.end(), [](auto&& left, auto&& right) -> bool{
|
||||||
return left.size() > right.size();
|
return left.size() > right.size();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -199,7 +199,7 @@ namespace rexy::cx{
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef REXY_STRING_BASE_HPP
|
#ifdef REXY_STRING_BASE_HPP
|
||||||
#include "string_hash.hpp"
|
#include "../string_hash.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -25,7 +25,7 @@ namespace rexy::cx{
|
|||||||
}
|
}
|
||||||
|
|
||||||
#include "../string_base.hpp"
|
#include "../string_base.hpp"
|
||||||
#include "utility.hpp"
|
#include "../utility.hpp"
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <cstddef> //ptrdiff_t
|
#include <cstddef> //ptrdiff_t
|
||||||
|
|
||||||
@ -67,7 +67,7 @@ namespace rexy::cx{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
constexpr string(const_pointer data)noexcept:
|
constexpr string(const_pointer data)noexcept:
|
||||||
m_length(cx::strlen(data))
|
m_length(strlen(data))
|
||||||
{
|
{
|
||||||
for(size_type i = 0;i < m_length;++i){
|
for(size_type i = 0;i < m_length;++i){
|
||||||
m_data[i] = data[i];
|
m_data[i] = data[i];
|
||||||
@ -101,7 +101,7 @@ namespace rexy::cx{
|
|||||||
~string(void)noexcept = default;
|
~string(void)noexcept = default;
|
||||||
|
|
||||||
constexpr string& operator=(const_pointer c)noexcept{
|
constexpr string& operator=(const_pointer c)noexcept{
|
||||||
m_length = cx::strlen(c);
|
m_length = strlen(c);
|
||||||
for(size_type i = 0;i < m_length;++i){
|
for(size_type i = 0;i < m_length;++i){
|
||||||
m_data[i] = c[i];
|
m_data[i] = c[i];
|
||||||
}
|
}
|
||||||
@ -160,7 +160,7 @@ namespace rexy::cx{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
constexpr void append(const_pointer data)noexcept{
|
constexpr void append(const_pointer data)noexcept{
|
||||||
append(data, cx::strlen(data));
|
append(data, strlen(data));
|
||||||
}
|
}
|
||||||
constexpr void append(const string& s)noexcept{
|
constexpr void append(const string& s)noexcept{
|
||||||
append(s.get(), s.length());
|
append(s.get(), s.length());
|
||||||
|
|||||||
@ -23,7 +23,7 @@
|
|||||||
#include <utility> //move, forward
|
#include <utility> //move, forward
|
||||||
|
|
||||||
#include "detail/bool_specialize_base.hpp"
|
#include "detail/bool_specialize_base.hpp"
|
||||||
#include "utility.hpp" //swap
|
#include "../utility.hpp" //swap
|
||||||
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
@ -60,7 +60,7 @@ namespace rexy::cx{
|
|||||||
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;
|
||||||
}
|
}
|
||||||
m_size = cx::min(count, max_elements);
|
m_size = min(count, max_elements);
|
||||||
}
|
}
|
||||||
|
|
||||||
~vector(void)noexcept = default;
|
~vector(void)noexcept = default;
|
||||||
@ -230,16 +230,16 @@ namespace rexy::cx{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
constexpr void swap(vector& other)
|
constexpr void swap(vector& other)
|
||||||
noexcept(noexcept(cx::swap(m_elements[0], other.m_elements[0])))
|
noexcept(noexcept(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){
|
||||||
cx::swap(m_elements[i], other.m_elements[i]);
|
swap(m_elements[i], other.m_elements[i]);
|
||||||
}
|
}
|
||||||
for(;i < other.m_size;++i){
|
for(;i < other.m_size;++i){
|
||||||
cx::swap(m_elements[i], other.m_elements[i]);
|
swap(m_elements[i], other.m_elements[i]);
|
||||||
}
|
}
|
||||||
cx::swap(m_size, other.m_size);
|
swap(m_size, other.m_size);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -280,7 +280,7 @@ namespace rexy::cx{
|
|||||||
for(size_type j = 0;j < bits_count;++j){
|
for(size_type j = 0;j < bits_count;++j){
|
||||||
m_elements[i][j] = value;
|
m_elements[i][j] = value;
|
||||||
}
|
}
|
||||||
m_size = cx::min(count, max_elements);
|
m_size = min(count, max_elements);
|
||||||
}
|
}
|
||||||
|
|
||||||
~vector(void)noexcept = default;
|
~vector(void)noexcept = default;
|
||||||
@ -422,7 +422,7 @@ namespace rexy::cx{
|
|||||||
}
|
}
|
||||||
constexpr void resize(size_type count, const value_type& value)noexcept{
|
constexpr void resize(size_type count, const value_type& value)noexcept{
|
||||||
if(count > m_size){
|
if(count > m_size){
|
||||||
auto actual_count = cx::min(count, max_size());
|
auto actual_count = min(count, max_size());
|
||||||
auto num = actual_count - m_size;
|
auto num = actual_count - m_size;
|
||||||
auto it = end();
|
auto it = end();
|
||||||
for(size_type i = 0;i < num;++i){
|
for(size_type i = 0;i < num;++i){
|
||||||
@ -446,12 +446,12 @@ namespace rexy::cx{
|
|||||||
++other_byte_count;
|
++other_byte_count;
|
||||||
size_type i = 0;
|
size_type i = 0;
|
||||||
for(;i < byte_count;++i){
|
for(;i < byte_count;++i){
|
||||||
cx::swap(m_elements[i], other.m_elements[i]);
|
swap(m_elements[i], other.m_elements[i]);
|
||||||
}
|
}
|
||||||
for(;i < other_byte_count;++i){
|
for(;i < other_byte_count;++i){
|
||||||
cx::swap(m_elements[i], other.m_elements[i]);
|
swap(m_elements[i], other.m_elements[i]);
|
||||||
}
|
}
|
||||||
cx::swap(m_size, other.m_size);
|
swap(m_size, other.m_size);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
86
include/rexy/detail/algorithm.hpp
Normal file
86
include/rexy/detail/algorithm.hpp
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
#ifndef REXY_DETAIL_ALGORITHM_HPP
|
||||||
|
#define REXY_DETAIL_ALGORITHM_HPP
|
||||||
|
|
||||||
|
#include "../utility.hpp" //swap
|
||||||
|
|
||||||
|
#include <type_traits> //nothrow_invocable
|
||||||
|
#include <functional> //less, greater
|
||||||
|
#include <utility> //pair
|
||||||
|
#include <iterator> //iterator_traits
|
||||||
|
#include <cstdlib> //size_t
|
||||||
|
|
||||||
|
namespace rexy::detail{
|
||||||
|
|
||||||
|
template<class Iter, class Compare>
|
||||||
|
constexpr Iter qs_partition(Iter left, Iter right, const Compare& cmp)
|
||||||
|
noexcept(std::is_nothrow_invocable<Compare,decltype(*left),decltype(*right)>::value &&
|
||||||
|
noexcept(swap(*left,*right)))
|
||||||
|
{
|
||||||
|
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 Op>
|
||||||
|
constexpr std::pair<size_t,size_t> max_suffix(const Iter& needle, size_t nlen, const Op& op = Op()){
|
||||||
|
using value_type = typename std::iterator_traits<Iter>::value_type;
|
||||||
|
size_t max_suffix = -1;
|
||||||
|
size_t j = 0;
|
||||||
|
size_t k = 1;
|
||||||
|
size_t period = 1;
|
||||||
|
value_type a;
|
||||||
|
value_type b;
|
||||||
|
|
||||||
|
while(j + k < nlen){
|
||||||
|
a = needle[j + k];
|
||||||
|
b = needle[max_suffix + k];
|
||||||
|
if(op(a, b)){
|
||||||
|
j += k;
|
||||||
|
k = 1;
|
||||||
|
period = j - max_suffix;
|
||||||
|
}else if(a == b){
|
||||||
|
if(k != period){
|
||||||
|
++k;
|
||||||
|
}else{
|
||||||
|
j += period;
|
||||||
|
k = 1;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
max_suffix = j++;
|
||||||
|
k = period = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {max_suffix, period};
|
||||||
|
}
|
||||||
|
template<class Iter>
|
||||||
|
constexpr std::pair<size_t,size_t> critical_factorization(const Iter& nstart, const Iter& nend){
|
||||||
|
auto msuffix = max_suffix(nstart, nend - nstart, std::less{});
|
||||||
|
auto msuffix_rev = max_suffix(nstart, nend - nstart, std::greater{});
|
||||||
|
if(msuffix.first < msuffix_rev.first){
|
||||||
|
return msuffix_rev;
|
||||||
|
}
|
||||||
|
return msuffix;
|
||||||
|
}
|
||||||
|
template<class Iter>
|
||||||
|
constexpr bool iter_compare(const Iter& left, const Iter& right, size_t length){
|
||||||
|
for(size_t i = 0;i < length;++i){
|
||||||
|
if(left[i] != right[i])
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
#include "string.hpp"
|
#include "string.hpp"
|
||||||
#include "binary.hpp"
|
#include "binary.hpp"
|
||||||
#include "cx/utility.hpp"
|
#include "utility.hpp"
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
namespace rexy{
|
namespace rexy{
|
||||||
@ -40,11 +40,11 @@ namespace rexy{
|
|||||||
filerd(const char* f, const char* mode = "r")noexcept;
|
filerd(const char* f, const char* mode = "r")noexcept;
|
||||||
filerd(const filerd&) = delete;
|
filerd(const filerd&) = delete;
|
||||||
constexpr filerd(filerd&& f)noexcept:
|
constexpr filerd(filerd&& f)noexcept:
|
||||||
m_fp(cx::exchange(f.m_fp, nullptr)){}
|
m_fp(exchange(f.m_fp, nullptr)){}
|
||||||
~filerd(void)noexcept;
|
~filerd(void)noexcept;
|
||||||
filerd& operator=(const filerd&) = delete;
|
filerd& operator=(const filerd&) = delete;
|
||||||
constexpr filerd& operator=(filerd&& f)noexcept{
|
constexpr filerd& operator=(filerd&& f)noexcept{
|
||||||
cx::swap(m_fp, f.m_fp);
|
swap(m_fp, f.m_fp);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -16,12 +16,12 @@
|
|||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef REXY_CX_HASH_HPP
|
#ifndef REXY_HASH_HPP
|
||||||
#define REXY_CX_HASH_HPP
|
#define REXY_HASH_HPP
|
||||||
|
|
||||||
#include <climits> //CHAR_BIT
|
#include <climits> //CHAR_BIT
|
||||||
|
|
||||||
namespace rexy::cx{
|
namespace rexy{
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
struct hash{
|
struct hash{
|
||||||
@ -16,13 +16,13 @@
|
|||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef REXY_CX_STATIC_STRING_HASH_HPP
|
#ifndef REXY_STATIC_STRING_HASH_HPP
|
||||||
#define REXY_CX_STATIC_STRING_HASH_HPP
|
#define REXY_STATIC_STRING_HASH_HPP
|
||||||
|
|
||||||
#include "string_hash.hpp"
|
#include "string_hash.hpp"
|
||||||
#include "../string_base.hpp"
|
#include "string_base.hpp"
|
||||||
|
|
||||||
namespace rexy::cx{
|
namespace rexy{
|
||||||
|
|
||||||
template<class Char>
|
template<class Char>
|
||||||
struct hash<rexy::static_string<Char>> : public string_hash<rexy::static_string<Char>>{};
|
struct hash<rexy::static_string<Char>> : public string_hash<rexy::static_string<Char>>{};
|
||||||
@ -27,7 +27,7 @@
|
|||||||
#include <iterator> //reverse_iterator
|
#include <iterator> //reverse_iterator
|
||||||
|
|
||||||
#include "steal.hpp"
|
#include "steal.hpp"
|
||||||
#include "cx/utility.hpp"
|
#include "utility.hpp"
|
||||||
#include "traits.hpp"
|
#include "traits.hpp"
|
||||||
#include "expression.hpp"
|
#include "expression.hpp"
|
||||||
#include "detail/string_appender.hpp"
|
#include "detail/string_appender.hpp"
|
||||||
@ -200,8 +200,18 @@ namespace rexy{
|
|||||||
constexpr reference operator[](size_type i)noexcept{return get_pointer()[i];}
|
constexpr reference operator[](size_type i)noexcept{return get_pointer()[i];}
|
||||||
constexpr const_reference operator[](size_type i)const noexcept{return get_pointer()[i];}
|
constexpr const_reference operator[](size_type i)const noexcept{return get_pointer()[i];}
|
||||||
|
|
||||||
//constexpr bool search(const string_base& s)const;
|
constexpr const_iterator search(const string_base& s)const;
|
||||||
//constexpr bool search(const_pointer c)const;
|
constexpr const_iterator search(const_pointer c)const;
|
||||||
|
constexpr iterator search(const string_base& s);
|
||||||
|
constexpr iterator search(const_pointer c);
|
||||||
|
template<class Searcher>
|
||||||
|
constexpr const_iterator search(const string_base& s, const Searcher& searcher)const;
|
||||||
|
template<class Searcher>
|
||||||
|
constexpr const_iterator search(const_pointer c, const Searcher& searcher)const;
|
||||||
|
template<class Searcher>
|
||||||
|
constexpr iterator search(const string_base& s, const Searcher& searcher);
|
||||||
|
template<class Searcher>
|
||||||
|
constexpr iterator search(const_pointer c, const Searcher& searcher);
|
||||||
constexpr bool compare(const string_base& s)const{return *this == s;}
|
constexpr bool compare(const string_base& s)const{return *this == s;}
|
||||||
constexpr bool compare(const_pointer c)const{return *this == c;}
|
constexpr bool compare(const_pointer c)const{return *this == c;}
|
||||||
|
|
||||||
@ -391,11 +401,11 @@ namespace rexy{
|
|||||||
|
|
||||||
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)noexcept{
|
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() && !strcmp(left.get(), right.get());
|
||||||
}
|
}
|
||||||
template<class Str, detail::enable_if_concrete_string<Str> = 0>
|
template<class Str, detail::enable_if_concrete_string<Str> = 0>
|
||||||
constexpr bool operator==(Str&& left, typename std::decay_t<Str>::const_pointer right)noexcept{
|
constexpr bool operator==(Str&& left, typename std::decay_t<Str>::const_pointer right)noexcept{
|
||||||
return left.valid() && right && !cx::strcmp(left.get(), right);
|
return left.valid() && right && !strcmp(left.get(), right);
|
||||||
}
|
}
|
||||||
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)noexcept{
|
constexpr bool operator!=(Str1&& left, Str2&& right)noexcept{
|
||||||
@ -463,7 +473,7 @@ namespace{
|
|||||||
#include "detail/binary_string_conv.hpp"
|
#include "detail/binary_string_conv.hpp"
|
||||||
#endif
|
#endif
|
||||||
#ifdef REXY_CX_HASH_HPP
|
#ifdef REXY_CX_HASH_HPP
|
||||||
#include "cx/static_string_hash.hpp"
|
#include "static_string_hash.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -23,13 +23,56 @@
|
|||||||
#include <cstdlib> //memcpy
|
#include <cstdlib> //memcpy
|
||||||
#include <cstring> //strlen, strcpy
|
#include <cstring> //strlen, strcpy
|
||||||
|
|
||||||
#include "cx/utility.hpp" //max
|
#include "utility.hpp" //max
|
||||||
#include "detail/string_appender.hpp"
|
#include "detail/string_appender.hpp"
|
||||||
|
#include "algorithm.hpp"
|
||||||
|
|
||||||
#define STOP_STRICT_ALIAS_WARNING(x) (x)
|
#define STOP_STRICT_ALIAS_WARNING(x) (x)
|
||||||
|
|
||||||
namespace rexy{
|
namespace rexy{
|
||||||
|
|
||||||
|
template<class Char>
|
||||||
|
constexpr auto string_base<Char>::search(const string_base& s)const -> const_iterator{
|
||||||
|
return two_way_search(cbegin(), cend(), s.begin(), s.end());
|
||||||
|
}
|
||||||
|
template<class Char>
|
||||||
|
constexpr auto string_base<Char>::search(const_pointer c)const -> const_iterator{
|
||||||
|
const auto len = strlen(c);
|
||||||
|
return two_way_search(cbegin(), cend(), c, c + len);
|
||||||
|
}
|
||||||
|
template<class Char>
|
||||||
|
constexpr auto string_base<Char>::search(const string_base& s) -> iterator{
|
||||||
|
return two_way_search(begin(), end(), s.begin(), s.end());
|
||||||
|
}
|
||||||
|
template<class Char>
|
||||||
|
constexpr auto string_base<Char>::search(const_pointer c) -> iterator{
|
||||||
|
const auto len = strlen(c);
|
||||||
|
return two_way_search(begin(), end(), c, c + len);
|
||||||
|
}
|
||||||
|
template<class Char>
|
||||||
|
template<class Searcher>
|
||||||
|
constexpr auto string_base<Char>::search(const string_base& s, const Searcher& searcher)const -> const_iterator{
|
||||||
|
return searcher(cbegin(), cend(), s.begin(), s.end());
|
||||||
|
}
|
||||||
|
template<class Char>
|
||||||
|
template<class Searcher>
|
||||||
|
constexpr auto string_base<Char>::search(const_pointer c, const Searcher& searcher)const -> const_iterator{
|
||||||
|
const auto len = strlen(c);
|
||||||
|
return searcher(cbegin(), cend(), c, c + len);
|
||||||
|
}
|
||||||
|
template<class Char>
|
||||||
|
template<class Searcher>
|
||||||
|
constexpr auto string_base<Char>::search(const string_base& s, const Searcher& searcher) -> iterator{
|
||||||
|
return searcher(begin(), end(), s.begin(), s.end());
|
||||||
|
}
|
||||||
|
template<class Char>
|
||||||
|
template<class Searcher>
|
||||||
|
constexpr auto string_base<Char>::search(const_pointer c, const Searcher& searcher) -> iterator{
|
||||||
|
const auto len = strlen(c);
|
||||||
|
return searcher(begin(), end(), c, c + len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//allocate string if longer than small string capacity, copy otherwise
|
//allocate string if longer than small string capacity, copy otherwise
|
||||||
template<class Char, class Allocator>
|
template<class Char, class Allocator>
|
||||||
void basic_string<Char,Allocator>::_copy_construct_string(const_pointer data, size_type len, size_type cap)
|
void basic_string<Char,Allocator>::_copy_construct_string(const_pointer data, size_type len, size_type cap)
|
||||||
@ -58,7 +101,7 @@ namespace rexy{
|
|||||||
constexpr basic_string<Char,Allocator>::basic_string(void)noexcept{}
|
constexpr basic_string<Char,Allocator>::basic_string(void)noexcept{}
|
||||||
template<class Char, class Allocator>
|
template<class Char, class Allocator>
|
||||||
constexpr basic_string<Char,Allocator>::basic_string(rexy::steal<pointer> data)noexcept:
|
constexpr basic_string<Char,Allocator>::basic_string(rexy::steal<pointer> data)noexcept:
|
||||||
basic_string(data.value(), data.value() ? cx::strlen(data.value()) : 0){}
|
basic_string(data.value(), data.value() ? strlen(data.value()) : 0){}
|
||||||
template<class Char, class Allocator>
|
template<class Char, class Allocator>
|
||||||
constexpr basic_string<Char,Allocator>::basic_string(rexy::steal<pointer> data, size_type len)noexcept:
|
constexpr basic_string<Char,Allocator>::basic_string(rexy::steal<pointer> data, size_type len)noexcept:
|
||||||
string_base<Char>(data.value(), len, len){}
|
string_base<Char>(data.value(), len, len){}
|
||||||
@ -78,7 +121,7 @@ namespace rexy{
|
|||||||
template<class Char, class Allocator>
|
template<class Char, class Allocator>
|
||||||
basic_string<Char,Allocator>::basic_string(const_pointer data)
|
basic_string<Char,Allocator>::basic_string(const_pointer data)
|
||||||
noexcept(noexcept(this->allocate(0))):
|
noexcept(noexcept(this->allocate(0))):
|
||||||
basic_string(data, data ? cx::strlen(data) : 0){}
|
basic_string(data, data ? strlen(data) : 0){}
|
||||||
template<class Char, class Allocator>
|
template<class Char, class Allocator>
|
||||||
basic_string<Char,Allocator>::basic_string(size_type cap)
|
basic_string<Char,Allocator>::basic_string(size_type cap)
|
||||||
noexcept(noexcept(this->allocate(0))):
|
noexcept(noexcept(this->allocate(0))):
|
||||||
@ -149,7 +192,7 @@ namespace rexy{
|
|||||||
noexcept(noexcept(this->allocate(0)) &&
|
noexcept(noexcept(this->allocate(0)) &&
|
||||||
noexcept(this->deallocate(nullptr,0)))
|
noexcept(this->deallocate(nullptr,0)))
|
||||||
{
|
{
|
||||||
return _copy_string(c, cx::strlen(c));
|
return _copy_string(c, strlen(c));
|
||||||
}
|
}
|
||||||
|
|
||||||
//Replace managed pointer. Frees existing value
|
//Replace managed pointer. Frees existing value
|
||||||
@ -157,7 +200,7 @@ namespace rexy{
|
|||||||
void basic_string<Char,Allocator>::reset(pointer val)
|
void basic_string<Char,Allocator>::reset(pointer val)
|
||||||
noexcept(noexcept(this->deallocate(nullptr,0)))
|
noexcept(noexcept(this->deallocate(nullptr,0)))
|
||||||
{
|
{
|
||||||
reset(val, val ? cx::strlen(val) : 0);
|
reset(val, val ? strlen(val) : 0);
|
||||||
}
|
}
|
||||||
template<class Char, class Allocator>
|
template<class Char, class Allocator>
|
||||||
void basic_string<Char,Allocator>::reset(pointer val, size_type len)
|
void basic_string<Char,Allocator>::reset(pointer val, size_type len)
|
||||||
@ -195,7 +238,7 @@ namespace rexy{
|
|||||||
this->set_length(mylen+len);
|
this->set_length(mylen+len);
|
||||||
raw[mylen+len] = 0;
|
raw[mylen+len] = 0;
|
||||||
}else{
|
}else{
|
||||||
auto newsize = cx::max(mylen+len, mycap*2);
|
auto newsize = max(mylen+len, mycap*2);
|
||||||
basic_string tmp(newsize);
|
basic_string tmp(newsize);
|
||||||
tmp.append(raw, mylen);
|
tmp.append(raw, mylen);
|
||||||
tmp.append(data, len);
|
tmp.append(data, len);
|
||||||
@ -208,7 +251,7 @@ namespace rexy{
|
|||||||
noexcept(this->deallocate(nullptr,0)))
|
noexcept(this->deallocate(nullptr,0)))
|
||||||
{
|
{
|
||||||
if(data)
|
if(data)
|
||||||
append(data, cx::strlen(data));
|
append(data, strlen(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Char, class Allocator>
|
template<class Char, class Allocator>
|
||||||
@ -304,10 +347,10 @@ namespace rexy{
|
|||||||
}
|
}
|
||||||
template<class Char>
|
template<class Char>
|
||||||
constexpr static_string<Char>::static_string(const_pointer c)noexcept:
|
constexpr static_string<Char>::static_string(const_pointer c)noexcept:
|
||||||
static_string(c, cx::strlen(c)){}
|
static_string(c, strlen(c)){}
|
||||||
template<class Char>
|
template<class Char>
|
||||||
constexpr static_string<Char>& static_string<Char>::operator=(const_pointer c)noexcept{
|
constexpr static_string<Char>& static_string<Char>::operator=(const_pointer c)noexcept{
|
||||||
size_type len = cx::strlen(c);
|
size_type len = strlen(c);
|
||||||
this->set_long_ptr(const_cast<pointer>(c));
|
this->set_long_ptr(const_cast<pointer>(c));
|
||||||
this->set_long_length(len);
|
this->set_long_length(len);
|
||||||
this->set_long_capacity(len);
|
this->set_long_capacity(len);
|
||||||
|
|||||||
@ -16,12 +16,12 @@
|
|||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef REXY_CX_STRING_HASH_HPP
|
#ifndef REXY_STRING_HASH_HPP
|
||||||
#define REXY_CX_STRING_HASH_HPP
|
#define REXY_STRING_HASH_HPP
|
||||||
|
|
||||||
#include "hash.hpp"
|
#include "hash.hpp"
|
||||||
|
|
||||||
namespace rexy::cx{
|
namespace rexy{
|
||||||
|
|
||||||
//jenkns one at a time hash
|
//jenkns one at a time hash
|
||||||
template<class Str>
|
template<class Str>
|
||||||
@ -16,13 +16,13 @@
|
|||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef REXY_CX_UTILITY_HPP
|
#ifndef REXY_UTILITY_HPP
|
||||||
#define REXY_CX_UTILITY_HPP
|
#define REXY_UTILITY_HPP
|
||||||
|
|
||||||
#include <utility> //forward, move
|
#include <utility> //forward, move
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
namespace rexy::cx{
|
namespace rexy{
|
||||||
|
|
||||||
namespace{
|
namespace{
|
||||||
template<class T>
|
template<class T>
|
||||||
@ -36,18 +36,18 @@ namespace rexy::cx{
|
|||||||
}
|
}
|
||||||
template<class Iter1, class Iter2>
|
template<class Iter1, class Iter2>
|
||||||
constexpr Iter2 swap_ranges(Iter1 start1, Iter1 end1, Iter2 start2)
|
constexpr Iter2 swap_ranges(Iter1 start1, Iter1 end1, Iter2 start2)
|
||||||
noexcept(noexcept(cx::swap(*start1, *start2)))
|
noexcept(noexcept(swap(*start1, *start2)))
|
||||||
{
|
{
|
||||||
while(start1 != end1){
|
while(start1 != end1){
|
||||||
cx::swap(start1++, start2++);
|
swap(start1++, start2++);
|
||||||
}
|
}
|
||||||
return start2;
|
return start2;
|
||||||
}
|
}
|
||||||
template<class T, size_t N>
|
template<class T, size_t N>
|
||||||
constexpr void swap(T (&l)[N], T (&r)[N])
|
constexpr void swap(T (&l)[N], T (&r)[N])
|
||||||
noexcept(noexcept(cx::swap(*l, *r)))
|
noexcept(noexcept(swap(*l, *r)))
|
||||||
{
|
{
|
||||||
cx::swap_ranges(l, l+N, r);
|
swap_ranges(l, l+N, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T, class U = T>
|
template<class T, class U = T>
|
||||||
@ -15,13 +15,13 @@
|
|||||||
#include "rexy/allocator.hpp"
|
#include "rexy/allocator.hpp"
|
||||||
#include "rexy/detail/string_appender.hpp"
|
#include "rexy/detail/string_appender.hpp"
|
||||||
|
|
||||||
#include "rexy/cx/algorithm.hpp"
|
#include "rexy/algorithm.hpp"
|
||||||
#include "rexy/cx/array.hpp"
|
#include "rexy/cx/array.hpp"
|
||||||
#include "rexy/cx/hash.hpp"
|
#include "rexy/hash.hpp"
|
||||||
#include "rexy/cx/hashmap.hpp"
|
#include "rexy/cx/hashmap.hpp"
|
||||||
#include "rexy/cx/string_hash.hpp"
|
#include "rexy/string_hash.hpp"
|
||||||
#include "rexy/cx/string.hpp"
|
#include "rexy/cx/string.hpp"
|
||||||
#include "rexy/cx/utility.hpp"
|
#include "rexy/utility.hpp"
|
||||||
#include "rexy/cx/vector.hpp"
|
#include "rexy/cx/vector.hpp"
|
||||||
|
|
||||||
#include "rexy/cx/detail/bool_specialize_base.hpp"
|
#include "rexy/cx/detail/bool_specialize_base.hpp"
|
||||||
|
|||||||
@ -243,6 +243,14 @@ void check_substring(){
|
|||||||
if(strcmp(test2.get(), "is") || test2.length() != 2)
|
if(strcmp(test2.get(), "is") || test2.length() != 2)
|
||||||
error("substring operation should have resulted in 'is'\n");
|
error("substring operation should have resulted in 'is'\n");
|
||||||
}
|
}
|
||||||
|
void check_string_search(){
|
||||||
|
rexy::string test1 = "this is a test string";
|
||||||
|
rexy::string test2 = "string";
|
||||||
|
auto res = test1.search(test2);
|
||||||
|
if(test1 + 15 != res){
|
||||||
|
error("string search operation did not result in a correct result");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int main(){
|
int main(){
|
||||||
check_empty_construction();
|
check_empty_construction();
|
||||||
@ -253,4 +261,5 @@ int main(){
|
|||||||
check_short_append();
|
check_short_append();
|
||||||
check_long_append();
|
check_long_append();
|
||||||
check_substring();
|
check_substring();
|
||||||
|
check_string_search();
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user