Update cx::string to be more level with string_view

This commit is contained in:
rexy712 2022-06-19 18:46:02 -07:00
parent e5d8c0f567
commit 00355a64c6
8 changed files with 269 additions and 137 deletions

View File

@ -201,6 +201,40 @@ namespace rexy{
return l = (l + r); return l = (l + r);
} }
template<class T, class Char, std::enable_if_t<is_string<T>::value, int> = 0>
constexpr std::size_t find_first_of(T&& t, const Char* c, std::size_t start, std::size_t size){
if(start > t.length()){
return rexy::npos;
}
for(auto it = t.cbegin() + start;it != t.cend();++it){
for(std::size_t i = 0;i < size;++i){
if(*it == c[i]){
return it - t.cbegin();
}
}
}
return rexy::npos;
}
template<class T, class Char, std::enable_if_t<is_string<T>::value, int> = 0>
constexpr std::size_t find_last_of(T&& t, const Char* c, std::size_t start, std::size_t size){
if(start > t.length()){
return rexy::npos;
}
const auto b = t.cend() - 1;
const auto e = t.cbegin() - 1 - start;
for(auto it = b;it != e;--it){
for(std::size_t i = 0;i < size;++i){
if(*it == c[i]){
return it - t.cbegin();
}
}
}
return rexy::npos;
}
} }
#endif #endif

View File

