path_traits.hpp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  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/utility/enable_if.hpp>
  14. #include <boost/type_traits/is_array.hpp>
  15. #include <boost/type_traits/decay.hpp>
  16. #include <boost/system/error_code.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. BOOST_FILESYSTEM_DECL
  74. void convert(const char* from,
  75. const char* from_end, // 0 for null terminated MBCS
  76. std::wstring & to,
  77. const codecvt_type& cvt);
  78. BOOST_FILESYSTEM_DECL
  79. void convert(const wchar_t* from,
  80. const wchar_t* from_end, // 0 for null terminated MBCS
  81. std::string & to,
  82. const codecvt_type& cvt);
  83. inline
  84. void convert(const char* from,
  85. std::wstring & to,
  86. const codecvt_type& cvt)
  87. {
  88. BOOST_ASSERT(from);
  89. convert(from, 0, to, cvt);
  90. }
  91. inline
  92. void convert(const wchar_t* from,
  93. std::string & to,
  94. const codecvt_type& cvt)
  95. {
  96. BOOST_ASSERT(from);
  97. convert(from, 0, to, cvt);
  98. }
  99. // value types same -----------------------------------------------------------------//
  100. // char
  101. inline
  102. void convert(const char* from, const char* from_end, std::string & to,
  103. const codecvt_type&)
  104. {
  105. BOOST_ASSERT(from);
  106. BOOST_ASSERT(from_end);
  107. to.append(from, from_end);
  108. }
  109. inline
  110. void convert(const char* from,
  111. std::string & to,
  112. const codecvt_type&)
  113. {
  114. BOOST_ASSERT(from);
  115. to += from;
  116. }
  117. // wchar_t
  118. inline
  119. void convert(const wchar_t* from, const wchar_t* from_end, std::wstring & to,
  120. const codecvt_type&)
  121. {
  122. BOOST_ASSERT(from);
  123. BOOST_ASSERT(from_end);
  124. to.append(from, from_end);
  125. }
  126. inline
  127. void convert(const wchar_t* from,
  128. std::wstring & to,
  129. const codecvt_type&)
  130. {
  131. BOOST_ASSERT(from);
  132. to += from;
  133. }
  134. // Source dispatch -----------------------------------------------------------------//
  135. // contiguous containers
  136. template <class U> inline
  137. void dispatch(const std::string& c, U& to, const codecvt_type& cvt)
  138. {
  139. if (c.size())
  140. convert(&*c.begin(), &*c.begin() + c.size(), to, cvt);
  141. }
  142. template <class U> inline
  143. void dispatch(const std::wstring& c, U& to, const codecvt_type& cvt)
  144. {
  145. if (c.size())
  146. convert(&*c.begin(), &*c.begin() + c.size(), to, cvt);
  147. }
  148. template <class U> inline
  149. void dispatch(const std::vector<char>& c, U& to, const codecvt_type& cvt)
  150. {
  151. if (c.size())
  152. convert(&*c.begin(), &*c.begin() + c.size(), to, cvt);
  153. }
  154. template <class U> inline
  155. void dispatch(const std::vector<wchar_t>& c, U& to, const codecvt_type& cvt)
  156. {
  157. if (c.size())
  158. convert(&*c.begin(), &*c.begin() + c.size(), to, cvt);
  159. }
  160. // non-contiguous containers
  161. template <class Container, class U> inline
  162. // disable_if aids broken compilers (IBM, old GCC, etc.) and is harmless for
  163. // conforming compilers. Replace by plain "void" at some future date (2012?)
  164. typename boost::disable_if<boost::is_array<Container>, void>::type
  165. dispatch(const Container & c, U& to, const codecvt_type& cvt)
  166. {
  167. if (c.size())
  168. {
  169. std::basic_string<typename Container::value_type> s(c.begin(), c.end());
  170. convert(s.c_str(), s.c_str()+s.size(), to, cvt);
  171. }
  172. }
  173. // c_str
  174. template <class T, class U> inline
  175. void dispatch(T * const & c_str, U& to, const codecvt_type& cvt)
  176. {
  177. // std::cout << "dispatch() const T *\n";
  178. BOOST_ASSERT(c_str);
  179. convert(c_str, to, cvt);
  180. }
  181. // Note: there is no dispatch on C-style arrays because the array may
  182. // contain a string smaller than the array size.
  183. BOOST_FILESYSTEM_DECL
  184. void dispatch(const directory_entry & de,
  185. # ifdef BOOST_WINDOWS_API
  186. std::wstring & to,
  187. # else
  188. std::string & to,
  189. # endif
  190. const codecvt_type&);
  191. }}} // namespace boost::filesystem::path_traits
  192. #include <boost/config/abi_suffix.hpp> // pops abi_prefix.hpp pragmas
  193. #endif // BOOST_FILESYSTEM_PATH_TRAITS_HPP