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:
rexy712 2020-09-19 09:44:05 -07:00
parent 2ea8c617f0
commit 28c8caae0a
22 changed files with 337 additions and 147 deletions

View File

@ -34,7 +34,7 @@ if(BUILD_TESTS)
add_subdirectory(tests)
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)
install(TARGETS rexy

109
include/rexy/algorithm.hpp Normal file
View 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

View File

@ -16,13 +16,13 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef REXY_CX_BASIC_STRING_HASH_HPP
#define REXY_CX_BASIC_STRING_HASH_HPP
#ifndef REXY_BASIC_STRING_HASH_HPP
#define REXY_BASIC_STRING_HASH_HPP
#include "string_hash.hpp"
#include "../string.hpp"
#include "string.hpp"
namespace rexy::cx{
namespace rexy{
template<>
struct hash<rexy::string> : public string_hash<rexy::string>{};

View File

@ -26,7 +26,7 @@
#include <type_traits>
#include <iterator> //reverse_iterator
#include "cx/utility.hpp" //max
#include "utility.hpp" //max
#include "steal.hpp"
#include "expression.hpp"
#include "traits.hpp"

View File

@ -23,12 +23,10 @@
#include <utility> //move
#include <cstring> //memcpy
#include <type_traits>
#include "cx/utility.hpp" //max
#include "utility.hpp" //max
#include "steal.hpp"
#include "detail/string_appender.hpp"
#include "cx/utility.hpp" //strlen
#define STOP_STRICT_ALIAS_WARNING(x) (x)
namespace rexy{
@ -42,7 +40,7 @@ namespace rexy{
constexpr binary_base::binary_base(const binary_base&)noexcept{}
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{
@ -109,7 +107,7 @@ namespace rexy{
constexpr basic_binary<Allocator>::basic_binary(void)noexcept{}
template<class Allocator>
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_size = m_cap;
@ -132,7 +130,7 @@ namespace rexy{
template<class Allocator>
basic_binary<Allocator>::basic_binary(const_pointer data)
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)
memcpy(m_data, data, m_cap);
@ -163,7 +161,7 @@ namespace rexy{
}
template<class Allocator>
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>
basic_binary<Allocator>::basic_binary(const binary_base& b)
noexcept(noexcept(this->allocate(0))):
@ -188,7 +186,7 @@ namespace rexy{
constexpr basic_binary<Allocator>& basic_binary<Allocator>::operator=(basic_binary&& b)noexcept{
m_size = b.m_size;
m_cap = b.m_cap;
cx::swap(m_data, b.m_data);
swap(m_data, b.m_data);
return *this;
}
template<class Allocator>
@ -231,7 +229,7 @@ namespace rexy{
if(!tmp)
return false;
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;
return true;
}
@ -241,7 +239,7 @@ namespace rexy{
noexcept(this->deallocate(nullptr,0)))
{
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);
m_size += len;
}
@ -263,7 +261,7 @@ namespace rexy{
constexpr static_binary::static_binary(const_pointer str, size_type len)noexcept:
binary_base(const_cast<pointer>(str), len, len){}
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:
static_binary(s.get(), s.size()){}
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{
m_data = const_cast<pointer>(str);
m_size = cx::strlen(str);
m_size = strlen(str);
m_cap = m_size;
return *this;
}

View File

@ -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

View File

@ -20,7 +20,7 @@
#define REXY_CX_ARRAY_HPP
#include <cstddef> //size_t
#include "utility.hpp" //swap
#include "../utility.hpp" //swap
#include "detail/bool_specialize_base.hpp"
#include <type_traits>
@ -117,10 +117,10 @@ namespace rexy::cx{
}
}
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){
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{
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]);
}
}
};

View File

@ -19,7 +19,7 @@
#ifndef REXY_CX_CX_STRING_HASH_HPP
#define REXY_CX_CX_STRING_HASH_HPP
#include "string_hash.hpp"
#include "../string_hash.hpp"
#include "string.hpp"
namespace rexy::cx{

View File

@ -22,7 +22,7 @@
#include <cstddef> //size_t
#include <utility> //move, forward, pair
#include <climits> //CHAR_BIT
#include "../utility.hpp" //swap
#include "../../utility.hpp" //swap
namespace rexy::cx::detail{

View File

@ -21,8 +21,8 @@
#include "vector.hpp"
#include "array.hpp"
#include "algorithm.hpp"
#include "hash.hpp"
#include "../algorithm.hpp"
#include "../hash.hpp"
#include <climits> //CHAR_BIT
#include <cstddef> //size_t, ptrdiff_t
@ -103,7 +103,7 @@ namespace rexy::cx{
}
//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();
});
@ -199,7 +199,7 @@ namespace rexy::cx{
}
#ifdef REXY_STRING_BASE_HPP
#include "string_hash.hpp"
#include "../string_hash.hpp"
#endif
#endif

View File

@ -25,7 +25,7 @@ namespace rexy::cx{
}
#include "../string_base.hpp"
#include "utility.hpp"
#include "../utility.hpp"
#include <type_traits>
#include <cstddef> //ptrdiff_t
@ -67,7 +67,7 @@ namespace rexy::cx{
}
}
constexpr string(const_pointer data)noexcept:
m_length(cx::strlen(data))
m_length(strlen(data))
{
for(size_type i = 0;i < m_length;++i){
m_data[i] = data[i];
@ -101,7 +101,7 @@ namespace rexy::cx{
~string(void)noexcept = default;
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){
m_data[i] = c[i];
}
@ -160,7 +160,7 @@ namespace rexy::cx{
}
}
constexpr void append(const_pointer data)noexcept{
append(data, cx::strlen(data));
append(data, strlen(data));
}
constexpr void append(const string& s)noexcept{
append(s.get(), s.length());

View File

@ -23,7 +23,7 @@
#include <utility> //move, forward
#include "detail/bool_specialize_base.hpp"
#include "utility.hpp" //swap
#include "../utility.hpp" //swap
#include <type_traits>
@ -60,7 +60,7 @@ namespace rexy::cx{
for(size_type i = 0;i < min(count, max_elements);++i){
m_elements[i] = value;
}
m_size = cx::min(count, max_elements);
m_size = min(count, max_elements);
}
~vector(void)noexcept = default;
@ -230,16 +230,16 @@ namespace rexy::cx{
}
}
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;
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){
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){
m_elements[i][j] = value;
}
m_size = cx::min(count, max_elements);
m_size = min(count, max_elements);
}
~vector(void)noexcept = default;
@ -422,7 +422,7 @@ namespace rexy::cx{
}
constexpr void resize(size_type count, const value_type& value)noexcept{
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 it = end();
for(size_type i = 0;i < num;++i){
@ -446,12 +446,12 @@ namespace rexy::cx{
++other_byte_count;
size_type i = 0;
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){
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);
}
};

View 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

View File

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

View File

@ -16,12 +16,12 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef REXY_CX_HASH_HPP
#define REXY_CX_HASH_HPP
#ifndef REXY_HASH_HPP
#define REXY_HASH_HPP
#include <climits> //CHAR_BIT
namespace rexy::cx{
namespace rexy{
template<class T>
struct hash{

View File

@ -16,13 +16,13 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef REXY_CX_STATIC_STRING_HASH_HPP
#define REXY_CX_STATIC_STRING_HASH_HPP
#ifndef REXY_STATIC_STRING_HASH_HPP
#define REXY_STATIC_STRING_HASH_HPP
#include "string_hash.hpp"
#include "../string_base.hpp"
#include "string_base.hpp"
namespace rexy::cx{
namespace rexy{
template<class Char>
struct hash<rexy::static_string<Char>> : public string_hash<rexy::static_string<Char>>{};

View File

@ -27,7 +27,7 @@
#include <iterator> //reverse_iterator
#include "steal.hpp"
#include "cx/utility.hpp"
#include "utility.hpp"
#include "traits.hpp"
#include "expression.hpp"
#include "detail/string_appender.hpp"
@ -200,8 +200,18 @@ namespace rexy{
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 bool search(const string_base& s)const;
//constexpr bool search(const_pointer c)const;
constexpr const_iterator search(const string_base& s)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_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>
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>
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>
constexpr bool operator!=(Str1&& left, Str2&& right)noexcept{
@ -463,7 +473,7 @@ namespace{
#include "detail/binary_string_conv.hpp"
#endif
#ifdef REXY_CX_HASH_HPP
#include "cx/static_string_hash.hpp"
#include "static_string_hash.hpp"
#endif
#endif

View File

@ -23,13 +23,56 @@
#include <cstdlib> //memcpy
#include <cstring> //strlen, strcpy
#include "cx/utility.hpp" //max
#include "utility.hpp" //max
#include "detail/string_appender.hpp"
#include "algorithm.hpp"
#define STOP_STRICT_ALIAS_WARNING(x) (x)
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
template<class Char, class Allocator>
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{}
template<class Char, class Allocator>
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>
constexpr basic_string<Char,Allocator>::basic_string(rexy::steal<pointer> data, size_type len)noexcept:
string_base<Char>(data.value(), len, len){}
@ -78,7 +121,7 @@ namespace rexy{
template<class Char, class Allocator>
basic_string<Char,Allocator>::basic_string(const_pointer data)
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>
basic_string<Char,Allocator>::basic_string(size_type cap)
noexcept(noexcept(this->allocate(0))):
@ -149,7 +192,7 @@ namespace rexy{
noexcept(noexcept(this->allocate(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
@ -157,7 +200,7 @@ namespace rexy{
void basic_string<Char,Allocator>::reset(pointer val)
noexcept(noexcept(this->deallocate(nullptr,0)))
{
reset(val, val ? cx::strlen(val) : 0);
reset(val, val ? strlen(val) : 0);
}
template<class Char, class Allocator>
void basic_string<Char,Allocator>::reset(pointer val, size_type len)
@ -195,7 +238,7 @@ namespace rexy{
this->set_length(mylen+len);
raw[mylen+len] = 0;
}else{
auto newsize = cx::max(mylen+len, mycap*2);
auto newsize = max(mylen+len, mycap*2);
basic_string tmp(newsize);
tmp.append(raw, mylen);
tmp.append(data, len);
@ -208,7 +251,7 @@ namespace rexy{
noexcept(this->deallocate(nullptr,0)))
{
if(data)
append(data, cx::strlen(data));
append(data, strlen(data));
}
template<class Char, class Allocator>
@ -304,10 +347,10 @@ namespace rexy{
}
template<class Char>
constexpr static_string<Char>::static_string(const_pointer c)noexcept:
static_string(c, cx::strlen(c)){}
static_string(c, strlen(c)){}
template<class Char>
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_length(len);
this->set_long_capacity(len);

View File

@ -16,12 +16,12 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef REXY_CX_STRING_HASH_HPP
#define REXY_CX_STRING_HASH_HPP
#ifndef REXY_STRING_HASH_HPP
#define REXY_STRING_HASH_HPP
#include "hash.hpp"
namespace rexy::cx{
namespace rexy{
//jenkns one at a time hash
template<class Str>

View File

@ -16,13 +16,13 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef REXY_CX_UTILITY_HPP
#define REXY_CX_UTILITY_HPP
#ifndef REXY_UTILITY_HPP
#define REXY_UTILITY_HPP
#include <utility> //forward, move
#include <type_traits>
namespace rexy::cx{
namespace rexy{
namespace{
template<class T>
@ -36,18 +36,18 @@ namespace rexy::cx{
}
template<class Iter1, class Iter2>
constexpr Iter2 swap_ranges(Iter1 start1, Iter1 end1, Iter2 start2)
noexcept(noexcept(cx::swap(*start1, *start2)))
noexcept(noexcept(swap(*start1, *start2)))
{
while(start1 != end1){
cx::swap(start1++, start2++);
swap(start1++, start2++);
}
return start2;
}
template<class T, size_t 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>

View File

@ -15,13 +15,13 @@
#include "rexy/allocator.hpp"
#include "rexy/detail/string_appender.hpp"
#include "rexy/cx/algorithm.hpp"
#include "rexy/algorithm.hpp"
#include "rexy/cx/array.hpp"
#include "rexy/cx/hash.hpp"
#include "rexy/hash.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/utility.hpp"
#include "rexy/utility.hpp"
#include "rexy/cx/vector.hpp"
#include "rexy/cx/detail/bool_specialize_base.hpp"

View File

@ -243,6 +243,14 @@ void check_substring(){
if(strcmp(test2.get(), "is") || test2.length() != 2)
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(){
check_empty_construction();
@ -253,4 +261,5 @@ int main(){
check_short_append();
check_long_append();
check_substring();
check_string_search();
}