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>
20#include <boost/utility/enable_if.hpp>
21#include <boost/type_traits/is_array.hpp>
22#include <boost/type_traits/decay.hpp>
23#include <boost/system/error_code.hpp>
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
35namespace 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;
49
50namespace path_traits {
51
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
75 // conforming compilers. Replace by plain "bool" at some future date (2012?)
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 {
229 if (c.size())
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 {
235 if (c.size())
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 {
241 if (c.size())
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 {
247 if (c.size())
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 {
255 if (c.size())
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 {
261 if (c.size())
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 {
267 if (c.size())
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 {
273 if (c.size())
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
280 // conforming compilers. Replace by plain "void" at some future date (2012?)
281 typename boost::disable_if<boost::is_array<Container>, void>::type
282 dispatch(const Container & c, U& to, const codecvt_type& cvt)
283 {
284 if (c.size())
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
301 // contain a string smaller than the array size.
302
303 BOOST_FILESYSTEM_DECL
304 void dispatch(const directory_entry & de,
305# ifdef BOOST_WINDOWS_API
306 std::wstring & to,
307# else
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
315 // conforming compilers. Replace by plain "void" at some future date (2012?)
316 typename boost::disable_if<boost::is_array<Container>, void>::type
317 dispatch(const Container & c, U& to)
318 {
319 if (c.size())
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
336 // contain a string smaller than the array size.
337
338 BOOST_FILESYSTEM_DECL
339 void dispatch(const directory_entry & de,
340# ifdef BOOST_WINDOWS_API
341 std::wstring & to
342# else
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
353