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.

1804 lines
64 KiB

  1. /* /////////////////////////////////////////////////////////////////////////
  2. * File: winstl/filesystem/findfile_sequence.hpp
  3. *
  4. * Purpose: Contains the basic_findfile_sequence template class, and ANSI
  5. * and Unicode specialisations thereof.
  6. *
  7. * Notes: 1. The original implementation of the class had the const_iterator
  8. * and value_type as nested classes. Unfortunately, Visual C++ 5 &
  9. * 6 both had either compilation or linking problems so these are
  10. * regretably now implemented as independent classes.
  11. *
  12. * 2. This class was described in detail in the article
  13. * "Adapting Windows Enumeration Models to STL Iterator Concepts"
  14. * (http://www.windevnet.com/documents/win0303a/), in the March
  15. * 2003 issue of Windows Developer Network (http://windevnet.com).
  16. * Note that later implementations use a shared-enumeration
  17. * context, and therefore do not suffer any of the copying/moving
  18. * ownership issues described in the article.
  19. *
  20. * Created: 15th January 2002
  21. * Updated: 22nd November 2009
  22. *
  23. * Thanks: To Nevin Liber for pressing upon me the need to lead by
  24. * example when writing books about good design/implementation;
  25. * to Florin L for DMC++ missing standard symbols.
  26. *
  27. * Home: http://stlsoft.org/
  28. *
  29. * Copyright (c) 2002-2009, Matthew Wilson and Synesis Software
  30. * All rights reserved.
  31. *
  32. * Redistribution and use in source and binary forms, with or without
  33. * modification, are permitted provided that the following conditions are met:
  34. *
  35. * - Redistributions of source code must retain the above copyright notice, this
  36. * list of conditions and the following disclaimer.
  37. * - Redistributions in binary form must reproduce the above copyright notice,
  38. * this list of conditions and the following disclaimer in the documentation
  39. * and/or other materials provided with the distribution.
  40. * - Neither the name(s) of Matthew Wilson and Synesis Software nor the names of
  41. * any contributors may be used to endorse or promote products derived from
  42. * this software without specific prior written permission.
  43. *
  44. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  45. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  46. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  47. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  48. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  49. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  50. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  51. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  52. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  53. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  54. * POSSIBILITY OF SUCH DAMAGE.
  55. *
  56. * ////////////////////////////////////////////////////////////////////// */
  57. /** \file winstl/filesystem/findfile_sequence.hpp
  58. *
  59. * \brief [C++ only] Definition of the winstl::basic_findfile_sequence class
  60. * template
  61. * (\ref group__library__filesystem "File System" Library).
  62. */
  63. #ifndef WINSTL_INCL_WINSTL_FILESYSTEM_HPP_FINDFILE_SEQUENCE
  64. #define WINSTL_INCL_WINSTL_FILESYSTEM_HPP_FINDFILE_SEQUENCE
  65. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  66. # define WINSTL_VER_WINSTL_FILESYSTEM_HPP_FINDFILE_SEQUENCE_MAJOR 4
  67. # define WINSTL_VER_WINSTL_FILESYSTEM_HPP_FINDFILE_SEQUENCE_MINOR 8
  68. # define WINSTL_VER_WINSTL_FILESYSTEM_HPP_FINDFILE_SEQUENCE_REVISION 1
  69. # define WINSTL_VER_WINSTL_FILESYSTEM_HPP_FINDFILE_SEQUENCE_EDIT 216
  70. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  71. /* /////////////////////////////////////////////////////////////////////////
  72. * Compatibility
  73. */
  74. /*
  75. [Incompatibilies-start]
  76. STLSOFT_COMPILER_IS_MSVC: _MSC_VER<1100
  77. [Incompatibilies-end]
  78. */
  79. /* /////////////////////////////////////////////////////////////////////////
  80. * Includes
  81. */
  82. #ifndef WINSTL_INCL_WINSTL_H_WINSTL
  83. # include <winstl/winstl.h>
  84. #endif /* !WINSTL_INCL_WINSTL_H_WINSTL */
  85. #if defined(STLSOFT_COMPILER_IS_MSVC) && \
  86. _MSC_VER < 1100
  87. # error winstl/findfile_sequence.hpp is not compatible with Visual C++ 4.2 or earlier
  88. #endif /* compiler */
  89. #ifndef WINSTL_INCL_WINSTL_FILESYSTEM_HPP_FILESYSTEM_TRAITS
  90. # include <winstl/filesystem/filesystem_traits.hpp>
  91. #endif /* !WINSTL_INCL_WINSTL_FILESYSTEM_HPP_FILESYSTEM_TRAITS */
  92. #ifndef WINSTL_INCL_WINSTL_FILESYSTEM_HPP_FILE_PATH_BUFFER
  93. # include <winstl/filesystem/file_path_buffer.hpp>
  94. #endif /* !WINSTL_INCL_WINSTL_FILESYSTEM_HPP_FILE_PATH_BUFFER */
  95. #ifndef WINSTL_INCL_WINSTL_SYSTEM_HPP_SYSTEM_VERSION
  96. # include <winstl/system/system_version.hpp>
  97. #endif /* !WINSTL_INCL_WINSTL_SYSTEM_HPP_SYSTEM_VERSION */
  98. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  99. # ifndef WINSTL_INCL_WINSTL_ERROR_HPP_WINDOWS_EXCEPTIONS
  100. # include <winstl/error/exceptions.hpp>
  101. # endif /* !WINSTL_INCL_WINSTL_ERROR_HPP_WINDOWS_EXCEPTIONS */
  102. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  103. #ifndef STLSOFT_INCL_STLSOFT_SHIMS_ACCESS_HPP_STRING
  104. # include <stlsoft/shims/access/string.hpp>
  105. #endif /* !STLSOFT_INCL_STLSOFT_SHIMS_ACCESS_HPP_STRING */
  106. #ifndef STLSOFT_COMPILER_IS_WATCOM
  107. #ifndef STLSOFT_INCL_STLSOFT_UTIL_STD_HPP_ITERATOR_HELPER
  108. # include <stlsoft/util/std/iterator_helper.hpp>
  109. #endif /* !STLSOFT_INCL_STLSOFT_UTIL_STD_HPP_ITERATOR_HELPER */
  110. #endif /* compiler */
  111. #ifndef STLSOFT_INCL_STLSOFT_SMARTPTR_HPP_SCOPED_HANDLE
  112. # include <stlsoft/smartptr/scoped_handle.hpp>
  113. #endif /* !STLSOFT_INCL_STLSOFT_SMARTPTR_HPP_SCOPED_HANDLE */
  114. #ifndef STLSOFT_INCL_STLSOFT_STRING_HPP_TOKENISER_FUNCTIONS
  115. # include <stlsoft/string/tokeniser_functions.hpp> // for find_next_token
  116. #endif /* !STLSOFT_INCL_STLSOFT_STRING_HPP_TOKENISER_FUNCTIONS */
  117. #ifndef WINSTL_INCL_WINSTL_MEMORY_HPP_PROCESSHEAP_ALLOCATOR
  118. # include <winstl/memory/processheap_allocator.hpp>
  119. #endif /* !WINSTL_INCL_WINSTL_MEMORY_HPP_PROCESSHEAP_ALLOCATOR */
  120. #ifndef STLSOFT_INCL_STLSOFT_COLLECTIONS_UTIL_HPP_COLLECTIONS
  121. # include <stlsoft/collections/util/collections.hpp>
  122. #endif /* !STLSOFT_INCL_STLSOFT_COLLECTIONS_UTIL_HPP_COLLECTIONS */
  123. #ifdef STLSOFT_UNITTEST
  124. # include <winstl/filesystem/current_directory.hpp>
  125. #endif /* STLSOFT_UNITTEST */
  126. /* /////////////////////////////////////////////////////////////////////////
  127. * Namespace
  128. */
  129. #ifndef _WINSTL_NO_NAMESPACE
  130. # if defined(_STLSOFT_NO_NAMESPACE) || \
  131. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  132. /* There is no stlsoft namespace, so must define ::winstl */
  133. namespace winstl
  134. {
  135. # else
  136. /* Define stlsoft::winstl_project */
  137. namespace stlsoft
  138. {
  139. namespace winstl_project
  140. {
  141. # endif /* _STLSOFT_NO_NAMESPACE */
  142. #endif /* !_WINSTL_NO_NAMESPACE */
  143. /* /////////////////////////////////////////////////////////////////////////
  144. * Forward declarations
  145. */
  146. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  147. template <ss_typename_param_k C, ss_typename_param_k T>
  148. class basic_findfile_sequence_value_type;
  149. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k V>
  150. class basic_findfile_sequence_const_input_iterator;
  151. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  152. /* /////////////////////////////////////////////////////////////////////////
  153. * Classes
  154. */
  155. // class basic_findfile_sequence
  156. /** \brief Presents an STL-like sequence interface over the items on the file-system
  157. *
  158. * \ingroup group__library__filesystem
  159. *
  160. * \param C The character type
  161. * \param T The traits type. On translators that support default template arguments this defaults to filesystem_traits<C>
  162. *
  163. * \note This class was described in detail in the article
  164. * "Adapting Windows Enumeration Models to STL Iterator Concepts"
  165. * (http://www.windevnet.com/documents/win0303a/), in the March 2003 issue of
  166. * Windows Developer Network (http://windevnet.com).
  167. */
  168. template< ss_typename_param_k C
  169. #ifdef STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT
  170. , ss_typename_param_k T = filesystem_traits<C>
  171. #else /* ? STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT */
  172. , ss_typename_param_k T /* = filesystem_traits<C> */
  173. #endif /* STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT */
  174. >
  175. class basic_findfile_sequence
  176. : public stlsoft_ns_qual(stl_collection_tag)
  177. {
  178. /// \name Member Types
  179. /// @{
  180. public:
  181. /// The character type
  182. typedef C char_type;
  183. /// The traits type
  184. typedef T traits_type;
  185. /// The current parameterisation of the type
  186. typedef basic_findfile_sequence<C, T> class_type;
  187. /// The value type
  188. typedef basic_findfile_sequence_value_type<C, T> value_type;
  189. /// The non-mutating (const) iterator type
  190. typedef basic_findfile_sequence_const_input_iterator<C, T, value_type> const_iterator;
  191. /// The reference type
  192. typedef value_type const reference;
  193. /// The non-mutable (const) reference type
  194. typedef value_type const const_reference;
  195. /// The find-data type
  196. typedef ss_typename_type_k traits_type::find_data_type find_data_type;
  197. /// The difference type
  198. typedef ws_ptrdiff_t difference_type;
  199. /// The size type
  200. typedef ws_size_t size_type;
  201. /// The Boolean type
  202. typedef ws_bool_t bool_type;
  203. /// The flags type
  204. typedef int flags_type;
  205. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  206. // For backwards compatibility
  207. typedef const_iterator const_input_iterator;
  208. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  209. /// @}
  210. /// \name Member Constants
  211. /// @{
  212. public:
  213. enum search_flags
  214. {
  215. includeDots = 0x0008 //!< Causes the search to include the "." and ".." directories, which are elided by default
  216. , directories = 0x0010 //!< Causes the search to include directories
  217. , files = 0x0020 //!< Causes the search to include files
  218. , skipReparseDirs = 0x0100 //!< Causes the search to skip directories that are reparse points
  219. , skipHiddenFiles = 0x0200 //!< Causes the search to skip files marked hidden
  220. , skipHiddenDirs = 0x0400 //!< Causes the search to skip directories marked hidden
  221. , relativePath = 0x0800 //!< Each file entry is presented as relative to the search directory.
  222. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  223. , throwOnAccessFailure = 0x2000 //!< Causes an exception to be thrown if a directory cannot be access
  224. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  225. };
  226. /// @}
  227. /// \name Construction
  228. /// @{
  229. public:
  230. /// Commence a search according to the given search pattern and flags, relative to the current directory
  231. ss_explicit_k basic_findfile_sequence( char_type const* pattern
  232. , flags_type flags = directories | files);
  233. /// Commence a search according to the given search composite pattern and delimiter, flags, relative to the current directory
  234. basic_findfile_sequence(char_type const* patterns
  235. , char_type delim
  236. , flags_type flags = directories | files);
  237. /// Commence a search according to the given search pattern and flags, relative to \c directory
  238. basic_findfile_sequence(char_type const* directory
  239. , char_type const* pattern
  240. , flags_type flags = directories | files);
  241. /// Commence a search according to the given search composite pattern and delimiter, flags, relative to \c directory
  242. basic_findfile_sequence(char_type const* directory
  243. , char_type const* patterns
  244. , char_type delim
  245. , flags_type flags = directories | files);
  246. /// Destructor
  247. ~basic_findfile_sequence() stlsoft_throw_0();
  248. /// @}
  249. /// \name Iteration
  250. /// @{
  251. public:
  252. /// Begins the iteration
  253. ///
  254. /// \return An iterator representing the start of the sequence
  255. const_iterator begin() const;
  256. /// Ends the iteration
  257. ///
  258. /// \return An iterator representing the end of the sequence
  259. const_iterator end() const;
  260. /// @}
  261. /// \name Attributes
  262. /// @{
  263. public:
  264. /// Returns the directory of the search
  265. ///
  266. /// \note Will be the empty string for instances created with the first constructor
  267. char_type const* get_directory(size_type* plen = NULL) const;
  268. /// @}
  269. /// \name State
  270. /// @{
  271. public:
  272. /// Indicates whether the sequence is empty
  273. ws_bool_t empty() const;
  274. /// Returns the maximum number of items in the sequence
  275. static size_type max_size();
  276. /// @}
  277. /// \name Members
  278. /// @{
  279. private:
  280. typedef basic_file_path_buffer<char_type> file_path_buffer_type_;
  281. typedef stlsoft_ns_qual(auto_buffer_old)< char_type
  282. , processheap_allocator<char_type>
  283. , 64
  284. > patterns_buffer_type_;
  285. const char_type m_delim;
  286. const flags_type m_flags;
  287. file_path_buffer_type_ m_directory; // The directory, as specified to the constructor
  288. patterns_buffer_type_ m_patterns; // The pattern(s) specified to the constructor
  289. const size_type m_directoryLen; // The directory length
  290. /// @}
  291. /// \name Invariant
  292. /// @{
  293. private:
  294. ws_bool_t is_valid() const;
  295. /// @}
  296. /// \name Implementation
  297. /// @{
  298. private:
  299. static flags_type validate_flags_(flags_type flags);
  300. static size_type validate_directory_(char_type const* directory, file_path_buffer_type_& dir, flags_type flags);
  301. /// @}
  302. /// \name Not to be implemented
  303. /// @{
  304. private:
  305. basic_findfile_sequence(class_type const&);
  306. class_type& operator =(class_type const&);
  307. /// @}
  308. };
  309. /* /////////////////////////////////////////////////////////////////////////
  310. * Typedefs for commonly encountered types
  311. */
  312. /** \brief Specialisation of the basic_findfile_sequence template for the ANSI character type \c char
  313. *
  314. * \ingroup group__library__filesystem
  315. */
  316. typedef basic_findfile_sequence<ws_char_a_t, filesystem_traits<ws_char_a_t> > findfile_sequence_a;
  317. /** \brief Specialisation of the basic_findfile_sequence template for the Unicode character type \c wchar_t
  318. *
  319. * \ingroup group__library__filesystem
  320. */
  321. typedef basic_findfile_sequence<ws_char_w_t, filesystem_traits<ws_char_w_t> > findfile_sequence_w;
  322. /** \brief Specialisation of the basic_findfile_sequence template for the Win32 character type \c TCHAR
  323. *
  324. * \ingroup group__library__filesystem
  325. */
  326. typedef basic_findfile_sequence<TCHAR, filesystem_traits<TCHAR> > findfile_sequence;
  327. /* ////////////////////////////////////////////////////////////////////// */
  328. // class basic_findfile_sequence_value_type
  329. /** \brief Value type for the basic_findfile_sequence
  330. *
  331. * \ingroup group__library__filesystem
  332. */
  333. template< ss_typename_param_k C
  334. , ss_typename_param_k T
  335. >
  336. class basic_findfile_sequence_value_type
  337. {
  338. /// \name Member Types
  339. /// @{
  340. private:
  341. typedef basic_findfile_sequence<C, T> sequence_type;
  342. public:
  343. /// The character type
  344. typedef C char_type;
  345. /// The traits type
  346. typedef T traits_type;
  347. /// The current parameterisation of the type
  348. typedef basic_findfile_sequence_value_type<C, T> class_type;
  349. /// The find-data type
  350. typedef ss_typename_type_k traits_type::find_data_type find_data_type;
  351. /// The size type
  352. typedef ss_typename_type_k sequence_type::size_type size_type;
  353. private:
  354. typedef ss_typename_type_k sequence_type::bool_type bool_type;
  355. typedef ss_typename_type_k sequence_type::flags_type flags_type;
  356. /// @}
  357. /// \name Construction
  358. /// @{
  359. public:
  360. /// Default constructor
  361. basic_findfile_sequence_value_type();
  362. private:
  363. basic_findfile_sequence_value_type(find_data_type const& data, char_type const* directory, size_type cchDirectory)
  364. : m_data(data)
  365. {
  366. WINSTL_ASSERT(NULL != directory);
  367. WINSTL_ASSERT(0 != cchDirectory);
  368. const size_type cchFilename = traits_type::str_len(data.cFileName);
  369. traits_type::char_copy(&m_path[0], directory, cchDirectory);
  370. m_path[cchDirectory] = '\0';
  371. if(!traits_type::has_dir_end(&m_path[0]))
  372. {
  373. traits_type::ensure_dir_end(&m_path[0] + (cchDirectory - 1));
  374. ++cchDirectory;
  375. }
  376. traits_type::char_copy(&m_path[0] + cchDirectory, data.cFileName, cchFilename);
  377. m_path[cchDirectory + cchFilename] = '\0';
  378. m_pathLen = cchDirectory + cchFilename;
  379. WINSTL_ASSERT(traits_type::str_len(m_path.c_str()) == m_pathLen);
  380. }
  381. public:
  382. /// Copy assignment operator
  383. class_type& operator =(class_type const& rhs);
  384. /// @}
  385. /// \name Accessors
  386. /// @{
  387. public:
  388. /// Returns a non-mutating reference to find-data
  389. find_data_type const& get_find_data() const;
  390. #ifdef STLSOFT_OBSOLETE
  391. /// Returns a non-mutating reference to find-data
  392. ///
  393. /// \deprecated This method may be removed in a future release. get_find_data() should be used instead
  394. find_data_type const& GetFindData() const; // Deprecated
  395. #endif /* STLSOFT_OBSOLETE */
  396. /// Returns the filename part of the item
  397. char_type const* get_filename() const;
  398. /// Returns the short form of the filename part of the item
  399. char_type const* get_short_filename() const;
  400. /// Returns the full path of the item
  401. ///
  402. /// \note The path is not canonicalised, so will not be in canonical form if the filename is a
  403. /// dots directory. For this you should use winstl::path, and call canonicalise()
  404. char_type const* get_path() const;
  405. /// Returns the full path of the item
  406. ///
  407. /// \note The path is not canonicalised, so will not be in canonical form if the filename is a
  408. /// dots directory. For this you should use winstl::path, and call canonicalise()
  409. char_type const* c_str() const;
  410. /// Returns the length of the full path
  411. ws_size_t length() const; // NOTE: The return type must be ws_size_t, due to a defect in VC++ 7.1
  412. /// Implicit conversion to a pointer-to-const of the full path
  413. ///
  414. /// \note The path is not canonicalised, so will not be in canonical form if the filename is a
  415. /// dots directory. For this you should use winstl::path, and call canonicalise()
  416. ///
  417. /// \deprecated This is provided for backwards compatibility with an earlier version, but since this
  418. /// class does not have an implicit conversion constructor, it's pretty harmless.
  419. operator char_type const* () const;
  420. /// Indicates whether the entry is a directory
  421. ws_bool_t is_directory() const;
  422. /// Indicates whether the entry is a file
  423. ws_bool_t is_file() const;
  424. /// Indicates whether the entry is compressed
  425. ws_bool_t is_compressed() const;
  426. #ifdef FILE_ATTRIBUTE_REPARSE_POINT
  427. /// Indicates whether the entry is a reparse point
  428. ws_bool_t is_reparse_point() const;
  429. #endif /* FILE_ATTRIBUTE_REPARSE_POINT */
  430. /// Indicates whether the entry is read-only
  431. ws_bool_t is_read_only() const;
  432. /// Indicates whether the entry is a system file/directory
  433. ws_bool_t is_system() const;
  434. /// Indicates whether the entry is hidden
  435. ws_bool_t is_hidden() const;
  436. /// @}
  437. /// \name Comparison
  438. /// @{
  439. public:
  440. /// \brief Determines whether the instance is equal to the given path
  441. ws_bool_t equal(char_type const* rhs) const;
  442. /// \brief Determines whether two instances are equal
  443. ws_bool_t equal(class_type const& rhs) const;
  444. /// @}
  445. /// \name Members
  446. /// @{
  447. private:
  448. friend class basic_findfile_sequence_const_input_iterator<C, T, class_type>;
  449. typedef basic_file_path_buffer<char_type> file_path_buffer_type_;
  450. find_data_type m_data;
  451. file_path_buffer_type_ m_path;
  452. size_type m_pathLen;
  453. /// @}
  454. };
  455. // class basic_findfile_sequence_const_input_iterator
  456. /** \brief Iterator type for the basic_findfile_sequence supporting the Input Iterator concept
  457. *
  458. * \ingroup group__library__filesystem
  459. */
  460. template< ss_typename_param_k C
  461. , ss_typename_param_k T
  462. , ss_typename_param_k V
  463. >
  464. class basic_findfile_sequence_const_input_iterator
  465. #ifndef STLSOFT_COMPILER_IS_WATCOM
  466. : public stlsoft_ns_qual(iterator_base)<winstl_ns_qual_std(input_iterator_tag)
  467. , V
  468. , ws_ptrdiff_t
  469. , void // By-Value Temporary reference
  470. , V // By-Value Temporary reference
  471. >
  472. #endif /* compiler */
  473. {
  474. /// \name Member Types
  475. /// @{
  476. private:
  477. typedef basic_findfile_sequence<C, T> sequence_type;
  478. public:
  479. /// The character type
  480. typedef C char_type;
  481. /// The traits type
  482. typedef T traits_type;
  483. /// The value type
  484. typedef V value_type;
  485. /// The current parameterisation of the type
  486. typedef basic_findfile_sequence_const_input_iterator<C, T, V> class_type;
  487. /// The find-data type
  488. typedef ss_typename_type_k traits_type::find_data_type find_data_type;
  489. /// The size type
  490. typedef ss_typename_type_k sequence_type::size_type size_type;
  491. private:
  492. typedef ss_typename_type_k sequence_type::bool_type bool_type;
  493. typedef ss_typename_type_k sequence_type::flags_type flags_type;
  494. /// @}
  495. /// \name Utility classes
  496. /// @{
  497. private:
  498. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  499. struct shared_handle
  500. {
  501. /// \name Member Types
  502. /// @{
  503. public:
  504. typedef shared_handle class_type;
  505. typedef HANDLE handle_type;
  506. /// @}
  507. /// \name Members
  508. /// @{
  509. public:
  510. handle_type hSrch;
  511. private:
  512. ss_sint32_t m_refCount;
  513. /// @}
  514. /// \name Construction
  515. /// @{
  516. public:
  517. ss_explicit_k shared_handle(handle_type h)
  518. : hSrch(h)
  519. , m_refCount(1)
  520. {}
  521. # if defined(STLSOFT_CF_COMPILER_WARNS_NO_PUBLIC_DTOR)
  522. protected:
  523. # else /* ? STLSOFT_CF_COMPILER_WARNS_NO_PUBLIC_DTOR */
  524. private:
  525. # endif /* STLSOFT_CF_COMPILER_WARNS_NO_PUBLIC_DTOR */
  526. ~shared_handle() stlsoft_throw_0()
  527. {
  528. WINSTL_MESSAGE_ASSERT("Shared search handle being destroyed with outstanding references!", 0 == m_refCount);
  529. if(INVALID_HANDLE_VALUE != hSrch)
  530. {
  531. traits_type::find_file_close(hSrch);
  532. }
  533. }
  534. /// @}
  535. /// \name Operations
  536. /// @{
  537. public:
  538. ss_sint32_t AddRef()
  539. {
  540. return ++m_refCount;
  541. }
  542. ss_sint32_t Release()
  543. {
  544. ss_sint32_t rc = --m_refCount;
  545. if(0 == rc)
  546. {
  547. delete this;
  548. }
  549. return rc;
  550. }
  551. /// @}
  552. /// \name Not to be implemented
  553. /// @{
  554. private:
  555. shared_handle(class_type const&);
  556. class_type& operator =(class_type const&);
  557. /// @}
  558. };
  559. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  560. /// @}
  561. /// \name Construction
  562. /// @{
  563. private:
  564. basic_findfile_sequence_const_input_iterator( sequence_type const& l
  565. , char_type const* patterns
  566. , char_type delim
  567. , flags_type flags);
  568. basic_findfile_sequence_const_input_iterator(sequence_type const& l);
  569. public:
  570. /// Default constructor
  571. basic_findfile_sequence_const_input_iterator();
  572. /// <a href = "http://synesis.com.au/resources/articles/cpp/movectors.pdf">Move constructor</a>
  573. basic_findfile_sequence_const_input_iterator(class_type const& rhs);
  574. /// Destructor
  575. ~basic_findfile_sequence_const_input_iterator() stlsoft_throw_0();
  576. // Copy assignment operator
  577. basic_findfile_sequence_const_input_iterator& operator =(class_type const& rhs);
  578. /// @}
  579. /// \name Input Iterator methods
  580. /// @{
  581. public:
  582. /// Pre-increment operator
  583. class_type& operator ++();
  584. /// Post-increment operator
  585. class_type operator ++(int);
  586. /// Dereference to return the value at the current position
  587. const value_type operator *() const;
  588. /// Evaluates whether \c this and \c rhs are equivalent
  589. ws_bool_t equal(class_type const& rhs) const;
  590. /// @}
  591. /// \name Implementation
  592. /// @{
  593. private:
  594. static HANDLE find_first_file_(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>;
  600. typedef basic_file_path_buffer<char_type> file_path_buffer_type_;
  601. sequence_type const* const m_list;
  602. shared_handle* m_handle;
  603. ss_typename_type_k traits_type::find_data_type m_data;
  604. file_path_buffer_type_ m_subpath;
  605. size_type m_subPathLen;
  606. char_type const* m_pattern0;
  607. char_type const* m_pattern1;
  608. char_type m_delim;
  609. flags_type m_flags;
  610. /// @}
  611. };
  612. ////////////////////////////////////////////////////////////////////////////
  613. // Operators
  614. // basic_findfile_sequence_const_input_iterator
  615. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k V>
  616. inline ws_bool_t operator ==( basic_findfile_sequence_const_input_iterator<C, T, V> const& lhs
  617. , basic_findfile_sequence_const_input_iterator<C, T, V> const& rhs)
  618. {
  619. return lhs.equal(rhs);
  620. }
  621. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k V>
  622. inline ws_bool_t operator !=( basic_findfile_sequence_const_input_iterator<C, T, V> const& lhs
  623. , basic_findfile_sequence_const_input_iterator<C, T, V> const& rhs)
  624. {
  625. return !lhs.equal(rhs);
  626. }
  627. // basic_findfile_sequence_value_type
  628. template <ss_typename_param_k C, ss_typename_param_k T>
  629. inline ws_bool_t operator == ( basic_findfile_sequence_value_type<C, T> const& lhs
  630. , basic_findfile_sequence_value_type<C, T> const& rhs)
  631. {
  632. return lhs.equal(rhs);
  633. }
  634. template <ss_typename_param_k C, ss_typename_param_k T>
  635. inline ws_bool_t operator == ( basic_findfile_sequence_value_type<C, T> const& lhs
  636. , C const* rhs)
  637. {
  638. return lhs.equal(rhs);
  639. }
  640. template <ss_typename_param_k C, ss_typename_param_k T>
  641. inline ws_bool_t operator == (C const* lhs, basic_findfile_sequence_value_type<C, T> const& rhs)
  642. {
  643. return rhs.equal(lhs);
  644. }
  645. template <ss_typename_param_k C, ss_typename_param_k T>
  646. inline ws_bool_t operator != ( basic_findfile_sequence_value_type<C, T> const& lhs
  647. , basic_findfile_sequence_value_type<C, T> const& rhs)
  648. {
  649. return !lhs.equal(rhs);
  650. }
  651. template <ss_typename_param_k C, ss_typename_param_k T>
  652. inline ws_bool_t operator != ( basic_findfile_sequence_value_type<C, T> const& lhs
  653. , C const* rhs)
  654. {
  655. return !lhs.equal(rhs);
  656. }
  657. template <ss_typename_param_k C, ss_typename_param_k T>
  658. inline ws_bool_t operator != (C const* lhs, basic_findfile_sequence_value_type<C, T> const& rhs)
  659. {
  660. return !rhs.equal(lhs);
  661. }
  662. /* /////////////////////////////////////////////////////////////////////////
  663. * IOStream compatibility
  664. */
  665. template <ss_typename_param_k S, ss_typename_param_k C, ss_typename_param_k T>
  666. inline S& operator <<(S& s, basic_findfile_sequence_value_type<C, T> const& value)
  667. {
  668. s << value.get_path();
  669. return s;
  670. }
  671. ////////////////////////////////////////////////////////////////////////////
  672. // Shims
  673. // c_str_data
  674. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  675. template <ss_typename_param_k T>
  676. inline ws_char_a_t const* c_str_data_a(winstl_ns_qual(basic_findfile_sequence_value_type)<ws_char_a_t, T> const& v)
  677. {
  678. return v.get_path();
  679. }
  680. template <ss_typename_param_k T>
  681. inline ws_char_w_t const* c_str_data_w(winstl_ns_qual(basic_findfile_sequence_value_type)<ws_char_w_t, T> const& v)
  682. {
  683. return v.get_path();
  684. }
  685. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  686. /** \brief \ref group__concept__shim__string_access__c_str_data for winstl::basic_findfile_sequence_value_type
  687. *
  688. * \ingroup group__concept__shim__string_access
  689. */
  690. template <ss_typename_param_k C, ss_typename_param_k T>
  691. inline C const* c_str_data(winstl_ns_qual(basic_findfile_sequence_value_type)<C, T> const& v)
  692. {
  693. return v.get_path();
  694. }
  695. // c_str_len
  696. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  697. template <ss_typename_param_k T>
  698. inline ws_size_t c_str_len_a(winstl_ns_qual(basic_findfile_sequence_value_type)<ws_char_a_t, T> const& v)
  699. {
  700. return v.length();
  701. }
  702. template <ss_typename_param_k T>
  703. inline ws_size_t c_str_len_w(winstl_ns_qual(basic_findfile_sequence_value_type)<ws_char_w_t, T> const& v)
  704. {
  705. return v.length();
  706. }
  707. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  708. /** \brief \ref group__concept__shim__string_access__c_str_len for winstl::basic_findfile_sequence_value_type
  709. *
  710. * \ingroup group__concept__shim__string_access
  711. */
  712. template <ss_typename_param_k C, ss_typename_param_k T>
  713. inline ws_size_t c_str_len(winstl_ns_qual(basic_findfile_sequence_value_type)<C, T> const& v)
  714. {
  715. return v.length();
  716. }
  717. // c_str_ptr
  718. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  719. template <ss_typename_param_k T>
  720. inline ws_char_a_t const* c_str_ptr_a(winstl_ns_qual(basic_findfile_sequence_value_type)<ws_char_a_t, T> const& v)
  721. {
  722. return v.get_path();
  723. }
  724. template <ss_typename_param_k T>
  725. inline ws_char_w_t const* c_str_ptr_w(winstl_ns_qual(basic_findfile_sequence_value_type)<ws_char_w_t, T> const& v)
  726. {
  727. return v.get_path();
  728. }
  729. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  730. /** \brief \ref group__concept__shim__string_access__c_str_ptr for winstl::basic_findfile_sequence_value_type
  731. *
  732. * \ingroup group__concept__shim__string_access
  733. */
  734. template <ss_typename_param_k C, ss_typename_param_k T>
  735. inline C const* c_str_ptr(winstl_ns_qual(basic_findfile_sequence_value_type)<C, T> const& v)
  736. {
  737. return v.get_path();
  738. }
  739. // c_str_ptr_null
  740. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  741. template <ss_typename_param_k T>
  742. inline ws_char_a_t const* c_str_ptr_null_a(winstl_ns_qual(basic_findfile_sequence_value_type)<ws_char_a_t, T> const& v)
  743. {
  744. return stlsoft_ns_qual(c_str_ptr_null_a(v.get_path()));
  745. }
  746. template <ss_typename_param_k T>
  747. inline ws_char_w_t const* c_str_ptr_null_w(winstl_ns_qual(basic_findfile_sequence_value_type)<ws_char_w_t, T> const& v)
  748. {
  749. return stlsoft_ns_qual(c_str_ptr_null_w(v.get_path()));
  750. }
  751. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  752. /** \brief \ref group__concept__shim__string_access__c_str_ptr_null for winstl::basic_findfile_sequence_value_type
  753. *
  754. * \ingroup group__concept__shim__string_access
  755. */
  756. template <ss_typename_param_k C, ss_typename_param_k T>
  757. inline C const* c_str_ptr_null(winstl_ns_qual(basic_findfile_sequence_value_type)<C, T> const& v)
  758. {
  759. return stlsoft_ns_qual(c_str_ptr_null(v.get_path()));
  760. }
  761. /* /////////////////////////////////////////////////////////////////////////
  762. * Deprecated Shims
  763. */
  764. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  765. template <ss_typename_param_k C, ss_typename_param_k T>
  766. inline ws_bool_t is_empty(basic_findfile_sequence<C, T> const& s)
  767. {
  768. return s.empty();
  769. }
  770. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  771. ////////////////////////////////////////////////////////////////////////////
  772. // Unit-testing
  773. #ifdef STLSOFT_UNITTEST
  774. # include "./unittest/findfile_sequence_unittest_.h"
  775. #endif /* STLSOFT_UNITTEST */
  776. ////////////////////////////////////////////////////////////////////////////
  777. // Implementation
  778. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  779. // basic_findfile_sequence
  780. template <ss_typename_param_k C, ss_typename_param_k T>
  781. inline /* static */ ss_typename_type_ret_k basic_findfile_sequence<C, T>::flags_type basic_findfile_sequence<C, T>::validate_flags_(ss_typename_type_k basic_findfile_sequence<C, T>::flags_type flags)
  782. {
  783. const flags_type validFlags = 0
  784. | includeDots
  785. | directories
  786. | files
  787. | skipReparseDirs
  788. | skipHiddenFiles
  789. | skipHiddenDirs
  790. | relativePath
  791. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  792. | throwOnAccessFailure
  793. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  794. | 0;
  795. WINSTL_MESSAGE_ASSERT("Specification of unrecognised/unsupported flags", flags == (flags & validFlags));
  796. STLSOFT_SUPPRESS_UNUSED(validFlags);
  797. if(0 == (flags & (directories | files)))
  798. {
  799. flags |= (directories | files);
  800. }
  801. return flags;
  802. }
  803. template <ss_typename_param_k C, ss_typename_param_k T>
  804. inline /* static */ ws_bool_t basic_findfile_sequence<C, T>::is_valid() const
  805. {
  806. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  807. if('\0' == m_directory[0])
  808. {
  809. # ifdef STLSOFT_UNITTEST
  810. fprintf(err, "m_directory is empty when exception handling is enabled\n");
  811. # endif /* STLSOFT_UNITTEST */
  812. return false;
  813. }
  814. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  815. // m_directory should either be empty, or should end with a slash
  816. if( '\0' != m_directory[0] &&
  817. !traits_type::has_dir_end(m_directory.c_str()))
  818. {
  819. #ifdef STLSOFT_UNITTEST
  820. fprintf(err, "m_directory is not empty and does not have a trailing path name separator; m_directory=%s\n", m_directory.c_str());
  821. #endif /* STLSOFT_UNITTEST */
  822. return false;
  823. }
  824. if(m_directoryLen != traits_type::str_len(m_directory.c_str()))
  825. {
  826. #ifdef STLSOFT_UNITTEST
  827. fprintf(err, "m_directory is not length indicated by m_directoryLen; m_directory=%s; m_directoryLen=%d\n", m_directory.c_str(), int(m_directoryLen));
  828. #endif /* STLSOFT_UNITTEST */
  829. return false;
  830. }
  831. return true;
  832. }
  833. template <ss_typename_param_k C, ss_typename_param_k T>
  834. inline /* static */ ss_typename_type_ret_k basic_findfile_sequence<C, T>::size_type
  835. basic_findfile_sequence<C, T>::validate_directory_(
  836. char_type const* directory
  837. , file_path_buffer_type_& dir
  838. , flags_type flags
  839. )
  840. {
  841. if( NULL == directory ||
  842. '\0' == *directory)
  843. {
  844. static const char_type s_cwd[] = { '.', '\0' };
  845. directory = &s_cwd[0];
  846. }
  847. size_type directoryLen = traits_type::str_len(directory);
  848. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  849. if(directoryLen > dir.size())
  850. {
  851. # ifndef CO_E_PATHTOOLONG
  852. enum { CO_E_PATHTOOLONG = int(0x80040212L) };
  853. # endif /* !CO_E_PATHTOOLONG */
  854. STLSOFT_THROW_X(windows_exception(static_cast<windows_exception::error_code_type>(CO_E_PATHTOOLONG)));
  855. }
  856. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  857. if(relativePath & flags)
  858. {
  859. WINSTL_ASSERT(directoryLen < dir.size());
  860. traits_type::char_copy(&dir[0], directory, directoryLen + 1);
  861. }
  862. else if(0 == (directoryLen = traits_type::get_full_path_name(directory, dir.size(), &dir[0])))
  863. {
  864. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  865. STLSOFT_THROW_X(windows_exception(::GetLastError()));
  866. #else /* ? STLSOFT_CF_EXCEPTION_SUPPORT */
  867. return validate_directory_(directory, dir, flags | relativePath);
  868. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  869. }
  870. WINSTL_ASSERT(directoryLen == traits_type::str_len(dir.c_str()));
  871. if( 0u != directoryLen &&
  872. !traits_type::has_dir_end(&dir[directoryLen - 1]))
  873. {
  874. traits_type::ensure_dir_end(&dir[directoryLen - 1]);
  875. ++directoryLen;
  876. }
  877. WINSTL_ASSERT(directoryLen == traits_type::str_len(dir.c_str()));
  878. return directoryLen;
  879. }
  880. // Construction
  881. template <ss_typename_param_k C, ss_typename_param_k T>
  882. inline basic_findfile_sequence<C, T>::basic_findfile_sequence(char_type const* pattern, flags_type flags /* = directories | files */)
  883. : m_delim(0)
  884. , m_flags(validate_flags_(flags))
  885. , m_directory()
  886. , m_patterns(1 + traits_type::str_len(pattern))
  887. , m_directoryLen(validate_directory_(NULL, m_directory, m_flags))
  888. {
  889. traits_type::char_copy(&m_patterns[0], pattern, m_patterns.size());
  890. WINSTL_ASSERT(is_valid());
  891. }
  892. template <ss_typename_param_k C, ss_typename_param_k T>
  893. inline basic_findfile_sequence<C, T>::basic_findfile_sequence( char_type const* patterns
  894. , char_type delim
  895. , flags_type flags /* = directories | files */)
  896. : m_delim(delim)
  897. , m_flags(validate_flags_(flags))
  898. , m_directory()
  899. , m_patterns(1 + traits_type::str_len(patterns))
  900. , m_directoryLen(validate_directory_(NULL, m_directory, m_flags))
  901. {
  902. traits_type::char_copy(&m_patterns[0], patterns, m_patterns.size());
  903. WINSTL_ASSERT(is_valid());
  904. }
  905. template <ss_typename_param_k C, ss_typename_param_k T>
  906. inline basic_findfile_sequence<C, T>::basic_findfile_sequence( char_type const* directory
  907. , char_type const* pattern
  908. , flags_type flags /* = directories | files */)
  909. : m_delim(0)
  910. , m_flags(validate_flags_(flags))
  911. , m_directory()
  912. , m_patterns(1 + traits_type::str_len(pattern))
  913. , m_directoryLen(validate_directory_(directory, m_directory, m_flags))
  914. {
  915. traits_type::char_copy(&m_patterns[0], pattern, m_patterns.size());
  916. WINSTL_ASSERT(is_valid());
  917. }
  918. template <ss_typename_param_k C, ss_typename_param_k T>
  919. inline basic_findfile_sequence<C, T>::basic_findfile_sequence( char_type const* directory
  920. , char_type const* patterns
  921. , char_type delim
  922. , flags_type flags /* = directories | files */)
  923. : m_delim(delim)
  924. , m_flags(validate_flags_(flags))
  925. , m_directory()
  926. , m_patterns(1 + traits_type::str_len(patterns))
  927. , m_directoryLen(validate_directory_(directory, m_directory, m_flags))
  928. {
  929. traits_type::char_copy(&m_patterns[0], patterns, m_patterns.size());
  930. WINSTL_ASSERT(is_valid());
  931. }
  932. template <ss_typename_param_k C, ss_typename_param_k T>
  933. inline basic_findfile_sequence<C, T>::~basic_findfile_sequence() stlsoft_throw_0()
  934. {
  935. WINSTL_ASSERT(is_valid());
  936. #ifdef _DEBUG
  937. m_directory[0] = '\0';
  938. m_patterns[0] = '\0';
  939. #endif /* _DEBUG */
  940. }
  941. // Iteration
  942. template <ss_typename_param_k C, ss_typename_param_k T>
  943. inline ss_typename_type_ret_k basic_findfile_sequence<C, T>::const_iterator basic_findfile_sequence<C, T>::begin() const
  944. {
  945. WINSTL_ASSERT(is_valid());
  946. #ifndef STLSOFT_CF_EXCEPTION_SUPPORT
  947. if('\0' == m_directory[0])
  948. {
  949. ::SetLastError(ERROR_INVALID_NAME);
  950. return const_iterator(*this);
  951. }
  952. #endif /* !STLSOFT_CF_EXCEPTION_SUPPORT */
  953. return const_iterator(*this, m_patterns.data(), m_delim, m_flags);
  954. }
  955. template <ss_typename_param_k C, ss_typename_param_k T>
  956. inline ss_typename_type_ret_k basic_findfile_sequence<C, T>::const_iterator basic_findfile_sequence<C, T>::end() const
  957. {
  958. WINSTL_ASSERT(is_valid());
  959. return const_iterator(*this);
  960. }
  961. // Attributes
  962. template <ss_typename_param_k C, ss_typename_param_k T>
  963. ss_typename_type_k basic_findfile_sequence<C, T>::char_type const* basic_findfile_sequence<C, T>::get_directory(size_type* plen /* = NULL */) const
  964. {
  965. WINSTL_ASSERT(is_valid());
  966. // Null Object (variable) pattern
  967. size_type len_;
  968. if(NULL == plen)
  969. {
  970. plen = &len_;
  971. }
  972. *plen = m_directoryLen;
  973. return m_directory.c_str();
  974. }
  975. // State
  976. template <ss_typename_param_k C, ss_typename_param_k T>
  977. inline ws_bool_t basic_findfile_sequence<C, T>::empty() const
  978. {
  979. WINSTL_ASSERT(is_valid());
  980. return begin() == end();
  981. }
  982. template <ss_typename_param_k C, ss_typename_param_k T>
  983. inline /* static */ ss_typename_type_ret_k basic_findfile_sequence<C, T>::size_type
  984. basic_findfile_sequence<C, T>::max_size()
  985. {
  986. return static_cast<size_type>(-1);
  987. }
  988. // basic_findfile_sequence_value_type
  989. template <ss_typename_param_k C, ss_typename_param_k T>
  990. inline basic_findfile_sequence_value_type<C, T>::basic_findfile_sequence_value_type()
  991. {
  992. m_data.dwFileAttributes = 0xFFFFFFFF;
  993. m_data.cFileName[0] = '\0';
  994. m_data.cAlternateFileName[0] = '\0';
  995. m_path[0] = '\0';
  996. m_pathLen = 0;
  997. }
  998. template <ss_typename_param_k C, ss_typename_param_k T>
  999. inline ss_typename_type_ret_k basic_findfile_sequence_value_type<C, T>::class_type& basic_findfile_sequence_value_type<C, T>::operator =(ss_typename_type_k basic_findfile_sequence_value_type<C, T>::class_type const& rhs)
  1000. {
  1001. m_data = rhs.m_data;
  1002. m_path = rhs.m_path;
  1003. m_pathLen = rhs.m_pathLen;
  1004. return *this;
  1005. }
  1006. template <ss_typename_param_k C, ss_typename_param_k T>
  1007. inline ss_typename_type_ret_k basic_findfile_sequence_value_type<C, T>::find_data_type const& basic_findfile_sequence_value_type<C, T>::get_find_data() const
  1008. {
  1009. return m_data;
  1010. }
  1011. #ifdef STLSOFT_OBSOLETE
  1012. template <ss_typename_param_k C, ss_typename_param_k T>
  1013. inline ss_typename_type_ret_k basic_findfile_sequence_value_type<C, T>::find_data_type const& basic_findfile_sequence_value_type<C, T>::GetFindData() const
  1014. {
  1015. return get_find_data();
  1016. }
  1017. #endif /* STLSOFT_OBSOLETE */
  1018. template <ss_typename_param_k C, ss_typename_param_k T>
  1019. inline ss_typename_type_ret_k basic_findfile_sequence_value_type<C, T>::char_type const* basic_findfile_sequence_value_type<C, T>::get_filename() const
  1020. {
  1021. return m_data.cFileName;
  1022. }
  1023. template <ss_typename_param_k C, ss_typename_param_k T>
  1024. inline ss_typename_type_ret_k basic_findfile_sequence_value_type<C, T>::char_type const* basic_findfile_sequence_value_type<C, T>::get_short_filename() const
  1025. {
  1026. return m_data.cAlternateFileName[0] != '\0' ? m_data.cAlternateFileName : m_data.cFileName;
  1027. }
  1028. template <ss_typename_param_k C, ss_typename_param_k T>
  1029. inline ss_typename_type_ret_k basic_findfile_sequence_value_type<C, T>::char_type const* basic_findfile_sequence_value_type<C, T>::get_path() const
  1030. {
  1031. return m_path.c_str();
  1032. }
  1033. template <ss_typename_param_k C, ss_typename_param_k T>
  1034. inline ss_typename_type_ret_k basic_findfile_sequence_value_type<C, T>::char_type const* basic_findfile_sequence_value_type<C, T>::c_str() const
  1035. {
  1036. return get_path();
  1037. }
  1038. template <ss_typename_param_k C, ss_typename_param_k T>
  1039. inline ws_size_t // NOTE: The return type must be ws_size_t, due to a defect in VC++ 7.1
  1040. basic_findfile_sequence_value_type<C, T>::length() const
  1041. {
  1042. WINSTL_ASSERT(traits_type::str_len(this->c_str()) == m_pathLen);
  1043. return m_pathLen;
  1044. }
  1045. template <ss_typename_param_k C, ss_typename_param_k T>
  1046. #if defined(STLSOFT_COMPILER_IS_GCC) || \
  1047. ( defined(STLSOFT_COMPILER_IS_MSVC) && \
  1048. _MSC_VER < 1100)
  1049. inline basic_findfile_sequence_value_type<C, T>::operator C const* () const
  1050. #else /* ? compiler */
  1051. inline basic_findfile_sequence_value_type<C, T>::operator ss_typename_type_k basic_findfile_sequence_value_type<C, T>::char_type const* () const
  1052. #endif /* compiler */
  1053. {
  1054. return get_path();
  1055. }
  1056. template <ss_typename_param_k C, ss_typename_param_k T>
  1057. inline ws_bool_t basic_findfile_sequence_value_type<C, T>::is_directory() const
  1058. {
  1059. return traits_type::is_directory(&m_data);
  1060. }
  1061. template <ss_typename_param_k C, ss_typename_param_k T>
  1062. inline ws_bool_t basic_findfile_sequence_value_type<C, T>::is_file() const
  1063. {
  1064. return traits_type::is_file(&m_data);
  1065. }
  1066. template <ss_typename_param_k C, ss_typename_param_k T>
  1067. inline ws_bool_t basic_findfile_sequence_value_type<C, T>::is_compressed() const
  1068. {
  1069. return 0 != (m_data.dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED);
  1070. }
  1071. #ifdef FILE_ATTRIBUTE_REPARSE_POINT
  1072. template <ss_typename_param_k C, ss_typename_param_k T>
  1073. inline ws_bool_t basic_findfile_sequence_value_type<C, T>::is_reparse_point() const
  1074. {
  1075. return 0 != (m_data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT);
  1076. }
  1077. #endif /* FILE_ATTRIBUTE_REPARSE_POINT */
  1078. template <ss_typename_param_k C, ss_typename_param_k T>
  1079. inline ws_bool_t basic_findfile_sequence_value_type<C, T>::is_read_only() const
  1080. {
  1081. return 0 != (m_data.dwFileAttributes & FILE_ATTRIBUTE_READONLY);
  1082. }
  1083. template <ss_typename_param_k C, ss_typename_param_k T>
  1084. inline ws_bool_t basic_findfile_sequence_value_type<C, T>::is_system() const
  1085. {
  1086. return 0 != (m_data.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM);
  1087. }
  1088. template <ss_typename_param_k C, ss_typename_param_k T>
  1089. inline ws_bool_t basic_findfile_sequence_value_type<C, T>::is_hidden() const
  1090. {
  1091. return 0 != (m_data.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN);
  1092. }
  1093. template <ss_typename_param_k C, ss_typename_param_k T>
  1094. inline ws_bool_t basic_findfile_sequence_value_type<C, T>::equal(char_type const* rhs) const
  1095. {
  1096. return 0 == traits_type::str_compare_no_case(this->get_path(), rhs);
  1097. }
  1098. template <ss_typename_param_k C, ss_typename_param_k T>
  1099. inline ws_bool_t basic_findfile_sequence_value_type<C, T>::equal(basic_findfile_sequence_value_type<C, T> const& rhs) const
  1100. {
  1101. return equal(rhs.get_path());
  1102. }
  1103. // basic_findfile_sequence_const_input_iterator
  1104. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k V>
  1105. inline /* static */ HANDLE basic_findfile_sequence_const_input_iterator<C, T, V>::find_first_file_(
  1106. ss_typename_type_k basic_findfile_sequence_const_input_iterator<C, T, V>::char_type const* searchSpec
  1107. , flags_type flags
  1108. , ss_typename_type_k basic_findfile_sequence_const_input_iterator<C, T, V>::find_data_type* findData
  1109. )
  1110. {
  1111. HANDLE hSrch = INVALID_HANDLE_VALUE;
  1112. // A constant makes Borland weep the tears of unfathomable sadness, so an enum is used instead
  1113. // const DWORD reparsePointConstant = 0x00000400;
  1114. enum
  1115. {
  1116. #ifdef FILE_ATTRIBUTE_REPARSE_POINT
  1117. reparsePointConstant = FILE_ATTRIBUTE_REPARSE_POINT
  1118. #else /* ? FILE_ATTRIBUTE_REPARSE_POINT */
  1119. reparsePointConstant = 0x00000400
  1120. #endif /* FILE_ATTRIBUTE_REPARSE_POINT */
  1121. };
  1122. #if defined(_WIN32_WINNT) && \
  1123. _WIN32_WINNT >= 0x0400
  1124. if( (sequence_type::directories == (flags & (sequence_type::directories | sequence_type::files))) &&
  1125. system_version::winnt() &&
  1126. system_version::major() >= 4)
  1127. {
  1128. hSrch = traits_type::find_first_file_ex(searchSpec, FindExSearchLimitToDirectories, findData);
  1129. }
  1130. else
  1131. #endif /* _WIN32_WINNT >= 0x0400 */
  1132. if(INVALID_HANDLE_VALUE == hSrch)
  1133. {
  1134. hSrch = traits_type::find_first_file(searchSpec, findData);
  1135. }
  1136. if(INVALID_HANDLE_VALUE == hSrch)
  1137. {
  1138. DWORD dw = ::GetLastError();
  1139. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  1140. if(ERROR_ACCESS_DENIED == dw)
  1141. {
  1142. if(flags & sequence_type::throwOnAccessFailure)
  1143. {
  1144. STLSOFT_THROW_X(access_exception(dw));
  1145. }
  1146. }
  1147. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  1148. }
  1149. // Now need to validate against the flags
  1150. for(; INVALID_HANDLE_VALUE != hSrch; )
  1151. {
  1152. if( traits_type::is_file(findData) &&
  1153. ( 0 == (flags & sequence_type::skipHiddenFiles) ||
  1154. 0 == (findData->dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)))
  1155. {
  1156. // A file, and files requested, so break
  1157. if(flags & sequence_type::files)
  1158. {
  1159. break;
  1160. }
  1161. }
  1162. else
  1163. {
  1164. if( 0 == (flags & sequence_type::skipHiddenDirs) ||
  1165. 0 == (findData->dwFileAttributes & FILE_ATTRIBUTE_HIDDEN))
  1166. {
  1167. if(traits_type::is_dots(findData->cFileName))
  1168. {
  1169. if(flags & sequence_type::includeDots)
  1170. {
  1171. // A dots file, and dots are requested
  1172. break;
  1173. }
  1174. }
  1175. else if(flags & sequence_type::directories)
  1176. {
  1177. // A directory, and directories requested
  1178. if( 0 == (flags & sequence_type::skipReparseDirs) ||
  1179. 0 == (findData->dwFileAttributes & reparsePointConstant))
  1180. {
  1181. // Either not requested to skip reparse points, or not a reparse point
  1182. break;
  1183. }
  1184. }
  1185. }
  1186. }
  1187. if(!traits_type::find_next_file(hSrch, findData))
  1188. {
  1189. ::FindClose(hSrch);
  1190. hSrch = INVALID_HANDLE_VALUE;
  1191. break;
  1192. }
  1193. }
  1194. return hSrch;
  1195. }
  1196. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k V>
  1197. inline basic_findfile_sequence_const_input_iterator<C, T, V>::basic_findfile_sequence_const_input_iterator()
  1198. : m_list(NULL)
  1199. , m_handle(NULL)
  1200. , m_subpath()
  1201. , m_subPathLen(0)
  1202. , m_pattern0(NULL)
  1203. , m_pattern1(NULL)
  1204. , m_delim('\0')
  1205. , m_flags(0)
  1206. {
  1207. m_subpath[0] = '\0';
  1208. }
  1209. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k V>
  1210. inline basic_findfile_sequence_const_input_iterator<C, T, V>::basic_findfile_sequence_const_input_iterator(
  1211. sequence_type const& l
  1212. #if 0
  1213. , ss_typename_type_k basic_findfile_sequence_const_input_iterator<C, T, V>::char_type const* rootDir
  1214. #endif /* 0 */
  1215. , ss_typename_type_k basic_findfile_sequence_const_input_iterator<C, T, V>::char_type const* patterns
  1216. , ss_typename_type_k basic_findfile_sequence_const_input_iterator<C, T, V>::char_type delim
  1217. , flags_type flags
  1218. )
  1219. : m_list(&l)
  1220. , m_handle(NULL)
  1221. , m_subpath()
  1222. , m_subPathLen(0)
  1223. , m_pattern0(patterns)
  1224. , m_pattern1(patterns)
  1225. , m_delim(delim)
  1226. , m_flags(flags)
  1227. {
  1228. m_subpath[0] = '\0';
  1229. operator ++();
  1230. }
  1231. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k V>
  1232. inline basic_findfile_sequence_const_input_iterator<C, T, V>::basic_findfile_sequence_const_input_iterator(sequence_type const& l)
  1233. : m_list(&l)
  1234. , m_handle(NULL)
  1235. , m_subpath()
  1236. , m_subPathLen(0)
  1237. , m_pattern0(NULL)
  1238. , m_pattern1(NULL)
  1239. , m_delim('\0')
  1240. , m_flags(0)
  1241. {
  1242. m_subpath[0] = '\0';
  1243. }
  1244. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k V>
  1245. inline basic_findfile_sequence_const_input_iterator<C, T, V>::basic_findfile_sequence_const_input_iterator(class_type const& rhs)
  1246. : m_list(rhs.m_list)
  1247. , m_handle(rhs.m_handle)
  1248. , m_data(rhs.m_data)
  1249. , m_subpath(rhs.m_subpath)
  1250. , m_subPathLen(rhs.m_subPathLen)
  1251. , m_pattern0(rhs.m_pattern0)
  1252. , m_pattern1(rhs.m_pattern1)
  1253. , m_delim(rhs.m_delim)
  1254. , m_flags(rhs.m_flags)
  1255. {
  1256. if(NULL != m_handle)
  1257. {
  1258. m_handle->AddRef();
  1259. }
  1260. }
  1261. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k V>
  1262. #ifndef STLSOFT_COMPILER_IS_WATCOM
  1263. inline ss_typename_type_ret_k basic_findfile_sequence_const_input_iterator<C, T, V>::class_type& basic_findfile_sequence_const_input_iterator<C, T, V>::operator =(ss_typename_param_k basic_findfile_sequence_const_input_iterator<C, T, V>::class_type const& rhs)
  1264. #else /* ? compiler */
  1265. inline basic_findfile_sequence_const_input_iterator<C, T, V> &basic_findfile_sequence_const_input_iterator<C, T, V>::operator =(basic_findfile_sequence_const_input_iterator<C, T, V> const& rhs)
  1266. #endif /* compiler */
  1267. {
  1268. WINSTL_MESSAGE_ASSERT("Assigning iterators from separate sequences", (m_list == NULL || rhs.m_list == NULL || rhs.m_list)); // Should only be comparing iterators from same container
  1269. shared_handle* this_handle = m_handle;
  1270. m_handle = rhs.m_handle;
  1271. m_data = rhs.m_data;
  1272. m_subpath = rhs.m_subpath;
  1273. m_subPathLen = rhs.m_subPathLen;
  1274. m_pattern0 = rhs.m_pattern0;
  1275. m_pattern1 = rhs.m_pattern1;
  1276. m_delim = rhs.m_delim;
  1277. m_flags = rhs.m_flags;
  1278. if(NULL != m_handle)
  1279. {
  1280. m_handle->AddRef();
  1281. }
  1282. if(NULL != this_handle)
  1283. {
  1284. this_handle->Release();
  1285. }
  1286. return *this;
  1287. }
  1288. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k V>
  1289. inline basic_findfile_sequence_const_input_iterator<C, T, V>::~basic_findfile_sequence_const_input_iterator() stlsoft_throw_0()
  1290. {
  1291. if(NULL != m_handle)
  1292. {
  1293. m_handle->Release();
  1294. }
  1295. }
  1296. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k V>
  1297. inline ss_typename_type_ret_k basic_findfile_sequence_const_input_iterator<C, T, V>::class_type& basic_findfile_sequence_const_input_iterator<C, T, V>::operator ++()
  1298. {
  1299. // Pre-condition enforcements
  1300. WINSTL_MESSAGE_ASSERT("Attempting to increment an invalid iterator!", '\0' != *m_pattern0);
  1301. WINSTL_ASSERT(NULL != m_pattern0);
  1302. WINSTL_ASSERT(NULL != m_pattern1);
  1303. enum
  1304. {
  1305. #ifdef FILE_ATTRIBUTE_REPARSE_POINT
  1306. reparsePointConstant = FILE_ATTRIBUTE_REPARSE_POINT
  1307. #else /* ? FILE_ATTRIBUTE_REPARSE_POINT */
  1308. reparsePointConstant = 0x00000400
  1309. #endif /* FILE_ATTRIBUTE_REPARSE_POINT */
  1310. };
  1311. STLSOFT_STATIC_ASSERT(reparsePointConstant); // Suppress silly Borland's warnings
  1312. for(; '\0' != *m_pattern0 || '\0' != *m_pattern1;)
  1313. {
  1314. if(NULL == m_handle)
  1315. {
  1316. // Walk through the patterns
  1317. while(stlsoft_ns_qual(find_next_token)(m_pattern0, m_pattern1, m_delim))
  1318. {
  1319. WINSTL_ASSERT(m_pattern0 <= m_pattern1);
  1320. if(m_pattern1 != m_pattern0) // Will return m_pattern0 == m_pattern1 for empty tokens
  1321. {
  1322. // We now have a non-empty pattern, so we need to concatenate
  1323. // it with the directory to form a search-spec for
  1324. // FindFirstFile()
  1325. //
  1326. // From this path we must also determine the sub-path for any items retrieved from
  1327. // this search, since WIN32_FIND_DATA will contain only the file-name. Since the
  1328. // sequence is tolerant of both slashes and backslashes, we need to find the last
  1329. // of each and take the end-most.
  1330. file_path_buffer_type_ search; // Buffer in which to prepare the search-spec for FindFirstFile()
  1331. size_type cch; // Used to make the strrchr operations faster
  1332. if(traits_type::is_path_rooted(m_pattern0))
  1333. {
  1334. search[0] = '\0';
  1335. cch = 0;
  1336. }
  1337. else
  1338. {
  1339. char_type const* directory = m_list->get_directory(&cch);
  1340. WINSTL_ASSERT(NULL != directory);
  1341. WINSTL_ASSERT(0 != cch);
  1342. WINSTL_ASSERT(cch <= search.size());
  1343. WINSTL_ASSERT(traits_type::has_dir_end(directory));
  1344. traits_type::char_copy(&search[0], directory, cch + 1);
  1345. }
  1346. size_type n2 = static_cast<size_type>(m_pattern1 - m_pattern0);
  1347. traits_type::char_copy(&search[0] + cch, m_pattern0, n2);
  1348. search[cch + n2] = '\0';
  1349. // Note: At this point, cch may be 1 under, because ensure_dir_end() may have added
  1350. // a character that we've not counted. But that's ok, because we don't use it as an
  1351. // exact value, just a minimum value
  1352. char_type const* slash = traits_type::str_rchr(&search[0] + cch, '/');
  1353. char_type const* bslash = traits_type::str_rchr(&search[0] + cch, '\\');
  1354. WINSTL_ASSERT(!traits_type::is_path_rooted(m_pattern0) || ((NULL != slash) || (NULL != bslash)));
  1355. if( NULL != slash &&
  1356. slash >= m_pattern1)
  1357. {
  1358. slash = NULL;
  1359. }
  1360. if( NULL != bslash &&
  1361. bslash >= m_pattern1)
  1362. {
  1363. bslash = NULL;
  1364. }
  1365. if( NULL != slash ||
  1366. NULL != bslash)
  1367. {
  1368. if(NULL == slash)
  1369. {
  1370. slash = bslash;
  1371. }
  1372. else if(NULL != bslash &&
  1373. slash < bslash)
  1374. {
  1375. slash = bslash;
  1376. }
  1377. const size_type n = static_cast<size_type>(slash - &search[0]);
  1378. traits_type::char_copy(&m_subpath[0], &search[0], n);
  1379. m_subPathLen = n;
  1380. m_subpath[n] = '\0';
  1381. }
  1382. HANDLE hSrch = find_first_file_(search.c_str(), m_flags, &m_data);
  1383. if(INVALID_HANDLE_VALUE != hSrch)
  1384. {
  1385. #if defined(STLSOFT_COMPILER_IS_MSVC) && \
  1386. _MSC_VER < 1200
  1387. stlsoft_ns_qual(scoped_handle)<HANDLE> cleanup(hSrch, (void (STLSOFT_STDCALL *)(HANDLE))&::FindClose, INVALID_HANDLE_VALUE);
  1388. #else /* ? compiler */
  1389. stlsoft_ns_qual(scoped_handle)<HANDLE> cleanup(hSrch, ::FindClose, INVALID_HANDLE_VALUE);
  1390. #endif /* compiler */
  1391. // Special case, where the pattern specified is either "." or ".."
  1392. // the API will return the directory name, but we want to keep the
  1393. // dot name.
  1394. if( '.' == m_pattern0[0] &&
  1395. ( m_pattern1 == m_pattern0 + 1 ||
  1396. ( '.' == m_pattern0[1] &&
  1397. m_pattern1 == m_pattern0 + 2)))
  1398. {
  1399. const size_type n = static_cast<size_type>(m_pattern1 - m_pattern0);
  1400. traits_type::char_copy(&m_data.cFileName[0], m_pattern0, n);
  1401. m_data.cFileName[n] = '\0';
  1402. }
  1403. m_handle = new shared_handle(hSrch);
  1404. if(NULL != m_handle)
  1405. {
  1406. cleanup.detach();
  1407. }
  1408. return *this;
  1409. }
  1410. else
  1411. {
  1412. #ifdef _DEBUG
  1413. DWORD dwErr = ::GetLastError();
  1414. STLSOFT_SUPPRESS_UNUSED(dwErr);
  1415. #endif /* _DEBUG */
  1416. }
  1417. }
  1418. }
  1419. }
  1420. if(NULL != m_handle)
  1421. {
  1422. for(; INVALID_HANDLE_VALUE != m_handle->hSrch; )
  1423. {
  1424. if(!traits_type::find_next_file(m_handle->hSrch, &m_data))
  1425. {
  1426. m_handle->Release();
  1427. m_handle = NULL;
  1428. break;
  1429. }
  1430. else
  1431. {
  1432. if( traits_type::is_file(&m_data) &&
  1433. ( 0 == (m_flags & sequence_type::skipHiddenFiles) ||
  1434. 0 == (m_data.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)))
  1435. {
  1436. // A file, and files requested, so break
  1437. if(m_flags & sequence_type::files)
  1438. {
  1439. return *this;
  1440. }
  1441. }
  1442. else
  1443. {
  1444. if( 0 == (m_flags & sequence_type::skipHiddenDirs) ||
  1445. 0 == (m_data.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN))
  1446. {
  1447. if(traits_type::is_dots(m_data.cFileName))
  1448. {
  1449. if(m_flags & sequence_type::includeDots)
  1450. {
  1451. // A dots file, and dots are requested
  1452. return *this;
  1453. }
  1454. }
  1455. else if(m_flags & sequence_type::directories)
  1456. {
  1457. // A directory, and directories requested
  1458. if( 0 == (m_flags & sequence_type::skipReparseDirs) ||
  1459. 0 == (m_data.dwFileAttributes & reparsePointConstant))
  1460. {
  1461. // Either not requested to skip reparse points, or not a reparse point
  1462. return *this;
  1463. }
  1464. }
  1465. }
  1466. }
  1467. }
  1468. }
  1469. }
  1470. }
  1471. return *this;
  1472. }
  1473. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k V>
  1474. inline ss_typename_type_ret_k basic_findfile_sequence_const_input_iterator<C, T, V>::class_type basic_findfile_sequence_const_input_iterator<C, T, V>::operator ++(int)
  1475. {
  1476. class_type ret(*this);
  1477. operator ++();
  1478. return ret;
  1479. }
  1480. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k V>
  1481. inline const ss_typename_type_k basic_findfile_sequence_const_input_iterator<C, T, V>::value_type basic_findfile_sequence_const_input_iterator<C, T, V>::operator *() const
  1482. {
  1483. WINSTL_MESSAGE_ASSERT("Dereferencing end()-valued iterator", NULL != m_handle);
  1484. WINSTL_ASSERT(m_subPathLen == traits_type::str_len(m_subpath.c_str()));
  1485. if(0 == m_subPathLen)
  1486. {
  1487. return value_type(m_data, m_list->get_directory(), traits_type::str_len(m_list->get_directory()));
  1488. }
  1489. else
  1490. {
  1491. return value_type(m_data, m_subpath.c_str(), m_subPathLen);
  1492. }
  1493. }
  1494. template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k V>
  1495. inline ws_bool_t basic_findfile_sequence_const_input_iterator<C, T, V>::equal(basic_findfile_sequence_const_input_iterator<C, T, V> const& rhs) const
  1496. {
  1497. // Should only be comparing iterators from same container
  1498. WINSTL_MESSAGE_ASSERT("Comparing iterators from separate sequences", (m_list == rhs.m_list || NULL == m_list || NULL == rhs.m_list));
  1499. return m_handle == rhs.m_handle;
  1500. }
  1501. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  1502. /* ////////////////////////////////////////////////////////////////////// */
  1503. #ifndef _WINSTL_NO_NAMESPACE
  1504. # if defined(_STLSOFT_NO_NAMESPACE) || \
  1505. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  1506. } // namespace winstl
  1507. # else
  1508. } // namespace winstl_project
  1509. } // namespace stlsoft
  1510. # endif /* _STLSOFT_NO_NAMESPACE */
  1511. #endif /* !_WINSTL_NO_NAMESPACE */
  1512. /* /////////////////////////////////////////////////////////////////////////
  1513. * Namespace
  1514. *
  1515. * The string access shims exist either in the stlsoft namespace, or in the
  1516. * global namespace. This is required by the lookup rules.
  1517. *
  1518. */
  1519. #ifndef _WINSTL_NO_NAMESPACE
  1520. # if !defined(_STLSOFT_NO_NAMESPACE) && \
  1521. !defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  1522. namespace stlsoft
  1523. {
  1524. # else /* ? _STLSOFT_NO_NAMESPACE */
  1525. /* There is no stlsoft namespace, so must define in the global namespace */
  1526. # endif /* !_STLSOFT_NO_NAMESPACE */
  1527. using ::winstl::c_str_len;
  1528. using ::winstl::c_str_len_a;
  1529. using ::winstl::c_str_len_w;
  1530. using ::winstl::c_str_data;
  1531. using ::winstl::c_str_data_a;
  1532. using ::winstl::c_str_data_w;
  1533. using ::winstl::c_str_ptr;
  1534. using ::winstl::c_str_ptr_a;
  1535. using ::winstl::c_str_ptr_w;
  1536. using ::winstl::c_str_ptr_null;
  1537. using ::winstl::c_str_ptr_null_a;
  1538. using ::winstl::c_str_ptr_null_w;
  1539. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  1540. using ::winstl::is_empty;
  1541. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  1542. # if !defined(_STLSOFT_NO_NAMESPACE) && \
  1543. !defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  1544. } // namespace stlsoft
  1545. # else /* ? _STLSOFT_NO_NAMESPACE */
  1546. /* There is no stlsoft namespace, so must define in the global namespace */
  1547. # endif /* !_STLSOFT_NO_NAMESPACE */
  1548. #endif /* !_WINSTL_NO_NAMESPACE */
  1549. /* ////////////////////////////////////////////////////////////////////// */
  1550. #endif /* WINSTL_INCL_WINSTL_FILESYSTEM_HPP_FINDFILE_SEQUENCE */
  1551. /* ///////////////////////////// end of file //////////////////////////// */