]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // filesystem path_traits.hpp --------------------------------------------------------// |
2 | ||
3 | // Copyright Beman Dawes 2009 | |
4 | ||
5 | // Distributed under the Boost Software License, Version 1.0. | |
6 | // See http://www.boost.org/LICENSE_1_0.txt | |
7 | ||
8 | // Library home page: http://www.boost.org/libs/filesystem | |
9 | ||
10 | #ifndef BOOST_FILESYSTEM_PATH_TRAITS_HPP | |
11 | #define BOOST_FILESYSTEM_PATH_TRAITS_HPP | |
12 | ||
13 | #include <boost/config.hpp> | |
14 | ||
15 | # if defined( BOOST_NO_STD_WSTRING ) | |
16 | # error Configuration not supported: Boost.Filesystem V3 and later requires std::wstring support | |
17 | # endif | |
18 | ||
19 | #include <boost/filesystem/config.hpp> | |
7c673cae FG |
20 | #include <boost/type_traits/is_array.hpp> |
21 | #include <boost/type_traits/decay.hpp> | |
22 | #include <boost/system/error_code.hpp> | |
92f5a8d4 | 23 | #include <boost/core/enable_if.hpp> |
7c673cae FG |
24 | #include <cwchar> // for mbstate_t |
25 | #include <string> | |
26 | #include <vector> | |
27 | #include <list> | |
28 | #include <iterator> | |
29 | #include <locale> | |
30 | #include <boost/assert.hpp> | |
31 | // #include <iostream> //**** comment me out **** | |
32 | ||
33 | #include <boost/config/abi_prefix.hpp> // must be the last #include | |
34 | ||
35 | namespace boost { namespace filesystem { | |
36 | ||
37 | BOOST_FILESYSTEM_DECL const system::error_category& codecvt_error_category(); | |
38 | // uses std::codecvt_base::result used for error codes: | |
39 | // | |
40 | // ok: Conversion successful. | |
41 | // partial: Not all source characters converted; one or more additional source | |
42 | // characters are needed to produce the final target character, or the | |
43 | // size of the target intermediate buffer was too small to hold the result. | |
44 | // error: A character in the source could not be converted to the target encoding. | |
45 | // noconv: The source and target characters have the same type and encoding, so no | |
46 | // conversion was necessary. | |
47 | ||
48 | class directory_entry; | |
92f5a8d4 | 49 | |
7c673cae | 50 | namespace path_traits { |
92f5a8d4 | 51 | |
7c673cae FG |
52 | typedef std::codecvt<wchar_t, char, std::mbstate_t> codecvt_type; |
53 | ||
54 | // is_pathable type trait; allows disabling over-agressive class path member templates | |
55 | ||
56 | template <class T> | |
57 | struct is_pathable { static const bool value = false; }; | |
58 | ||
59 | template<> struct is_pathable<char*> { static const bool value = true; }; | |
60 | template<> struct is_pathable<const char*> { static const bool value = true; }; | |
61 | template<> struct is_pathable<wchar_t*> { static const bool value = true; }; | |
62 | template<> struct is_pathable<const wchar_t*> { static const bool value = true; }; | |
63 | template<> struct is_pathable<std::string> { static const bool value = true; }; | |
64 | template<> struct is_pathable<std::wstring> { static const bool value = true; }; | |
65 | template<> struct is_pathable<std::vector<char> > { static const bool value = true; }; | |
66 | template<> struct is_pathable<std::vector<wchar_t> > { static const bool value = true; }; | |
67 | template<> struct is_pathable<std::list<char> > { static const bool value = true; }; | |
68 | template<> struct is_pathable<std::list<wchar_t> > { static const bool value = true; }; | |
69 | template<> struct is_pathable<directory_entry> { static const bool value = true; }; | |
70 | ||
71 | // Pathable empty | |
72 | ||
73 | template <class Container> inline | |
74 | // disable_if aids broken compilers (IBM, old GCC, etc.) and is harmless for | |
92f5a8d4 | 75 | // conforming compilers. Replace by plain "bool" at some future date (2012?) |
7c673cae FG |
76 | typename boost::disable_if<boost::is_array<Container>, bool>::type |
77 | empty(const Container & c) | |
78 | { return c.begin() == c.end(); } | |
79 | ||
80 | template <class T> inline | |
81 | bool empty(T * const & c_str) | |
82 | { | |
83 | BOOST_ASSERT(c_str); | |
84 | return !*c_str; | |
85 | } | |
86 | ||
87 | template <typename T, size_t N> inline | |
88 | bool empty(T (&x)[N]) | |
89 | { return !x[0]; } | |
90 | ||
91 | // value types differ ---------------------------------------------------------------// | |
92 | // | |
93 | // A from_end argument of 0 is less efficient than a known end, so use only if needed | |
94 | ||
95 | // with codecvt | |
96 | ||
97 | BOOST_FILESYSTEM_DECL | |
98 | void convert(const char* from, | |
99 | const char* from_end, // 0 for null terminated MBCS | |
100 | std::wstring & to, | |
101 | const codecvt_type& cvt); | |
102 | ||
103 | BOOST_FILESYSTEM_DECL | |
104 | void convert(const wchar_t* from, | |
105 | const wchar_t* from_end, // 0 for null terminated MBCS | |
106 | std::string & to, | |
107 | const codecvt_type& cvt); | |
108 | ||
109 | inline | |
110 | void convert(const char* from, | |
111 | std::wstring & to, | |
112 | const codecvt_type& cvt) | |
113 | { | |
114 | BOOST_ASSERT(from); | |
115 | convert(from, 0, to, cvt); | |
116 | } | |
117 | ||
118 | inline | |
119 | void convert(const wchar_t* from, | |
120 | std::string & to, | |
121 | const codecvt_type& cvt) | |
122 | { | |
123 | BOOST_ASSERT(from); | |
124 | convert(from, 0, to, cvt); | |
125 | } | |
126 | ||
127 | // without codecvt | |
128 | ||
129 | inline | |
130 | void convert(const char* from, | |
131 | const char* from_end, // 0 for null terminated MBCS | |
132 | std::wstring & to); | |
133 | ||
134 | inline | |
135 | void convert(const wchar_t* from, | |
136 | const wchar_t* from_end, // 0 for null terminated MBCS | |
137 | std::string & to); | |
138 | ||
139 | inline | |
140 | void convert(const char* from, | |
141 | std::wstring & to); | |
142 | ||
143 | inline | |
144 | void convert(const wchar_t* from, | |
145 | std::string & to); | |
146 | ||
147 | // value types same -----------------------------------------------------------------// | |
148 | ||
149 | // char with codecvt | |
150 | ||
151 | inline | |
152 | void convert(const char* from, const char* from_end, std::string & to, | |
153 | const codecvt_type&) | |
154 | { | |
155 | BOOST_ASSERT(from); | |
156 | BOOST_ASSERT(from_end); | |
157 | to.append(from, from_end); | |
158 | } | |
159 | ||
160 | inline | |
161 | void convert(const char* from, | |
162 | std::string & to, | |
163 | const codecvt_type&) | |
164 | { | |
165 | BOOST_ASSERT(from); | |
166 | to += from; | |
167 | } | |
168 | ||
169 | // wchar_t with codecvt | |
170 | ||
171 | inline | |
172 | void convert(const wchar_t* from, const wchar_t* from_end, std::wstring & to, | |
173 | const codecvt_type&) | |
174 | { | |
175 | BOOST_ASSERT(from); | |
176 | BOOST_ASSERT(from_end); | |
177 | to.append(from, from_end); | |
178 | } | |
179 | ||
180 | inline | |
181 | void convert(const wchar_t* from, | |
182 | std::wstring & to, | |
183 | const codecvt_type&) | |
184 | { | |
185 | BOOST_ASSERT(from); | |
186 | to += from; | |
187 | } | |
188 | ||
189 | // char without codecvt | |
190 | ||
191 | inline | |
192 | void convert(const char* from, const char* from_end, std::string & to) | |
193 | { | |
194 | BOOST_ASSERT(from); | |
195 | BOOST_ASSERT(from_end); | |
196 | to.append(from, from_end); | |
197 | } | |
198 | ||
199 | inline | |
200 | void convert(const char* from, std::string & to) | |
201 | { | |
202 | BOOST_ASSERT(from); | |
203 | to += from; | |
204 | } | |
205 | ||
206 | // wchar_t without codecvt | |
207 | ||
208 | inline | |
209 | void convert(const wchar_t* from, const wchar_t* from_end, std::wstring & to) | |
210 | { | |
211 | BOOST_ASSERT(from); | |
212 | BOOST_ASSERT(from_end); | |
213 | to.append(from, from_end); | |
214 | } | |
215 | ||
216 | inline | |
217 | void convert(const wchar_t* from, std::wstring & to) | |
218 | { | |
219 | BOOST_ASSERT(from); | |
220 | to += from; | |
221 | } | |
222 | ||
223 | // Source dispatch -----------------------------------------------------------------// | |
224 | ||
225 | // contiguous containers with codecvt | |
226 | template <class U> inline | |
227 | void dispatch(const std::string& c, U& to, const codecvt_type& cvt) | |
228 | { | |
20effc67 | 229 | if (!c.empty()) |
7c673cae FG |
230 | convert(&*c.begin(), &*c.begin() + c.size(), to, cvt); |
231 | } | |
232 | template <class U> inline | |
233 | void dispatch(const std::wstring& c, U& to, const codecvt_type& cvt) | |
234 | { | |
20effc67 | 235 | if (!c.empty()) |
7c673cae FG |
236 | convert(&*c.begin(), &*c.begin() + c.size(), to, cvt); |
237 | } | |
238 | template <class U> inline | |
239 | void dispatch(const std::vector<char>& c, U& to, const codecvt_type& cvt) | |
240 | { | |
20effc67 | 241 | if (!c.empty()) |
7c673cae FG |
242 | convert(&*c.begin(), &*c.begin() + c.size(), to, cvt); |
243 | } | |
244 | template <class U> inline | |
245 | void dispatch(const std::vector<wchar_t>& c, U& to, const codecvt_type& cvt) | |
246 | { | |
20effc67 | 247 | if (!c.empty()) |
7c673cae FG |
248 | convert(&*c.begin(), &*c.begin() + c.size(), to, cvt); |
249 | } | |
250 | ||
251 | // contiguous containers without codecvt | |
252 | template <class U> inline | |
253 | void dispatch(const std::string& c, U& to) | |
254 | { | |
20effc67 | 255 | if (!c.empty()) |
7c673cae FG |
256 | convert(&*c.begin(), &*c.begin() + c.size(), to); |
257 | } | |
258 | template <class U> inline | |
259 | void dispatch(const std::wstring& c, U& to) | |
260 | { | |
20effc67 | 261 | if (!c.empty()) |
7c673cae FG |
262 | convert(&*c.begin(), &*c.begin() + c.size(), to); |
263 | } | |
264 | template <class U> inline | |
265 | void dispatch(const std::vector<char>& c, U& to) | |
266 | { | |
20effc67 | 267 | if (!c.empty()) |
7c673cae FG |
268 | convert(&*c.begin(), &*c.begin() + c.size(), to); |
269 | } | |
270 | template <class U> inline | |
271 | void dispatch(const std::vector<wchar_t>& c, U& to) | |
272 | { | |
20effc67 | 273 | if (!c.empty()) |
7c673cae FG |
274 | convert(&*c.begin(), &*c.begin() + c.size(), to); |
275 | } | |
276 | ||
277 | // non-contiguous containers with codecvt | |
278 | template <class Container, class U> inline | |
279 | // disable_if aids broken compilers (IBM, old GCC, etc.) and is harmless for | |
92f5a8d4 | 280 | // conforming compilers. Replace by plain "void" at some future date (2012?) |
7c673cae FG |
281 | typename boost::disable_if<boost::is_array<Container>, void>::type |
282 | dispatch(const Container & c, U& to, const codecvt_type& cvt) | |
283 | { | |
20effc67 | 284 | if (!c.empty()) |
7c673cae FG |
285 | { |
286 | std::basic_string<typename Container::value_type> s(c.begin(), c.end()); | |
287 | convert(s.c_str(), s.c_str()+s.size(), to, cvt); | |
288 | } | |
289 | } | |
290 | ||
291 | // c_str | |
292 | template <class T, class U> inline | |
293 | void dispatch(T * const & c_str, U& to, const codecvt_type& cvt) | |
294 | { | |
295 | // std::cout << "dispatch() const T *\n"; | |
296 | BOOST_ASSERT(c_str); | |
297 | convert(c_str, to, cvt); | |
298 | } | |
299 | ||
300 | // Note: there is no dispatch on C-style arrays because the array may | |
92f5a8d4 | 301 | // contain a string smaller than the array size. |
7c673cae FG |
302 | |
303 | BOOST_FILESYSTEM_DECL | |
304 | void dispatch(const directory_entry & de, | |
305 | # ifdef BOOST_WINDOWS_API | |
306 | std::wstring & to, | |
92f5a8d4 | 307 | # else |
7c673cae FG |
308 | std::string & to, |
309 | # endif | |
310 | const codecvt_type&); | |
311 | ||
312 | // non-contiguous containers without codecvt | |
313 | template <class Container, class U> inline | |
314 | // disable_if aids broken compilers (IBM, old GCC, etc.) and is harmless for | |
92f5a8d4 | 315 | // conforming compilers. Replace by plain "void" at some future date (2012?) |
7c673cae FG |
316 | typename boost::disable_if<boost::is_array<Container>, void>::type |
317 | dispatch(const Container & c, U& to) | |
318 | { | |
20effc67 | 319 | if (!c.empty()) |
7c673cae FG |
320 | { |
321 | std::basic_string<typename Container::value_type> seq(c.begin(), c.end()); | |
322 | convert(seq.c_str(), seq.c_str()+seq.size(), to); | |
323 | } | |
324 | } | |
325 | ||
326 | // c_str | |
327 | template <class T, class U> inline | |
328 | void dispatch(T * const & c_str, U& to) | |
329 | { | |
330 | // std::cout << "dispatch() const T *\n"; | |
331 | BOOST_ASSERT(c_str); | |
332 | convert(c_str, to); | |
333 | } | |
334 | ||
335 | // Note: there is no dispatch on C-style arrays because the array may | |
92f5a8d4 | 336 | // contain a string smaller than the array size. |
7c673cae FG |
337 | |
338 | BOOST_FILESYSTEM_DECL | |
339 | void dispatch(const directory_entry & de, | |
340 | # ifdef BOOST_WINDOWS_API | |
341 | std::wstring & to | |
92f5a8d4 | 342 | # else |
7c673cae FG |
343 | std::string & to |
344 | # endif | |
345 | ); | |
346 | ||
347 | ||
348 | }}} // namespace boost::filesystem::path_traits | |
349 | ||
350 | #include <boost/config/abi_suffix.hpp> // pops abi_prefix.hpp pragmas | |
351 | ||
352 | #endif // BOOST_FILESYSTEM_PATH_TRAITS_HPP |