libstdc++: P1423R3 char8_t remediation (1/4)
Decouple constraints for u8path from path constructors This patch moves helper classes and functions for std::filesystem::path out of the class definition to a detail namespace so that they are available to the implementations of std::filesystem::u8path. Prior to this patch, the SFINAE constraints for those implementations were specified via delegation to the overloads of path constructors with a std::locale parameter; it just so happened that those overloads had the same constraints. As of P1423R3, u8path and those overloads no longer have the same constraints, so this dependency must be broken. This patch also updates the experimental implementation of the filesystem TS to add SFINAE constraints to its implementations of u8path. These functions were previously unconstrained and marked with a TODO comment. This patch does not provide any intentional behavioral changes other than the added constraints to the experimental filesystem TS implementation of u8path. Alternatives to this refactoring would have been to make the u8path overloads friends of class path, or to make the helpers public members. Both of those approaches struck me as less desirable than this approach, though this approach does require more code changes and will affect implementation detail portions of mangled names for path constructors and inline member functions (mostly function template specializations). 2019-11-29 Tom Honermann <tom@honermann.net> Decouple constraints for u8path from path constructors * include/bits/fs_path.h: Moved helper utilities out of std::filesystem::path into a detail namespace to make them available for use by u8path. * include/experimental/bits/fs_path.h: Moved helper utilities out of std::experimental::filesystem::v1::path into a detail namespace to make them available for use by u8path. From-SVN: r278855
This commit is contained in:
parent
6851de8b90
commit
a1e7d33bb9
@ -1,3 +1,13 @@
|
||||
2019-11-29 Tom Honermann <tom@honermann.net>
|
||||
|
||||
Decouple constraints for u8path from path constructors
|
||||
* include/bits/fs_path.h: Moved helper utilities out of
|
||||
std::filesystem::path into a detail namespace to make them
|
||||
available for use by u8path.
|
||||
* include/experimental/bits/fs_path.h: Moved helper utilities out
|
||||
of std::experimental::filesystem::v1::path into a detail
|
||||
namespace to make them available for use by u8path.
|
||||
|
||||
2019-11-29 Jonathan Wakely <jwakely@redhat.com>
|
||||
|
||||
PR libstdc++/91997
|
||||
|
@ -63,99 +63,107 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
|
||||
* @{
|
||||
*/
|
||||
|
||||
class path;
|
||||
|
||||
/// @cond undocumented
|
||||
namespace __detail
|
||||
{
|
||||
template<typename _CharT>
|
||||
using __is_encoded_char = __is_one_of<remove_const_t<_CharT>,
|
||||
char,
|
||||
#ifdef _GLIBCXX_USE_CHAR8_T
|
||||
char8_t,
|
||||
#endif
|
||||
#if _GLIBCXX_USE_WCHAR_T
|
||||
wchar_t,
|
||||
#endif
|
||||
char16_t, char32_t>;
|
||||
|
||||
template<typename _Iter,
|
||||
typename _Iter_traits = std::iterator_traits<_Iter>>
|
||||
using __is_path_iter_src
|
||||
= __and_<__is_encoded_char<typename _Iter_traits::value_type>,
|
||||
std::is_base_of<std::input_iterator_tag,
|
||||
typename _Iter_traits::iterator_category>>;
|
||||
|
||||
template<typename _Iter>
|
||||
static __is_path_iter_src<_Iter>
|
||||
__is_path_src(_Iter, int);
|
||||
|
||||
template<typename _CharT, typename _Traits, typename _Alloc>
|
||||
static __is_encoded_char<_CharT>
|
||||
__is_path_src(const basic_string<_CharT, _Traits, _Alloc>&, int);
|
||||
|
||||
template<typename _CharT, typename _Traits>
|
||||
static __is_encoded_char<_CharT>
|
||||
__is_path_src(const basic_string_view<_CharT, _Traits>&, int);
|
||||
|
||||
template<typename _Unknown>
|
||||
static std::false_type
|
||||
__is_path_src(const _Unknown&, ...);
|
||||
|
||||
template<typename _Tp1, typename _Tp2>
|
||||
struct __constructible_from;
|
||||
|
||||
template<typename _Iter>
|
||||
struct __constructible_from<_Iter, _Iter>
|
||||
: __is_path_iter_src<_Iter>
|
||||
{ };
|
||||
|
||||
template<typename _Source>
|
||||
struct __constructible_from<_Source, void>
|
||||
: decltype(__is_path_src(std::declval<_Source>(), 0))
|
||||
{ };
|
||||
|
||||
template<typename _Tp1, typename _Tp2 = void>
|
||||
using _Path = typename
|
||||
std::enable_if<__and_<__not_<is_same<remove_cv_t<_Tp1>, path>>,
|
||||
__not_<is_void<remove_pointer_t<_Tp1>>>,
|
||||
__constructible_from<_Tp1, _Tp2>>::value,
|
||||
path>::type;
|
||||
|
||||
template<typename _Source>
|
||||
static _Source
|
||||
_S_range_begin(_Source __begin) { return __begin; }
|
||||
|
||||
struct __null_terminated { };
|
||||
|
||||
template<typename _Source>
|
||||
static __null_terminated
|
||||
_S_range_end(_Source) { return {}; }
|
||||
|
||||
template<typename _CharT, typename _Traits, typename _Alloc>
|
||||
static const _CharT*
|
||||
_S_range_begin(const basic_string<_CharT, _Traits, _Alloc>& __str)
|
||||
{ return __str.data(); }
|
||||
|
||||
template<typename _CharT, typename _Traits, typename _Alloc>
|
||||
static const _CharT*
|
||||
_S_range_end(const basic_string<_CharT, _Traits, _Alloc>& __str)
|
||||
{ return __str.data() + __str.size(); }
|
||||
|
||||
template<typename _CharT, typename _Traits>
|
||||
static const _CharT*
|
||||
_S_range_begin(const basic_string_view<_CharT, _Traits>& __str)
|
||||
{ return __str.data(); }
|
||||
|
||||
template<typename _CharT, typename _Traits>
|
||||
static const _CharT*
|
||||
_S_range_end(const basic_string_view<_CharT, _Traits>& __str)
|
||||
{ return __str.data() + __str.size(); }
|
||||
|
||||
template<typename _Tp,
|
||||
typename _Iter = decltype(_S_range_begin(std::declval<_Tp>())),
|
||||
typename _Val = typename std::iterator_traits<_Iter>::value_type>
|
||||
using __value_type_is_char
|
||||
= std::enable_if_t<std::is_same_v<std::remove_const_t<_Val>, char>>;
|
||||
|
||||
} // namespace __detail
|
||||
/// @endcond
|
||||
|
||||
/// A filesystem path.
|
||||
class path
|
||||
{
|
||||
template<typename _CharT>
|
||||
using __is_encoded_char = __is_one_of<remove_const_t<_CharT>,
|
||||
char,
|
||||
#ifdef _GLIBCXX_USE_CHAR8_T
|
||||
char8_t,
|
||||
#endif
|
||||
#if _GLIBCXX_USE_WCHAR_T
|
||||
wchar_t,
|
||||
#endif
|
||||
char16_t, char32_t>;
|
||||
|
||||
template<typename _Iter,
|
||||
typename _Iter_traits = std::iterator_traits<_Iter>>
|
||||
using __is_path_iter_src
|
||||
= __and_<__is_encoded_char<typename _Iter_traits::value_type>,
|
||||
std::is_base_of<std::input_iterator_tag,
|
||||
typename _Iter_traits::iterator_category>>;
|
||||
|
||||
template<typename _Iter>
|
||||
static __is_path_iter_src<_Iter>
|
||||
__is_path_src(_Iter, int);
|
||||
|
||||
template<typename _CharT, typename _Traits, typename _Alloc>
|
||||
static __is_encoded_char<_CharT>
|
||||
__is_path_src(const basic_string<_CharT, _Traits, _Alloc>&, int);
|
||||
|
||||
template<typename _CharT, typename _Traits>
|
||||
static __is_encoded_char<_CharT>
|
||||
__is_path_src(const basic_string_view<_CharT, _Traits>&, int);
|
||||
|
||||
template<typename _Unknown>
|
||||
static std::false_type
|
||||
__is_path_src(const _Unknown&, ...);
|
||||
|
||||
template<typename _Tp1, typename _Tp2>
|
||||
struct __constructible_from;
|
||||
|
||||
template<typename _Iter>
|
||||
struct __constructible_from<_Iter, _Iter>
|
||||
: __is_path_iter_src<_Iter>
|
||||
{ };
|
||||
|
||||
template<typename _Source>
|
||||
struct __constructible_from<_Source, void>
|
||||
: decltype(__is_path_src(std::declval<_Source>(), 0))
|
||||
{ };
|
||||
|
||||
template<typename _Tp1, typename _Tp2 = void>
|
||||
using _Path = typename
|
||||
std::enable_if<__and_<__not_<is_same<remove_cv_t<_Tp1>, path>>,
|
||||
__not_<is_void<remove_pointer_t<_Tp1>>>,
|
||||
__constructible_from<_Tp1, _Tp2>>::value,
|
||||
path>::type;
|
||||
|
||||
template<typename _Source>
|
||||
static _Source
|
||||
_S_range_begin(_Source __begin) { return __begin; }
|
||||
|
||||
struct __null_terminated { };
|
||||
|
||||
template<typename _Source>
|
||||
static __null_terminated
|
||||
_S_range_end(_Source) { return {}; }
|
||||
|
||||
template<typename _CharT, typename _Traits, typename _Alloc>
|
||||
static const _CharT*
|
||||
_S_range_begin(const basic_string<_CharT, _Traits, _Alloc>& __str)
|
||||
{ return __str.data(); }
|
||||
|
||||
template<typename _CharT, typename _Traits, typename _Alloc>
|
||||
static const _CharT*
|
||||
_S_range_end(const basic_string<_CharT, _Traits, _Alloc>& __str)
|
||||
{ return __str.data() + __str.size(); }
|
||||
|
||||
template<typename _CharT, typename _Traits>
|
||||
static const _CharT*
|
||||
_S_range_begin(const basic_string_view<_CharT, _Traits>& __str)
|
||||
{ return __str.data(); }
|
||||
|
||||
template<typename _CharT, typename _Traits>
|
||||
static const _CharT*
|
||||
_S_range_end(const basic_string_view<_CharT, _Traits>& __str)
|
||||
{ return __str.data() + __str.size(); }
|
||||
|
||||
template<typename _Tp,
|
||||
typename _Iter = decltype(_S_range_begin(std::declval<_Tp>())),
|
||||
typename _Val = typename std::iterator_traits<_Iter>::value_type>
|
||||
using __value_type_is_char
|
||||
= std::enable_if_t<std::is_same_v<std::remove_const_t<_Val>, char>>;
|
||||
|
||||
public:
|
||||
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
using value_type = wchar_t;
|
||||
@ -193,29 +201,29 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
|
||||
{ _M_split_cmpts(); }
|
||||
|
||||
template<typename _Source,
|
||||
typename _Require = _Path<_Source>>
|
||||
typename _Require = __detail::_Path<_Source>>
|
||||
path(_Source const& __source, format = auto_format)
|
||||
: _M_pathname(_S_convert(_S_range_begin(__source),
|
||||
_S_range_end(__source)))
|
||||
: _M_pathname(_S_convert(__detail::_S_range_begin(__source),
|
||||
__detail::_S_range_end(__source)))
|
||||
{ _M_split_cmpts(); }
|
||||
|
||||
template<typename _InputIterator,
|
||||
typename _Require = _Path<_InputIterator, _InputIterator>>
|
||||
typename _Require = __detail::_Path<_InputIterator, _InputIterator>>
|
||||
path(_InputIterator __first, _InputIterator __last, format = auto_format)
|
||||
: _M_pathname(_S_convert(__first, __last))
|
||||
{ _M_split_cmpts(); }
|
||||
|
||||
template<typename _Source,
|
||||
typename _Require = _Path<_Source>,
|
||||
typename _Require2 = __value_type_is_char<_Source>>
|
||||
typename _Require = __detail::_Path<_Source>,
|
||||
typename _Require2 = __detail::__value_type_is_char<_Source>>
|
||||
path(_Source const& __source, const locale& __loc, format = auto_format)
|
||||
: _M_pathname(_S_convert_loc(_S_range_begin(__source),
|
||||
_S_range_end(__source), __loc))
|
||||
: _M_pathname(_S_convert_loc(__detail::_S_range_begin(__source),
|
||||
__detail::_S_range_end(__source), __loc))
|
||||
{ _M_split_cmpts(); }
|
||||
|
||||
template<typename _InputIterator,
|
||||
typename _Require = _Path<_InputIterator, _InputIterator>,
|
||||
typename _Require2 = __value_type_is_char<_InputIterator>>
|
||||
typename _Require = __detail::_Path<_InputIterator, _InputIterator>,
|
||||
typename _Require2 = __detail::__value_type_is_char<_InputIterator>>
|
||||
path(_InputIterator __first, _InputIterator __last, const locale& __loc,
|
||||
format = auto_format)
|
||||
: _M_pathname(_S_convert_loc(__first, __last, __loc))
|
||||
@ -231,17 +239,17 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
|
||||
path& assign(string_type&& __source);
|
||||
|
||||
template<typename _Source>
|
||||
_Path<_Source>&
|
||||
__detail::_Path<_Source>&
|
||||
operator=(_Source const& __source)
|
||||
{ return *this = path(__source); }
|
||||
|
||||
template<typename _Source>
|
||||
_Path<_Source>&
|
||||
__detail::_Path<_Source>&
|
||||
assign(_Source const& __source)
|
||||
{ return *this = path(__source); }
|
||||
|
||||
template<typename _InputIterator>
|
||||
_Path<_InputIterator, _InputIterator>&
|
||||
__detail::_Path<_InputIterator, _InputIterator>&
|
||||
assign(_InputIterator __first, _InputIterator __last)
|
||||
{ return *this = path(__first, __last); }
|
||||
|
||||
@ -250,23 +258,25 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
|
||||
path& operator/=(const path& __p);
|
||||
|
||||
template <class _Source>
|
||||
_Path<_Source>&
|
||||
__detail::_Path<_Source>&
|
||||
operator/=(_Source const& __source)
|
||||
{
|
||||
_M_append(_S_convert(_S_range_begin(__source), _S_range_end(__source)));
|
||||
_M_append(_S_convert(__detail::_S_range_begin(__source),
|
||||
__detail::_S_range_end(__source)));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename _Source>
|
||||
_Path<_Source>&
|
||||
__detail::_Path<_Source>&
|
||||
append(_Source const& __source)
|
||||
{
|
||||
_M_append(_S_convert(_S_range_begin(__source), _S_range_end(__source)));
|
||||
_M_append(_S_convert(__detail::_S_range_begin(__source),
|
||||
__detail::_S_range_end(__source)));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename _InputIterator>
|
||||
_Path<_InputIterator, _InputIterator>&
|
||||
__detail::_Path<_InputIterator, _InputIterator>&
|
||||
append(_InputIterator __first, _InputIterator __last)
|
||||
{
|
||||
_M_append(_S_convert(__first, __last));
|
||||
@ -282,23 +292,24 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
|
||||
path& operator+=(basic_string_view<value_type> __x);
|
||||
|
||||
template<typename _Source>
|
||||
_Path<_Source>&
|
||||
__detail::_Path<_Source>&
|
||||
operator+=(_Source const& __x) { return concat(__x); }
|
||||
|
||||
template<typename _CharT>
|
||||
_Path<_CharT*, _CharT*>&
|
||||
__detail::_Path<_CharT*, _CharT*>&
|
||||
operator+=(_CharT __x);
|
||||
|
||||
template<typename _Source>
|
||||
_Path<_Source>&
|
||||
__detail::_Path<_Source>&
|
||||
concat(_Source const& __x)
|
||||
{
|
||||
_M_concat(_S_convert(_S_range_begin(__x), _S_range_end(__x)));
|
||||
_M_concat(_S_convert(__detail::_S_range_begin(__x),
|
||||
__detail::_S_range_end(__x)));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename _InputIterator>
|
||||
_Path<_InputIterator, _InputIterator>&
|
||||
__detail::_Path<_InputIterator, _InputIterator>&
|
||||
concat(_InputIterator __first, _InputIterator __last)
|
||||
{
|
||||
_M_concat(_S_convert(__first, __last));
|
||||
@ -496,11 +507,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
|
||||
struct _Cvt;
|
||||
|
||||
static basic_string_view<value_type>
|
||||
_S_convert(value_type* __src, __null_terminated)
|
||||
_S_convert(value_type* __src, __detail::__null_terminated)
|
||||
{ return __src; }
|
||||
|
||||
static basic_string_view<value_type>
|
||||
_S_convert(const value_type* __src, __null_terminated)
|
||||
_S_convert(const value_type* __src, __detail::__null_terminated)
|
||||
{ return __src; }
|
||||
|
||||
static basic_string_view<value_type>
|
||||
@ -522,7 +533,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
|
||||
|
||||
template<typename _InputIterator>
|
||||
static string_type
|
||||
_S_convert(_InputIterator __src, __null_terminated)
|
||||
_S_convert(_InputIterator __src, __detail::__null_terminated)
|
||||
{
|
||||
// Read from iterator into basic_string until a null value is seen:
|
||||
auto __s = _S_string_from_iter(__src);
|
||||
@ -544,7 +555,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
|
||||
|
||||
template<typename _InputIterator>
|
||||
static string_type
|
||||
_S_convert_loc(_InputIterator __src, __null_terminated,
|
||||
_S_convert_loc(_InputIterator __src, __detail::__null_terminated,
|
||||
const std::locale& __loc)
|
||||
{
|
||||
const std::string __s = _S_string_from_iter(__src);
|
||||
@ -657,10 +668,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
|
||||
*
|
||||
* @relates std::filesystem::path
|
||||
*/
|
||||
template<typename _InputIterator>
|
||||
inline auto
|
||||
template<typename _InputIterator,
|
||||
typename _Require = __detail::_Path<_InputIterator, _InputIterator>,
|
||||
typename _Require2 = __detail::__value_type_is_char<_InputIterator>>
|
||||
inline path
|
||||
u8path(_InputIterator __first, _InputIterator __last)
|
||||
-> decltype(filesystem::path(__first, __last, std::locale::classic()))
|
||||
{
|
||||
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
// XXX This assumes native wide encoding is UTF-16.
|
||||
@ -691,10 +703,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
|
||||
*
|
||||
* @relates std::filesystem::path
|
||||
*/
|
||||
template<typename _Source>
|
||||
inline auto
|
||||
template<typename _Source,
|
||||
typename _Require = __detail::_Path<_Source>,
|
||||
typename _Require2 = __detail::__value_type_is_char<_Source>>
|
||||
inline path
|
||||
u8path(const _Source& __source)
|
||||
-> decltype(filesystem::path(__source, std::locale::classic()))
|
||||
{
|
||||
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
if constexpr (is_convertible_v<const _Source&, std::string_view>)
|
||||
@ -950,7 +963,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
|
||||
}
|
||||
|
||||
template<typename _CharT>
|
||||
inline path::_Path<_CharT*, _CharT*>&
|
||||
inline __detail::_Path<_CharT*, _CharT*>&
|
||||
path::operator+=(_CharT __x)
|
||||
{
|
||||
auto* __addr = std::__addressof(__x);
|
||||
|
@ -71,111 +71,116 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
|
||||
using std::basic_string_view;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @addtogroup filesystem-ts
|
||||
* @{
|
||||
/** @addtogroup filesystem-ts
|
||||
* @{
|
||||
*/
|
||||
|
||||
/// @cond undocumented
|
||||
namespace __detail
|
||||
{
|
||||
template<typename _CharT,
|
||||
typename _Ch = typename remove_const<_CharT>::type>
|
||||
using __is_encoded_char
|
||||
= __or_<is_same<_Ch, char>,
|
||||
is_same<_Ch, wchar_t>,
|
||||
#ifdef _GLIBCXX_USE_CHAR8_T
|
||||
is_same<_Ch, char8_t>,
|
||||
#endif
|
||||
is_same<_Ch, char16_t>,
|
||||
is_same<_Ch, char32_t>>;
|
||||
|
||||
template<typename _Iter,
|
||||
typename _Iter_traits = std::iterator_traits<_Iter>>
|
||||
using __is_path_iter_src
|
||||
= __and_<__is_encoded_char<typename _Iter_traits::value_type>,
|
||||
std::is_base_of<std::input_iterator_tag,
|
||||
typename _Iter_traits::iterator_category>>;
|
||||
|
||||
template<typename _Iter>
|
||||
static __is_path_iter_src<_Iter>
|
||||
__is_path_src(_Iter, int);
|
||||
|
||||
template<typename _CharT, typename _Traits, typename _Alloc>
|
||||
static __is_encoded_char<_CharT>
|
||||
__is_path_src(const basic_string<_CharT, _Traits, _Alloc>&, int);
|
||||
|
||||
#if __cplusplus >= 201402L
|
||||
template<typename _CharT, typename _Traits>
|
||||
static __is_encoded_char<_CharT>
|
||||
__is_path_src(const basic_string_view<_CharT, _Traits>&, int);
|
||||
#endif
|
||||
|
||||
template<typename _Unknown>
|
||||
static std::false_type
|
||||
__is_path_src(const _Unknown&, ...);
|
||||
|
||||
template<typename _Tp1, typename _Tp2>
|
||||
struct __constructible_from;
|
||||
|
||||
template<typename _Iter>
|
||||
struct __constructible_from<_Iter, _Iter>
|
||||
: __is_path_iter_src<_Iter>
|
||||
{ };
|
||||
|
||||
template<typename _Source>
|
||||
struct __constructible_from<_Source, void>
|
||||
: decltype(__is_path_src(std::declval<_Source>(), 0))
|
||||
{ };
|
||||
|
||||
template<typename _Tp1, typename _Tp2 = void,
|
||||
typename _Tp1_nocv = typename remove_cv<_Tp1>::type,
|
||||
typename _Tp1_noptr = typename remove_pointer<_Tp1>::type>
|
||||
using _Path = typename
|
||||
std::enable_if<__and_<__not_<is_same<_Tp1_nocv, path>>,
|
||||
__not_<is_void<_Tp1_noptr>>,
|
||||
__constructible_from<_Tp1, _Tp2>>::value,
|
||||
path>::type;
|
||||
|
||||
template<typename _Source>
|
||||
static _Source
|
||||
_S_range_begin(_Source __begin) { return __begin; }
|
||||
|
||||
struct __null_terminated { };
|
||||
|
||||
template<typename _Source>
|
||||
static __null_terminated
|
||||
_S_range_end(_Source) { return {}; }
|
||||
|
||||
template<typename _CharT, typename _Traits, typename _Alloc>
|
||||
static const _CharT*
|
||||
_S_range_begin(const basic_string<_CharT, _Traits, _Alloc>& __str)
|
||||
{ return __str.data(); }
|
||||
|
||||
template<typename _CharT, typename _Traits, typename _Alloc>
|
||||
static const _CharT*
|
||||
_S_range_end(const basic_string<_CharT, _Traits, _Alloc>& __str)
|
||||
{ return __str.data() + __str.size(); }
|
||||
|
||||
#if __cplusplus >= 201402L
|
||||
template<typename _CharT, typename _Traits>
|
||||
static const _CharT*
|
||||
_S_range_begin(const basic_string_view<_CharT, _Traits>& __str)
|
||||
{ return __str.data(); }
|
||||
|
||||
template<typename _CharT, typename _Traits>
|
||||
static const _CharT*
|
||||
_S_range_end(const basic_string_view<_CharT, _Traits>& __str)
|
||||
{ return __str.data() + __str.size(); }
|
||||
#endif
|
||||
|
||||
template<typename _Tp,
|
||||
typename _Iter = decltype(_S_range_begin(std::declval<_Tp>())),
|
||||
typename _Val = typename std::iterator_traits<_Iter>::value_type>
|
||||
using __value_type_is_char = typename std::enable_if<
|
||||
std::is_same<typename std::remove_const<_Val>::type, char>::value
|
||||
>::type;
|
||||
|
||||
} // namespace __detail
|
||||
/// @endcond
|
||||
|
||||
/// A filesystem path.
|
||||
class path
|
||||
{
|
||||
template<typename _CharT,
|
||||
typename _Ch = typename remove_const<_CharT>::type>
|
||||
using __is_encoded_char
|
||||
= __or_<is_same<_Ch, char>,
|
||||
is_same<_Ch, wchar_t>,
|
||||
#ifdef _GLIBCXX_USE_CHAR8_T
|
||||
is_same<_Ch, char8_t>,
|
||||
#endif
|
||||
is_same<_Ch, char16_t>,
|
||||
is_same<_Ch, char32_t>>;
|
||||
|
||||
template<typename _Iter,
|
||||
typename _Iter_traits = std::iterator_traits<_Iter>>
|
||||
using __is_path_iter_src
|
||||
= __and_<__is_encoded_char<typename _Iter_traits::value_type>,
|
||||
std::is_base_of<std::input_iterator_tag,
|
||||
typename _Iter_traits::iterator_category>>;
|
||||
|
||||
template<typename _Iter>
|
||||
static __is_path_iter_src<_Iter>
|
||||
__is_path_src(_Iter, int);
|
||||
|
||||
template<typename _CharT, typename _Traits, typename _Alloc>
|
||||
static __is_encoded_char<_CharT>
|
||||
__is_path_src(const basic_string<_CharT, _Traits, _Alloc>&, int);
|
||||
|
||||
#if __cplusplus >= 201402L
|
||||
template<typename _CharT, typename _Traits>
|
||||
static __is_encoded_char<_CharT>
|
||||
__is_path_src(const basic_string_view<_CharT, _Traits>&, int);
|
||||
#endif
|
||||
|
||||
template<typename _Unknown>
|
||||
static std::false_type
|
||||
__is_path_src(const _Unknown&, ...);
|
||||
|
||||
template<typename _Tp1, typename _Tp2>
|
||||
struct __constructible_from;
|
||||
|
||||
template<typename _Iter>
|
||||
struct __constructible_from<_Iter, _Iter>
|
||||
: __is_path_iter_src<_Iter>
|
||||
{ };
|
||||
|
||||
template<typename _Source>
|
||||
struct __constructible_from<_Source, void>
|
||||
: decltype(__is_path_src(std::declval<_Source>(), 0))
|
||||
{ };
|
||||
|
||||
template<typename _Tp1, typename _Tp2 = void,
|
||||
typename _Tp1_nocv = typename remove_cv<_Tp1>::type,
|
||||
typename _Tp1_noptr = typename remove_pointer<_Tp1>::type>
|
||||
using _Path = typename
|
||||
std::enable_if<__and_<__not_<is_same<_Tp1_nocv, path>>,
|
||||
__not_<is_void<_Tp1_noptr>>,
|
||||
__constructible_from<_Tp1, _Tp2>>::value,
|
||||
path>::type;
|
||||
|
||||
template<typename _Source>
|
||||
static _Source
|
||||
_S_range_begin(_Source __begin) { return __begin; }
|
||||
|
||||
struct __null_terminated { };
|
||||
|
||||
template<typename _Source>
|
||||
static __null_terminated
|
||||
_S_range_end(_Source) { return {}; }
|
||||
|
||||
template<typename _CharT, typename _Traits, typename _Alloc>
|
||||
static const _CharT*
|
||||
_S_range_begin(const basic_string<_CharT, _Traits, _Alloc>& __str)
|
||||
{ return __str.data(); }
|
||||
|
||||
template<typename _CharT, typename _Traits, typename _Alloc>
|
||||
static const _CharT*
|
||||
_S_range_end(const basic_string<_CharT, _Traits, _Alloc>& __str)
|
||||
{ return __str.data() + __str.size(); }
|
||||
|
||||
#if __cplusplus >= 201402L
|
||||
template<typename _CharT, typename _Traits>
|
||||
static const _CharT*
|
||||
_S_range_begin(const basic_string_view<_CharT, _Traits>& __str)
|
||||
{ return __str.data(); }
|
||||
|
||||
template<typename _CharT, typename _Traits>
|
||||
static const _CharT*
|
||||
_S_range_end(const basic_string_view<_CharT, _Traits>& __str)
|
||||
{ return __str.data() + __str.size(); }
|
||||
#endif
|
||||
|
||||
template<typename _Tp,
|
||||
typename _Iter = decltype(_S_range_begin(std::declval<_Tp>())),
|
||||
typename _Val = typename std::iterator_traits<_Iter>::value_type>
|
||||
using __value_type_is_char = typename std::enable_if<
|
||||
std::is_same<typename std::remove_const<_Val>::type, char>::value
|
||||
>::type;
|
||||
|
||||
public:
|
||||
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
typedef wchar_t value_type;
|
||||
@ -205,29 +210,29 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
|
||||
{ _M_split_cmpts(); }
|
||||
|
||||
template<typename _Source,
|
||||
typename _Require = _Path<_Source>>
|
||||
typename _Require = __detail::_Path<_Source>>
|
||||
path(_Source const& __source)
|
||||
: _M_pathname(_S_convert(_S_range_begin(__source),
|
||||
_S_range_end(__source)))
|
||||
: _M_pathname(_S_convert(__detail::_S_range_begin(__source),
|
||||
__detail::_S_range_end(__source)))
|
||||
{ _M_split_cmpts(); }
|
||||
|
||||
template<typename _InputIterator,
|
||||
typename _Require = _Path<_InputIterator, _InputIterator>>
|
||||
typename _Require = __detail::_Path<_InputIterator, _InputIterator>>
|
||||
path(_InputIterator __first, _InputIterator __last)
|
||||
: _M_pathname(_S_convert(__first, __last))
|
||||
{ _M_split_cmpts(); }
|
||||
|
||||
template<typename _Source,
|
||||
typename _Require = _Path<_Source>,
|
||||
typename _Require2 = __value_type_is_char<_Source>>
|
||||
typename _Require = __detail::_Path<_Source>,
|
||||
typename _Require2 = __detail::__value_type_is_char<_Source>>
|
||||
path(_Source const& __source, const locale& __loc)
|
||||
: _M_pathname(_S_convert_loc(_S_range_begin(__source),
|
||||
_S_range_end(__source), __loc))
|
||||
: _M_pathname(_S_convert_loc(__detail::_S_range_begin(__source),
|
||||
__detail::_S_range_end(__source), __loc))
|
||||
{ _M_split_cmpts(); }
|
||||
|
||||
template<typename _InputIterator,
|
||||
typename _Require = _Path<_InputIterator, _InputIterator>,
|
||||
typename _Require2 = __value_type_is_char<_InputIterator>>
|
||||
typename _Require = __detail::_Path<_InputIterator, _InputIterator>,
|
||||
typename _Require2 = __detail::__value_type_is_char<_InputIterator>>
|
||||
path(_InputIterator __first, _InputIterator __last, const locale& __loc)
|
||||
: _M_pathname(_S_convert_loc(__first, __last, __loc))
|
||||
{ _M_split_cmpts(); }
|
||||
@ -242,17 +247,17 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
|
||||
path& assign(string_type&& __source);
|
||||
|
||||
template<typename _Source>
|
||||
_Path<_Source>&
|
||||
__detail::_Path<_Source>&
|
||||
operator=(_Source const& __source)
|
||||
{ return *this = path(__source); }
|
||||
|
||||
template<typename _Source>
|
||||
_Path<_Source>&
|
||||
__detail::_Path<_Source>&
|
||||
assign(_Source const& __source)
|
||||
{ return *this = path(__source); }
|
||||
|
||||
template<typename _InputIterator>
|
||||
_Path<_InputIterator, _InputIterator>&
|
||||
__detail::_Path<_InputIterator, _InputIterator>&
|
||||
assign(_InputIterator __first, _InputIterator __last)
|
||||
{ return *this = path(__first, __last); }
|
||||
|
||||
@ -261,20 +266,20 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
|
||||
path& operator/=(const path& __p) { return _M_append(__p._M_pathname); }
|
||||
|
||||
template <class _Source>
|
||||
_Path<_Source>&
|
||||
__detail::_Path<_Source>&
|
||||
operator/=(_Source const& __source)
|
||||
{ return append(__source); }
|
||||
|
||||
template<typename _Source>
|
||||
_Path<_Source>&
|
||||
__detail::_Path<_Source>&
|
||||
append(_Source const& __source)
|
||||
{
|
||||
return _M_append(_S_convert(_S_range_begin(__source),
|
||||
_S_range_end(__source)));
|
||||
return _M_append(_S_convert(__detail::_S_range_begin(__source),
|
||||
__detail::_S_range_end(__source)));
|
||||
}
|
||||
|
||||
template<typename _InputIterator>
|
||||
_Path<_InputIterator, _InputIterator>&
|
||||
__detail::_Path<_InputIterator, _InputIterator>&
|
||||
append(_InputIterator __first, _InputIterator __last)
|
||||
{ return _M_append(_S_convert(__first, __last)); }
|
||||
|
||||
@ -289,20 +294,23 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
|
||||
#endif
|
||||
|
||||
template<typename _Source>
|
||||
_Path<_Source>&
|
||||
__detail::_Path<_Source>&
|
||||
operator+=(_Source const& __x) { return concat(__x); }
|
||||
|
||||
template<typename _CharT>
|
||||
_Path<_CharT*, _CharT*>&
|
||||
__detail::_Path<_CharT*, _CharT*>&
|
||||
operator+=(_CharT __x);
|
||||
|
||||
template<typename _Source>
|
||||
_Path<_Source>&
|
||||
__detail::_Path<_Source>&
|
||||
concat(_Source const& __x)
|
||||
{ return *this += _S_convert(_S_range_begin(__x), _S_range_end(__x)); }
|
||||
{
|
||||
return *this += _S_convert(__detail::_S_range_begin(__x),
|
||||
__detail::_S_range_end(__x));
|
||||
}
|
||||
|
||||
template<typename _InputIterator>
|
||||
_Path<_InputIterator, _InputIterator>&
|
||||
__detail::_Path<_InputIterator, _InputIterator>&
|
||||
concat(_InputIterator __first, _InputIterator __last)
|
||||
{ return *this += _S_convert(__first, __last); }
|
||||
|
||||
@ -446,11 +454,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
|
||||
struct _Cvt;
|
||||
|
||||
static string_type
|
||||
_S_convert(value_type* __src, __null_terminated)
|
||||
_S_convert(value_type* __src, __detail::__null_terminated)
|
||||
{ return string_type(__src); }
|
||||
|
||||
static string_type
|
||||
_S_convert(const value_type* __src, __null_terminated)
|
||||
_S_convert(const value_type* __src, __detail::__null_terminated)
|
||||
{ return string_type(__src); }
|
||||
|
||||
template<typename _Iter>
|
||||
@ -464,7 +472,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
|
||||
|
||||
template<typename _InputIterator>
|
||||
static string_type
|
||||
_S_convert(_InputIterator __src, __null_terminated)
|
||||
_S_convert(_InputIterator __src, __detail::__null_terminated)
|
||||
{
|
||||
auto __s = _S_string_from_iter(__src);
|
||||
return _S_convert(__s.c_str(), __s.c_str() + __s.size());
|
||||
@ -484,7 +492,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
|
||||
|
||||
template<typename _InputIterator>
|
||||
static string_type
|
||||
_S_convert_loc(_InputIterator __src, __null_terminated,
|
||||
_S_convert_loc(_InputIterator __src, __detail::__null_terminated,
|
||||
const std::locale& __loc)
|
||||
{
|
||||
const std::string __s = _S_string_from_iter(__src);
|
||||
@ -580,8 +588,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
|
||||
}
|
||||
|
||||
/// Create a path from a UTF-8-encoded sequence of char
|
||||
// TODO constrain with _Path<InputIterator, InputIterator> and __value_type_is_char
|
||||
template<typename _InputIterator>
|
||||
template<typename _InputIterator,
|
||||
typename _Require = __detail::_Path<_InputIterator, _InputIterator>,
|
||||
typename _Require2 = __detail::__value_type_is_char<_InputIterator>>
|
||||
inline path
|
||||
u8path(_InputIterator __first, _InputIterator __last)
|
||||
{
|
||||
@ -602,8 +611,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
|
||||
}
|
||||
|
||||
/// Create a path from a UTF-8-encoded sequence of char
|
||||
// TODO constrain with _Path<Source> and __value_type_is_char
|
||||
template<typename _Source>
|
||||
template<typename _Source,
|
||||
typename _Require = __detail::_Path<_Source>,
|
||||
typename _Require2 = __detail::__value_type_is_char<_Source>>
|
||||
inline path
|
||||
u8path(const _Source& __source)
|
||||
{
|
||||
@ -872,7 +882,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
|
||||
#endif
|
||||
|
||||
template<typename _CharT>
|
||||
inline path::_Path<_CharT*, _CharT*>&
|
||||
inline __detail::_Path<_CharT*, _CharT*>&
|
||||
path::operator+=(_CharT __x)
|
||||
{
|
||||
auto* __addr = std::__addressof(__x);
|
||||
|
Loading…
Reference in New Issue
Block a user