@ -21,50 +21,13 @@
#include "../../string_base.hpp" #include "../../string_base.hpp"
#include <concepts> //convertible_to #include <utility> //forward
#include <utility> //forward, as_const
#include <type_traits> //decay, is_nothrow_assignable #include <type_traits> //decay, is_nothrow_assignable
#include "../../concepts/string.hpp"
namespace rexy{ namespace rexy{
template<class T>
concept BasicString = requires(const T& a){
{std::as_const(a).length()} -> std::convertible_to<typename std::decay_t<T>::size_type>;
{std::as_const(a).c_str()} -> std::convertible_to<typename std::decay_t<T>::const_pointer>;
{std::as_const(a)[0]} -> std::convertible_to<typename std::decay_t<T>::const_reference>;
{std::as_const(a).begin()} -> std::convertible_to<typename std::decay_t<T>::const_iterator>;
{std::as_const(a).end()} -> std::convertible_to<typename std::decay_t<T>::const_iterator>;
};
template<class T>
concept StringExpr = rexy::is_template_type<T,string_cat_expr>::value;
template<class T>
concept String = BasicString<T> || StringExpr<T>;
template<class T>
struct is_string{
static constexpr bool value = BasicString<T>;
};
template<class T>
static constexpr bool is_string_v = is_string<T>::value;
template<class... Ts>
struct are_strings{
static constexpr bool value = (BasicString<Ts> && ...);
};
template<class... Ts>
static constexpr bool are_strings_v = are_strings<Ts...>::value;
template<class T>
struct is_string_expr{
static constexpr bool value = StringExpr<T>;
};
template<class T>
static constexpr bool is_string_expr_v = is_string_expr<T>::value;
template<class... Ts>
struct are_string_expr{
static constexpr bool value = (StringExpr<Ts> && ...);
};
template<class... Ts>
static constexpr bool are_string_expr_v = are_string_expr<Ts...>::value;
//Compare //Compare
template<BasicString Str1, BasicString Str2> template<BasicString Str1, BasicString Str2>
constexpr bool operator==(Str1&& left, Str2&& right){ constexpr bool operator==(Str1&& left, Str2&& right){
@ -145,6 +108,40 @@ namespace rexy{
return l = (l + r); return l = (l + r);
} }
template<BasicString T, class Char>
constexpr std::size_t find_first_of(T&& t, const Char* c, std::size_t start, std::size_t size){
if(start > t.length()){
return rexy::npos;
}
for(auto it = t.cbegin() + start;it != t.cend();++it){
for(std::size_t i = 0;i < size;++i){
if(*it == c[i]){
return it - t.cbegin();
}
}
}
return rexy::npos;
}
template<BasicString T, class Char>
constexpr std::size_t find_last_of(T&& t, const Char* c, std::size_t start, std::size_t size){
if(start > t.length()){
return rexy::npos;
}
const auto b = t.cend() - 1;
const auto e = t.cbegin() - 1 - start;
for(auto it = b;it != e;--it){
for(std::size_t i = 0;i < size;++i){
if(*it == c[i]){
return it - t.cbegin();
}
}
}
return rexy::npos;
}
} }
#endif #endif

View File

@ -0,0 +1,34 @@
/**
This file is a part of rexy's general purpose library
Copyright (C) 2022 rexy712
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef REXY_COMPAT_STRING_BASE_HPP
#define REXY_COMPAT_STRING_BASE_HPP
#include <cstddef> //size_t
namespace rexy{
static constexpr std::size_t npos = std::size_t{-1};
}
#ifdef __cpp_concepts
#include "cpp20/string_base.hpp"
#else
#include "cpp20/string_base.tpp"
#endif
#endif

View File

@ -0,0 +1,73 @@
/**
This file is a part of rexy's general purpose library
Copyright (C) 2022 rexy712
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef REXY_CONCEPTS_STRING_HPP
#define REXY_CONCEPTS_STRING_HPP
#include <type_traits> //decay
#include <concepts> //convertible_to
#include <utility> //as_const
#include "../traits.hpp"
namespace rexy{
template<class Left, class Right>
class string_cat_expr;
template<class T>
concept BasicString = requires(const T& a){
{std::as_const(a).length()} -> std::convertible_to<typename std::decay_t<T>::size_type>;
{std::as_const(a).c_str()} -> std::convertible_to<typename std::decay_t<T>::const_pointer>;
{std::as_const(a)[0]} -> std::convertible_to<typename std::decay_t<T>::const_reference>;
{std::as_const(a).begin()} -> std::convertible_to<typename std::decay_t<T>::const_iterator>;
{std::as_const(a).end()} -> std::convertible_to<typename std::decay_t<T>::const_iterator>;
};
template<class T>
concept StringExpr = rexy::is_template_type<T,string_cat_expr>::value;
template<class T>
concept String = BasicString<T> || StringExpr<T>;
template<class T>
struct is_string{
static constexpr bool value = BasicString<T>;
};
template<class T>
static constexpr bool is_string_v = is_string<T>::value;
template<class... Ts>
struct are_strings{
static constexpr bool value = (BasicString<Ts> && ...);
};
template<class... Ts>
static constexpr bool are_strings_v = are_strings<Ts...>::value;
template<class T>
struct is_string_expr{
static constexpr bool value = StringExpr<T>;
};
template<class T>
static constexpr bool is_string_expr_v = is_string_expr<T>::value;
template<class... Ts>
struct are_string_expr{
static constexpr bool value = (StringExpr<Ts> && ...);
};
template<class... Ts>
static constexpr bool are_string_expr_v = are_string_expr<Ts...>::value;
}
#endif

View File

@ -27,11 +27,14 @@ namespace rexy::cx{
} }
#include "../string_base.hpp" //string_cat_expr #include "../string_base.hpp" //string_cat_expr
#include "../utility.hpp" //strlen #include "../string_view.hpp"
#include "../utility.hpp" //strlen, strcmp
#include "../detail/string_appender.hpp" #include "../detail/string_appender.hpp"
#include <type_traits> //nothrow_invocable, integral_constant, declval, remove_cvref_t #include <type_traits> //nothrow_invocable, integral_constant, declval, remove_cvref_t
#include <iterator> //reverse_iterator
#include "../compat/standard.hpp" #include "../compat/standard.hpp"
#include "../compat/string_base.hpp"
//This is different from rexy::string_view in that this doesn't hold a pointer to a constant string array. //This is different from rexy::string_view in that this doesn't hold a pointer to a constant string array.
//This holds a mutable array of data which can be modified during compile time. string_view is //This holds a mutable array of data which can be modified during compile time. string_view is
@ -52,9 +55,13 @@ namespace rexy::cx{
using const_reference = const value_type&; using const_reference = const value_type&;
using iterator = pointer; using iterator = pointer;
using const_iterator = const_pointer; using const_iterator = const_pointer;
using reverse_iterator = std::reverse_iterator<iterator>;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
public: public:
static constexpr std::size_t max_size = N; static constexpr size_type max_size = N;
static constexpr size_type npos = size_type{-1};
public: public:
value_type m_data[N] = {}; value_type m_data[N] = {};
size_type m_length = 0; size_type m_length = 0;
@ -117,43 +124,59 @@ namespace rexy::cx{
constexpr string& operator=(const string&)noexcept = default; constexpr string& operator=(const string&)noexcept = default;
constexpr string& operator=(string&&)noexcept = default; constexpr string& operator=(string&&)noexcept = default;
constexpr bool operator==(const string& s)noexcept{return !rexy::strcmp(m_data, s.m_data);}
constexpr bool operator!=(const string& s)noexcept{return rexy::strcmp(m_data, s.m_data);}
constexpr size_type length(void)const noexcept constexpr size_type length(void)const noexcept{return m_length;}
{return m_length;} constexpr size_type size(void)const noexcept{return m_length;}
constexpr size_type capacity(void)const noexcept constexpr size_type capacity(void)const noexcept{return max_size;}
{return max_size;} constexpr bool empty(void)const noexcept{return m_length == 0;}
constexpr pointer c_str(void)noexcept
{return m_data;}
constexpr const_pointer c_str(void)const noexcept
{return m_data;}
constexpr pointer get(void)noexcept
{return m_data;}
constexpr const_pointer get(void)const noexcept
{return m_data;}
constexpr operator pointer(void)noexcept
{return m_data;}
constexpr operator const_pointer(void)const noexcept
{return m_data;}
constexpr iterator begin(void)noexcept constexpr pointer c_str(void)noexcept{return m_data;}
{return m_data;} constexpr const_pointer c_str(void)const noexcept{return m_data;}
constexpr const_iterator begin(void)const noexcept constexpr pointer get(void)noexcept{return m_data;}
{return m_data;} constexpr const_pointer get(void)const noexcept{return m_data;}
constexpr const_iterator cbegin(void)const noexcept constexpr operator pointer(void)noexcept{return m_data;}
{return m_data;} constexpr operator const_pointer(void)const noexcept{return m_data;}
constexpr iterator end(void)noexcept
{return m_data+m_length;}
constexpr const_iterator end(void)const noexcept
{return m_data+m_length;}
constexpr const_iterator cend(void)const noexcept
{return m_data+m_length;}
constexpr bool valid(void)const noexcept constexpr reference operator[](size_type i)noexcept{return m_data[i];}
{return m_length > 0;} constexpr const_reference operator[](size_type i)const noexcept{return m_data[i];}
constexpr reference operator[](size_type i)noexcept constexpr reference at(size_type i)noexcept{return m_data[i];}
{return m_data[i];} constexpr const_reference at(size_type i)const noexcept{return m_data[i];}
constexpr const_reference operator[](size_type i)const noexcept constexpr const_reference front(size_type i)const noexcept{return m_data[0];}
{return m_data[i];} constexpr const_reference back(size_type i)const noexcept{return m_data[m_length-1];}
constexpr const_iterator search(const basic_string_view<value_type>& s)const{
return two_way_search(cbegin(), cend(), s.cbegin(), s.cend());
}
constexpr const_iterator search(const_pointer c)const{
return search(basic_string_view<value_type>{c});
}
template<class Searcher>
constexpr const_iterator search(const basic_string_view<value_type>& s, Searcher&& searcher)const{
return searcher(cbegin(), cend(), s.cbegin(), s.cend());
}
template<class Searcher>
constexpr const_iterator search(const_pointer c, Searcher&& searcher)const{
return search(basic_string_view<value_type>{c}, searcher);
}
constexpr iterator begin(void)noexcept{return m_data;}
constexpr const_iterator begin(void)const noexcept{return m_data;}
constexpr const_iterator cbegin(void)const noexcept{return m_data;}
constexpr iterator end(void)noexcept{return m_data+m_length;}
constexpr const_iterator end(void)const noexcept{return m_data+m_length;}
constexpr const_iterator cend(void)const noexcept{return m_data+m_length;}
constexpr const_reverse_iterator rbegin(void)const{return const_reverse_iterator(m_data+m_length);}
constexpr const_reverse_iterator rend(void)const{return const_reverse_iterator(m_data-1);}
constexpr const_reverse_iterator crbegin(void)const{return rbegin();}
constexpr const_reverse_iterator crend(void)const{return rend();}
constexpr bool valid(void)const noexcept{return m_length > 0;}
constexpr bool compare(const string& s)const{return *this == s;}
constexpr bool compare(const_pointer c)const{return *this == c;}
constexpr bool resize(size_type i)noexcept{ constexpr bool resize(size_type i)noexcept{
if(i >= capacity()){ if(i >= capacity()){
@ -169,12 +192,29 @@ namespace rexy::cx{
m_data[m_length++] = data[i]; m_data[m_length++] = data[i];
} }
} }
constexpr void append(const_pointer data)noexcept constexpr void append(const_pointer data)noexcept{append(data, rexy::strlen(data));}
{append(data, rexy::strlen(data));} constexpr void append(const string& s)noexcept{append(s.get(), s.length());}
constexpr void append(const string& s)noexcept constexpr void append(const rexy::basic_string_view<value_type>& s)noexcept{append(s.get(), s.length());}
{append(s.get(), s.length());}
constexpr void append(const rexy::basic_string_view<value_type>& s)noexcept constexpr size_type find_first_of(value_type v, size_type start = 0)const{
{append(s.get(), s.length());} return rexy::find_first_of(*this, &v, start, 1);
}
constexpr size_type find_first_of(const_pointer c, size_type pos = 0)const{
return rexy::find_first_of(*this, c, pos, rexy::strlen(c));
}
constexpr size_type find_first_of(const_pointer c, size_type start, size_type size)const{
return rexy::find_first_of(*this, c, start, size);
}
constexpr size_type find_last_of(value_type v, size_type start = 0)const{
return rexy::find_last_of(*this, &v, start, 1);
}
constexpr size_type find_last_of(const_pointer c, size_type start = 0)const{
return rexy::find_last_of(*this, c, start, rexy::strlen(c));
}
constexpr size_type find_last_of(const_pointer c, size_type start, size_type size)const{
return rexy::find_last_of(*this, c, start, size);
}
}; };
template<class Char, std::size_t N> template<class Char, std::size_t N>
string(const Char(&data)[N]) -> string<N, Char>; string(const Char(&data)[N]) -> string<N, Char>;

View File

@ -28,11 +28,7 @@
#include "compat/to_address.hpp" #include "compat/to_address.hpp"
#include "string_view.hpp" #include "string_view.hpp"
#ifdef __cpp_concepts #include "compat/string_base.hpp"
#include "compat/cpp20/string_base.hpp"
#else
#include "compat/cpp17/string_base.hpp"
#endif
namespace rexy{ namespace rexy{

View File

@ -67,7 +67,6 @@ namespace rexy{
constexpr basic_string_view& operator=(const basic_string_view& s)noexcept = default; constexpr basic_string_view& operator=(const basic_string_view& s)noexcept = default;
constexpr basic_string_view& operator=(basic_string_view&&)noexcept = default; constexpr basic_string_view& operator=(basic_string_view&&)noexcept = default;
//Length of string not including null terminator //Length of string not including null terminator
constexpr size_type length(void)const noexcept{return m_length;} constexpr size_type length(void)const noexcept{return m_length;}
constexpr size_type size(void)const noexcept{return m_length;} constexpr size_type size(void)const noexcept{return m_length;}

View File

@ -23,6 +23,8 @@
#include "utility.hpp" #include "utility.hpp"
#include "string_base.hpp" #include "string_base.hpp"
#include "compat/string_base.hpp"
namespace rexy{ namespace rexy{
template<class Char> template<class Char>
@ -93,70 +95,27 @@ namespace rexy{
} }
template<class Char> template<class Char>
constexpr auto basic_string_view<Char>::find_first_of(value_type v, size_type start)const -> size_type{ constexpr auto basic_string_view<Char>::find_first_of(value_type v, size_type start)const -> size_type{
if(start >= m_length){ return rexy::find_first_of(*this, &v, start, 1);
return npos;
}
for(auto it = begin() + start;it != end();++it){
if(*it == v){
return it - begin();
}
}
return npos;
} }
template<class Char> template<class Char>
constexpr auto basic_string_view<Char>::find_first_of(const_pointer c, size_type start)const -> size_type{ constexpr auto basic_string_view<Char>::find_first_of(const_pointer c, size_type start)const -> size_type{
return find_first_of(c, start, ::rexy::strlen(c)); return rexy::find_first_of(*this, c, start, rexy::strlen(c));
} }
template<class Char> template<class Char>
constexpr auto basic_string_view<Char>::find_first_of(const_pointer c, size_type start, size_type size)const -> size_type{ constexpr auto basic_string_view<Char>::find_first_of(const_pointer c, size_type start, size_type size)const -> size_type{
if(start > m_length){ return rexy::find_first_of(*this, c, start, size);
return npos;
}
for(auto it = begin() + start;it != end();++it){
for(size_type i = 0;i < size;++i){
if(*it == c[i]){
return it - begin();
}
}
}
return npos;
} }
template<class Char> template<class Char>
constexpr auto basic_string_view<Char>::find_last_of(value_type v, size_type start)const -> size_type{ constexpr auto basic_string_view<Char>::find_last_of(value_type v, size_type start)const -> size_type{
if(start >= m_length){ return rexy::find_last_of(*this, &v, start, 1);
return npos;
}
const auto b = end() - 1;
const auto e = begin() - 1 - start;
for(auto it = b;it != e;--it){
if(*it == v){
return it - begin();
}
}
return npos;
} }
template<class Char> template<class Char>
constexpr auto basic_string_view<Char>::find_last_of(const_pointer c, size_type start)const -> size_type{ constexpr auto basic_string_view<Char>::find_last_of(const_pointer c, size_type start)const -> size_type{
return find_last_of(c, start, ::rexy::strlen(c)); return rexy::find_last_of(*this, c, start, rexy::strlen(c));
} }
template<class Char> template<class Char>
constexpr auto basic_string_view<Char>::find_last_of(const_pointer c, size_type start, size_type size)const -> size_type{ constexpr auto basic_string_view<Char>::find_last_of(const_pointer c, size_type start, size_type size)const -> size_type{
if(start > m_length){ return rexy::find_last_of(*this, c, start, size);
return npos;
}
const auto b = end() - 1;
const auto e = begin() - 1 - start;
for(auto it = b;it != e;--it){
for(size_type i = 0;i < size;++i){
if(*it == c[i]){
return it - begin();
}
}
}
return npos;
} }
} }