Separated string_view from string_base. Add c++20 string concepts and created a new subfolder for c++17 compatability.
This commit is contained in:
parent
e576229d90
commit
1ece6dccca
@ -39,7 +39,7 @@ if(BUILD_TESTS)
|
|||||||
add_subdirectory(tests)
|
add_subdirectory(tests)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(LIBREXY_PUBLIC_HEADERS "include/rexy/rexy.hpp" "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/mpmc_queue.hpp" "include/rexy/mpmc_queue.tpp" "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" "include/rexy/meta.hpp" "include/rexy/buffer.hpp" "include/rexy/buffer.tpp" "include/rexy/debug_print.hpp" "include/rexy/deferred.hpp" "include/rexy/demangle.hpp" "include/rexy/enum_traits.hpp" "include/rexy/source_location.hpp" "include/rexy/storage_for.hpp" "include/rexy/storage_for.tpp")
|
set(LIBREXY_PUBLIC_HEADERS "include/rexy/rexy.hpp" "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/mpmc_queue.hpp" "include/rexy/mpmc_queue.tpp" "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" "include/rexy/meta.hpp" "include/rexy/buffer.hpp" "include/rexy/buffer.tpp" "include/rexy/debug_print.hpp" "include/rexy/deferred.hpp" "include/rexy/demangle.hpp" "include/rexy/enum_traits.hpp" "include/rexy/storage_for.hpp" "include/rexy/storage_for.tpp" "include/rexy/visitor.hpp")
|
||||||
target_compile_options(rexy PRIVATE -Wall -Wextra -pedantic -std=c++20)
|
target_compile_options(rexy PRIVATE -Wall -Wextra -pedantic -std=c++20)
|
||||||
|
|
||||||
install(TARGETS rexy
|
install(TARGETS rexy
|
||||||
@ -52,6 +52,7 @@ install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/pc/librexy.pc"
|
|||||||
install(FILES ${LIBREXY_PUBLIC_HEADERS} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/rexy/")
|
install(FILES ${LIBREXY_PUBLIC_HEADERS} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/rexy/")
|
||||||
install(DIRECTORY "include/rexy/detail" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/rexy" FILES_MATCHING PATTERN "*.hpp" PATTERN "*.tpp")
|
install(DIRECTORY "include/rexy/detail" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/rexy" FILES_MATCHING PATTERN "*.hpp" PATTERN "*.tpp")
|
||||||
install(DIRECTORY "include/rexy/cx" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/rexy" FILES_MATCHING PATTERN "*.hpp" PATTERN "*.tpp")
|
install(DIRECTORY "include/rexy/cx" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/rexy" FILES_MATCHING PATTERN "*.hpp" PATTERN "*.tpp")
|
||||||
|
install(DIRECTORY "include/rexy/compat" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/rexy" FILES_MATCHING PATTERN "*.hpp" PATTERN "*.tpp")
|
||||||
|
|
||||||
configure_file(
|
configure_file(
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/pc/librexy.pc.cmake.in"
|
"${CMAKE_CURRENT_SOURCE_DIR}/pc/librexy.pc.cmake.in"
|
||||||
|
|||||||
@ -32,7 +32,7 @@
|
|||||||
#define CONSTEVAL constexpr
|
#define CONSTEVAL constexpr
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace rexy{
|
namespace rexy::compat{
|
||||||
|
|
||||||
class source_location
|
class source_location
|
||||||
{
|
{
|
||||||
@ -111,7 +111,7 @@ namespace rexy{
|
|||||||
|
|
||||||
#include <source_location>
|
#include <source_location>
|
||||||
|
|
||||||
namespace rexy{
|
namespace rexy::compat{
|
||||||
|
|
||||||
using source_location = std::source_location;
|
using source_location = std::source_location;
|
||||||
|
|
||||||
50
include/rexy/compat/to_address.hpp
Normal file
50
include/rexy/compat/to_address.hpp
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/**
|
||||||
|
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_TO_ADDRESS_HPP
|
||||||
|
#define REXY_COMPAT_TO_ADDRESS_HPP
|
||||||
|
|
||||||
|
#if __cplusplus >= 202002L
|
||||||
|
#include <memory> //to_address
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
namespace rexy::compat{
|
||||||
|
#if __cplusplus >= 202002L
|
||||||
|
template<class T>
|
||||||
|
constexpr T* to_address(T* p)noexcept{
|
||||||
|
return std::to_address(p);
|
||||||
|
}
|
||||||
|
template<class Ptr>
|
||||||
|
constexpr auto to_address(const Ptr& p)noexcept{
|
||||||
|
return std::to_address(p);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
template<class T>
|
||||||
|
constexpr T* to_address(T* p)noexcept{
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
template<class Ptr>
|
||||||
|
constexpr auto to_address(const Ptr& p)noexcept{
|
||||||
|
return to_address(p.operator->());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -83,7 +83,7 @@ namespace rexy::cx{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr string(const rexy::string_view<value_type>& str)noexcept:
|
constexpr string(const rexy::basic_string_view<value_type>& str)noexcept:
|
||||||
m_length(str.length())
|
m_length(str.length())
|
||||||
{
|
{
|
||||||
for(size_type i = 0;i < m_length;++i){
|
for(size_type i = 0;i < m_length;++i){
|
||||||
@ -167,7 +167,7 @@ namespace rexy::cx{
|
|||||||
constexpr void append(const string& s)noexcept{
|
constexpr void append(const string& s)noexcept{
|
||||||
append(s.get(), s.length());
|
append(s.get(), s.length());
|
||||||
}
|
}
|
||||||
constexpr void append(const rexy::string_view<value_type>& s)noexcept{
|
constexpr void append(const rexy::basic_string_view<value_type>& s)noexcept{
|
||||||
append(s.get(), s.length());
|
append(s.get(), s.length());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -193,11 +193,11 @@ namespace rexy::cx{
|
|||||||
}
|
}
|
||||||
template<class Str1, std::enable_if_t<detail::is_cx_string<Str1>::value,int> = 0>
|
template<class Str1, std::enable_if_t<detail::is_cx_string<Str1>::value,int> = 0>
|
||||||
constexpr auto operator+(Str1&& l, const char* r)noexcept{
|
constexpr auto operator+(Str1&& l, const char* r)noexcept{
|
||||||
return string_cat_expr(std::forward<Str1>(l), rexy::string_view<char>(r));
|
return string_cat_expr(std::forward<Str1>(l), rexy::basic_string_view<char>(r));
|
||||||
}
|
}
|
||||||
template<class Str1, std::enable_if_t<detail::is_cx_string<Str1>::value,int> = 0>
|
template<class Str1, std::enable_if_t<detail::is_cx_string<Str1>::value,int> = 0>
|
||||||
constexpr auto operator+(const char* l, Str1&& r)noexcept{
|
constexpr auto operator+(const char* l, Str1&& r)noexcept{
|
||||||
return string_cat_expr(rexy::string_view<char>(l), std::forward<Str1>(r));
|
return string_cat_expr(rexy::basic_string_view<char>(l), std::forward<Str1>(r));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -40,7 +40,7 @@
|
|||||||
#include <cstdio> //fprintf, vfprintf
|
#include <cstdio> //fprintf, vfprintf
|
||||||
#include <utility> //forward
|
#include <utility> //forward
|
||||||
|
|
||||||
#include "source_location.hpp"
|
#include "compat/source_location.hpp"
|
||||||
|
|
||||||
|
|
||||||
namespace rexy::debug{
|
namespace rexy::debug{
|
||||||
@ -53,7 +53,7 @@
|
|||||||
}
|
}
|
||||||
template<class... Args>
|
template<class... Args>
|
||||||
struct print{
|
struct print{
|
||||||
explicit print(Args&&... args, const rexy::source_location& loc = rexy::source_location::current()){
|
explicit print(Args&&... args, const rexy::compat::source_location& loc = rexy::compat::source_location::current()){
|
||||||
std::fprintf(stderr, "%s:%s:%d: ", loc.file_name(), loc.function_name(), loc.line());
|
std::fprintf(stderr, "%s:%s:%d: ", loc.file_name(), loc.function_name(), loc.line());
|
||||||
std::fprintf(stderr, std::forward<Args>(args)...);
|
std::fprintf(stderr, std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
@ -67,7 +67,7 @@
|
|||||||
#ifdef REXY_ENABLE_COLOR_DEBUG
|
#ifdef REXY_ENABLE_COLOR_DEBUG
|
||||||
template<class... Args>
|
template<class... Args>
|
||||||
struct print_succ{
|
struct print_succ{
|
||||||
explicit print_succ(Args&&... args, const rexy::source_location& loc = rexy::source_location::current()){
|
explicit print_succ(Args&&... args, const rexy::compat::source_location& loc = rexy::compat::source_location::current()){
|
||||||
std::fprintf(stderr, "%s", detail::color_green);
|
std::fprintf(stderr, "%s", detail::color_green);
|
||||||
std::fprintf(stderr, "%s:%s:%d: ", loc.file_name(), loc.function_name(), loc.line());
|
std::fprintf(stderr, "%s:%s:%d: ", loc.file_name(), loc.function_name(), loc.line());
|
||||||
std::fprintf(stderr, std::forward<Args>(args)...);
|
std::fprintf(stderr, std::forward<Args>(args)...);
|
||||||
@ -80,7 +80,7 @@
|
|||||||
};
|
};
|
||||||
template<class... Args>
|
template<class... Args>
|
||||||
struct print_info{
|
struct print_info{
|
||||||
explicit print_info(Args&&... args, const rexy::source_location& loc = rexy::source_location::current()){
|
explicit print_info(Args&&... args, const rexy::compat::source_location& loc = rexy::compat::source_location::current()){
|
||||||
std::fprintf(stderr, "%s", detail::color_blue);
|
std::fprintf(stderr, "%s", detail::color_blue);
|
||||||
std::fprintf(stderr, "%s:%s:%d: ", loc.file_name(), loc.function_name(), loc.line());
|
std::fprintf(stderr, "%s:%s:%d: ", loc.file_name(), loc.function_name(), loc.line());
|
||||||
std::fprintf(stderr, std::forward<Args>(args)...);
|
std::fprintf(stderr, std::forward<Args>(args)...);
|
||||||
@ -93,7 +93,7 @@
|
|||||||
};
|
};
|
||||||
template<class... Args>
|
template<class... Args>
|
||||||
struct print_warn{
|
struct print_warn{
|
||||||
explicit print_warn(Args&&... args, const rexy::source_location& loc = rexy::source_location::current()){
|
explicit print_warn(Args&&... args, const rexy::compat::source_location& loc = rexy::compat::source_location::current()){
|
||||||
std::fprintf(stderr, "%s", detail::color_yellow);
|
std::fprintf(stderr, "%s", detail::color_yellow);
|
||||||
std::fprintf(stderr, "%s:%s:%d: ", loc.file_name(), loc.function_name(), loc.line());
|
std::fprintf(stderr, "%s:%s:%d: ", loc.file_name(), loc.function_name(), loc.line());
|
||||||
std::fprintf(stderr, std::forward<Args>(args)...);
|
std::fprintf(stderr, std::forward<Args>(args)...);
|
||||||
@ -106,7 +106,7 @@
|
|||||||
};
|
};
|
||||||
template<class... Args>
|
template<class... Args>
|
||||||
struct print_error{
|
struct print_error{
|
||||||
explicit print_error(Args&&... args, const rexy::source_location& loc = rexy::source_location::current()){
|
explicit print_error(Args&&... args, const rexy::compat::source_location& loc = rexy::compat::source_location::current()){
|
||||||
std::fprintf(stderr, "%s", detail::color_red);
|
std::fprintf(stderr, "%s", detail::color_red);
|
||||||
std::fprintf(stderr, "%s:%s:%d: ", loc.file_name(), loc.function_name(), loc.line());
|
std::fprintf(stderr, "%s:%s:%d: ", loc.file_name(), loc.function_name(), loc.line());
|
||||||
std::fprintf(stderr, std::forward<Args>(args)...);
|
std::fprintf(stderr, std::forward<Args>(args)...);
|
||||||
|
|||||||
@ -24,7 +24,7 @@
|
|||||||
#include <cstring> //memcpy
|
#include <cstring> //memcpy
|
||||||
|
|
||||||
namespace rexy{
|
namespace rexy{
|
||||||
template<class Str, detail::enable_if_concrete_string<Str> = 0>
|
template<class Str, std::enable_if_t<is_string_v<Str>,int> = 0>
|
||||||
auto binary_to_string(const binary_base& b)
|
auto binary_to_string(const binary_base& b)
|
||||||
noexcept(std::is_nothrow_constructible<Str, decltype(b.size())>::value)
|
noexcept(std::is_nothrow_constructible<Str, decltype(b.size())>::value)
|
||||||
{
|
{
|
||||||
@ -32,7 +32,7 @@ namespace rexy{
|
|||||||
s.append(b.get(), b.size());
|
s.append(b.get(), b.size());
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
template<class Al, class Str, detail::enable_if_concrete_string<Str> = 0, std::enable_if_t<std::is_same<std::decay_t<Al>,typename Str::allocator_type>::value,int> = 0>
|
template<class Al, class Str, std::enable_if_t<is_string_v<Str>,int> = 0, std::enable_if_t<std::is_same<std::decay_t<Al>,typename Str::allocator_type>::value,int> = 0>
|
||||||
auto binary_to_string(basic_binary<Al>&& b)noexcept{
|
auto binary_to_string(basic_binary<Al>&& b)noexcept{
|
||||||
return Str(rexy::steal(b.release()), b.size());
|
return Str(rexy::steal(b.release()), b.size());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,7 +26,7 @@
|
|||||||
namespace rexy{
|
namespace rexy{
|
||||||
|
|
||||||
template<class Char>
|
template<class Char>
|
||||||
struct hash<rexy::string_view<Char>> : public string_hash<rexy::string_view<Char>>{};
|
struct hash<rexy::basic_string_view<Char>> : public string_hash<rexy::basic_string_view<Char>>{};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -34,7 +34,7 @@ namespace rexy{
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
template<class U>
|
template<class U>
|
||||||
constexpr steal(U&& u)
|
constexpr explicit steal(U&& u)
|
||||||
noexcept(std::is_nothrow_constructible<T,U&&>::value):
|
noexcept(std::is_nothrow_constructible<T,U&&>::value):
|
||||||
m_val(std::forward<U>(u)){}
|
m_val(std::forward<U>(u)){}
|
||||||
|
|
||||||
|
|||||||
@ -33,6 +33,14 @@ namespace rexy{
|
|||||||
extern template class basic_string<char16_t,allocator<char16_t>>;
|
extern template class basic_string<char16_t,allocator<char16_t>>;
|
||||||
extern template class basic_string<char32_t,allocator<char32_t>>;
|
extern template class basic_string<char32_t,allocator<char32_t>>;
|
||||||
|
|
||||||
|
|
||||||
|
using string_view = basic_string_view<char>;
|
||||||
|
|
||||||
|
extern template class basic_string_view<char>;
|
||||||
|
extern template class basic_string_view<wchar_t>;
|
||||||
|
extern template class basic_string_view<char16_t>;
|
||||||
|
extern template class basic_string_view<char32_t>;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef REXY_CX_HASH_HPP
|
#ifdef REXY_CX_HASH_HPP
|
||||||
|
|||||||
@ -37,8 +37,90 @@
|
|||||||
|
|
||||||
#include "detail/cpp20.hpp"
|
#include "detail/cpp20.hpp"
|
||||||
|
|
||||||
|
#if __cplusplus >= 202002L
|
||||||
|
#include <concepts>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace rexy{
|
namespace rexy{
|
||||||
|
|
||||||
|
template<class Char>
|
||||||
|
class string_base;
|
||||||
|
|
||||||
|
template<class Char>
|
||||||
|
class basic_string_view
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using value_type = Char;
|
||||||
|
using size_type = size_t;
|
||||||
|
using difference_type = ptrdiff_t;
|
||||||
|
using pointer = value_type*;
|
||||||
|
using const_pointer = const value_type*;
|
||||||
|
using reference = value_type&;
|
||||||
|
using const_reference = const value_type&;
|
||||||
|
using iterator = pointer;
|
||||||
|
using const_iterator = const_pointer;
|
||||||
|
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||||
|
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const_pointer m_data = nullptr;
|
||||||
|
size_type m_length = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
constexpr basic_string_view(void)noexcept;
|
||||||
|
constexpr basic_string_view(const_pointer str, size_type len)noexcept;
|
||||||
|
constexpr basic_string_view(const_pointer c)noexcept;
|
||||||
|
constexpr basic_string_view(const basic_string_view& s)noexcept;
|
||||||
|
constexpr basic_string_view(const string_base<Char>& s)noexcept;
|
||||||
|
constexpr basic_string_view(basic_string_view&& s)noexcept;
|
||||||
|
template<class InIter>
|
||||||
|
constexpr basic_string_view(InIter start, InIter fin)noexcept;
|
||||||
|
REXY_CPP20_CONSTEXPR ~basic_string_view(void)noexcept = default;
|
||||||
|
|
||||||
|
constexpr basic_string_view& operator=(const_pointer c)noexcept;
|
||||||
|
constexpr basic_string_view& operator=(const basic_string_view& s)noexcept;
|
||||||
|
constexpr basic_string_view& operator=(basic_string_view&&)noexcept;
|
||||||
|
|
||||||
|
|
||||||
|
//Length of string not including null terminator
|
||||||
|
constexpr size_type length(void)const noexcept{return m_length;}
|
||||||
|
//direct access to managed pointer
|
||||||
|
constexpr const_pointer c_str(void)const noexcept{return m_data;}
|
||||||
|
constexpr const_pointer get(void)const noexcept{return m_data;}
|
||||||
|
constexpr operator const_pointer(void)const noexcept{return m_data;}
|
||||||
|
//true if m_data is not empty
|
||||||
|
constexpr bool valid(void)const noexcept{return m_length > 0;}
|
||||||
|
|
||||||
|
constexpr const_reference operator[](size_type i)const noexcept{return m_data[i];}
|
||||||
|
|
||||||
|
constexpr const_iterator search(const basic_string_view& s)const;
|
||||||
|
constexpr const_iterator search(const_pointer c)const;
|
||||||
|
template<class Searcher>
|
||||||
|
constexpr const_iterator search(const basic_string_view& s, const Searcher& searcher)const;
|
||||||
|
template<class Searcher>
|
||||||
|
constexpr const_iterator search(const_pointer c, const Searcher& searcher)const;
|
||||||
|
constexpr bool compare(const basic_string_view& s)const{return *this == s;}
|
||||||
|
constexpr bool compare(const_pointer c)const{return *this == c;}
|
||||||
|
|
||||||
|
constexpr const_iterator begin(void)const{return m_data;}
|
||||||
|
constexpr const_iterator end(void)const{return m_data+m_length;}
|
||||||
|
constexpr const_iterator cbegin(void)const{return begin();}
|
||||||
|
constexpr const_iterator cend(void)const{return end();}
|
||||||
|
|
||||||
|
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();}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
basic_string_view(const T*) -> basic_string_view<T>;
|
||||||
|
template<class T>
|
||||||
|
basic_string_view(const T*, size_t) -> basic_string_view<T>;
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
using static_string [[deprecated]] = basic_string_view<T>;
|
||||||
|
|
||||||
//Base of all RAII strings. Its use is allowing passing of rexy strings to functions without knowing the exact type
|
//Base of all RAII strings. Its use is allowing passing of rexy strings to functions without knowing the exact type
|
||||||
template<class Char>
|
template<class Char>
|
||||||
class string_base
|
class string_base
|
||||||
@ -274,6 +356,7 @@ namespace rexy{
|
|||||||
REXY_CPP20_CONSTEXPR basic_string(size_type len, size_type cap)noexcept(noexcept(this->allocate(0)));
|
REXY_CPP20_CONSTEXPR basic_string(size_type len, size_type cap)noexcept(noexcept(this->allocate(0)));
|
||||||
template<class InputIt>
|
template<class InputIt>
|
||||||
REXY_CPP20_CONSTEXPR basic_string(InputIt start, InputIt fin)noexcept(noexcept(this->allocate(0)));
|
REXY_CPP20_CONSTEXPR basic_string(InputIt start, InputIt fin)noexcept(noexcept(this->allocate(0)));
|
||||||
|
REXY_CPP20_CONSTEXPR basic_string(const basic_string_view<Char>& sv)noexcept(noexcept(this->allocate(0)));
|
||||||
//normal copy and move ctors
|
//normal copy and move ctors
|
||||||
REXY_CPP20_CONSTEXPR basic_string(const basic_string& b)noexcept(noexcept(this->allocate(0)));
|
REXY_CPP20_CONSTEXPR basic_string(const basic_string& b)noexcept(noexcept(this->allocate(0)));
|
||||||
constexpr basic_string(basic_string&& s)noexcept;
|
constexpr basic_string(basic_string&& s)noexcept;
|
||||||
@ -291,6 +374,9 @@ namespace rexy{
|
|||||||
REXY_CPP20_CONSTEXPR basic_string& operator=(const string_base<Char>& s)
|
REXY_CPP20_CONSTEXPR basic_string& operator=(const string_base<Char>& s)
|
||||||
noexcept(noexcept(this->allocate(0)) &&
|
noexcept(noexcept(this->allocate(0)) &&
|
||||||
noexcept(this->deallocate(nullptr,0)));
|
noexcept(this->deallocate(nullptr,0)));
|
||||||
|
REXY_CPP20_CONSTEXPR basic_string& operator=(const basic_string_view<Char>& sv)
|
||||||
|
noexcept(noexcept(this->allocate(0)) &&
|
||||||
|
noexcept(this->deallocate(nullptr,0)));
|
||||||
//Copy from c string
|
//Copy from c string
|
||||||
REXY_CPP20_CONSTEXPR basic_string& operator=(const_pointer c)
|
REXY_CPP20_CONSTEXPR basic_string& operator=(const_pointer c)
|
||||||
noexcept(noexcept(this->allocate(0)) &&
|
noexcept(noexcept(this->allocate(0)) &&
|
||||||
@ -355,146 +441,249 @@ namespace rexy{
|
|||||||
template<class Left, class Right>
|
template<class Left, class Right>
|
||||||
string_cat_expr(Left&&,Right&&) -> string_cat_expr<Left&&,Right&&>;
|
string_cat_expr(Left&&,Right&&) -> string_cat_expr<Left&&,Right&&>;
|
||||||
|
|
||||||
template<class Char>
|
#if __cplusplus >= 202002L
|
||||||
class string_view : public string_base<Char>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using value_type = typename string_base<Char>::value_type;
|
|
||||||
using size_type = typename string_base<Char>::size_type;
|
|
||||||
using difference_type = typename string_base<Char>::difference_type;
|
|
||||||
using pointer = typename string_base<Char>::pointer;
|
|
||||||
using const_pointer = typename string_base<Char>::const_pointer;
|
|
||||||
using reference = typename string_base<Char>::reference;
|
|
||||||
using const_reference = typename string_base<Char>::const_reference;
|
|
||||||
using iterator = typename string_base<Char>::iterator;
|
|
||||||
using const_iterator = typename string_base<Char>::const_iterator;
|
|
||||||
|
|
||||||
public:
|
template<class T>
|
||||||
constexpr string_view(void)noexcept;
|
concept BasicString = requires(T a){
|
||||||
constexpr string_view(const_pointer str, size_type len)noexcept;
|
{a.length()} -> std::same_as<typename std::decay_t<T>::size_type>;
|
||||||
constexpr string_view(const_pointer c)noexcept;
|
{a.c_str()} -> std::same_as<typename std::decay_t<T>::const_pointer>;
|
||||||
constexpr string_view(const string_view& s)noexcept;
|
{a[0]} -> std::same_as<typename std::decay_t<T>::const_reference>;
|
||||||
constexpr string_view(const string_base<Char>& s)noexcept;
|
{a.begin()} -> std::same_as<typename std::decay_t<T>::const_iterator>;
|
||||||
constexpr string_view(string_view&& s)noexcept;
|
{a.end()} -> std::same_as<typename std::decay_t<T>::const_iterator>;
|
||||||
template<class InIter>
|
|
||||||
constexpr string_view(InIter start, InIter fin)noexcept;
|
|
||||||
REXY_CPP20_CONSTEXPR ~string_view(void)noexcept = default;
|
|
||||||
|
|
||||||
constexpr string_view& operator=(const_pointer c)noexcept;
|
|
||||||
constexpr string_view& operator=(const string_view& s)noexcept;
|
|
||||||
constexpr string_view& operator=(string_view&&)noexcept;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
string_view(const T*) -> string_view<T>;
|
concept StringExpr = rexy::is_template_type<T,string_cat_expr>::value;
|
||||||
template<class T>
|
template<class T>
|
||||||
string_view(const T*, size_t) -> string_view<T>;
|
concept String = BasicString<T> || StringExpr<T>;
|
||||||
|
|
||||||
template<class T>
|
|
||||||
using static_string [[deprecated]] = string_view<T>;
|
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
struct is_string{
|
struct is_string{
|
||||||
static constexpr bool value = rexy::is_template_derived_type<T,string_base>::value || rexy::is_template_type<T,string_cat_expr>::value;
|
static constexpr bool value = BasicString<T>;
|
||||||
};
|
};
|
||||||
template<class T>
|
template<class T>
|
||||||
struct is_concrete_string{
|
static constexpr bool is_string_v = is_string<T>::value;
|
||||||
static constexpr bool value = rexy::is_template_derived_type<T,string_base>::value;
|
template<class... Ts>
|
||||||
|
struct are_strings{
|
||||||
|
static constexpr bool value = (BasicString<Ts> && ...);
|
||||||
};
|
};
|
||||||
namespace detail{
|
|
||||||
|
|
||||||
template<class... Ts>
|
template<class... Ts>
|
||||||
using enable_if_string = std::enable_if_t<(is_string<Ts>::value && ...),int>;
|
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>
|
template<class... Ts>
|
||||||
using enable_if_concrete_string = std::enable_if_t<(is_concrete_string<Ts>::value && ...),int>;
|
struct are_string_expr{
|
||||||
|
static constexpr bool value = (StringExpr<Ts> && ...);
|
||||||
|
};
|
||||||
template<class... Ts>
|
template<class... Ts>
|
||||||
using enable_if_expr_string = std::enable_if_t<(rexy::is_template_type<Ts,string_cat_expr>::value && ...),int>;
|
static constexpr bool are_string_expr_v = are_string_expr<Ts...>::value;
|
||||||
|
|
||||||
} //namespace detail
|
//Compare
|
||||||
|
template<BasicString Str1, BasicString Str2>
|
||||||
template<class Str1, class Str2, detail::enable_if_concrete_string<Str1,Str2> = 0>
|
constexpr bool operator==(Str1&& left, Str2&& right){
|
||||||
constexpr bool operator==(Str1&& left, Str2&& right)noexcept{
|
return left.length() == right.length() && !strcmp(left.c_str(), right.c_str());
|
||||||
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<BasicString Str1, BasicString Str2>
|
||||||
constexpr bool operator==(Str&& left, typename std::decay_t<Str>::const_pointer right)noexcept{
|
constexpr bool operator!=(Str1&& left, Str2&& right){
|
||||||
return left.valid() && right && !strcmp(left.get(), right);
|
return !(std::forward<Str1>(left) == std::forward<Str2>(right));
|
||||||
}
|
|
||||||
template<class Str1, class Str2, detail::enable_if_concrete_string<Str1,Str2> = 0>
|
|
||||||
constexpr bool operator!=(Str1&& left, Str2&& right)noexcept{
|
|
||||||
return !(left == right);
|
|
||||||
}
|
|
||||||
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 == right);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Left, class Right, detail::enable_if_string<Left,Right> = 0>
|
//String + string concat
|
||||||
|
template<String Left, String Right>
|
||||||
constexpr auto operator+(Left&& l, Right&& r)
|
constexpr auto operator+(Left&& l, Right&& r)
|
||||||
//uses deduction guide whereas std::is_nothrow_constructible couldn't
|
//uses deduction guide whereas std::is_nothrow_constructible couldn't
|
||||||
noexcept(noexcept(::new (nullptr) string_cat_expr(std::forward<Left>(l), std::forward<Right>(r))))
|
noexcept(noexcept(::new (nullptr) string_cat_expr(std::forward<Left>(l), std::forward<Right>(r))))
|
||||||
{
|
{
|
||||||
return string_cat_expr(std::forward<Left>(l), std::forward<Right>(r));
|
return string_cat_expr(std::forward<Left>(l), std::forward<Right>(r));
|
||||||
}
|
}
|
||||||
template<class Right, detail::enable_if_string<Right> = 0>
|
template<String Right>
|
||||||
constexpr auto operator+(typename std::decay_t<Right>::const_pointer left, Right&& right)
|
constexpr auto operator+(typename std::decay_t<Right>::const_pointer left, Right&& right)
|
||||||
noexcept(noexcept(::new (nullptr) string_cat_expr(rexy::string_view(left), std::forward<Right>(right))))
|
noexcept(noexcept(::new (nullptr) string_cat_expr(rexy::basic_string_view(left), std::forward<Right>(right))))
|
||||||
{
|
{
|
||||||
return string_cat_expr(rexy::string_view(left), std::forward<Right>(right));
|
return string_cat_expr(rexy::basic_string_view(left), std::forward<Right>(right));
|
||||||
}
|
}
|
||||||
|
template<String Left>
|
||||||
template<class Left, detail::enable_if_string<Left> = 0>
|
|
||||||
constexpr auto operator+(Left&& left, typename std::decay_t<Left>::const_pointer right)
|
constexpr auto operator+(Left&& left, typename std::decay_t<Left>::const_pointer right)
|
||||||
noexcept(noexcept(::new (nullptr) string_cat_expr(std::forward<Left>(left), rexy::string_view(right))))
|
noexcept(noexcept(::new (nullptr) string_cat_expr(std::forward<Left>(left), rexy::basic_string_view(right))))
|
||||||
{
|
{
|
||||||
return rexy::string_cat_expr(std::forward<Left>(left), rexy::string_view(right));
|
return rexy::string_cat_expr(std::forward<Left>(left), rexy::basic_string_view(right));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Left, class Right, detail::enable_if_concrete_string<Left> = 0, detail::enable_if_string<Right> = 0>
|
//String concat assign
|
||||||
|
template<BasicString Left, String Right>
|
||||||
REXY_CPP20_CONSTEXPR decltype(auto) operator+=(Left& l, Right&& r)
|
REXY_CPP20_CONSTEXPR decltype(auto) operator+=(Left& l, Right&& r)
|
||||||
noexcept(noexcept(l + std::forward<Right>(r)) && std::is_nothrow_assignable<Left, decltype(l + std::forward<Right>(r))>::value)
|
noexcept(noexcept(l + std::forward<Right>(r)) && std::is_nothrow_assignable<Left, decltype(l + std::forward<Right>(r))>::value)
|
||||||
{
|
{
|
||||||
return l = (l + std::forward<Right>(r));
|
return l = (l + std::forward<Right>(r));
|
||||||
}
|
}
|
||||||
template<class Left, detail::enable_if_concrete_string<Left> = 0>
|
template<BasicString Left>
|
||||||
REXY_CPP20_CONSTEXPR decltype(auto) operator+=(Left& l, typename std::decay_t<Left>::const_pointer r)
|
REXY_CPP20_CONSTEXPR decltype(auto) operator+=(Left& l, typename std::decay_t<Left>::const_pointer r)
|
||||||
noexcept(noexcept(l + r) && std::is_nothrow_assignable<Left, decltype(l + r)>::value)
|
noexcept(noexcept(l + r) && std::is_nothrow_assignable<Left, decltype(l + r)>::value)
|
||||||
{
|
{
|
||||||
return l = (l + r);
|
return l = (l + r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else //__cplusplus == 202002L
|
||||||
|
|
||||||
|
#define HAS_MEMFUN_WITH_RET(type, ret, fun, ...) \
|
||||||
|
template<class T> \
|
||||||
|
struct has_##fun##_f{ \
|
||||||
|
std::false_type check(...); \
|
||||||
|
template<class type> \
|
||||||
|
auto check(type* u) -> std::enable_if<std::is_same_v<std::declval<type>().fun(__VA_ARGS__),ret>,std::true_type>; \
|
||||||
|
\
|
||||||
|
static constexpr bool value = decltype(check(std::declval<T*>()))::value; \
|
||||||
|
}; \
|
||||||
|
template<class T> \
|
||||||
|
static constexpr bool has_##fun##_f_v = has_##fun##_f<T>::value
|
||||||
|
|
||||||
|
#define HAS_MEMOP_WITH_RET(type, ret, opname, op, ...) \
|
||||||
|
template<class T> \
|
||||||
|
struct has_##opname##_f{ \
|
||||||
|
std::false_type check(...); \
|
||||||
|
template<class type> \
|
||||||
|
auto check(type* u) -> std::enable_if<std::is_same_v<std::declval<type>().operator op(__VA_ARGS__),ret>,std::true_type>; \
|
||||||
|
\
|
||||||
|
static constexpr bool value = decltype(check(std::declval<T*>()))::value; \
|
||||||
|
}; \
|
||||||
|
template<class T> \
|
||||||
|
static constexpr bool has_##opname##_f_v = has_##opname##_f<T>::value
|
||||||
|
|
||||||
|
|
||||||
|
HAS_MEMFUN_WITH_RET(U, typename U::size_type, length);
|
||||||
|
HAS_MEMFUN_WITH_RET(U, typename U::const_pointer, c_str);
|
||||||
|
HAS_MEMOP_WITH_RET(U, typename U::const_reference, indexop, [], 0);
|
||||||
|
HAS_MEMFUN_WITH_RET(U, typename U::const_iterator, begin);
|
||||||
|
HAS_MEMFUN_WITH_RET(U, typename U::const_iterator, end);
|
||||||
|
|
||||||
|
#undef HAS_MEMFUN_WITH_RET
|
||||||
|
#undef HAS_MEMOP_WITH_RET
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
struct is_string{
|
||||||
|
static constexpr bool value = has_length_f_v<T> && has_c_str_f_v<T> && has_indexop_f_v<T> && has_begin_f_v<T> && has_end_f_v<T>;
|
||||||
|
};
|
||||||
|
template<class T>
|
||||||
|
static constexpr bool is_string_v = is_string<T>::value;
|
||||||
|
template<class... Ts>
|
||||||
|
struct are_strings{
|
||||||
|
static constexpr bool value = (is_string<Ts>::value && ...);
|
||||||
|
};
|
||||||
|
template<class... Ts>
|
||||||
|
static constexpr bool are_strings_v = are_strings<Ts...>::value;
|
||||||
|
template<class T>
|
||||||
|
struct is_string_expr{
|
||||||
|
static constexpr bool value = rexy::is_template_type<T,string_cat_expr>::value;
|
||||||
|
};
|
||||||
|
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 = (is_string_expr<Ts>::value && ...);
|
||||||
|
};
|
||||||
|
template<class... Ts>
|
||||||
|
static constexpr bool are_string_expr_v = are_string_expr<Ts...>::value;
|
||||||
|
|
||||||
|
//Compare
|
||||||
|
template<class Str1, class Str2, std::enable_if_t<are_strings<Str1, Str2>::value,int> = 0>
|
||||||
|
constexpr bool operator==(Str1&& left, Str2&& right){
|
||||||
|
return left.length() == right.length() && !strcmp(left.c_str(), right.c_str());
|
||||||
|
}
|
||||||
|
template<class Str1, class Str2, std::enable_if_t<are_strings<Str1, Str2>::value,int> = 0>
|
||||||
|
constexpr bool operator!=(Str1&& left, Str2&& right)noexcept{
|
||||||
|
return !(std::forward<Str1>(left) == std::forward<Str2>(right));
|
||||||
|
}
|
||||||
|
|
||||||
|
//String + string concat
|
||||||
|
template<class Left, class Right, std::enable_if_t<are_strings<Left, Right>::value,int> = 0>
|
||||||
|
constexpr auto operator+(Left&& l, Right&& r)
|
||||||
|
//uses deduction guide whereas std::is_nothrow_constructible couldn't
|
||||||
|
noexcept(noexcept(::new (nullptr) string_cat_expr(std::forward<Left>(l), std::forward<Right>(r))))
|
||||||
|
{
|
||||||
|
return string_cat_expr(std::forward<Left>(l), std::forward<Right>(r));
|
||||||
|
}
|
||||||
|
template<class Right, std::enable_if_t<is_string<Right>::value,int> = 0>
|
||||||
|
constexpr auto operator+(typename std::decay_t<Right>::const_pointer left, Right&& right)
|
||||||
|
noexcept(noexcept(::new (nullptr) string_cat_expr(rexy::basic_string_view(left), std::forward<Right>(right))))
|
||||||
|
{
|
||||||
|
return string_cat_expr(rexy::basic_string_view(left), std::forward<Right>(right));
|
||||||
|
}
|
||||||
|
template<class Left, std::enable_if_t<is_string<Left>::value,int> = 0>
|
||||||
|
constexpr auto operator+(Left&& left, typename std::decay_t<Left>::const_pointer right)
|
||||||
|
noexcept(noexcept(::new (nullptr) string_cat_expr(std::forward<Left>(left), rexy::basic_string_view(right))))
|
||||||
|
{
|
||||||
|
return rexy::string_cat_expr(std::forward<Left>(left), rexy::basic_string_view(right));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//String + expr concat
|
||||||
|
template<class Left, class Right, std::enable_if_t<is_string<Left>::value && is_string_expr<Right>::value,int> = 0>
|
||||||
|
constexpr auto operator+(Left&& left, Right&& right){
|
||||||
|
return string_cat_expr(std::forward<Left>(left), std::forward<Right>(right));
|
||||||
|
}
|
||||||
|
template<class Left, class Right, std::enable_if_t<is_string_expr<Left>::value && is_string<Right>::value,int> = 0>
|
||||||
|
constexpr auto operator+(Left&& left, Right&& right){
|
||||||
|
return string_cat_expr(std::forward<Left>(left), std::forward<Right>(right));
|
||||||
|
}
|
||||||
|
|
||||||
|
//String concat assignment
|
||||||
|
template<class Left, class Right, std::enable_if_t<are_strings<Left,Right>::value,int> = 0>
|
||||||
|
REXY_CPP20_CONSTEXPR decltype(auto) operator+=(Left& l, Right&& r)
|
||||||
|
noexcept(noexcept(l + std::forward<Right>(r)) && std::is_nothrow_assignable<Left, decltype(l + std::forward<Right>(r))>::value)
|
||||||
|
{
|
||||||
|
return l = (l + std::forward<Right>(r));
|
||||||
|
}
|
||||||
|
template<class Left, class Right, std::enable_if_t<is_string<Left>::value && is_string_expr<Right>::value,int> = 0>
|
||||||
|
REXY_CPP20_CONSTEXPR decltype(auto) operator+=(Left& l, Right&& r)
|
||||||
|
noexcept(noexcept(l + std::forward<Right>(r)) && std::is_nothrow_assignable<Left, decltype(l + std::forward<Right>(r))>::value)
|
||||||
|
{
|
||||||
|
return l = (l + std::forward<Right>(r));
|
||||||
|
}
|
||||||
|
template<class Left, std::enable_if_t<is_string<Left>::value, int> = 0>
|
||||||
|
REXY_CPP20_CONSTEXPR decltype(auto) operator+=(Left& l, typename std::decay_t<Left>::const_pointer r)
|
||||||
|
noexcept(noexcept(l + r) && std::is_nothrow_assignable<Left, decltype(l + r)>::value)
|
||||||
|
{
|
||||||
|
return l = (l + r);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //__cplusplus == 202002L
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "string_base.tpp"
|
#include "string_base.tpp"
|
||||||
|
|
||||||
namespace{
|
namespace{
|
||||||
[[deprecated]]
|
[[deprecated]]
|
||||||
constexpr inline rexy::string_view<char> operator"" _ss(const char* str, size_t len)noexcept{
|
constexpr inline rexy::basic_string_view<char> operator"" _ss(const char* str, size_t len)noexcept{
|
||||||
return rexy::string_view(str, len);
|
return rexy::basic_string_view(str, len);
|
||||||
}
|
}
|
||||||
[[deprecated]]
|
[[deprecated]]
|
||||||
constexpr inline rexy::string_view<wchar_t> operator"" _ss(const wchar_t* str, size_t len)noexcept{
|
constexpr inline rexy::basic_string_view<wchar_t> operator"" _ss(const wchar_t* str, size_t len)noexcept{
|
||||||
return rexy::string_view(str, len);
|
return rexy::basic_string_view(str, len);
|
||||||
}
|
}
|
||||||
[[deprecated]]
|
[[deprecated]]
|
||||||
constexpr inline rexy::string_view<char16_t> operator"" _ss(const char16_t* str, size_t len)noexcept{
|
constexpr inline rexy::basic_string_view<char16_t> operator"" _ss(const char16_t* str, size_t len)noexcept{
|
||||||
return rexy::string_view(str, len);
|
return rexy::basic_string_view(str, len);
|
||||||
}
|
}
|
||||||
[[deprecated]]
|
[[deprecated]]
|
||||||
constexpr inline rexy::string_view<char32_t> operator"" _ss(const char32_t* str, size_t len)noexcept{
|
constexpr inline rexy::basic_string_view<char32_t> operator"" _ss(const char32_t* str, size_t len)noexcept{
|
||||||
return rexy::string_view(str, len);
|
return rexy::basic_string_view(str, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr inline rexy::string_view<char> operator"" _sv(const char* str, size_t len)noexcept{
|
constexpr inline rexy::basic_string_view<char> operator"" _sv(const char* str, size_t len)noexcept{
|
||||||
return rexy::string_view(str, len);
|
return rexy::basic_string_view(str, len);
|
||||||
}
|
}
|
||||||
constexpr inline rexy::string_view<wchar_t> operator"" _sv(const wchar_t* str, size_t len)noexcept{
|
constexpr inline rexy::basic_string_view<wchar_t> operator"" _sv(const wchar_t* str, size_t len)noexcept{
|
||||||
return rexy::string_view(str, len);
|
return rexy::basic_string_view(str, len);
|
||||||
}
|
}
|
||||||
constexpr inline rexy::string_view<char16_t> operator"" _sv(const char16_t* str, size_t len)noexcept{
|
constexpr inline rexy::basic_string_view<char16_t> operator"" _sv(const char16_t* str, size_t len)noexcept{
|
||||||
return rexy::string_view(str, len);
|
return rexy::basic_string_view(str, len);
|
||||||
}
|
}
|
||||||
constexpr inline rexy::string_view<char32_t> operator"" _sv(const char32_t* str, size_t len)noexcept{
|
constexpr inline rexy::basic_string_view<char32_t> operator"" _sv(const char32_t* str, size_t len)noexcept{
|
||||||
return rexy::string_view(str, len);
|
return rexy::basic_string_view(str, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Char, class Alloc>
|
template<class Char, class Alloc>
|
||||||
@ -502,7 +691,7 @@ namespace{
|
|||||||
return os << str.c_str();
|
return os << str.c_str();
|
||||||
}
|
}
|
||||||
template<class Char>
|
template<class Char>
|
||||||
std::ostream& operator<<(std::ostream& os, const rexy::string_view<Char>& str){
|
std::ostream& operator<<(std::ostream& os, const rexy::basic_string_view<Char>& str){
|
||||||
return os << str.c_str();
|
return os << str.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
This file is a part of rexy's general purpose library
|
This file is a part of rexy's general purpose library
|
||||||
Copyright (C) 2020 rexy712
|
Copyright (C) 2020-2022 rexy712
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -22,11 +22,11 @@
|
|||||||
#include <utility> //forward, move, swap, etc
|
#include <utility> //forward, move, swap, etc
|
||||||
#include <cstdlib> //memcpy
|
#include <cstdlib> //memcpy
|
||||||
#include <cstring> //strlen, strcpy
|
#include <cstring> //strlen, strcpy
|
||||||
#include <memory> //to_address
|
|
||||||
|
|
||||||
#include "utility.hpp" //max
|
#include "utility.hpp" //max
|
||||||
#include "detail/string_appender.hpp"
|
#include "detail/string_appender.hpp"
|
||||||
#include "algorithm.hpp"
|
#include "algorithm.hpp"
|
||||||
|
#include "compat/to_address.hpp"
|
||||||
|
|
||||||
#define STOP_STRICT_ALIAS_WARNING(x) (x)
|
#define STOP_STRICT_ALIAS_WARNING(x) (x)
|
||||||
|
|
||||||
@ -133,6 +133,13 @@ namespace rexy{
|
|||||||
{
|
{
|
||||||
_copy_construct_string(nullptr, len, cap);
|
_copy_construct_string(nullptr, len, cap);
|
||||||
}
|
}
|
||||||
|
template<class Char, class Allocator>
|
||||||
|
REXY_CPP20_CONSTEXPR basic_string<Char,Allocator>::basic_string(const basic_string_view<Char>& sv)
|
||||||
|
noexcept(noexcept(this->allocate(0)))
|
||||||
|
{
|
||||||
|
_copy_construct_string(sv.c_str(), sv.length(), sv.length());
|
||||||
|
}
|
||||||
|
|
||||||
template<class Char, class Allocator>
|
template<class Char, class Allocator>
|
||||||
template<class InputIt>
|
template<class InputIt>
|
||||||
REXY_CPP20_CONSTEXPR basic_string<Char,Allocator>::basic_string(InputIt start, InputIt fin)
|
REXY_CPP20_CONSTEXPR basic_string<Char,Allocator>::basic_string(InputIt start, InputIt fin)
|
||||||
@ -200,6 +207,14 @@ namespace rexy{
|
|||||||
return (*this = basic_string(s));
|
return (*this = basic_string(s));
|
||||||
}
|
}
|
||||||
//Copy from c string
|
//Copy from c string
|
||||||
|
template<class Char, class Allocator>
|
||||||
|
REXY_CPP20_CONSTEXPR basic_string<Char,Allocator>& basic_string<Char,Allocator>::operator=(const basic_string_view<Char>& sv)
|
||||||
|
noexcept(noexcept(this->allocate(0)) &&
|
||||||
|
noexcept(this->deallocate(nullptr,0)))
|
||||||
|
{
|
||||||
|
return _copy_string(sv.c_str(), sv.length());
|
||||||
|
}
|
||||||
|
|
||||||
template<class Char, class Allocator>
|
template<class Char, class Allocator>
|
||||||
REXY_CPP20_CONSTEXPR basic_string<Char,Allocator>& basic_string<Char,Allocator>::operator=(const_pointer c)
|
REXY_CPP20_CONSTEXPR basic_string<Char,Allocator>& basic_string<Char,Allocator>::operator=(const_pointer c)
|
||||||
noexcept(noexcept(this->allocate(0)) &&
|
noexcept(noexcept(this->allocate(0)) &&
|
||||||
@ -327,7 +342,7 @@ namespace rexy{
|
|||||||
noexcept(noexcept(this->allocate(0)) &&
|
noexcept(noexcept(this->allocate(0)) &&
|
||||||
noexcept(this->deallocate(nullptr,0)))
|
noexcept(this->deallocate(nullptr,0)))
|
||||||
{
|
{
|
||||||
if(!len)
|
if(!s || !len)
|
||||||
return (*this = basic_string(rexy::steal<pointer>(nullptr), 0, 0));
|
return (*this = basic_string(rexy::steal<pointer>(nullptr), 0, 0));
|
||||||
if(len <= this->length()){
|
if(len <= this->length()){
|
||||||
this->set_length(len);
|
this->set_length(len);
|
||||||
@ -359,63 +374,48 @@ namespace rexy{
|
|||||||
|
|
||||||
|
|
||||||
template<class Char>
|
template<class Char>
|
||||||
constexpr string_view<Char>::string_view(void)noexcept:
|
constexpr basic_string_view<Char>::basic_string_view(void)noexcept:
|
||||||
string_view(nullptr, 0){}
|
basic_string_view(nullptr, 0){}
|
||||||
|
|
||||||
template<class Char>
|
template<class Char>
|
||||||
constexpr string_view<Char>::string_view(const_pointer str, size_type len)noexcept{
|
constexpr basic_string_view<Char>::basic_string_view(const_pointer str, size_type len)noexcept:
|
||||||
if(!str)
|
m_data(str), m_length(len){}
|
||||||
this->set_long_ptr(nullptr);
|
|
||||||
else
|
|
||||||
this->set_long_ptr(const_cast<pointer>(str));
|
|
||||||
this->set_long_length(len);
|
|
||||||
this->set_long_capacity(len);
|
|
||||||
}
|
|
||||||
template<class Char>
|
template<class Char>
|
||||||
constexpr string_view<Char>::string_view(const string_view& s)noexcept:
|
constexpr basic_string_view<Char>::basic_string_view(const basic_string_view& s)noexcept:
|
||||||
string_view(s.get_long_ptr(), s.get_long_length()){}
|
m_data(s.m_data), m_length(s.m_length){}
|
||||||
template<class Char>
|
template<class Char>
|
||||||
constexpr string_view<Char>::string_view(const string_base<Char>& s)noexcept:
|
constexpr basic_string_view<Char>::basic_string_view(const string_base<Char>& s)noexcept:
|
||||||
string_view(s.c_str(), s.length()){}
|
m_data(s.c_str()), m_length(s.length()){}
|
||||||
template<class Char>
|
template<class Char>
|
||||||
constexpr string_view<Char>::string_view(string_view&& s)noexcept:
|
constexpr basic_string_view<Char>::basic_string_view(basic_string_view&& s)noexcept:
|
||||||
string_view(s.get_long_ptr(), s.get_long_length()){}
|
m_data(s.m_data), m_length(s.m_length){}
|
||||||
template<class Char>
|
template<class Char>
|
||||||
template<class InIter>
|
template<class InIter>
|
||||||
constexpr string_view<Char>::string_view(InIter start, InIter fin)noexcept:
|
constexpr basic_string_view<Char>::basic_string_view(InIter start, InIter fin)noexcept:
|
||||||
string_view(std::to_address(start), fin - start){}
|
basic_string_view(compat::to_address(start), fin - start){}
|
||||||
|
|
||||||
template<class Char>
|
template<class Char>
|
||||||
constexpr string_view<Char>& string_view<Char>::operator=(const string_view& s)noexcept{
|
constexpr basic_string_view<Char>& basic_string_view<Char>::operator=(const basic_string_view& s)noexcept{
|
||||||
this->set_long_ptr(const_cast<pointer>(s.get_long_ptr()));
|
m_data = s.m_data;
|
||||||
this->set_long_length(s.get_long_length());
|
m_length = s.m_length;
|
||||||
this->set_long_capacity(s.get_long_capacity());
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
template<class Char>
|
template<class Char>
|
||||||
constexpr string_view<Char>::string_view(const_pointer c)noexcept:
|
constexpr basic_string_view<Char>::basic_string_view(const_pointer c)noexcept:
|
||||||
string_view(c, strlen(c)){}
|
basic_string_view(c, strlen(c)){}
|
||||||
template<class Char>
|
template<class Char>
|
||||||
constexpr string_view<Char>& string_view<Char>::operator=(const_pointer c)noexcept{
|
constexpr basic_string_view<Char>& basic_string_view<Char>::operator=(const_pointer c)noexcept{
|
||||||
size_type len = strlen(c);
|
m_data = c;
|
||||||
this->set_long_ptr(const_cast<pointer>(c));
|
m_length = strlen(c);
|
||||||
this->set_long_length(len);
|
|
||||||
this->set_long_capacity(len);
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
template<class Char>
|
template<class Char>
|
||||||
constexpr string_view<Char>& string_view<Char>::operator=(string_view&& s)noexcept{
|
constexpr basic_string_view<Char>& basic_string_view<Char>::operator=(basic_string_view&& s)noexcept{
|
||||||
this->set_long_ptr(s.get_long_ptr());
|
m_data = s.m_data;
|
||||||
this->set_long_length(s.get_long_length());
|
m_length = s.m_length;
|
||||||
this->set_long_capacity(s.get_long_capacity());
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern template class string_view<char>;
|
|
||||||
extern template class string_view<wchar_t>;
|
|
||||||
extern template class string_view<char16_t>;
|
|
||||||
extern template class string_view<char32_t>;
|
|
||||||
|
|
||||||
} //namespace rexy
|
} //namespace rexy
|
||||||
|
|
||||||
#undef STOP_STRICT_ALIAS_WARNING
|
#undef STOP_STRICT_ALIAS_WARNING
|
||||||
|
|||||||
@ -21,10 +21,10 @@
|
|||||||
#include "rexy/meta.hpp"
|
#include "rexy/meta.hpp"
|
||||||
#include "rexy/enum_traits.hpp"
|
#include "rexy/enum_traits.hpp"
|
||||||
#include "rexy/deferred.hpp"
|
#include "rexy/deferred.hpp"
|
||||||
#include "rexy/source_location.hpp"
|
|
||||||
#include "rexy/demangle.hpp"
|
#include "rexy/demangle.hpp"
|
||||||
#include "rexy/debug_print.hpp"
|
#include "rexy/debug_print.hpp"
|
||||||
#include "rexy/storage_for.hpp"
|
#include "rexy/storage_for.hpp"
|
||||||
|
#include "rexy/visitor.hpp"
|
||||||
|
|
||||||
#include "rexy/detail/binary_string_conv.hpp"
|
#include "rexy/detail/binary_string_conv.hpp"
|
||||||
#include "rexy/detail/string_appender.hpp"
|
#include "rexy/detail/string_appender.hpp"
|
||||||
@ -35,3 +35,6 @@
|
|||||||
#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"
|
||||||
|
|
||||||
|
#include "rexy/compat/to_address.hpp"
|
||||||
|
#include "rexy/compat/source_location.hpp"
|
||||||
|
|||||||
@ -20,9 +20,9 @@
|
|||||||
|
|
||||||
namespace rexy{
|
namespace rexy{
|
||||||
|
|
||||||
template class string_view<char>;
|
template class basic_string_view<char>;
|
||||||
template class string_view<wchar_t>;
|
template class basic_string_view<wchar_t>;
|
||||||
template class string_view<char16_t>;
|
template class basic_string_view<char16_t>;
|
||||||
template class string_view<char32_t>;
|
template class basic_string_view<char32_t>;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user