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.

1536 lines
55 KiB

  1. /* /////////////////////////////////////////////////////////////////////////
  2. * File: inetstl/filesystem/findfile_sequence.hpp (originally MInetEnm.h)
  3. *
  4. * Purpose: Contains the basic_findfile_sequence template class, and ANSI
  5. * and Unicode specialisations thereof.
  6. *
  7. * Created: 30th April 1999
  8. * Updated: 10th August 2009
  9. *
  10. * Home: http://stlsoft.org/
  11. *
  12. * Copyright (c) 1999-2009, Matthew Wilson and Synesis Software
  13. * All rights reserved.
  14. *
  15. * Redistribution and use in source and binary forms, with or without
  16. * modification, are permitted provided that the following conditions are met:
  17. *
  18. * - Redistributions of source code must retain the above copyright notice, this
  19. * list of conditions and the following disclaimer.
  20. * - Redistributions in binary form must reproduce the above copyright notice,
  21. * this list of conditions and the following disclaimer in the documentation
  22. * and/or other materials provided with the distribution.
  23. * - Neither the name(s) of Matthew Wilson and Synesis Software nor the names of
  24. * any contributors may be used to endorse or promote products derived from
  25. * this software without specific prior written permission.
  26. *
  27. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  28. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  29. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  30. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  31. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  32. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  33. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  34. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  35. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  36. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  37. * POSSIBILITY OF SUCH DAMAGE.
  38. *
  39. * ////////////////////////////////////////////////////////////////////// */
  40. /** \file inetstl/filesystem/findfile_sequence.hpp
  41. *
  42. * \brief [C++ only] Definition of the inetstl::findfile_sequence
  43. * class template
  44. * (\ref group__library__filesystem "File System" Library).
  45. */
  46. #ifndef INETSTL_INCL_INETSTL_FILESYSTEM_HPP_FINDFILE_SEQUENCE
  47. #define INETSTL_INCL_INETSTL_FILESYSTEM_HPP_FINDFILE_SEQUENCE
  48. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  49. # define INETSTL_VER_INETSTL_FILESYSTEM_HPP_FINDFILE_SEQUENCE_MAJOR 3
  50. # define INETSTL_VER_INETSTL_FILESYSTEM_HPP_FINDFILE_SEQUENCE_MINOR 0
  51. # define INETSTL_VER_INETSTL_FILESYSTEM_HPP_FINDFILE_SEQUENCE_REVISION 11
  52. # define INETSTL_VER_INETSTL_FILESYSTEM_HPP_FINDFILE_SEQUENCE_EDIT 139
  53. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  54. /* /////////////////////////////////////////////////////////////////////////
  55. * Compatibility
  56. */
  57. /*
  58. [Incompatibilies-start]
  59. STLSOFT_COMPILER_IS_MSVC: _MSC_VER<1100
  60. [Incompatibilies-end]
  61. */
  62. /* /////////////////////////////////////////////////////////////////////////
  63. * Includes
  64. */
  65. #ifndef INETSTL_INCL_INETSTL_H_INETSTL
  66. # include <inetstl/inetstl.h>
  67. #endif /* !INETSTL_INCL_INETSTL_H_INETSTL */
  68. #ifndef INETSTL_OS_IS_WINDOWS
  69. # error This file is currently compatible only with the Win32/Win64 API
  70. #endif /* !INETSTL_OS_IS_WINDOWS */
  71. #ifndef INETSTL_INCL_INETSTL_FILESYSTEM_HPP_FILESYSTEM_TRAITS
  72. # include <inetstl/filesystem/filesystem_traits.hpp>
  73. #endif /* !INETSTL_INCL_INETSTL_FILESYSTEM_HPP_FILESYSTEM_TRAITS */
  74. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  75. # ifndef INETSTL_INCL_INETSTL_ERROR_HPP_EXCEPTIONS
  76. # include <inetstl/error/exceptions.hpp> // for throw_internet_exception_policy
  77. # endif /* !INETSTL_INCL_INETSTL_ERROR_HPP_EXCEPTIONS */
  78. #else /* ? STLSOFT_CF_EXCEPTION_SUPPORT */
  79. # ifndef STLSOFT_INCL_STLSOFT_ERROR_HPP_EXCEPTIONS
  80. # include <stlsoft/error/exceptions.hpp> // for stlsoft::null_exception_policy
  81. # endif /* !STLSOFT_INCL_STLSOFT_ERROR_HPP_EXCEPTIONS */
  82. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  83. #ifndef STLSOFT_INCL_STLSOFT_COLLECTIONS_UTIL_HPP_COLLECTIONS
  84. # include <stlsoft/collections/util/collections.hpp>
  85. #endif /* !STLSOFT_INCL_STLSOFT_COLLECTIONS_UTIL_HPP_COLLECTIONS */
  86. #ifndef STLSOFT_INCL_STLSOFT_STRING_HPP_SIMPLE_STRING
  87. # include <stlsoft/string/simple_string.hpp>
  88. #endif /* !STLSOFT_INCL_STLSOFT_STRING_HPP_SIMPLE_STRING */
  89. #ifndef STLSOFT_INCL_STLSOFT_STRING_HPP_TOKENISER_FUNCTIONS
  90. # include <stlsoft/string/tokeniser_functions.hpp> // for find_next_token
  91. #endif /* !STLSOFT_INCL_STLSOFT_STRING_HPP_TOKENISER_FUNCTIONS */
  92. #ifndef STLSOFT_INCL_STLSOFT_UTIL_STD_HPP_ITERATOR_HELPER
  93. # include <stlsoft/util/std/iterator_helper.hpp>
  94. #endif /* !STLSOFT_INCL_STLSOFT_UTIL_STD_HPP_ITERATOR_HELPER */
  95. #ifndef STLSOFT_INCL_STLSOFT_SHIMS_ACCESS_HPP_STRING
  96. # include <stlsoft/shims/access/string.hpp>
  97. #endif /* !STLSOFT_INCL_STLSOFT_SHIMS_ACCESS_HPP_STRING */
  98. #ifdef STLSOFT_UNITTEST
  99. # include <stlsoft/conversion/integer_to_string.hpp>
  100. # include <inetstl/network/connection.hpp>
  101. # include <inetstl/network/session.hpp>
  102. # include <stdio.h>
  103. # include <string.h>
  104. #endif /* STLSOFT_UNITTEST */
  105. /* /////////////////////////////////////////////////////////////////////////
  106. * Namespace
  107. */
  108. #ifndef _INETSTL_NO_NAMESPACE
  109. # if defined(_STLSOFT_NO_NAMESPACE) || \
  110. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  111. /* There is no stlsoft namespace, so must define ::inetstl */
  112. namespace inetstl
  113. {
  114. # else
  115. /* Define stlsoft::inetstl_project */
  116. namespace stlsoft
  117. {
  118. namespace inetstl_project
  119. {
  120. # endif /* _STLSOFT_NO_NAMESPACE */
  121. #endif /* !_INETSTL_NO_NAMESPACE */
  122. /* /////////////////////////////////////////////////////////////////////////
  123. * Forward declarations
  124. */
  125. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  126. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k X>
  127. class basic_findfile_sequence;
  128. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k X>
  129. class basic_findfile_sequence_value_type;
  130. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k X, ss_typename_param_k V>
  131. class basic_findfile_sequence_const_input_iterator;
  132. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  133. /* /////////////////////////////////////////////////////////////////////////
  134. * Classes
  135. */
  136. // class basic_findfile_sequence
  137. /** \brief Presents an STL-like sequence interface over the items on the file-system
  138. *
  139. * \ingroup group__library__filesystem
  140. *
  141. * \param C The character type
  142. * \param T The traits type. On translators that support default template arguments this defaults to filesystem_traits<C>
  143. *
  144. * \note This class was described in detail in the article
  145. * "Adapting Windows Enumeration Models to STL Iterator Concepts"
  146. * (http://www.windevnet.com/documents/win0303a/), in the March 2003 issue of
  147. * Windows Developer Network (http://windevnet.com).
  148. */
  149. template< ss_typename_param_k C
  150. #ifdef STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT
  151. , ss_typename_param_k T = filesystem_traits<C>
  152. # ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  153. , ss_typename_param_k X = throw_internet_exception_policy
  154. # else /* ? STLSOFT_CF_EXCEPTION_SUPPORT */
  155. , ss_typename_param_k X = stlsoft_ns_qual(null_exception_policy)
  156. # endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  157. #else /* ? STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT */
  158. , ss_typename_param_k T /* = filesystem_traits<C> */
  159. , ss_typename_param_k X /* = throw_internet_exception_policy */
  160. #endif /* STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT */
  161. >
  162. class basic_findfile_sequence
  163. : public stlsoft_ns_qual(stl_collection_tag)
  164. {
  165. /// \name Member Types
  166. /// @{
  167. public:
  168. /// The character type
  169. typedef C char_type;
  170. /// The exception policy type
  171. typedef X exception_policy_type;
  172. /// The type thrown
  173. typedef ss_typename_param_k exception_policy_type::thrown_type thrown_type;
  174. /// The traits type
  175. typedef T traits_type;
  176. /// The current parameterisation of the type
  177. typedef basic_findfile_sequence<C, T, X> class_type;
  178. /// The value type
  179. typedef basic_findfile_sequence_value_type<C, T, X> value_type;
  180. /// The non-mutating (const) iterator type supporting the Input Iterator concept
  181. typedef basic_findfile_sequence_const_input_iterator<C, T, X, value_type> const_input_iterator;
  182. /// The non-mutating (const) iterator type
  183. typedef const_input_iterator const_iterator;
  184. /// The reference type
  185. typedef value_type& reference;
  186. /// The non-mutable (const) reference type
  187. typedef value_type const& const_reference;
  188. /// The find-data type
  189. typedef ss_typename_type_k traits_type::find_data_type find_data_type;
  190. /// The difference type
  191. typedef is_ptrdiff_t difference_type;
  192. /// The size type
  193. typedef is_size_t size_type;
  194. /// The Boolean type
  195. typedef is_bool_t bool_type;
  196. private:
  197. typedef is_sint_t flags_type;
  198. typedef stlsoft_ns_qual(basic_simple_string)<char_type> string_type;
  199. /// @}
  200. /// \name Member Constants
  201. /// @{
  202. public:
  203. enum search_flags
  204. {
  205. includeDots = 0x0008 //!< Causes the search to include the "." and ".." directories, which are elided by default
  206. , directories = 0x0010 //!< Causes the search to include directories
  207. , files = 0x0020 //!< Causes the search to include files
  208. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  209. , noSort = 0 /* 0x0100 */ //!<
  210. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  211. };
  212. /// @}
  213. /// \name Construction
  214. /// @{
  215. public:
  216. /// Commence a search according to the given search pattern and flags
  217. basic_findfile_sequence(HINTERNET hconn
  218. , char_type const* pattern
  219. , flags_type flags = directories | files);
  220. /// Commence a search according to the given search pattern and flags, relative to \c directory
  221. basic_findfile_sequence(HINTERNET hconn
  222. , char_type const* directory
  223. , char_type const* pattern
  224. , flags_type flags = directories | files);
  225. /// Commence a search according to the given search pattern and flags, relative to \c directory
  226. basic_findfile_sequence(HINTERNET hconn
  227. , char_type const* directory
  228. , char_type const* patterns
  229. , char_type delim
  230. , flags_type flags = directories | files);
  231. /// Destructor
  232. ~basic_findfile_sequence() stlsoft_throw_0();
  233. /// @}
  234. /// \name Iteration
  235. /// @{
  236. public:
  237. /// Begins the iteration
  238. ///
  239. /// \return An iterator representing the start of the sequence
  240. const_iterator begin() const;
  241. /// Ends the iteration
  242. ///
  243. /// \return An iterator representing the end of the sequence
  244. const_iterator end() const;
  245. /// @}
  246. /// \name Attributes
  247. /// @{
  248. public:
  249. /// Returns the directory of the search
  250. ///
  251. /// \note Will be the empty string for instances created with the first constructor
  252. char_type const* get_directory(size_type* pn = NULL) const;
  253. /// @}
  254. /// \name State
  255. /// @{
  256. public:
  257. #ifdef STLSOFT_OBSOLETE
  258. /// Returns the number of items in the sequence
  259. ///
  260. /// \note This is a potentially very expensive operation
  261. /// \deprecated
  262. size_type size() const;
  263. #endif /* STLSOFT_OBSOLETE */
  264. /// Indicates whether the sequence is empty
  265. bool_type empty() const;
  266. /// Returns the maximum number of items in the sequence
  267. static size_type max_size();
  268. /// @}
  269. /// \name Members
  270. /// @{
  271. private:
  272. friend class basic_findfile_sequence_value_type<C, T, X>;
  273. friend class basic_findfile_sequence_const_input_iterator<C, T, X, value_type>;
  274. const HINTERNET m_hconn;
  275. const char_type m_delim;
  276. const flags_type m_flags;
  277. const string_type m_rootDir;
  278. const string_type m_patterns;
  279. /// @}
  280. /// \name Invariant
  281. /// @{
  282. private:
  283. bool_type is_valid() const;
  284. /// @}
  285. /// \name Implementation
  286. /// @{
  287. private:
  288. static flags_type validate_flags_(flags_type flags);
  289. static void extract_subpath_(HINTERNET hconn, char_type *dest, char_type const* pattern);
  290. static HINTERNET find_first_file_(HINTERNET hconn, char_type const* spec, flags_type flags, find_data_type *findData);
  291. /// @}
  292. /// \name Not to be implemented
  293. /// @{
  294. private:
  295. basic_findfile_sequence(class_type const&);
  296. class_type& operator =(class_type const&);
  297. /// @}
  298. };
  299. /* /////////////////////////////////////////////////////////////////////////
  300. * Typedefs for commonly encountered types
  301. */
  302. /** \brief Specialisation of the basic_findfile_sequence template for the ANSI character type \c char
  303. *
  304. * \ingroup group__library__filesystem
  305. */
  306. typedef basic_findfile_sequence<is_char_a_t
  307. , filesystem_traits<is_char_a_t>
  308. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  309. , throw_internet_exception_policy
  310. #else /* ? STLSOFT_CF_EXCEPTION_SUPPORT */
  311. , stlsoft_ns_qual(null_exception_policy)
  312. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  313. > findfile_sequence_a;
  314. /** \brief Specialisation of the basic_findfile_sequence template for the Unicode character type \c wchar_t
  315. *
  316. * \ingroup group__library__filesystem
  317. */
  318. typedef basic_findfile_sequence<is_char_w_t
  319. , filesystem_traits<is_char_w_t>
  320. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  321. , throw_internet_exception_policy
  322. #else /* ? STLSOFT_CF_EXCEPTION_SUPPORT */
  323. , stlsoft_ns_qual(null_exception_policy)
  324. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  325. > findfile_sequence_w;
  326. /** \brief Specialisation of the basic_findfile_sequence template for the Win32 character type \c TCHAR
  327. *
  328. * \ingroup group__library__filesystem
  329. */
  330. typedef basic_findfile_sequence<TCHAR
  331. , filesystem_traits<TCHAR>
  332. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  333. , throw_internet_exception_policy
  334. #else /* ? STLSOFT_CF_EXCEPTION_SUPPORT */
  335. , stlsoft_ns_qual(null_exception_policy)
  336. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  337. > findfile_sequence;
  338. /* ////////////////////////////////////////////////////////////////////// */
  339. // class basic_findfile_sequence_value_type
  340. /** \brief Value type for the basic_findfile_sequence
  341. *
  342. * \ingroup group__library__filesystem
  343. */
  344. template< ss_typename_param_k C
  345. , ss_typename_param_k T
  346. , ss_typename_param_k X
  347. >
  348. class basic_findfile_sequence_value_type
  349. {
  350. /// \name Member Types
  351. /// @{
  352. private:
  353. typedef basic_findfile_sequence<C, T, X> sequence_type;
  354. public:
  355. /// The character type
  356. typedef C char_type;
  357. /// The exception policy type
  358. typedef X exception_policy_type;
  359. /// The type thrown
  360. typedef ss_typename_param_k exception_policy_type::thrown_type thrown_type;
  361. /// The traits type
  362. typedef T traits_type;
  363. /// The current parameterisation of the type
  364. typedef basic_findfile_sequence_value_type<C, T, X> class_type;
  365. /// The find-data type
  366. typedef ss_typename_type_k traits_type::find_data_type find_data_type;
  367. /// The size type
  368. typedef ss_typename_type_k sequence_type::size_type size_type;
  369. private:
  370. typedef ss_typename_type_k sequence_type::bool_type bool_type;
  371. typedef ss_typename_type_k sequence_type::flags_type flags_type;
  372. typedef stlsoft_ns_qual(basic_simple_string)<char_type> string_type;
  373. /// @}
  374. /// \name Construction
  375. /// @{
  376. public:
  377. /// Default constructor
  378. basic_findfile_sequence_value_type();
  379. private:
  380. basic_findfile_sequence_value_type(find_data_type const& data, char_type const* path, size_type cchPath)
  381. : m_data(data)
  382. {
  383. INETSTL_ASSERT(NULL != path || 0 == cchPath);
  384. INETSTL_ASSERT(cchPath < STLSOFT_NUM_ELEMENTS(m_path));
  385. STLSOFT_SUPPRESS_UNUSED(cchPath);
  386. size_type cchFile = traits_type::str_len(data.cFileName);
  387. if('/' != data.cFileName[0])
  388. {
  389. traits_type::char_copy(m_path, path, cchPath + 1);
  390. if(!traits_type::has_dir_end(m_path))
  391. {
  392. traits_type::ensure_dir_end(m_path);
  393. ++cchPath;
  394. }
  395. }
  396. else
  397. {
  398. m_path[0] = '\0';
  399. cchPath = 0u;
  400. }
  401. traits_type::char_copy(m_path + cchPath, data.cFileName, cchFile + 1);
  402. }
  403. // @}
  404. /** \brief Accessors
  405. *
  406. * \ingroup group__library__filesystem
  407. */
  408. // @{
  409. public:
  410. /// Returns a non-mutating reference to find-data
  411. find_data_type const& get_find_data() const;
  412. #ifdef STLSOFT_OBSOLETE
  413. /// Returns a non-mutating reference to find-data
  414. ///
  415. /// \deprecated This method may be removed in a future release. get_find_data() should be used instead
  416. find_data_type const& GetFindData() const; // Deprecated
  417. #endif /* STLSOFT_OBSOLETE */
  418. /// Returns the filename part of the item
  419. char_type const* get_filename() const;
  420. /// Returns the short form of the filename part of the item
  421. char_type const* get_short_filename() const;
  422. /// Returns the full path of the item
  423. char_type const* get_path() const;
  424. /// Returns the full path of the item
  425. char_type const* c_str() const;
  426. /// Implicit conversion to a pointer-to-const of the full path
  427. operator char_type const* () const;
  428. /// Indicates whether the entry is a directory
  429. is_bool_t is_directory() const;
  430. /// Indicates whether the entry is a file
  431. is_bool_t is_file() const;
  432. /// Indicates whether the entry is read-only
  433. is_bool_t is_read_only() const;
  434. is_bool_t equal(char_type const* rhs) const;
  435. is_bool_t equal(class_type const& rhs) const;
  436. // @}
  437. /// \name Members
  438. /// @{
  439. private:
  440. friend class basic_findfile_sequence_const_input_iterator<C, T, X, class_type>;
  441. find_data_type m_data;
  442. char_type m_path[1 + _MAX_PATH];
  443. /// @}
  444. };
  445. // class basic_findfile_sequence_const_input_iterator
  446. /** \brief Iterator type for the basic_findfile_sequence supporting the Input Iterator concept
  447. *
  448. * \ingroup group__library__filesystem
  449. */
  450. template< ss_typename_param_k C
  451. , ss_typename_param_k T
  452. , ss_typename_param_k X
  453. , ss_typename_param_k V
  454. >
  455. class basic_findfile_sequence_const_input_iterator
  456. #ifndef STLSOFT_COMPILER_IS_WATCOM
  457. : public stlsoft_ns_qual(iterator_base)<inetstl_ns_qual_std(input_iterator_tag)
  458. , V
  459. , is_ptrdiff_t
  460. , void // By-Value Temporary reference
  461. , V // By-Value Temporary reference
  462. >
  463. #endif /* compiler */
  464. {
  465. /// \name Member Types
  466. /// @{
  467. private:
  468. typedef basic_findfile_sequence<C, T, X> sequence_type;
  469. public:
  470. /// The character type
  471. typedef C char_type;
  472. /// The exception policy type
  473. typedef X exception_policy_type;
  474. /// The type thrown
  475. typedef ss_typename_param_k exception_policy_type::thrown_type thrown_type;
  476. /// The traits type
  477. typedef T traits_type;
  478. /// The value type
  479. typedef V value_type;
  480. /// The current parameterisation of the type
  481. typedef basic_findfile_sequence_const_input_iterator<C, T, X, V> class_type;
  482. /// The find-data type
  483. typedef ss_typename_type_k traits_type::find_data_type find_data_type;
  484. /// The size type
  485. typedef ss_typename_type_k sequence_type::size_type size_type;
  486. private:
  487. typedef ss_typename_type_k sequence_type::bool_type bool_type;
  488. typedef ss_typename_type_k sequence_type::flags_type flags_type;
  489. typedef ss_typename_type_k sequence_type::string_type string_type;
  490. /// @}
  491. /// \name Utility classes
  492. /// @{
  493. private:
  494. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  495. struct shared_handle
  496. {
  497. /// \name Member Types
  498. /// @{
  499. public:
  500. typedef shared_handle class_type;
  501. typedef HINTERNET handle_type;
  502. /// @}
  503. /// \name Members
  504. /// @{
  505. public:
  506. handle_type hSrch;
  507. private:
  508. ss_sint32_t m_refCount;
  509. /// @}
  510. /// \name Construction
  511. /// @{
  512. public:
  513. ss_explicit_k shared_handle(handle_type h)
  514. : hSrch(h)
  515. , m_refCount(1)
  516. {}
  517. # if defined(STLSOFT_CF_COMPILER_WARNS_NO_PUBLIC_DTOR)
  518. protected:
  519. # else /* ? STLSOFT_CF_COMPILER_WARNS_NO_PUBLIC_DTOR */
  520. private:
  521. # endif /* STLSOFT_CF_COMPILER_WARNS_NO_PUBLIC_DTOR */
  522. ~shared_handle() stlsoft_throw_0()
  523. {
  524. INETSTL_MESSAGE_ASSERT("Shared search handle being destroyed with outstanding references!", 0 == m_refCount);
  525. if(NULL != hSrch)
  526. {
  527. traits_type::find_close(hSrch);
  528. }
  529. }
  530. /// @}
  531. /// \name Operations
  532. /// @{
  533. public:
  534. ss_sint32_t AddRef()
  535. {
  536. return ++m_refCount;
  537. }
  538. ss_sint32_t Release()
  539. {
  540. ss_sint32_t rc = --m_refCount;
  541. if(0 == rc)
  542. {
  543. delete this;
  544. }
  545. return rc;
  546. }
  547. /// @}
  548. /// \name Not to be implemented
  549. /// @{
  550. private:
  551. shared_handle(class_type const&);
  552. class_type& operator =(class_type const&);
  553. /// @}
  554. };
  555. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  556. /// @}
  557. /// \name Construction
  558. /// @{
  559. private:
  560. basic_findfile_sequence_const_input_iterator(
  561. sequence_type const& l
  562. , char_type const* rootDir
  563. , char_type const* patterns
  564. , char_type delim
  565. , flags_type flags
  566. );
  567. basic_findfile_sequence_const_input_iterator( sequence_type const& l);
  568. public:
  569. /// Default constructor
  570. basic_findfile_sequence_const_input_iterator();
  571. /// <a href = "http://synesis.com.au/resources/articles/cpp/movectors.pdf">Move constructor</a>
  572. basic_findfile_sequence_const_input_iterator(class_type const& rhs);
  573. /// Destructor
  574. ~basic_findfile_sequence_const_input_iterator() stlsoft_throw_0();
  575. // Copy assignment operator
  576. basic_findfile_sequence_const_input_iterator& operator =(class_type const& rhs);
  577. /// @}
  578. /// \name Input Iterator methods
  579. /// @{
  580. public:
  581. /// Pre-increment operator
  582. class_type& operator ++();
  583. /// Post-increment operator
  584. class_type operator ++(int);
  585. /// Dereference to return the value at the current position
  586. const value_type operator *() const;
  587. /// Evaluates whether \c this and \c rhs are equivalent
  588. is_bool_t equal(class_type const& rhs) const;
  589. /// @}
  590. /// \name Implementation
  591. /// @{
  592. private:
  593. static int find_next_pattern_(char_type const*& p0, char_type const*& p1, char_type delim);
  594. static HINTERNET find_first_file_(HINTERNET hconn, char_type const* spec, flags_type flags, find_data_type *findData);
  595. /// @}
  596. /// \name Members
  597. /// @{
  598. private:
  599. friend class basic_findfile_sequence<C, T, X>;
  600. sequence_type const* const m_list;
  601. shared_handle* m_handle;
  602. ss_typename_type_k traits_type::find_data_type m_data;
  603. char_type const* m_rootDir;
  604. char_type const* m_pattern0;
  605. char_type const* m_pattern1;
  606. char_type m_delim;
  607. flags_type m_flags;
  608. /// @}
  609. };
  610. ////////////////////////////////////////////////////////////////////////////
  611. // Operators
  612. // basic_findfile_sequence_const_input_iterator
  613. template< ss_typename_param_k C
  614. , ss_typename_param_k T
  615. , ss_typename_param_k X
  616. , ss_typename_param_k V
  617. >
  618. inline is_bool_t operator ==( basic_findfile_sequence_const_input_iterator<C, T, X, V> const& lhs
  619. , basic_findfile_sequence_const_input_iterator<C, T, X, V> const& rhs)
  620. {
  621. return lhs.equal(rhs);
  622. }
  623. template< ss_typename_param_k C
  624. , ss_typename_param_k T
  625. , ss_typename_param_k X
  626. , ss_typename_param_k V
  627. >
  628. inline is_bool_t operator !=( basic_findfile_sequence_const_input_iterator<C, T, X, V> const& lhs
  629. , basic_findfile_sequence_const_input_iterator<C, T, X, V> const& rhs)
  630. {
  631. return !lhs.equal(rhs);
  632. }
  633. // basic_findfile_sequence_value_type
  634. template< ss_typename_param_k C
  635. , ss_typename_param_k T
  636. , ss_typename_param_k X
  637. >
  638. inline is_bool_t operator == ( basic_findfile_sequence_value_type<C, T, X> const& lhs
  639. , basic_findfile_sequence_value_type<C, T, X> const& rhs)
  640. {
  641. return lhs.equal(rhs);
  642. }
  643. template< ss_typename_param_k C
  644. , ss_typename_param_k T
  645. , ss_typename_param_k X
  646. >
  647. inline is_bool_t operator == ( basic_findfile_sequence_value_type<C, T, X> const& lhs
  648. , C const* rhs)
  649. {
  650. return lhs.equal(rhs);
  651. }
  652. template< ss_typename_param_k C
  653. , ss_typename_param_k T
  654. , ss_typename_param_k X
  655. >
  656. inline is_bool_t operator == (C const* lhs, basic_findfile_sequence_value_type<C, T, X> const& rhs)
  657. {
  658. return rhs.equal(lhs);
  659. }
  660. template< ss_typename_param_k C
  661. , ss_typename_param_k T
  662. , ss_typename_param_k X
  663. >
  664. inline is_bool_t operator != ( basic_findfile_sequence_value_type<C, T, X> const& lhs
  665. , basic_findfile_sequence_value_type<C, T, X> const& rhs)
  666. {
  667. return !lhs.equal(rhs);
  668. }
  669. template< ss_typename_param_k C
  670. , ss_typename_param_k T
  671. , ss_typename_param_k X
  672. >
  673. inline is_bool_t operator != ( basic_findfile_sequence_value_type<C, T, X> const& lhs
  674. , C const* rhs)
  675. {
  676. return !lhs.equal(rhs);
  677. }
  678. template< ss_typename_param_k C
  679. , ss_typename_param_k T
  680. , ss_typename_param_k X
  681. >
  682. inline is_bool_t operator != ( C const* lhs, basic_findfile_sequence_value_type<C, T, X> const& rhs)
  683. {
  684. return !rhs.equal(lhs);
  685. }
  686. ////////////////////////////////////////////////////////////////////////////
  687. // Shims
  688. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  689. template <ss_typename_param_k T, ss_typename_param_k X>
  690. inline is_char_a_t const* c_str_data_a(inetstl_ns_qual(basic_findfile_sequence_value_type)<is_char_a_t, T, X> const& v)
  691. {
  692. return v.get_path();
  693. }
  694. template <ss_typename_param_k T, ss_typename_param_k X>
  695. inline is_char_w_t const* c_str_data_w(inetstl_ns_qual(basic_findfile_sequence_value_type)<is_char_w_t, T, X> const& v)
  696. {
  697. return v.get_path();
  698. }
  699. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  700. /** \brief \ref group__concept__shim__string_access__c_str_data for inetstl::basic_findfile_sequence_value_type
  701. *
  702. * \ingroup group__concept__shim__string_access
  703. *
  704. */
  705. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k X>
  706. inline C const* c_str_data(inetstl_ns_qual(basic_findfile_sequence_value_type)<C, T, X> const& v)
  707. {
  708. return v.get_path();
  709. }
  710. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  711. template <ss_typename_param_k T, ss_typename_param_k X>
  712. inline is_size_t c_str_len_a(inetstl_ns_qual(basic_findfile_sequence_value_type)<is_char_a_t, T, X> const& v)
  713. {
  714. return stlsoft_ns_qual(c_str_len_a(v.get_path()));
  715. }
  716. template <ss_typename_param_k T, ss_typename_param_k X>
  717. inline is_size_t c_str_len_w(inetstl_ns_qual(basic_findfile_sequence_value_type)<is_char_w_t, T, X> const& v)
  718. {
  719. return stlsoft_ns_qual(c_str_len_w(v.get_path()));
  720. }
  721. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  722. /** \brief \ref group__concept__shim__string_access__c_str_len for inetstl::basic_findfile_sequence_value_type
  723. *
  724. * \ingroup group__concept__shim__string_access
  725. */
  726. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k X>
  727. inline is_size_t c_str_len(inetstl_ns_qual(basic_findfile_sequence_value_type)<C, T, X> const& v)
  728. {
  729. return stlsoft_ns_qual(c_str_len(v.get_path()));
  730. }
  731. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  732. template <ss_typename_param_k T, ss_typename_param_k X>
  733. inline is_char_a_t const* c_str_ptr_a(inetstl_ns_qual(basic_findfile_sequence_value_type)<is_char_a_t, T, X> const& v)
  734. {
  735. return v.get_path();
  736. }
  737. template <ss_typename_param_k T, ss_typename_param_k X>
  738. inline is_char_w_t const* c_str_ptr_w(inetstl_ns_qual(basic_findfile_sequence_value_type)<is_char_w_t, T, X> const& v)
  739. {
  740. return v.get_path();
  741. }
  742. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  743. /** \brief \ref group__concept__shim__string_access__c_str_ptr for inetstl::basic_findfile_sequence_value_type
  744. *
  745. * \ingroup group__concept__shim__string_access
  746. */
  747. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k X>
  748. inline C const* c_str_ptr(inetstl_ns_qual(basic_findfile_sequence_value_type)<C, T, X> const& v)
  749. {
  750. return v.get_path();
  751. }
  752. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  753. template <ss_typename_param_k T, ss_typename_param_k X>
  754. inline is_char_a_t const* c_str_ptr_null_a(inetstl_ns_qual(basic_findfile_sequence_value_type)<is_char_a_t, T, X> const& v)
  755. {
  756. return stlsoft_ns_qual(c_str_ptr_null(v.get_path()));
  757. }
  758. template <ss_typename_param_k T, ss_typename_param_k X>
  759. inline is_char_w_t const* c_str_ptr_null_w(inetstl_ns_qual(basic_findfile_sequence_value_type)<is_char_w_t, T, X> const& v)
  760. {
  761. return stlsoft_ns_qual(c_str_ptr_null(v.get_path()));
  762. }
  763. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  764. /** \brief \ref group__concept__shim__string_access__c_str_ptr_null for inetstl::basic_findfile_sequence_value_type
  765. *
  766. * \ingroup group__concept__shim__string_access
  767. */
  768. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k X>
  769. inline C const* c_str_ptr_null(inetstl_ns_qual(basic_findfile_sequence_value_type)<C, T, X> const& v)
  770. {
  771. return stlsoft_ns_qual(c_str_ptr_null(v.get_path()));
  772. }
  773. ////////////////////////////////////////////////////////////////////////////
  774. // Unit-testing
  775. #ifdef STLSOFT_UNITTEST
  776. # include "./unittest/findfile_sequence_unittest_.h"
  777. #endif /* STLSOFT_UNITTEST */
  778. ////////////////////////////////////////////////////////////////////////////
  779. // Implementation
  780. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  781. // basic_findfile_sequence
  782. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k X>
  783. inline /* static */ HINTERNET basic_findfile_sequence<C, T, X>::find_first_file_(
  784. HINTERNET hconn
  785. , ss_typename_type_k basic_findfile_sequence<C, T, X>::char_type const* spec
  786. , ss_typename_type_k basic_findfile_sequence<C, T, X>::flags_type /* flags */
  787. , ss_typename_type_k basic_findfile_sequence<C, T, X>::find_data_type* findData
  788. )
  789. {
  790. HINTERNET hSrch = traits_type::find_first_file(hconn, spec, findData);
  791. if(NULL == hSrch)
  792. {
  793. DWORD dwErr = ::GetLastError();
  794. if(ERROR_FTP_TRANSFER_IN_PROGRESS == dwErr)
  795. {
  796. exception_policy_type()("Already enumerating using current connection", dwErr);
  797. }
  798. else
  799. {
  800. exception_policy_type()("Search failed", dwErr);
  801. }
  802. }
  803. return hSrch;
  804. }
  805. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k X>
  806. inline /* static */ ss_typename_type_ret_k basic_findfile_sequence<C, T, X>::flags_type basic_findfile_sequence<C, T, X>::validate_flags_(ss_typename_type_k basic_findfile_sequence<C, T, X>::flags_type flags)
  807. {
  808. const flags_type validFlags = 0
  809. | includeDots
  810. | directories
  811. | files
  812. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  813. | noSort
  814. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  815. | 0;
  816. INETSTL_MESSAGE_ASSERT("Specification of unrecognised/unsupported flags", flags == (flags & validFlags));
  817. STLSOFT_SUPPRESS_UNUSED(validFlags);
  818. if(0 == (flags & (directories | files)))
  819. {
  820. flags |= (directories | files);
  821. }
  822. return flags;
  823. }
  824. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k X>
  825. inline /* static */ is_bool_t basic_findfile_sequence<C, T, X>::is_valid() const
  826. {
  827. return true;
  828. }
  829. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k X>
  830. inline /* static */ void basic_findfile_sequence<C, T, X>::extract_subpath_(HINTERNET hconn, char_type *dest, char_type const* pattern)
  831. {
  832. char_type* pFile;
  833. traits_type::get_full_path_name(hconn, pattern, _MAX_PATH, dest, &pFile);
  834. if(NULL != pFile)
  835. {
  836. *pFile = '\0';
  837. }
  838. }
  839. // Construction
  840. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k X>
  841. inline basic_findfile_sequence<C, T, X>::basic_findfile_sequence(HINTERNET hconn, char_type const* pattern, ss_typename_type_k basic_findfile_sequence<C, T, X>::flags_type flags /* = directories | files */)
  842. : m_hconn(hconn)
  843. , m_delim('\0')
  844. , m_flags(validate_flags_(flags))
  845. , m_rootDir()
  846. , m_patterns(pattern)
  847. {
  848. INETSTL_ASSERT(is_valid());
  849. }
  850. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k X>
  851. inline basic_findfile_sequence<C, T, X>::basic_findfile_sequence(HINTERNET hconn, char_type const* directory, char_type const* pattern, ss_typename_type_k basic_findfile_sequence<C, T, X>::flags_type flags /* = directories | files */)
  852. : m_hconn(hconn)
  853. , m_delim('\0')
  854. , m_flags(validate_flags_(flags))
  855. , m_rootDir(directory)
  856. , m_patterns(pattern)
  857. {
  858. INETSTL_ASSERT(is_valid());
  859. }
  860. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k X>
  861. inline basic_findfile_sequence<C, T, X>::basic_findfile_sequence(
  862. HINTERNET hconn
  863. , char_type const* directory
  864. , char_type const* patterns
  865. , char_type delim
  866. , ss_typename_type_k basic_findfile_sequence<C, T, X>::flags_type flags /* = directories | files */
  867. )
  868. : m_hconn(hconn)
  869. , m_delim(delim)
  870. , m_flags(validate_flags_(flags))
  871. , m_rootDir(directory)
  872. , m_patterns(patterns)
  873. {
  874. INETSTL_ASSERT(is_valid());
  875. }
  876. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k X>
  877. inline basic_findfile_sequence<C, T, X>::~basic_findfile_sequence() stlsoft_throw_0()
  878. {
  879. INETSTL_ASSERT(is_valid());
  880. }
  881. // Iteration
  882. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k X>
  883. inline ss_typename_type_ret_k basic_findfile_sequence<C, T, X>::const_iterator basic_findfile_sequence<C, T, X>::begin() const
  884. {
  885. INETSTL_ASSERT(is_valid());
  886. return const_input_iterator(*this, stlsoft_ns_qual(c_str_ptr)(m_rootDir), stlsoft_ns_qual(c_str_ptr)(m_patterns), m_delim, m_flags);
  887. }
  888. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k X>
  889. inline ss_typename_type_ret_k basic_findfile_sequence<C, T, X>::const_iterator basic_findfile_sequence<C, T, X>::end() const
  890. {
  891. INETSTL_ASSERT(is_valid());
  892. return const_input_iterator(*this);
  893. }
  894. // Attributes
  895. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k X>
  896. ss_typename_type_k basic_findfile_sequence<C, T, X>::char_type const* basic_findfile_sequence<C, T, X>::get_directory(ss_typename_type_k basic_findfile_sequence<C, T, X>::size_type* pn) const
  897. {
  898. INETSTL_ASSERT(is_valid());
  899. size_type n_;
  900. if(NULL == pn)
  901. {
  902. pn = &n_;
  903. }
  904. *pn = m_rootDir.size();
  905. return m_rootDir.c_str();
  906. }
  907. // State
  908. #ifdef STLSOFT_OBSOLETE
  909. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k X>
  910. inline ss_typename_type_ret_k basic_findfile_sequence<C, T, X>::size_type basic_findfile_sequence<C, T, X>::size() const
  911. {
  912. INETSTL_ASSERT(is_valid());
  913. return stlsoft_ns_qual_std(distance)(begin(), end());
  914. }
  915. #endif /* STLSOFT_OBSOLETE */
  916. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k X>
  917. inline is_bool_t basic_findfile_sequence<C, T, X>::empty() const
  918. {
  919. INETSTL_ASSERT(is_valid());
  920. return begin() == end();
  921. }
  922. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k X>
  923. inline /* static */ ss_typename_type_ret_k basic_findfile_sequence<C, T, X>::size_type basic_findfile_sequence<C, T, X>::max_size()
  924. {
  925. return static_cast<size_type>(-1);
  926. }
  927. // basic_findfile_sequence_value_type
  928. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k X>
  929. inline basic_findfile_sequence_value_type<C, T, X>::basic_findfile_sequence_value_type()
  930. {
  931. m_data.dwFileAttributes = 0xFFFFFFFF;
  932. m_data.cFileName[0] = '\0';
  933. m_data.cAlternateFileName[0] = '\0';
  934. m_path[0] = '\0';
  935. }
  936. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k X>
  937. inline ss_typename_type_ret_k basic_findfile_sequence_value_type<C, T, X>::find_data_type const& basic_findfile_sequence_value_type<C, T, X>::get_find_data() const
  938. {
  939. return m_data;
  940. }
  941. #ifdef STLSOFT_OBSOLETE
  942. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k X>
  943. inline ss_typename_type_ret_k basic_findfile_sequence_value_type<C, T, X>::find_data_type const& basic_findfile_sequence_value_type<C, T, X>::GetFindData() const
  944. {
  945. return get_find_data();
  946. }
  947. #endif /* STLSOFT_OBSOLETE */
  948. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k X>
  949. inline ss_typename_type_ret_k basic_findfile_sequence_value_type<C, T, X>::char_type const* basic_findfile_sequence_value_type<C, T, X>::get_filename() const
  950. {
  951. return m_data.cFileName;
  952. }
  953. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k X>
  954. inline ss_typename_type_ret_k basic_findfile_sequence_value_type<C, T, X>::char_type const* basic_findfile_sequence_value_type<C, T, X>::get_short_filename() const
  955. {
  956. return m_data.cAlternateFileName[0] != '\0' ? m_data.cAlternateFileName : m_data.cFileName;
  957. }
  958. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k X>
  959. inline ss_typename_type_ret_k basic_findfile_sequence_value_type<C, T, X>::char_type const* basic_findfile_sequence_value_type<C, T, X>::get_path() const
  960. {
  961. return &m_path[0];
  962. }
  963. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k X>
  964. inline ss_typename_type_ret_k basic_findfile_sequence_value_type<C, T, X>::char_type const* basic_findfile_sequence_value_type<C, T, X>::c_str() const
  965. {
  966. return get_path();
  967. }
  968. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k X>
  969. #if defined(STLSOFT_COMPILER_IS_GCC) || \
  970. ( defined(STLSOFT_COMPILER_IS_MSVC) && \
  971. _MSC_VER < 1100)
  972. inline basic_findfile_sequence_value_type<C, T, X>::operator C const* () const
  973. #else /* ? compiler */
  974. inline basic_findfile_sequence_value_type<C, T, X>::operator ss_typename_type_k basic_findfile_sequence_value_type<C, T, X>::char_type const* () const
  975. #endif /* !compiler */
  976. {
  977. return get_path();
  978. }
  979. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k X>
  980. inline is_bool_t basic_findfile_sequence_value_type<C, T, X>::is_directory() const
  981. {
  982. return traits_type::is_directory(&m_data);
  983. }
  984. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k X>
  985. inline is_bool_t basic_findfile_sequence_value_type<C, T, X>::is_file() const
  986. {
  987. return traits_type::is_file(&m_data);
  988. }
  989. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k X>
  990. inline is_bool_t basic_findfile_sequence_value_type<C, T, X>::is_read_only() const
  991. {
  992. return 0 != (m_data.dwFileAttributes & FILE_ATTRIBUTE_READONLY);
  993. }
  994. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k X>
  995. inline is_bool_t basic_findfile_sequence_value_type<C, T, X>::equal(char_type const* rhs) const
  996. {
  997. INETSTL_ASSERT(NULL != rhs);
  998. return 0 == traits_type::str_compare(this->get_path(), rhs);
  999. }
  1000. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k X>
  1001. inline is_bool_t basic_findfile_sequence_value_type<C, T, X>::equal(basic_findfile_sequence_value_type<C, T, X> const& rhs) const
  1002. {
  1003. return equal(rhs.get_path());
  1004. }
  1005. // basic_findfile_sequence_const_input_iterator
  1006. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k X, ss_typename_param_k V>
  1007. inline /* static */ int basic_findfile_sequence_const_input_iterator<C, T, X, V>::find_next_pattern_( ss_typename_type_k basic_findfile_sequence_const_input_iterator<C, T, X, V>::char_type const*& p0
  1008. , ss_typename_type_k basic_findfile_sequence_const_input_iterator<C, T, X, V>::char_type const*& p1
  1009. , ss_typename_type_k basic_findfile_sequence_const_input_iterator<C, T, X, V>::char_type delim)
  1010. {
  1011. INETSTL_ASSERT(NULL != p0);
  1012. INETSTL_ASSERT(NULL != p1);
  1013. INETSTL_ASSERT(p0 <= p1);
  1014. return stlsoft_ns_qual(find_next_token)(p0, p1, delim);
  1015. }
  1016. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k X, ss_typename_param_k V>
  1017. inline /* static */ HINTERNET basic_findfile_sequence_const_input_iterator<C, T, X, V>::find_first_file_( HINTERNET hconn
  1018. #ifdef STLSOFT_CF_FUNCTION_SIGNATURE_FULL_ARG_QUALIFICATION_REQUIRED
  1019. , ss_typename_type_k basic_findfile_sequence_const_input_iterator<C, T, X, V>::char_type const* pattern
  1020. , ss_typename_type_k basic_findfile_sequence_const_input_iterator<C, T, X, V>::flags_type flags
  1021. , ss_typename_type_k basic_findfile_sequence_const_input_iterator<C, T, X, V>::find_data_type* findData)
  1022. #else /* ? STLSOFT_CF_FUNCTION_SIGNATURE_FULL_ARG_QUALIFICATION_REQUIRED */
  1023. , char_type const* pattern
  1024. , flags_type flags
  1025. , find_data_type* findData)
  1026. #endif /* STLSOFT_CF_FUNCTION_SIGNATURE_FULL_ARG_QUALIFICATION_REQUIRED */
  1027. {
  1028. HINTERNET hSrch = traits_type::find_first_file(hconn, pattern, findData);
  1029. if(hSrch != NULL)
  1030. {
  1031. // Now need to validate against the flags
  1032. for(; hSrch != NULL; )
  1033. {
  1034. if(0 == (findData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
  1035. {
  1036. // A file, and files requested, so break
  1037. if(flags & sequence_type::files)
  1038. {
  1039. break;
  1040. }
  1041. }
  1042. else
  1043. {
  1044. if(traits_type::is_dots(findData->cFileName))
  1045. {
  1046. if(flags & sequence_type::includeDots)
  1047. {
  1048. // A dots file, and dots are requested
  1049. break;
  1050. }
  1051. }
  1052. else if(flags & sequence_type::directories)
  1053. {
  1054. // A directory, and directories requested
  1055. break;
  1056. }
  1057. }
  1058. if(!traits_type::find_next_file(hSrch, findData))
  1059. {
  1060. traits_type::find_close(hSrch);
  1061. hSrch = NULL;
  1062. break;
  1063. }
  1064. }
  1065. }
  1066. return hSrch;
  1067. }
  1068. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k X, ss_typename_param_k V>
  1069. inline basic_findfile_sequence_const_input_iterator<C, T, X, V>::basic_findfile_sequence_const_input_iterator()
  1070. : m_list(NULL)
  1071. , m_handle(NULL)
  1072. , m_rootDir(NULL)
  1073. , m_pattern0(NULL)
  1074. , m_pattern1(NULL)
  1075. , m_delim('\0')
  1076. , m_flags(0)
  1077. {}
  1078. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k X, ss_typename_param_k V>
  1079. inline basic_findfile_sequence_const_input_iterator<C, T, X, V>::basic_findfile_sequence_const_input_iterator( sequence_type const& l
  1080. #ifdef STLSOFT_CF_FUNCTION_SIGNATURE_FULL_ARG_QUALIFICATION_REQUIRED
  1081. , ss_typename_type_k basic_findfile_sequence_const_input_iterator<C, T, X, V>::char_type const* rootDir
  1082. , ss_typename_type_k basic_findfile_sequence_const_input_iterator<C, T, X, V>::char_type const* patterns
  1083. , ss_typename_type_k basic_findfile_sequence_const_input_iterator<C, T, X, V>::char_type delim
  1084. , ss_typename_type_k basic_findfile_sequence_const_input_iterator<C, T, X, V>::flags_type flags)
  1085. #else /* ? STLSOFT_CF_FUNCTION_SIGNATURE_FULL_ARG_QUALIFICATION_REQUIRED */
  1086. , char_type const* rootDir
  1087. , char_type const* patterns
  1088. , char_type delim
  1089. , flags_type flags)
  1090. #endif /* STLSOFT_CF_FUNCTION_SIGNATURE_FULL_ARG_QUALIFICATION_REQUIRED */
  1091. : m_list(&l)
  1092. , m_handle(NULL)
  1093. , m_rootDir(rootDir)
  1094. , m_pattern0(patterns)
  1095. , m_pattern1(patterns)
  1096. , m_delim(delim)
  1097. , m_flags(flags)
  1098. {
  1099. operator ++();
  1100. }
  1101. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k X, ss_typename_param_k V>
  1102. inline basic_findfile_sequence_const_input_iterator<C, T, X, V>::basic_findfile_sequence_const_input_iterator(sequence_type const& l)
  1103. : m_list(&l)
  1104. , m_handle(NULL)
  1105. , m_rootDir(NULL)
  1106. , m_pattern0(NULL)
  1107. , m_pattern1(NULL)
  1108. , m_delim('\0')
  1109. , m_flags(0)
  1110. {}
  1111. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k X, ss_typename_param_k V>
  1112. inline basic_findfile_sequence_const_input_iterator<C, T, X, V>::basic_findfile_sequence_const_input_iterator(class_type const& rhs)
  1113. : m_list(rhs.m_list)
  1114. , m_handle(rhs.m_handle)
  1115. , m_data(rhs.m_data)
  1116. , m_rootDir(rhs.m_rootDir)
  1117. , m_pattern0(rhs.m_pattern0)
  1118. , m_pattern1(rhs.m_pattern1)
  1119. , m_delim(rhs.m_delim)
  1120. , m_flags(rhs.m_flags)
  1121. {
  1122. if(NULL != m_handle)
  1123. {
  1124. m_handle->AddRef();
  1125. }
  1126. }
  1127. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k X, ss_typename_param_k V>
  1128. #ifndef STLSOFT_COMPILER_IS_WATCOM
  1129. inline ss_typename_type_ret_k basic_findfile_sequence_const_input_iterator<C, T, X, V>::class_type& basic_findfile_sequence_const_input_iterator<C, T, X, V>::operator =(ss_typename_param_k basic_findfile_sequence_const_input_iterator<C, T, X, V>::class_type const& rhs)
  1130. #else /* ? compiler */
  1131. inline basic_findfile_sequence_const_input_iterator<C, T, X, V> &basic_findfile_sequence_const_input_iterator<C, T, X, V>::operator =(basic_findfile_sequence_const_input_iterator<C, T, X, V> const& rhs)
  1132. #endif /* compiler */
  1133. {
  1134. INETSTL_MESSAGE_ASSERT("Assigning iterators from separate sequences", (NULL == m_list || NULL == rhs.m_list || m_list == rhs.m_list)); // Should only be comparing iterators from same container
  1135. shared_handle* this_handle = m_handle;
  1136. m_handle = rhs.m_handle;
  1137. m_data = rhs.m_data;
  1138. m_rootDir = rhs.m_rootDir;
  1139. m_pattern0 = rhs.m_pattern0;
  1140. m_pattern1 = rhs.m_pattern1;
  1141. m_delim = rhs.m_delim;
  1142. m_flags = rhs.m_flags;
  1143. if(NULL != m_handle)
  1144. {
  1145. m_handle->AddRef();
  1146. }
  1147. if(NULL != this_handle)
  1148. {
  1149. this_handle->Release();
  1150. }
  1151. return *this;
  1152. }
  1153. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k X, ss_typename_param_k V>
  1154. inline basic_findfile_sequence_const_input_iterator<C, T, X, V>::~basic_findfile_sequence_const_input_iterator() stlsoft_throw_0()
  1155. {
  1156. if(NULL != m_handle)
  1157. {
  1158. m_handle->Release();
  1159. }
  1160. }
  1161. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k X, ss_typename_param_k V>
  1162. inline ss_typename_type_ret_k basic_findfile_sequence_const_input_iterator<C, T, X, V>::class_type& basic_findfile_sequence_const_input_iterator<C, T, X, V>::operator ++()
  1163. {
  1164. INETSTL_ASSERT(NULL != m_pattern0);
  1165. INETSTL_ASSERT(NULL != m_pattern1);
  1166. INETSTL_MESSAGE_ASSERT("Attempting to increment an invalid iterator!", '\0' != *m_pattern0);
  1167. // Possible call states:
  1168. //
  1169. // 1. starting out
  1170. // 2.
  1171. for(; '\0' != *m_pattern0 || '\0' != *m_pattern1;)
  1172. {
  1173. if(NULL == m_handle)
  1174. {
  1175. // Need to work through the
  1176. while(find_next_pattern_(m_pattern0, m_pattern1, m_delim))
  1177. {
  1178. if(m_pattern1 != m_pattern0) // Will return m_pattern0 == m_pattern1 for empty tokens
  1179. {
  1180. string_type pattern(m_pattern0, m_pattern1);
  1181. string_type search = m_rootDir;
  1182. if(search.back() != '/')
  1183. {
  1184. static const char_type slash[] = { '/', '\0' };
  1185. search += slash;
  1186. }
  1187. search += pattern;
  1188. //printf("[%s]\n", search.c_str());
  1189. HINTERNET hSrch = find_first_file_(m_list->m_hconn, stlsoft_ns_qual(c_str_ptr)(search), m_flags, &m_data);
  1190. if(NULL != hSrch)
  1191. {
  1192. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  1193. try
  1194. {
  1195. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  1196. m_handle = new shared_handle(hSrch);
  1197. if(NULL == m_handle)
  1198. {
  1199. ::FindClose(hSrch);
  1200. }
  1201. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  1202. }
  1203. catch(...)
  1204. {
  1205. ::FindClose(hSrch);
  1206. throw;
  1207. }
  1208. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  1209. return *this;
  1210. }
  1211. }
  1212. }
  1213. }
  1214. if(NULL != m_handle)
  1215. {
  1216. for(; m_handle->hSrch != NULL; )
  1217. {
  1218. if(!traits_type::find_next_file(m_handle->hSrch, &m_data))
  1219. {
  1220. m_handle->Release();
  1221. m_handle = NULL;
  1222. break;
  1223. }
  1224. else
  1225. {
  1226. if((m_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
  1227. {
  1228. // A file, and files requested, so break
  1229. if(m_flags & sequence_type::files)
  1230. {
  1231. return *this;
  1232. }
  1233. }
  1234. else
  1235. {
  1236. if(traits_type::is_dots(m_data.cFileName))
  1237. {
  1238. if(m_flags & sequence_type::includeDots)
  1239. {
  1240. // A dots file, and dots are requested
  1241. return *this;
  1242. }
  1243. }
  1244. else if(m_flags & sequence_type::directories)
  1245. {
  1246. // A directory, and directories requested
  1247. return *this;
  1248. }
  1249. }
  1250. }
  1251. }
  1252. }
  1253. }
  1254. return *this;
  1255. }
  1256. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k X, ss_typename_param_k V>
  1257. inline ss_typename_type_ret_k basic_findfile_sequence_const_input_iterator<C, T, X, V>::class_type basic_findfile_sequence_const_input_iterator<C, T, X, V>::operator ++(int)
  1258. {
  1259. class_type ret(*this);
  1260. operator ++();
  1261. return ret;
  1262. }
  1263. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k X, ss_typename_param_k V>
  1264. inline const ss_typename_type_k basic_findfile_sequence_const_input_iterator<C, T, X, V>::value_type basic_findfile_sequence_const_input_iterator<C, T, X, V>::operator *() const
  1265. {
  1266. if(NULL != m_handle)
  1267. {
  1268. size_type dirLen = 0;
  1269. char_type const* dir = m_list->get_directory(&dirLen);
  1270. return value_type(m_data, dir, dirLen);
  1271. }
  1272. else
  1273. {
  1274. INETSTL_MESSAGE_ASSERT("Dereferencing end()-valued iterator", 0);
  1275. return value_type();
  1276. }
  1277. }
  1278. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k X, ss_typename_param_k V>
  1279. inline is_bool_t basic_findfile_sequence_const_input_iterator<C, T, X, V>::equal(class_type const& rhs) const
  1280. {
  1281. // Should only be comparing iterators from same container
  1282. INETSTL_MESSAGE_ASSERT("Comparing iterators from separate sequences", (m_list == rhs.m_list || NULL == m_list || NULL == rhs.m_list));
  1283. return m_handle == rhs.m_handle;
  1284. }
  1285. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  1286. /* ////////////////////////////////////////////////////////////////////// */
  1287. #ifndef _INETSTL_NO_NAMESPACE
  1288. # if defined(_STLSOFT_NO_NAMESPACE) || \
  1289. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  1290. } // namespace inetstl
  1291. # else
  1292. } // namespace inetstl_project
  1293. } // namespace stlsoft
  1294. # endif /* _STLSOFT_NO_NAMESPACE */
  1295. #endif /* !_INETSTL_NO_NAMESPACE */
  1296. /* /////////////////////////////////////////////////////////////////////////
  1297. * Namespace
  1298. *
  1299. * The string access shims exist either in the stlsoft namespace, or in the
  1300. * global namespace. This is required by the lookup rules.
  1301. *
  1302. */
  1303. #ifndef _INETSTL_NO_NAMESPACE
  1304. # if !defined(_STLSOFT_NO_NAMESPACE) && \
  1305. !defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  1306. namespace stlsoft
  1307. {
  1308. # else /* ? _STLSOFT_NO_NAMESPACE */
  1309. /* There is no stlsoft namespace, so must define in the global namespace */
  1310. # endif /* !_STLSOFT_NO_NAMESPACE */
  1311. using ::inetstl::c_str_data;
  1312. using ::inetstl::c_str_data_a;
  1313. using ::inetstl::c_str_data_w;
  1314. using ::inetstl::c_str_len;
  1315. using ::inetstl::c_str_len_a;
  1316. using ::inetstl::c_str_len_w;
  1317. using ::inetstl::c_str_ptr;
  1318. using ::inetstl::c_str_ptr_a;
  1319. using ::inetstl::c_str_ptr_w;
  1320. using ::inetstl::c_str_ptr_null;
  1321. using ::inetstl::c_str_ptr_null_a;
  1322. using ::inetstl::c_str_ptr_null_w;
  1323. # if !defined(_STLSOFT_NO_NAMESPACE) && \
  1324. !defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  1325. } // namespace stlsoft
  1326. # else /* ? _STLSOFT_NO_NAMESPACE */
  1327. /* There is no stlsoft namespace, so must define in the global namespace */
  1328. # endif /* !_STLSOFT_NO_NAMESPACE */
  1329. #endif /* !_INETSTL_NO_NAMESPACE */
  1330. /* ////////////////////////////////////////////////////////////////////// */
  1331. #endif /* INETSTL_INCL_INETSTL_FILESYSTEM_HPP_FINDFILE_SEQUENCE */
  1332. /* ///////////////////////////// end of file //////////////////////////// */