path_traits.hpp 10 KB

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