6
6
#include < iostream>
7
7
#include < utility>
8
8
9
- namespace of {
10
- namespace filesystem {
11
-
12
9
// general approach to return type:
13
10
// - use `path` and path &` to wrap std:: return values
14
11
// - use bool when bool (for self-documenting API)
15
12
// - use (const) auto (inheriting from std:: implementation) for others
16
13
14
+ namespace of ::filesystem {
15
+
17
16
class path {
18
17
private:
19
18
std::filesystem::path path_; // simple composition
20
19
21
- #if defined(TARGET_WIN32)
22
- // TODO better (ideal) impl this just copy-pasted for proof of concept
23
- mutable std::string cached_narrow_str_;
24
- const char * to_narrow_cstr () const {
25
- std::mbstate_t state = std::mbstate_t ();
26
- size_t size_needed = std::wcstombs (nullptr , wstring ().c_str (), 0 ) + 1 ;
27
- if (size_needed == static_cast <size_t >(-1 )) {
28
- throw std::runtime_error (" Conversion error from wstring to string" );
29
- }
30
- cached_narrow_str_.resize (size_needed);
31
- std::wcstombs (&cached_narrow_str_[0 ], wstring ().c_str (), size_needed);
32
- return cached_narrow_str_.c_str ();
33
- }
34
- #endif
35
-
36
20
public:
37
21
// MARK: construction
38
22
path () = default ;
@@ -53,15 +37,29 @@ class path {
53
37
explicit operator const std::filesystem::path::value_type*() const { return path_.c_str (); }
54
38
55
39
// MARK: string conversions
56
-
57
- #if defined(TARGET_WIN32)
40
+
41
+ #if defined(TARGET_WIN32) // superfluous but usefull to facilitate testing on mac/linux
42
+
43
+ // TODO better (ideal) impl this just copy-pasted for proof of concept
44
+ mutable std::string cached_narrow_str_;
45
+ const char * to_narrow_cstr () const {
46
+ std::mbstate_t state = std::mbstate_t ();
47
+ size_t size_needed = std::wcstombs (nullptr , wstring ().c_str (), 0 ) + 1 ;
48
+ if (size_needed == static_cast <size_t >(-1 )) {
49
+ throw std::runtime_error (" Conversion error from wstring to string" );
50
+ }
51
+ cached_narrow_str_.resize (size_needed);
52
+ std::wcstombs (&cached_narrow_str_[0 ], wstring ().c_str (), size_needed);
53
+ return cached_narrow_str_.c_str ();
54
+ }
55
+
58
56
operator std::wstring () const { return path_.wstring (); }
59
57
operator const char *() const { return to_narrow_cstr (); } // should try catch on win
60
58
operator std::string () const { return path_.string (); } // should try catch on win
61
59
explicit operator const std::string () const { return path_.string (); } // should try catch on win
62
60
#else
63
61
operator std::filesystem::path::string_type () const { return path_.string (); }
64
- explicit operator const std::filesystem::path::string_type () const { return path_.string (); }
62
+ explicit operator const std::filesystem::path::string_type () const { return path_.string (); }
65
63
#endif
66
64
67
65
auto wstring () const { return path_.wstring (); }
@@ -76,7 +74,7 @@ class path {
76
74
auto u16string () const { return path_.u16string (); }
77
75
auto u32string () const { return path_.u32string (); }
78
76
const auto c_str () const noexcept { return path_.c_str (); }
79
-
77
+
80
78
const std::filesystem::path& native_path () const { return path_; }
81
79
82
80
static constexpr auto preferred_separator = std::filesystem::path::preferred_separator;
@@ -96,12 +94,12 @@ class path {
96
94
auto file_size () const { return std::filesystem::file_size (path_); }
97
95
auto last_write_time () const { return std::filesystem::last_write_time (path_); }
98
96
auto get_permissions () const { return std::filesystem::status (path_).permissions (); }
99
-
97
+
100
98
// MARK: path type
101
99
path lexically_normal () const {
102
100
return path (path_.lexically_normal ());
103
101
}
104
-
102
+
105
103
template <typename ... Args>
106
104
path lexically_relative (Args&&... args) const {
107
105
return path (path_.lexically_relative (std::forward<Args>(args)...));
@@ -111,7 +109,7 @@ class path {
111
109
path lexically_proximate (Args&&... args) const {
112
110
return path (path_.lexically_proximate (std::forward<Args>(args)...));
113
111
}
114
-
112
+
115
113
// MARK: comparison
116
114
// TODO: C++20: spaceship simplification
117
115
template <typename T> bool operator ==(T&& other) const noexcept { return path_ == std::forward<T>(other); }
@@ -122,35 +120,35 @@ class path {
122
120
template <typename T> bool operator >=(T&& other) const noexcept { return path_ >= std::forward<T>(other); }
123
121
124
122
bool operator !() const noexcept { return empty (); }
125
-
123
+
126
124
template <typename ... Args>
127
125
auto compare (Args&&... args) const { return path_.compare (std::forward<Args>(args)...); }
128
126
129
127
void swap (path & other) noexcept { path_.swap (other.path_ ); }
130
-
128
+
131
129
132
130
// MARK: path transformation (return *this)
133
- path& replace_extension (const path & ext = std::filesystem::path()) {
131
+ path& replace_extension (const path & ext = std::filesystem::path()) {
134
132
path_.replace_extension (ext);
135
133
return *this ;
136
134
}
137
-
138
- path& replace_filename (const path & ext = std::filesystem::path()) {
135
+
136
+ path& replace_filename (const path & ext = std::filesystem::path()) {
139
137
path_.replace_filename (ext);
140
138
return *this ;
141
139
}
142
-
140
+
143
141
template <typename T>
144
142
path& assign (T&& p) noexcept {
145
143
path_.assign (std::move (std::forward<T>(p)));
146
144
return *this ;
147
145
}
148
-
146
+
149
147
path& append (path&& p) noexcept {
150
148
path_ /= std::move (p.path_ );
151
149
return *this ;
152
150
}
153
-
151
+
154
152
path& operator /=(path&& p) noexcept {
155
153
path_ /= std::move (p.path_ );
156
154
return *this ;
@@ -202,7 +200,7 @@ class path {
202
200
const friend path operator +(const path& lhs, const RHS& rhs) {
203
201
return path (lhs.path_ .string () + rhs);
204
202
}
205
-
203
+
206
204
// MARK: other sub paths
207
205
path root_name () const { return path (path_.root_name ()); }
208
206
path root_directory () const { return path (path_.root_directory ()); }
@@ -212,7 +210,7 @@ class path {
212
210
path filename () const { return path (path_.filename ()); }
213
211
path stem () const { return path (path_.stem ()); }
214
212
path extension () const { return path (path_.extension ()); }
215
-
213
+
216
214
// MARK: file info
217
215
bool has_extension () const { return path_.has_extension (); }
218
216
bool has_filename () const { return path_.has_filename (); }
@@ -221,13 +219,10 @@ class path {
221
219
bool has_root_directory () const { return path_.has_root_directory (); }
222
220
bool has_relative_path () const { return path_.has_relative_path (); }
223
221
bool has_stem () const { return path_.has_stem (); }
224
-
222
+
225
223
friend std::ostream& operator <<(std::ostream& os, const path& p) {
226
224
return os << p.string ();
227
225
}
228
226
};
229
-
230
- } // namespace filesystem
231
- } // namespace of
232
-
227
+ }
233
228
#endif // OF_FILESYSTEM_PATH_H
0 commit comments