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.

263 lines
9.2 KiB

  1. /* /////////////////////////////////////////////////////////////////////////
  2. * File: inetstl/filesystem/functionals.hpp
  3. *
  4. * Purpose: File-system functionals.
  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 inetstl/filesystem/functionals.hpp
  40. *
  41. * \brief [C++ only] File-system functionals
  42. * (\ref group__library__filesystem "File System" Library).
  43. */
  44. #ifndef INETSTL_INCL_INETSTL_FILESYSTEM_HPP_FUNCTIONALS
  45. #define INETSTL_INCL_INETSTL_FILESYSTEM_HPP_FUNCTIONALS
  46. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  47. # define INETSTL_VER_INETSTL_FILESYSTEM_HPP_FUNCTIONALS_MAJOR 4
  48. # define INETSTL_VER_INETSTL_FILESYSTEM_HPP_FUNCTIONALS_MINOR 0
  49. # define INETSTL_VER_INETSTL_FILESYSTEM_HPP_FUNCTIONALS_REVISION 4
  50. # define INETSTL_VER_INETSTL_FILESYSTEM_HPP_FUNCTIONALS_EDIT 34
  51. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  52. /* /////////////////////////////////////////////////////////////////////////
  53. * Includes
  54. */
  55. #ifndef INETSTL_INCL_INETSTL_H_INETSTL
  56. # include <inetstl/inetstl.h>
  57. #endif /* !INETSTL_INCL_INETSTL_H_INETSTL */
  58. #ifndef INETSTL_OS_IS_WINDOWS
  59. # error This file is currently compatible only with the Win32/Win64 API
  60. #endif /* !INETSTL_OS_IS_WINDOWS */
  61. #ifndef STLSOFT_INCL_STLSOFT_SHIMS_ACCESS_HPP_STRING
  62. # include <stlsoft/shims/access/string.hpp>
  63. #endif /* !STLSOFT_INCL_STLSOFT_SHIMS_ACCESS_HPP_STRING */
  64. #ifndef INETSTL_INCL_INETSTL_FILESYSTEM_HPP_FILESYSTEM_TRAITS
  65. # include <inetstl/filesystem/filesystem_traits.hpp>
  66. #endif /* !INETSTL_INCL_INETSTL_FILESYSTEM_HPP_FILESYSTEM_TRAITS */
  67. #ifndef STLSOFT_INCL_STLSOFT_UTIL_HPP_MINMAX
  68. # include <stlsoft/util/minmax.hpp>
  69. #endif /* !STLSOFT_INCL_STLSOFT_UTIL_HPP_MINMAX */
  70. #ifndef _INETSTL_FUNCTIONALS_NO_STD
  71. # include <functional>
  72. #else /* ? _INETSTL_FUNCTIONALS_NO_STD */
  73. # error Now need to write that std_binary_function stuff!!
  74. #endif /* _INETSTL_FUNCTIONALS_NO_STD */
  75. /* /////////////////////////////////////////////////////////////////////////
  76. * Namespace
  77. */
  78. #ifndef _INETSTL_NO_NAMESPACE
  79. # if defined(_STLSOFT_NO_NAMESPACE) || \
  80. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  81. /* There is no stlsoft namespace, so must define ::inetstl */
  82. namespace inetstl
  83. {
  84. # else
  85. /* Define stlsoft::inetstl_project */
  86. namespace stlsoft
  87. {
  88. namespace inetstl_project
  89. {
  90. # endif /* _STLSOFT_NO_NAMESPACE */
  91. #endif /* !_INETSTL_NO_NAMESPACE */
  92. /* /////////////////////////////////////////////////////////////////////////
  93. * Classes
  94. */
  95. /** \brief A function class that compares two file-system paths
  96. *
  97. * \ingroup group__library__filesystem
  98. *
  99. * \param C The character type
  100. * \param A1 The left-hand argument type; defaults to C const*
  101. * \param A2 The right-hand argument type; defaults to C const*
  102. */
  103. // [[synesis:class:function-class:binary-predicate: path_compare<T<C>, T<A1>, T<A2>>]]
  104. template< ss_typename_param_k C
  105. , ss_typename_param_k A1 = C const*
  106. , ss_typename_param_k A2 = C const*
  107. >
  108. struct path_compare
  109. : public inetstl_ns_qual_std(binary_function)<A1, A2, is_bool_t>
  110. {
  111. public:
  112. /// The character type
  113. typedef C char_type;
  114. private:
  115. typedef inetstl_ns_qual_std(binary_function)<A1, A2, is_bool_t> parent_class_type;
  116. public:
  117. /// The first argument type
  118. typedef ss_typename_type_k parent_class_type::first_argument_type first_argument_type;
  119. /// The second argument type
  120. typedef ss_typename_type_k parent_class_type::second_argument_type second_argument_type;
  121. /// The result type
  122. typedef ss_typename_type_k parent_class_type::result_type result_type;
  123. /// The traits type
  124. typedef filesystem_traits<C> traits_type;
  125. /// The current parameterisation of the type
  126. typedef path_compare<C, A1, A2> class_type;
  127. public:
  128. /// Function call, compares \c s1 with \c s2
  129. ///
  130. /// \note The comparison is determined by evaluation the full-paths of both \c s1 and \c s2
  131. #ifdef STLSOFT_CF_MEMBER_TEMPLATE_FUNCTION_SUPPORT
  132. template<ss_typename_param_k T1, ss_typename_param_k T2>
  133. result_type operator ()(T1 const& s1, T2 const& s2) const
  134. #else /* ? STLSOFT_CF_MEMBER_TEMPLATE_FUNCTION_SUPPORT */
  135. result_type operator ()(first_argument_type s1, second_argument_type s2) const
  136. #endif /* STLSOFT_CF_MEMBER_TEMPLATE_FUNCTION_SUPPORT */
  137. {
  138. return compare_(stlsoft_ns_qual(c_str_ptr)(s1), stlsoft_ns_qual(c_str_ptr)(s2));
  139. }
  140. // Implementation
  141. private:
  142. static result_type compare_(char_type const* s1, char_type const* s2)
  143. {
  144. char_type path1[_MAX_PATH + 1];
  145. char_type path2[_MAX_PATH + 1];
  146. is_size_t const len1 = traits_type::str_len(s1);
  147. is_size_t const len2 = traits_type::str_len(s2);
  148. traits_type::char_copy(&path1[0], s1, stlsoft_ns_qual(minimum)(STLSOFT_NUM_ELEMENTS(path1), len1));
  149. path1[len1] = '\0';
  150. traits_type::char_copy(&path2[0], s2, stlsoft_ns_qual(minimum)(STLSOFT_NUM_ELEMENTS(path2), len2));
  151. path2[len2] = '\0';
  152. traits_type::remove_dir_end(&path1[0]);
  153. traits_type::remove_dir_end(&path2[0]);
  154. s1 = &path1[0];
  155. s2 = &path2[0];
  156. return 0 == traits_type::str_compare(s1, s2);
  157. }
  158. };
  159. /** \brief Predicate that indicates whether a given path exists
  160. *
  161. * \ingroup group__library__filesystem
  162. *
  163. * \param C The character type
  164. * \param A The argument type; defaults to C const*
  165. */
  166. template< ss_typename_param_k C
  167. , ss_typename_param_k A = C const*
  168. >
  169. // [[synesis:class:function-class:unary-predicate: path_exists<T<C>, T<A>>]]
  170. struct path_exists
  171. : public inetstl_ns_qual_std(unary_function)<A, is_bool_t>
  172. {
  173. public:
  174. /// The character type
  175. typedef C char_type;
  176. /// The traits type
  177. typedef filesystem_traits<C> traits_type;
  178. /// The current parameterisation of the type
  179. typedef path_exists<C> class_type;
  180. public:
  181. ss_explicit_k path_exists(HINTERNET hConnection)
  182. : m_hConnection(hConnection)
  183. {}
  184. public:
  185. #ifdef STLSOFT_CF_MEMBER_TEMPLATE_FUNCTION_SUPPORT
  186. template <ss_typename_param_k S>
  187. is_bool_t operator ()(S const& s) const
  188. #else /* ? STLSOFT_CF_MEMBER_TEMPLATE_FUNCTION_SUPPORT */
  189. is_bool_t operator ()(argument_type s) const
  190. #endif /* STLSOFT_CF_MEMBER_TEMPLATE_FUNCTION_SUPPORT */
  191. {
  192. return exists_(stlsoft_ns_qual(c_str_ptr)(s));
  193. }
  194. private:
  195. is_bool_t exists_(char_type const* s) const
  196. {
  197. char_type sz0[1 + _MAX_PATH];
  198. is_dword_t dw;
  199. if(!traits_type::get_full_path_name(m_hConnection, s, STLSOFT_NUM_ELEMENTS(sz0), sz0))
  200. {
  201. dw = 0xFFFFFFFF;
  202. }
  203. else
  204. {
  205. dw = ::GetFileAttributes(sz0);
  206. }
  207. return 0xFFFFFFFF != dw;
  208. }
  209. private:
  210. HINTERNET m_hConnection;
  211. };
  212. ////////////////////////////////////////////////////////////////////////////
  213. // Unit-testing
  214. #ifdef STLSOFT_UNITTEST
  215. # include "./unittest/functionals_unittest_.h"
  216. #endif /* STLSOFT_UNITTEST */
  217. /* ////////////////////////////////////////////////////////////////////// */
  218. #ifndef _INETSTL_NO_NAMESPACE
  219. # if defined(_STLSOFT_NO_NAMESPACE) || \
  220. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  221. } // namespace inetstl
  222. # else
  223. } // namespace inetstl_project
  224. } // namespace stlsoft
  225. # endif /* _STLSOFT_NO_NAMESPACE */
  226. #endif /* !_INETSTL_NO_NAMESPACE */
  227. /* ////////////////////////////////////////////////////////////////////// */
  228. #endif /* INETSTL_INCL_INETSTL_FILESYSTEM_HPP_FUNCTIONALS */
  229. /* ///////////////////////////// end of file //////////////////////////// */