diff --git a/libcxx/include/__filesystem/path.h b/libcxx/include/__filesystem/path.h index b3f324342f800..990833116aebe 100644 --- a/libcxx/include/__filesystem/path.h +++ b/libcxx/include/__filesystem/path.h @@ -324,6 +324,7 @@ struct _PathCVT { } }; +# if _LIBCPP_HAS_LOCALIZATION template struct _PathExport { typedef __narrow_to_utf8 _Narrower; @@ -364,7 +365,7 @@ struct _PathExport { } }; -# if _LIBCPP_HAS_CHAR8_T +# if _LIBCPP_HAS_CHAR8_T template <> struct _PathExport { typedef __narrow_to_utf8 _Narrower; @@ -374,7 +375,8 @@ struct _PathExport { _Narrower()(back_inserter(__dest), __src.data(), __src.data() + __src.size()); } }; -# endif // _LIBCPP_HAS_CHAR8_T +# endif // _LIBCPP_HAS_CHAR8_T +# endif // _LIBCPP_HAS_LOCALIZATION # endif /* _LIBCPP_WIN32API */ class _LIBCPP_EXPORTED_FROM_ABI path { diff --git a/libcxx/include/__filesystem/u8path.h b/libcxx/include/__filesystem/u8path.h index 885372b0d1f86..0a1ec556833fd 100644 --- a/libcxx/include/__filesystem/u8path.h +++ b/libcxx/include/__filesystem/u8path.h @@ -13,7 +13,9 @@ #include <__algorithm/unwrap_iter.h> #include <__config> #include <__filesystem/path.h> -#include <__locale> +#if !defined(_LIBCPP_WIN32API) || _LIBCPP_HAS_LOCALIZATION +# include <__locale> +#endif #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -24,17 +26,39 @@ _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM -template ::value, int> = 0> -_LIBCPP_HIDE_FROM_ABI _LIBCPP_DEPRECATED_WITH_CHAR8_T path u8path(_InputIt __f, _InputIt __l) { +# if defined(_LIBCPP_WIN32API) && _LIBCPP_HAS_LOCALIZATION +# define _LIBCPP_FS_U8PATH_CONVERTS_ENCODING 1 +# else +# define _LIBCPP_FS_U8PATH_CONVERTS_ENCODING 0 +# endif + +# if _LIBCPP_FS_U8PATH_CONVERTS_ENCODING +template +_LIBCPP_HIDE_FROM_ABI string __make_tmp_string_for_u8path(_InputIt __f, _Sentinel __l) { + static_assert(__is_pathable<_InputIt>::value); static_assert( -# if _LIBCPP_HAS_CHAR8_T +# if _LIBCPP_HAS_CHAR8_T is_same::__char_type, char8_t>::value || -# endif - is_same::__char_type, char>::value, - "u8path(Iter, Iter) requires Iter have a value_type of type 'char'" - " or 'char8_t'"); -# if defined(_LIBCPP_WIN32API) - string __tmp(__f, __l); +# endif + is_same::__char_type, char>::value); + + if constexpr (is_same_v<_Sentinel, _NullSentinel>) { + string __tmp; + constexpr char __sentinel{}; + for (; *__f != __sentinel; ++__f) + __tmp.push_back(*__f); + return __tmp; + } else { + static_assert(is_same_v<_InputIt, _Sentinel>); + return string(__f, __l); + } +} +# endif // _LIBCPP_FS_U8PATH_CONVERTS_ENCODING + +template +_LIBCPP_HIDE_FROM_ABI path __u8path(_InputIt __f, _Sentinel __l) { +# if _LIBCPP_FS_U8PATH_CONVERTS_ENCODING + auto __tmp = std::filesystem::__make_tmp_string_for_u8path(__f, __l); using _CVT = __widen_from_utf8; std::wstring __w; __w.reserve(__tmp.size()); @@ -42,30 +66,20 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_DEPRECATED_WITH_CHAR8_T path u8path(_InputIt __f, return path(__w); # else return path(__f, __l); -# endif /* !_LIBCPP_WIN32API */ +# endif // _LIBCPP_FS_U8PATH_CONVERTS_ENCODING } -# if defined(_LIBCPP_WIN32API) template ::value, int> = 0> -_LIBCPP_HIDE_FROM_ABI _LIBCPP_DEPRECATED_WITH_CHAR8_T path u8path(_InputIt __f, _NullSentinel) { +_LIBCPP_HIDE_FROM_ABI _LIBCPP_DEPRECATED_WITH_CHAR8_T path u8path(_InputIt __f, _InputIt __l) { static_assert( -# if _LIBCPP_HAS_CHAR8_T +# if _LIBCPP_HAS_CHAR8_T is_same::__char_type, char8_t>::value || -# endif +# endif is_same::__char_type, char>::value, "u8path(Iter, Iter) requires Iter have a value_type of type 'char'" " or 'char8_t'"); - string __tmp; - const char __sentinel = char{}; - for (; *__f != __sentinel; ++__f) - __tmp.push_back(*__f); - using _CVT = __widen_from_utf8; - std::wstring __w; - __w.reserve(__tmp.size()); - _CVT()(back_inserter(__w), __tmp.data(), __tmp.data() + __tmp.size()); - return path(__w); + return std::filesystem::__u8path(__f, __l); } -# endif /* _LIBCPP_WIN32API */ template ::value, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_DEPRECATED_WITH_CHAR8_T path u8path(const _Source& __s) { @@ -76,14 +90,17 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_DEPRECATED_WITH_CHAR8_T path u8path(const _Source& is_same::__char_type, char>::value, "u8path(Source const&) requires Source have a character type of type " "'char' or 'char8_t'"); -# if defined(_LIBCPP_WIN32API) +# if _LIBCPP_FS_U8PATH_CONVERTS_ENCODING using _Traits = __is_pathable<_Source>; - return u8path(std::__unwrap_iter(_Traits::__range_begin(__s)), std::__unwrap_iter(_Traits::__range_end(__s))); + return std::filesystem::__u8path( + std::__unwrap_iter(_Traits::__range_begin(__s)), std::__unwrap_iter(_Traits::__range_end(__s))); # else return path(__s); -# endif +# endif // _LIBCPP_FS_U8PATH_CONVERTS_ENCODING } +# undef _LIBCPP_FS_U8PATH_CONVERTS_ENCODING + _LIBCPP_END_NAMESPACE_FILESYSTEM #endif // _LIBCPP_STD_VER >= 17