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/type_traits/is_array.hpp> 21 #include <boost/type_traits/decay.hpp> 22 #include <boost/system/error_code.hpp> 23 #include <boost/core/enable_if.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 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; 49 50 namespace 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 empty(const Container & c)77 empty(const Container & c) 78 { return c.begin() == c.end(); } 79 80 template <class T> inline empty(T * const & c_str)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 empty(T (& x)[N])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 convert(const char * from,std::wstring & to,const codecvt_type & cvt)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 convert(const wchar_t * from,std::string & to,const codecvt_type & cvt)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 convert(const char * from,const char * from_end,std::string & to,const codecvt_type &)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 convert(const char * from,std::string & to,const codecvt_type &)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 convert(const wchar_t * from,const wchar_t * from_end,std::wstring & to,const codecvt_type &)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 convert(const wchar_t * from,std::wstring & to,const codecvt_type &)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 convert(const char * from,const char * from_end,std::string & to)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 convert(const char * from,std::string & to)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 convert(const wchar_t * from,const wchar_t * from_end,std::wstring & to)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 convert(const wchar_t * from,std::wstring & to)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 dispatch(const std::string & c,U & to,const codecvt_type & cvt)227 void dispatch(const std::string& c, U& to, const codecvt_type& cvt) 228 { 229 if (!c.empty()) 230 convert(&*c.begin(), &*c.begin() + c.size(), to, cvt); 231 } 232 template <class U> inline dispatch(const std::wstring & c,U & to,const codecvt_type & cvt)233 void dispatch(const std::wstring& c, U& to, const codecvt_type& cvt) 234 { 235 if (!c.empty()) 236 convert(&*c.begin(), &*c.begin() + c.size(), to, cvt); 237 } 238 template <class U> inline dispatch(const std::vector<char> & c,U & to,const codecvt_type & cvt)239 void dispatch(const std::vector<char>& c, U& to, const codecvt_type& cvt) 240 { 241 if (!c.empty()) 242 convert(&*c.begin(), &*c.begin() + c.size(), to, cvt); 243 } 244 template <class U> inline dispatch(const std::vector<wchar_t> & c,U & to,const codecvt_type & cvt)245 void dispatch(const std::vector<wchar_t>& c, U& to, const codecvt_type& cvt) 246 { 247 if (!c.empty()) 248 convert(&*c.begin(), &*c.begin() + c.size(), to, cvt); 249 } 250 251 // contiguous containers without codecvt 252 template <class U> inline dispatch(const std::string & c,U & to)253 void dispatch(const std::string& c, U& to) 254 { 255 if (!c.empty()) 256 convert(&*c.begin(), &*c.begin() + c.size(), to); 257 } 258 template <class U> inline dispatch(const std::wstring & c,U & to)259 void dispatch(const std::wstring& c, U& to) 260 { 261 if (!c.empty()) 262 convert(&*c.begin(), &*c.begin() + c.size(), to); 263 } 264 template <class U> inline dispatch(const std::vector<char> & c,U & to)265 void dispatch(const std::vector<char>& c, U& to) 266 { 267 if (!c.empty()) 268 convert(&*c.begin(), &*c.begin() + c.size(), to); 269 } 270 template <class U> inline dispatch(const std::vector<wchar_t> & c,U & to)271 void dispatch(const std::vector<wchar_t>& c, U& to) 272 { 273 if (!c.empty()) 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 dispatch(const Container & c,U & to,const codecvt_type & cvt)282 dispatch(const Container & c, U& to, const codecvt_type& cvt) 283 { 284 if (!c.empty()) 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 dispatch(T * const & c_str,U & to,const codecvt_type & cvt)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 dispatch(const Container & c,U & to)317 dispatch(const Container & c, U& to) 318 { 319 if (!c.empty()) 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 dispatch(T * const & c_str,U & to)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