You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

528 lines
17 KiB

  1. /* /////////////////////////////////////////////////////////////////////////
  2. * File: winstl/filesystem/functionals.hpp
  3. *
  4. * Purpose: File-system related functions and predicates.
  5. *
  6. * Created: 19th January 2002
  7. * Updated: 29th November 2010
  8. *
  9. * Home: http://stlsoft.org/
  10. *
  11. * Copyright (c) 2002-2010, Matthew Wilson and Synesis Software
  12. * All rights reserved.
  13. *
  14. * Redistribution and use in source and binary forms, with or without
  15. * modification, are permitted provided that the following conditions are met:
  16. *
  17. * - Redistributions of source code must retain the above copyright notice, this
  18. * list of conditions and the following disclaimer.
  19. * - Redistributions in binary form must reproduce the above copyright notice,
  20. * this list of conditions and the following disclaimer in the documentation
  21. * and/or other materials provided with the distribution.
  22. * - Neither the name(s) of Matthew Wilson and Synesis Software nor the names of
  23. * any contributors may be used to endorse or promote products derived from
  24. * this software without specific prior written permission.
  25. *
  26. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  27. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  28. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  29. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  30. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  31. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  32. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  33. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  34. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  35. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  36. * POSSIBILITY OF SUCH DAMAGE.
  37. *
  38. * ////////////////////////////////////////////////////////////////////// */
  39. /** \file winstl/filesystem/functionals.hpp
  40. *
  41. * \brief [C++ only] Definition of the winstl::path_compare,
  42. * winstl::path_compare_env, winstl::path_exists, winstl::path_exists_env
  43. * and winstl::path_contains_file function classes
  44. * (\ref group__library__filesystem "File System" Library).
  45. */
  46. #ifndef WINSTL_INCL_WINSTL_FILESYSTEM_HPP_FUNCTIONALS
  47. #define WINSTL_INCL_WINSTL_FILESYSTEM_HPP_FUNCTIONALS
  48. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  49. # define WINSTL_VER_WINSTL_FILESYSTEM_HPP_FUNCTIONALS_MAJOR 4
  50. # define WINSTL_VER_WINSTL_FILESYSTEM_HPP_FUNCTIONALS_MINOR 1
  51. # define WINSTL_VER_WINSTL_FILESYSTEM_HPP_FUNCTIONALS_REVISION 4
  52. # define WINSTL_VER_WINSTL_FILESYSTEM_HPP_FUNCTIONALS_EDIT 82
  53. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  54. /* /////////////////////////////////////////////////////////////////////////
  55. * Compatibility
  56. */
  57. /*
  58. [Incompatibilies-start]
  59. [Incompatibilies-end]
  60. STLSOFT_COMPILER_IS_MSVC: _MSC_VER<1200
  61. */
  62. /* /////////////////////////////////////////////////////////////////////////
  63. * Includes
  64. */
  65. #ifndef WINSTL_INCL_WINSTL_H_WINSTL
  66. # include <winstl/winstl.h>
  67. #endif /* !WINSTL_INCL_WINSTL_H_WINSTL */
  68. #ifndef WINSTL_INCL_WINSTL_FILESYSTEM_HPP_FILESYSTEM_TRAITS
  69. # include <winstl/filesystem/filesystem_traits.hpp>
  70. #endif /* !WINSTL_INCL_WINSTL_FILESYSTEM_HPP_FILESYSTEM_TRAITS */
  71. #ifndef WINSTL_INCL_WINSTL_FILESYSTEM_HPP_FILE_PATH_BUFFER
  72. # include <winstl/filesystem/file_path_buffer.hpp>
  73. #endif /* !WINSTL_INCL_WINSTL_FILESYSTEM_HPP_FILE_PATH_BUFFER */
  74. #ifndef STLSOFT_INCL_STLSOFT_SHIMS_ACCESS_HPP_STRING
  75. # include <stlsoft/shims/access/string.hpp>
  76. #endif /* !STLSOFT_INCL_STLSOFT_SHIMS_ACCESS_HPP_STRING */
  77. #ifndef WINSTL_INCL_WINSTL_SHIMS_ACCESS_HPP_STRING
  78. # include <winstl/shims/access/string.hpp>
  79. #endif /* !WINSTL_INCL_WINSTL_SHIMS_ACCESS_HPP_STRING */
  80. #ifndef STLSOFT_INCL_STLSOFT_MEMORY_HPP_AUTO_BUFFER
  81. # include <stlsoft/memory/auto_buffer.hpp>
  82. #endif /* !STLSOFT_INCL_STLSOFT_MEMORY_HPP_AUTO_BUFFER */
  83. #ifndef _WINSTL_FUNCTIONALS_NO_STD
  84. # include <functional>
  85. #else /* ? _WINSTL_FUNCTIONALS_NO_STD */
  86. # error Now need to write that std_binary_function stuff!!
  87. #endif /* _WINSTL_FUNCTIONALS_NO_STD */
  88. /* /////////////////////////////////////////////////////////////////////////
  89. * Namespace
  90. */
  91. #ifndef _WINSTL_NO_NAMESPACE
  92. # if defined(_STLSOFT_NO_NAMESPACE) || \
  93. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  94. /* There is no stlsoft namespace, so must define ::winstl */
  95. namespace winstl
  96. {
  97. # else
  98. /* Define stlsoft::winstl_project */
  99. namespace stlsoft
  100. {
  101. namespace winstl_project
  102. {
  103. # endif /* _STLSOFT_NO_NAMESPACE */
  104. #endif /* !_WINSTL_NO_NAMESPACE */
  105. /* /////////////////////////////////////////////////////////////////////////
  106. * Utility functions
  107. */
  108. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  109. template <ss_typename_param_k C>
  110. inline bool file_exists_envx_(C const* s, ws_bool_t bExpandEnvironmentStrings)
  111. {
  112. typedef filesystem_traits<C> traits_t;
  113. typedef basic_file_path_buffer<C> buffer_t;
  114. buffer_t nvx;
  115. buffer_t full;
  116. if( bExpandEnvironmentStrings &&
  117. NULL == traits_t::str_chr(s, '%'))
  118. {
  119. bExpandEnvironmentStrings = false;
  120. }
  121. if(bExpandEnvironmentStrings)
  122. {
  123. if(!traits_t::expand_environment_strings(s, &nvx[0], nvx.size()))
  124. {
  125. return false;
  126. }
  127. else
  128. {
  129. s = nvx.c_str();
  130. }
  131. }
  132. if(!traits_t::get_full_path_name(s, full.size(), &full[0]))
  133. {
  134. return false;
  135. }
  136. else
  137. {
  138. return traits_t::file_exists(&full[0]);
  139. }
  140. }
  141. template <ss_typename_param_k C>
  142. inline bool are_paths_equal_envx_(C const* s1, C const* s2, ws_bool_t bExpandEnvironmentStrings)
  143. {
  144. typedef filesystem_traits<C> traits_t;
  145. typedef basic_file_path_buffer<C> buffer_t;
  146. buffer_t full1;
  147. buffer_t full2;
  148. buffer_t nvx1;
  149. buffer_t nvx2;
  150. C *dummy;
  151. if( bExpandEnvironmentStrings &&
  152. NULL == traits_t::str_chr(s1, '%') &&
  153. NULL == traits_t::str_chr(s2, '%'))
  154. {
  155. bExpandEnvironmentStrings = false;
  156. }
  157. if(bExpandEnvironmentStrings)
  158. {
  159. if( !traits_t::expand_environment_strings(s1, &nvx1[0], nvx1.size()) ||
  160. !traits_t::expand_environment_strings(s2, &nvx2[0], nvx2.size()))
  161. {
  162. return false;
  163. }
  164. else
  165. {
  166. s1 = nvx1.c_str();
  167. s2 = nvx2.c_str();
  168. }
  169. }
  170. if( !traits_t::get_full_path_name(s1, full1.size(), &full1[0], &dummy) ||
  171. !traits_t::get_full_path_name(s2, full2.size(), &full2[0], &dummy))
  172. {
  173. return false;
  174. }
  175. else
  176. {
  177. traits_t::remove_dir_end(&full1[0]);
  178. traits_t::remove_dir_end(&full2[0]);
  179. s1 = full1.c_str();
  180. s2 = full2.c_str();
  181. }
  182. return 0 == traits_t::str_compare_no_case(s1, s2);
  183. }
  184. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  185. /* /////////////////////////////////////////////////////////////////////////
  186. * Classes
  187. */
  188. /** \brief Binary predicate that compares two file-system paths.
  189. *
  190. * \ingroup group__library__filesystem
  191. *
  192. * \note Does not expand environment variables in the argument passed to
  193. * the function call operator
  194. *
  195. * \param C The character type
  196. * \param A1 The left-hand argument type; defaults to C const*
  197. * \param A2 The right-hand argument type; defaults to C const*
  198. */
  199. template< ss_typename_param_k C
  200. , ss_typename_param_k A1 = C const*
  201. , ss_typename_param_k A2 = C const*
  202. >
  203. // [[synesis:class:function-class:binary-predicate: path_compare<T<C>, T<A1>, T<A2>>]]
  204. struct path_compare
  205. : public winstl_ns_qual_std(binary_function)<A1, A2, ws_bool_t>
  206. {
  207. /// \name Member Types
  208. /// @{
  209. private:
  210. typedef winstl_ns_qual_std(binary_function)<A1, A2, ws_bool_t> parent_class_type;
  211. public:
  212. /// The character type
  213. typedef C char_type;
  214. /// The first argument type
  215. typedef ss_typename_type_k parent_class_type::first_argument_type first_argument_type;
  216. /// The second argument type
  217. typedef ss_typename_type_k parent_class_type::second_argument_type second_argument_type;
  218. /// The result type
  219. typedef ss_typename_type_k parent_class_type::result_type result_type;
  220. /// The current parameterisation of the type
  221. typedef path_compare<C, A1, A2> class_type;
  222. /// @}
  223. /// \name Operations
  224. /// @{
  225. public:
  226. /// Function call, compares \c s1 with \c s2
  227. ///
  228. /// \note The comparison is determined by evaluation the full-paths of both \c s1 and \c s2
  229. #ifdef STLSOFT_CF_MEMBER_TEMPLATE_FUNCTION_SUPPORT
  230. template<ss_typename_param_k T1, ss_typename_param_k T2>
  231. result_type operator ()(T1 const& s1, T2 const& s2) const
  232. #else /* ? STLSOFT_CF_MEMBER_TEMPLATE_FUNCTION_SUPPORT */
  233. result_type operator ()(first_argument_type s1, second_argument_type s2) const
  234. #endif /* STLSOFT_CF_MEMBER_TEMPLATE_FUNCTION_SUPPORT */
  235. {
  236. return are_paths_equal_envx_(stlsoft_ns_qual(c_str_ptr)(s1), stlsoft_ns_qual(c_str_ptr)(s2), false);
  237. }
  238. /// @}
  239. };
  240. /** \brief Binary predicate object that compares two file-system paths,
  241. * after expanding environment variables in the compared path strings.
  242. *
  243. * \ingroup group__library__filesystem
  244. *
  245. * \note Does not expand environment variables in the argument passed to
  246. * the function call operator
  247. *
  248. * \param C The character type
  249. * \param A1 The left-hand argument type; defaults to C const*
  250. * \param A2 The right-hand argument type; defaults to C const*
  251. */
  252. template< ss_typename_param_k C
  253. , ss_typename_param_k A1 = C const*
  254. , ss_typename_param_k A2 = C const*
  255. >
  256. // [[synesis:class:function-class:binary-predicate: path_compare_env<T<C>, T<A1>, T<A2>>]]
  257. struct path_compare_env
  258. : public winstl_ns_qual_std(binary_function)<A1, A2, ws_bool_t>
  259. {
  260. /// \name Member Types
  261. /// @{
  262. private:
  263. typedef winstl_ns_qual_std(binary_function)<A1, A2, ws_bool_t> parent_class_type;
  264. public:
  265. /// The character type
  266. typedef C char_type;
  267. /// The first argument type
  268. typedef ss_typename_type_k parent_class_type::first_argument_type first_argument_type;
  269. /// The second argument type
  270. typedef ss_typename_type_k parent_class_type::second_argument_type second_argument_type;
  271. /// The result type
  272. typedef ss_typename_type_k parent_class_type::result_type result_type;
  273. /// The current parameterisation of the type
  274. typedef path_compare_env<C, A1, A2> class_type;
  275. /// @}
  276. /// \name Operations
  277. /// @{
  278. public:
  279. /// Function call, compares \c s1 with \c s2
  280. ///
  281. /// \note The comparison is determined by evaluation the full-paths of both \c s1 and \c s2
  282. #ifdef STLSOFT_CF_MEMBER_TEMPLATE_FUNCTION_SUPPORT
  283. template<ss_typename_param_k T1, ss_typename_param_k T2>
  284. result_type operator ()(T1 const& s1, T2 const& s2) const
  285. #else /* ? STLSOFT_CF_MEMBER_TEMPLATE_FUNCTION_SUPPORT */
  286. result_type operator ()(first_argument_type s1, second_argument_type s2) const
  287. #endif /* STLSOFT_CF_MEMBER_TEMPLATE_FUNCTION_SUPPORT */
  288. {
  289. return are_paths_equal_envx_(stlsoft_ns_qual(c_str_ptr)(s1), stlsoft_ns_qual(c_str_ptr)(s2), true);
  290. }
  291. /// @}
  292. };
  293. /** \brief Unary predicate that indicates whether a given path exists.
  294. *
  295. * \ingroup group__library__filesystem
  296. *
  297. * \note Does not expand environment variables in the argument passed to
  298. * the function call operator
  299. *
  300. * \param C The character type
  301. * \param A The argument type; defaults to C const*
  302. */
  303. template< ss_typename_param_k C
  304. , ss_typename_param_k A = C const*
  305. >
  306. // [[synesis:class:function-class:unary-predicate: path_exists<T<C>, T<A>>]]
  307. struct path_exists
  308. : public winstl_ns_qual_std(unary_function)<A, ws_bool_t>
  309. {
  310. /// \name Member Types
  311. /// @{
  312. private:
  313. typedef winstl_ns_qual_std(unary_function)<A, ws_bool_t> parent_class_type;
  314. public:
  315. /// The character type
  316. typedef C char_type;
  317. /// The argument type
  318. typedef A argument_type;
  319. /// The current parameterisation of the type
  320. typedef path_exists<C, A> class_type;
  321. /// @}
  322. /// \name Operations
  323. /// @{
  324. public:
  325. #ifdef STLSOFT_CF_MEMBER_TEMPLATE_FUNCTION_SUPPORT
  326. template <ss_typename_param_k S>
  327. ws_bool_t operator ()(S const& s) const
  328. #else /* ? STLSOFT_CF_MEMBER_TEMPLATE_FUNCTION_SUPPORT */
  329. ws_bool_t operator ()(argument_type s) const
  330. #endif /* STLSOFT_CF_MEMBER_TEMPLATE_FUNCTION_SUPPORT */
  331. {
  332. return file_exists_envx_(stlsoft_ns_qual(c_str_ptr)(s), false);
  333. }
  334. /// @}
  335. };
  336. /** \brief Unary predicate that indicates whether a given path exists, after
  337. * expanding environment variables in the path string.
  338. *
  339. * \ingroup group__library__filesystem
  340. *
  341. * \note Expands environment variables in the argument passed to
  342. * the function call operator
  343. *
  344. * \param C The character type
  345. * \param A The argument type; defaults to C const*
  346. */
  347. template< ss_typename_param_k C
  348. , ss_typename_param_k A = C const*
  349. >
  350. // [[synesis:class:function-class:unary-predicate: path_exists_env<T<C>, T<A>>]]
  351. struct path_exists_env
  352. : public winstl_ns_qual_std(unary_function)<A, ws_bool_t>
  353. {
  354. /// \name Member Types
  355. /// @{
  356. private:
  357. typedef winstl_ns_qual_std(unary_function)<A, ws_bool_t> parent_class_type;
  358. public:
  359. /// The character type
  360. typedef C char_type;
  361. /// The argument type
  362. typedef A argument_type;
  363. /// The current parameterisation of the type
  364. typedef path_exists_env<C, A> class_type;
  365. /// @}
  366. /// \name Operations
  367. /// @{
  368. public:
  369. #ifdef STLSOFT_CF_MEMBER_TEMPLATE_FUNCTION_SUPPORT
  370. template <ss_typename_param_k S>
  371. ws_bool_t operator ()(S const& s) const
  372. #else /* ? STLSOFT_CF_MEMBER_TEMPLATE_FUNCTION_SUPPORT */
  373. ws_bool_t operator ()(argument_type s) const
  374. #endif /* STLSOFT_CF_MEMBER_TEMPLATE_FUNCTION_SUPPORT */
  375. {
  376. return file_exists_envx_(stlsoft_ns_qual(c_str_ptr)(s), true);
  377. }
  378. /// @}
  379. };
  380. /** \brief Unary predicate that searches for the existance of a given file
  381. * in the directory presented in its function call argument.
  382. *
  383. * \ingroup group__library__filesystem
  384. *
  385. * \param C The character type
  386. * \param A The argument type; defaults to C const*
  387. */
  388. /** \brief \note The file-name passed to the constructor is retained as a
  389. * pointer, rather than an instance of a string class. Consequently, the
  390. * behaviour is undefined if the memory pointed to by the constructor
  391. * argument does not persist for the lifetime of the function object.
  392. *
  393. * \ingroup group__library__filesystem
  394. */
  395. template< ss_typename_param_k C
  396. , ss_typename_param_k A = C const*
  397. >
  398. // [[synesis:class:function-class:unary-predicate: path_contains_file<T<C>, T<A>>]]
  399. struct path_contains_file
  400. : public winstl_ns_qual_std(unary_function)<A, ws_bool_t>
  401. {
  402. /// \name Member Types
  403. /// @{
  404. private:
  405. typedef winstl_ns_qual_std(unary_function)<A, ws_bool_t> parent_class_type;
  406. public:
  407. /// The character type
  408. typedef C char_type;
  409. /// The argument type
  410. typedef A argument_type;
  411. /// The current parameterisation of the type
  412. typedef path_contains_file<C, A> class_type;
  413. /// @}
  414. /// \name Construction
  415. /// @{
  416. public:
  417. path_contains_file(char_type const* file)
  418. : m_file(file)
  419. {}
  420. /// @}
  421. /// \name Operations
  422. /// @{
  423. public:
  424. #ifdef STLSOFT_CF_MEMBER_TEMPLATE_FUNCTION_SUPPORT
  425. template <ss_typename_param_k S>
  426. ws_bool_t operator ()(S const& s) const
  427. #else /* ? STLSOFT_CF_MEMBER_TEMPLATE_FUNCTION_SUPPORT */
  428. ws_bool_t operator ()(argument_type s) const
  429. #endif /* STLSOFT_CF_MEMBER_TEMPLATE_FUNCTION_SUPPORT */
  430. {
  431. return path_contains_file_(stlsoft_ns_qual(c_str_ptr)(s), m_file);
  432. }
  433. /// @}
  434. /// \name Implementation
  435. /// @{
  436. private:
  437. static ws_bool_t path_contains_file_(char_type const* directory, char_type const* file)
  438. {
  439. typedef filesystem_traits<char_type> traits_t;
  440. typedef stlsoft_ns_qual(auto_buffer)<char_type> buffer_t;
  441. const ws_size_t cchDirectory = traits_t::str_len(directory);
  442. const ws_size_t cchFile = traits_t::str_len(file);
  443. buffer_t path(1 + cchDirectory + 1 + cchFile + 1);
  444. traits_t::char_copy(&path[0], directory, cchDirectory);
  445. path[cchDirectory] = '\0';
  446. traits_t::ensure_dir_end(&path[0]);
  447. traits_t::str_cat(&path[0], file);
  448. return traits_t::file_exists(path.data());
  449. }
  450. /// @}
  451. /// \name Members
  452. /// @{
  453. private:
  454. char_type const* m_file;
  455. /// @}
  456. };
  457. ////////////////////////////////////////////////////////////////////////////
  458. // Unit-testing
  459. #ifdef STLSOFT_UNITTEST
  460. # include "./unittest/functionals_unittest_.h"
  461. #endif /* STLSOFT_UNITTEST */
  462. /* ////////////////////////////////////////////////////////////////////// */
  463. #ifndef _WINSTL_NO_NAMESPACE
  464. # if defined(_STLSOFT_NO_NAMESPACE) || \
  465. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  466. } // namespace winstl
  467. # else
  468. } // namespace winstl_project
  469. } // namespace stlsoft
  470. # endif /* _STLSOFT_NO_NAMESPACE */
  471. #endif /* !_WINSTL_NO_NAMESPACE */
  472. /* ////////////////////////////////////////////////////////////////////// */
  473. #endif /* WINSTL_INCL_WINSTL_FILESYSTEM_HPP_FUNCTIONALS */
  474. /* ///////////////////////////// end of file //////////////////////////// */