Skip to content

Commit e83e0ca

Browse files
committed
[libcxx] Make filesystem::path::value_type wchar_t on windows
Also set the preferred separator to backslash. libc++ doesn't compile successfully for windows prior to this change, and this change on its own isn't enough to make it compile successfully either, but is the first stepping stone towards making it work correctly. Most of operations.cpp will need to be touched, both for calling functions that take wchar paths, but also for using other windows specific functions instead of the posix functions used so far; that is handled in later commits. Changing parts of operations.cpp to generalize the string type handling in code that doesn't touch system functions. Differential Revision: https://reviews.llvm.org/D91135
1 parent 569676c commit e83e0ca

File tree

3 files changed

+194
-43
lines changed

3 files changed

+194
-43
lines changed

libcxx/include/filesystem

Lines changed: 153 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -568,9 +568,19 @@ struct __can_convert_char<char32_t> {
568568
template <class _ECharT>
569569
typename enable_if<__can_convert_char<_ECharT>::value, bool>::type
570570
__is_separator(_ECharT __e) {
571+
#if defined(_LIBCPP_WIN32API)
572+
return __e == _ECharT('/') || __e == _ECharT('\\');
573+
#else
571574
return __e == _ECharT('/');
575+
#endif
572576
}
573577

578+
#ifndef _LIBCPP_NO_HAS_CHAR8_T
579+
typedef u8string __u8_string;
580+
#else
581+
typedef string __u8_string;
582+
#endif
583+
574584
struct _NullSentinel {};
575585

576586
template <class _Tp>
@@ -672,6 +682,14 @@ struct __is_pathable<_Tp, false, true, false> : __is_pathable_char_array<_Tp> {
672682
template <class _Tp>
673683
struct __is_pathable<_Tp, false, false, true> : __is_pathable_iter<_Tp> {};
674684

685+
#if defined(_LIBCPP_WIN32API)
686+
typedef wstring __path_string;
687+
typedef wchar_t __path_value;
688+
#else
689+
typedef string __path_string;
690+
typedef char __path_value;
691+
#endif
692+
675693
template <class _ECharT>
676694
struct _PathCVT;
677695

@@ -682,37 +700,60 @@ struct _PathCVT {
682700
"Char type not convertible");
683701

684702
typedef __narrow_to_utf8<sizeof(_ECharT) * __CHAR_BIT__> _Narrower;
703+
#if defined(_LIBCPP_WIN32API)
704+
typedef __widen_from_utf8<sizeof(wchar_t) * __CHAR_BIT__> _Widener;
705+
#endif
685706

686-
static void __append_range(string& __dest, _ECharT const* __b,
707+
static void __append_range(__path_string& __dest, _ECharT const* __b,
687708
_ECharT const* __e) {
709+
#if defined(_LIBCPP_WIN32API)
710+
string __utf8;
711+
_Narrower()(back_inserter(__utf8), __b, __e);
712+
_Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size());
713+
#else
688714
_Narrower()(back_inserter(__dest), __b, __e);
715+
#endif
689716
}
690717

691718
template <class _Iter>
692-
static void __append_range(string& __dest, _Iter __b, _Iter __e) {
719+
static void __append_range(__path_string& __dest, _Iter __b, _Iter __e) {
693720
static_assert(!is_same<_Iter, _ECharT*>::value, "Call const overload");
694721
if (__b == __e)
695722
return;
696723
basic_string<_ECharT> __tmp(__b, __e);
724+
#if defined(_LIBCPP_WIN32API)
725+
string __utf8;
726+
_Narrower()(back_inserter(__utf8), __tmp.data(),
727+
__tmp.data() + __tmp.length());
728+
_Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size());
729+
#else
697730
_Narrower()(back_inserter(__dest), __tmp.data(),
698731
__tmp.data() + __tmp.length());
732+
#endif
699733
}
700734

701735
template <class _Iter>
702-
static void __append_range(string& __dest, _Iter __b, _NullSentinel) {
736+
static void __append_range(__path_string& __dest, _Iter __b, _NullSentinel) {
703737
static_assert(!is_same<_Iter, _ECharT*>::value, "Call const overload");
704738
const _ECharT __sentinel = _ECharT{};
705739
if (*__b == __sentinel)
706740
return;
707741
basic_string<_ECharT> __tmp;
708742
for (; *__b != __sentinel; ++__b)
709743
__tmp.push_back(*__b);
744+
#if defined(_LIBCPP_WIN32API)
745+
string __utf8;
746+
_Narrower()(back_inserter(__utf8), __tmp.data(),
747+
__tmp.data() + __tmp.length());
748+
_Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size());
749+
#else
710750
_Narrower()(back_inserter(__dest), __tmp.data(),
711751
__tmp.data() + __tmp.length());
752+
#endif
712753
}
713754

714755
template <class _Source>
715-
static void __append_source(string& __dest, _Source const& __s) {
756+
static void __append_source(__path_string& __dest, _Source const& __s) {
716757
using _Traits = __is_pathable<_Source>;
717758
__append_range(__dest, _Traits::__range_begin(__s),
718759
_Traits::__range_end(__s));
@@ -721,36 +762,79 @@ struct _PathCVT {
721762
#endif // !_LIBCPP_HAS_NO_LOCALIZATION
722763

723764
template <>
724-
struct _PathCVT<char> {
765+
struct _PathCVT<__path_value> {
725766

726767
template <class _Iter>
727768
static typename enable_if<__is_exactly_cpp17_input_iterator<_Iter>::value>::type
728-
__append_range(string& __dest, _Iter __b, _Iter __e) {
769+
__append_range(__path_string& __dest, _Iter __b, _Iter __e) {
729770
for (; __b != __e; ++__b)
730771
__dest.push_back(*__b);
731772
}
732773

733774
template <class _Iter>
734775
static typename enable_if<__is_cpp17_forward_iterator<_Iter>::value>::type
735-
__append_range(string& __dest, _Iter __b, _Iter __e) {
776+
__append_range(__path_string& __dest, _Iter __b, _Iter __e) {
736777
__dest.__append_forward_unsafe(__b, __e);
737778
}
738779

739780
template <class _Iter>
740-
static void __append_range(string& __dest, _Iter __b, _NullSentinel) {
781+
static void __append_range(__path_string& __dest, _Iter __b, _NullSentinel) {
741782
const char __sentinel = char{};
742783
for (; *__b != __sentinel; ++__b)
743784
__dest.push_back(*__b);
744785
}
745786

746787
template <class _Source>
747-
static void __append_source(string& __dest, _Source const& __s) {
788+
static void __append_source(__path_string& __dest, _Source const& __s) {
748789
using _Traits = __is_pathable<_Source>;
749790
__append_range(__dest, _Traits::__range_begin(__s),
750791
_Traits::__range_end(__s));
751792
}
752793
};
753794

795+
#if defined(_LIBCPP_WIN32API)
796+
template <class _ECharT>
797+
struct _PathExport {
798+
typedef __narrow_to_utf8<sizeof(wchar_t) * __CHAR_BIT__> _Narrower;
799+
typedef __widen_from_utf8<sizeof(_ECharT) * __CHAR_BIT__> _Widener;
800+
801+
template <class _Str>
802+
static void __append(_Str& __dest, const __path_string& __src) {
803+
string __utf8;
804+
_Narrower()(back_inserter(__utf8), __src.data(), __src.data() + __src.size());
805+
_Widener()(back_inserter(__dest), __utf8.data(), __utf8.data() + __utf8.size());
806+
}
807+
};
808+
809+
template <>
810+
struct _PathExport<wchar_t> {
811+
template <class _Str>
812+
static void __append(_Str& __dest, const __path_string& __src) {
813+
__dest.append(__src.begin(), __src.end());
814+
}
815+
};
816+
817+
template <>
818+
struct _PathExport<char16_t> {
819+
template <class _Str>
820+
static void __append(_Str& __dest, const __path_string& __src) {
821+
__dest.append(__src.begin(), __src.end());
822+
}
823+
};
824+
825+
#ifndef _LIBCPP_NO_HAS_CHAR8_T
826+
template <>
827+
struct _PathExport<char8_t> {
828+
typedef __narrow_to_utf8<sizeof(wchar_t) * __CHAR_BIT__> _Narrower;
829+
830+
template <class _Str>
831+
static void __append(_Str& __dest, const __path_string& __src) {
832+
_Narrower()(back_inserter(__dest), __src.data(), __src.data() + __src.size());
833+
}
834+
};
835+
#endif /* !_LIBCPP_NO_HAS_CHAR8_T */
836+
#endif /* _LIBCPP_WIN32API */
837+
754838
class _LIBCPP_TYPE_VIS path {
755839
template <class _SourceOrIter, class _Tp = path&>
756840
using _EnableIfPathable =
@@ -763,10 +847,15 @@ class _LIBCPP_TYPE_VIS path {
763847
using _SourceCVT = _PathCVT<_SourceChar<_Tp> >;
764848

765849
public:
850+
#if defined(_LIBCPP_WIN32API)
851+
typedef wchar_t value_type;
852+
static constexpr value_type preferred_separator = L'\\';
853+
#else
766854
typedef char value_type;
767-
typedef basic_string<value_type> string_type;
768-
typedef _VSTD::string_view __string_view;
769855
static constexpr value_type preferred_separator = '/';
856+
#endif
857+
typedef basic_string<value_type> string_type;
858+
typedef basic_string_view<value_type> __string_view;
770859

771860
enum class _LIBCPP_ENUM_VIS format : unsigned char {
772861
auto_format,
@@ -1000,6 +1089,52 @@ public:
10001089

10011090
_LIBCPP_INLINE_VISIBILITY operator string_type() const { return __pn_; }
10021091

1092+
#if defined(_LIBCPP_WIN32API)
1093+
_LIBCPP_INLINE_VISIBILITY _VSTD::wstring wstring() const { return __pn_; }
1094+
1095+
_VSTD::wstring generic_wstring() const { return __pn_; }
1096+
1097+
#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
1098+
template <class _ECharT, class _Traits = char_traits<_ECharT>,
1099+
class _Allocator = allocator<_ECharT> >
1100+
basic_string<_ECharT, _Traits, _Allocator>
1101+
string(const _Allocator& __a = _Allocator()) const {
1102+
using _Str = basic_string<_ECharT, _Traits, _Allocator>;
1103+
_Str __s(__a);
1104+
__s.reserve(__pn_.size());
1105+
_PathExport<_ECharT>::__append(__s, __pn_);
1106+
return __s;
1107+
}
1108+
1109+
_LIBCPP_INLINE_VISIBILITY _VSTD::string string() const {
1110+
return string<char>();
1111+
}
1112+
_LIBCPP_INLINE_VISIBILITY __u8_string u8string() const {
1113+
return string<__u8_string::value_type>();
1114+
}
1115+
1116+
_LIBCPP_INLINE_VISIBILITY _VSTD::u16string u16string() const {
1117+
return string<char16_t>();
1118+
}
1119+
_LIBCPP_INLINE_VISIBILITY _VSTD::u32string u32string() const {
1120+
return string<char32_t>();
1121+
}
1122+
1123+
// generic format observers
1124+
template <class _ECharT, class _Traits = char_traits<_ECharT>,
1125+
class _Allocator = allocator<_ECharT> >
1126+
basic_string<_ECharT, _Traits, _Allocator>
1127+
generic_string(const _Allocator& __a = _Allocator()) const {
1128+
return string<_ECharT, _Traits, _Allocator>(__a);
1129+
}
1130+
1131+
_VSTD::string generic_string() const { return generic_string<char>(); }
1132+
_VSTD::u16string generic_u16string() const { return generic_string<char16_t>(); }
1133+
_VSTD::u32string generic_u32string() const { return generic_string<char32_t>(); }
1134+
__u8_string generic_u8string() const { return u8string(); }
1135+
#endif /* !_LIBCPP_HAS_NO_LOCALIZATION */
1136+
#else /* _LIBCPP_WIN32API */
1137+
10031138
_LIBCPP_INLINE_VISIBILITY _VSTD::string string() const { return __pn_; }
10041139
#ifndef _LIBCPP_NO_HAS_CHAR8_T
10051140
_LIBCPP_INLINE_VISIBILITY _VSTD::u8string u8string() const { return _VSTD::u8string(__pn_.begin(), __pn_.end()); }
@@ -1029,7 +1164,7 @@ public:
10291164
_LIBCPP_INLINE_VISIBILITY _VSTD::u32string u32string() const {
10301165
return string<char32_t>();
10311166
}
1032-
#endif
1167+
#endif /* !_LIBCPP_HAS_NO_LOCALIZATION */
10331168

10341169
// generic format observers
10351170
_VSTD::string generic_string() const { return __pn_; }
@@ -1050,7 +1185,8 @@ public:
10501185
_VSTD::wstring generic_wstring() const { return string<wchar_t>(); }
10511186
_VSTD::u16string generic_u16string() const { return string<char16_t>(); }
10521187
_VSTD::u32string generic_u32string() const { return string<char32_t>(); }
1053-
#endif
1188+
#endif /* !_LIBCPP_HAS_NO_LOCALIZATION */
1189+
#endif /* !_LIBCPP_WIN32API */
10541190

10551191
private:
10561192
int __compare(__string_view) const;
@@ -1157,8 +1293,8 @@ public:
11571293
#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
11581294
template <class _CharT, class _Traits>
11591295
_LIBCPP_INLINE_VISIBILITY friend
1160-
typename enable_if<is_same<_CharT, char>::value &&
1161-
is_same<_Traits, char_traits<char> >::value,
1296+
typename enable_if<is_same<_CharT, value_type>::value &&
1297+
is_same<_Traits, char_traits<value_type> >::value,
11621298
basic_ostream<_CharT, _Traits>&>::type
11631299
operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) {
11641300
__os << _VSTD::__quoted(__p.native());
@@ -1167,8 +1303,8 @@ public:
11671303

11681304
template <class _CharT, class _Traits>
11691305
_LIBCPP_INLINE_VISIBILITY friend
1170-
typename enable_if<!is_same<_CharT, char>::value ||
1171-
!is_same<_Traits, char_traits<char> >::value,
1306+
typename enable_if<!is_same<_CharT, value_type>::value ||
1307+
!is_same<_Traits, char_traits<value_type> >::value,
11721308
basic_ostream<_CharT, _Traits>&>::type
11731309
operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) {
11741310
__os << _VSTD::__quoted(__p.string<_CharT, _Traits>());

libcxx/src/filesystem/filesystem_common.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,12 @@
3838
#pragma GCC diagnostic ignored "-Wunused-function"
3939
#endif
4040

41+
#if defined(_LIBCPP_WIN32API)
42+
#define PS(x) (L##x)
43+
#else
44+
#define PS(x) (x)
45+
#endif
46+
4147
_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM
4248

4349
namespace detail {
@@ -94,8 +100,8 @@ static string format_string_imp(const char* msg, ...) {
94100
return result;
95101
}
96102

97-
const char* unwrap(string const& s) { return s.c_str(); }
98-
const char* unwrap(path const& p) { return p.native().c_str(); }
103+
const path::value_type* unwrap(path::string_type const& s) { return s.c_str(); }
104+
const path::value_type* unwrap(path const& p) { return p.native().c_str(); }
99105
template <class Arg>
100106
Arg const& unwrap(Arg const& a) {
101107
static_assert(!is_class<Arg>::value, "cannot pass class here");

0 commit comments

Comments
 (0)