From 1885818461adfd20e47f03bc052c2adee4dda48b Mon Sep 17 00:00:00 2001
From: Beman Dawes Header convenience.hpp
provides convenience functions that combine lower-level functions in useful
ways. The entire contents of the header is in namespace boost::filesystem.
+
boost/filesystem/convenience.hppContents
+
+
+
+
+
+basic_recursive_directory_iteratorIntroduction
+
Contents
+create_directories
+create_directories
@@ -50,7 +52,7 @@ establishment of the postcondition.
@@ -75,7 +77,7 @@ discussed the ADS issue.-
@@ -93,7 +95,7 @@ ending at the last dot (the dot is not included). Otherwise, returns-
@@ -118,10 +120,85 @@ is to drop the precondition. +-basic_recursive_directory_iterator
+ +template< class Path > +class basic_recursive_directory_iterator + : public boost::iterator_facade< + basic_recursive_directory_iterator<Path>, Path, + boost::single_pass_traversal_tag > +{ +public: + typedef Path path_type; + + basic_recursive_directory_iterator(){} // creates the "end" iterator + + explicit basic_recursive_directory_iterator( const Path & dir_path ); + + int level() const; + + void pop(); + void no_push(); + + status_flags status( system_error_type * ec=0 ) const; + status_flags status( const symlink_t &, system_error_type * ec=0 ) const; + + bool exists() const; + bool is_directory() const; + bool is_file() const; + bool is_other() const; + bool is_symlink() const; + +private: + int m_level; // for exposition only +}; + +typedef basic_recursive_directory_iterator<path> recursive_directory_iterator; +typedef basic_recursive_directory_iterator<wpath> wrecursive_directory_iterator;+ +The behavior of basic_recursive_directory_iterator member functions is +the same as basic_directory_iterator +functions of the same name, except:
++
+- When an iterator is constructed,
+m_levelis set to 0;- When an iterator
+itfor whichit.is_directory()+ is true is incremented,++m_level, the directory is visited, and + its contents recursively iterated over, unlessno_push()was + called prior to incrementing.- When an iterator reaches the end of the directory currently being iterated + over, or when
+pop()is called,--m_level, and + iteration continues with the parent directory, until thedir_path+ directory is reached.- +
level()returnsm_level.- +
level(),pop(), andno_push()all + have the precondition that the iterator not be the end iterator.The issue of duplicates (caused by symlinks and hard links) should be +consider when using basic_recursive_directory_iterator. + Both duplicate detecting and non-detecting are needed, depending on the +application. Non-detecting is far + more efficient, but some apps will require duplicate detection.
+When duplicate prevention is required, consider simply not following symlinks. +Use the
+no_push()function to avoid recursion into directories +reached by symlinks. If a more comprehensive solution is required, consider +these factors:+
+ +- Names are useless for duplicate detection because of links and other file + system alias mechanisms such as drive mapping, mounts.
+- inodes are unstable if handles are not held open, and it isn't + feasible to hold unlimited number of handles open.
+- Size, dates, etc., are subject to race conditions.
+- No one method is likely to serve all needs, but a starting point might + be to keep a hash-table keyed on a size/date based signature, then do + equivalent() on all equal keys.
+Contributed by Beman Dawes
Revised -14 May, 2005
-© Copyright Vladimir Prus, 2003
+12 July, 2005 +© Copyright Beman Dawes, 2005
+© Copyright Vladimir Prus, 2003Use, modification, and distribution are subject to the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at diff --git a/doc/do-list.htm b/doc/do-list.htm index b84d09a..9df3fbd 100644 --- a/doc/do-list.htm +++ b/doc/do-list.htm @@ -9,54 +9,13 @@ Do-list
Defer until after mini-review
- Should operations.cpp assert or BOOST_ASSERT on more preconditions?
-- Look into the basic_directory_iterator friend problem in more detail.
- Apply PJP's Wide/Narrow conversion proposal to traits, once he stabilizes it.
-- Filtered directory iterator, glob syntax -> regex syntax converter. See +
- Glob syntax -> regex syntax converter. See Rich Johnson's lists.boost.org/boost-users/2004/01/5770.php, and John Maddock's lists.boost.org/boost-users/2004/01/5770.php
-- Recursive directory iterator. See thread beginning with Thorsten Ottosen's - lists.boost.org/boost/2004/03/2842.php
--
-- Depth first vs breadth first - Unspecified. Most imps will use depth - first as more efficient.
-- Issue of duplicates (caused by symlinks and hard links) is critical. - Both duplicate detecting and non-detecting are needed; non-detecting is far - more efficient, but some apps will require duplicate detection.
--
-- Names are useless for dup detection because of links, other file - system alias mechanisms such as drive mapping, mounts.
-- inodes are unstable if handles are not held open, and it isn't - feasible to hold unlimited number of handles open.
-- Size, dates, etc., are subject to race conditions.
-- No one method is likely to serve all needs, but a starting point might - be to keep a hash-table keyed on a size/dates based signature, then do - equivalent() on all equal keys.
-- Note Terence Wilson's efficiency concerns re: filtering; see - - //lists.boost.org/MailArchives/boost/msg79583.php
-- Some or all of the above concerns may be easier to meet if - directory_iterator (or a wrapper) called a function object:
-
-- Argument is const char * name or const path & or ? (is there a significant - efficiency difference?)
-- Return is a code:
--
-- Continue; that is, return iterator pointing to this entry.
-- Skip; ignore this entry completely.
-- Skip returning this entry, but do iterate into it if directory - (assuming recursive iteration).
-- Do return this entry, but don't iterate into if if a directory (don't - recurse).
-- Skip and stop; return end iterator.
-- Do return this entry, but force end iterator on next increment.
-- Add a path::swap member function guaranteed not to throw? (Geurt Vos).
- Add an operations function based on statvfs/GetDiskFreeSpaceEx? (Steve Hartmann/Thomas Matelich)
-- Add an is_other() function?
- Add constant basic_path overloads for constructors, operator=, operator/, operator/. (Adrian Martin)
- const path &
diff --git a/doc/i18n.html b/doc/i18n.html index 37f4282..c55d0d4 100644 --- a/doc/i18n.html +++ b/doc/i18n.html @@ -35,7 +35,10 @@ include:Preservation of existing user code whenever possible. -
More efficient operations when iterating over directories. +More efficient operations when iterating over directories. +
+A recursive + directory iterator is now provided. Rationale for some of the changes is also provided.
Internationalization
@@ -107,13 +110,17 @@ without any possibility of an exception being thrown. The status() function was added to meet this need. It also proved clearer to specify the semantics of predicate functions in terms of status(). -is_file()
+is_file()
About the same time, Jeff Garland suggested that an is_file() predicate would compliment is_directory(). In working on the analysis below, it became obvious that the expectations for is_file() were different from the expectations for !is_directory(), so is_file() was added.
+is_other()
+On some operating systems, it is possible to have a directory entry which is +not for either a directory or a file. The is_other() +function identifies such cases.
Should predicates throw on errors?
Some conditions reported by operating systems as errors (see footnote) clearly simply indicate that the predicate is diff --git a/doc/operations.htm b/doc/operations.htm index 1f37186..b95e3be 100644 --- a/doc/operations.htm +++ b/doc/operations.htm @@ -17,7 +17,8 @@ Header synopsis
{ namespace filesystem { - template<class Path> class basic_directory_iterator - : public boost::iterator_facade< - basic_directory_iterator<Path>, - Path, boost::single_pass_traversal_tag > - { - public: - basic_directory_iterator(){} // creates the "end" iterator - explicit basic_directory_iterator( const Path & directory_path ); - }; - - typedef basic_directory_iterator<path> directory_iterator; - typedef basic_directory_iterator<wpath> wdirectory_iterator; - typedef bitmask-type status_flags; // see C++ std 17.3.2.1.2 [lib.bitmask.types] static const status_flags error_flag; @@ -87,51 +75,51 @@ header. struct symlink_t{}; extern symlink_t symlink; - template<class Path> status_flags status( const Path & ph, system_error_type * ec = 0 ); - template<class DirItr> status_flags status( const DirItr & it, system_error_type * ec = 0 ); - template<class Path> status_flags status( const Path & ph, const symlink_t &, system_error_type * ec = 0 ); - template<class DirItr> status_flags status( const DirItr & it, const symlink_t &, system_error_type * ec = 0 ); + template<class Path> class basic_directory_iterator + : public boost::iterator_facade< + basic_directory_iterator<Path>, + Path, boost::single_pass_traversal_tag > + { + public: + typedef Path path_type; - template<class Path> bool exists( const Path & ph ); - template<class DirItr> bool exists( const DirItr & ph ); + basic_directory_iterator(); // creates the "end" iterator + explicit basic_directory_iterator( const Path & directory_path ); - template<class Path> bool is_directory( const
Class basic_directory_iterator
Constructors
-Operations functions
+ Other member functions
+Operations non-member functions
"Do-the-right-thing" rule
status
exists
@@ -62,19 +63,6 @@ header.Path& ph ); - template<class DirItr> bool is_directory( const DirItr & ph ); + status_flags status( system_error_type * ec=0 ) const; + status_flags status( const symlink_t &, system_error_type * ec=0 ) const; + bool exists() const; + bool is_directory() const; + bool is_file() const; + bool is_other() const; + bool is_symlink() const; + }; - template<class Path> bool is_file( constPath& ph ); - template<class DirItr> bool is_file( const DirItr & ph ); + typedef basic_directory_iterator<path> directory_iterator; + typedef basic_directory_iterator<wpath> wdirectory_iterator; - template<class Path> bool is_symlink( constPath& ph ); - template<class DirItr> bool is_symlink( const DirItr & ph ); - - template<class Path> bool is_empty( constPath& ph ); + template<class Path> status_flags status( const Path & ph, system_error_type * ec = 0 ); + template<class Path> status_flags status( const Path & ph, const symlink_t &, system_error_type * ec = 0 ); + template<class Path> bool exists( const Path & ph ); + template<class Path> bool is_directory( constPath& ph ); + template<class Path> bool is_file( constPath& ph ); + template<class Path> bool is_other( constPath& ph ); + template<class Path> bool is_symlink( constPath& ph ); + template<class Path> bool is_empty( constPath& ph ); template<class Path> bool equivalent( constPath& ph1, constPath& ph2 ); - template<class Path> boost::intmax_t file_size( constPath& ph ); - template<class Path> std::time_t last_write_time( constPath& ph ); - template<class Path> void last_write_time( constPath& ph, std::time_t new_time ); - template<class Path> bool create_directory( constPath& directory_ph ); - template<class Path> void create_hard_link( const Path & existing_file_ph, const Path & new_file_ph ); - template<class Path> bool remove( constPath& ph ); - template<class Path> unsigned long remove_all( constPath& ph ); - template<class Path> void rename( constPath& from_path, constPath& to_path ); - template<class Path> void copy_file( constPath& source_file, constPath& target_file ); - template<class Path>Pathcomplete( constPath& ph, constPath& base = initial_path<Path>() ); - template<class Path>Pathsystem_complete( constPath& ph ); - template<class Path> const Path & initial_path(); - template<class Path>Pathcurrent_path(); } // namespace filesystem @@ -179,10 +167,10 @@ directory entry.Performance note: Implementations are permitted to cache a copy of status information for a directory entry within -an iterator. This attribute information can later be used by -status() and other query functions taking iterator arguments, resulting in 3 -to 6 times faster operation than for query functions taking Path arguments. However, -cached attributes are not updated when the contents of the external file system +a directory iterator. This attribute information can later be used by iterator +member query functions, resulting in 3 +to 6 times faster operation than for the non-member query functions. Note, however, +that attributes cached in iterators are not updated when the contents of the external file system changes, so the iterator form of query functions should not be used if stale attributes might pose a problem.
@@ -206,10 +194,18 @@ empty(directory_ph), the past-the-end value. directory_iterator(current_path<path>()) rather thandirectory_iterator("").
These member functions have the same behavior as the non-member operations +functions of the same name, except that they may rely on cached status +information. See performance note.
+ +All have a precondition that the iterator not be the end iterator.
+ +-The non-member functions provide common operations on files and directories. +The operations non-member functions provide common operations on files and directories. They follow traditional practice of the C, and C++ standard libraries, except that they:
@@ -268,9 +264,7 @@ exposition, only the templated version of each non-member function is shown.template<class Path> status_flags status( const Path & ph, system_error_type * ec = 0 ); -template<class DirItr> status_flags status( const DirItr & it, system_error_type * ec = 0 ); -template<class Path> status_flags status( const Path & ph, const symlink_t &, system_error_type * ec = 0 ); -template<class DirItr> status_flags status( const DirItr & it, const symlink_t &, system_error_type * ec = 0 );+template<class Path> status_flags status( const Path & ph, const symlink_t &, system_error_type * ec = 0 );Effects:
- If
ph.empty()orit->empty():
@@ -357,31 +351,28 @@ will be portable to systems like POSIX, where symbolic links may be present.exists
--
template<class Path> bool exists( const Path & ph );
-template<class DirItr> bool exists( const DirItr & ph );See performance note for subtle - differences between behavior of Path and DirItr template signatures.
+
template<class Path> bool exists( const Path & ph );Throws: If
status(ph) == error_flag.Returns:
status(ph) != not_found_flagis_directory
--
template<class Path> bool is_directory( const Path & ph );
-template<class DirItr> bool is_directory( const DirItr & ph );See performance note for subtle - differences between behavior of Path and DirItr template signatures.
+
template<class Path> bool is_directory( const Path & ph );Throws: If
status(ph) == error_flag.Returns:
(status(ph) & directory_flag) != 0is_file
-+-
template<class Path> bool is_file( const Path & ph );
-template<class DirItr> bool is_file( const DirItr & ph );See performance note for subtle - differences between behavior of Path and DirItr template signatures.
+
template<class Path> bool is_file( const Path & ph );Throws: If
status(ph) == error_flag.Returns:
(status(ph) & file_flag) != 0is_other
+++
template<class Path> bool is_other( const Path & ph );Throws: If
+status(ph) == error_flag.Returns:
+(status(ph) & other_flag) != 0is_symlink
template<class Path> bool is_symlink( const Path & ph );
@@ -447,7 +438,6 @@ function which iterates over a directory returning a count.last_write_time
-
template<class Path> std::time_t last_write_time( const Path & ph );Warning: The times associated with files are subject to many vicissitudes. Each type of file system differs slightly in the details and resolution of how times are recorded. The resolution is as low as one hour on @@ -462,9 +452,7 @@ operating system. If the time cannot be determined, returns (std::time_t)(-1).
To convert the returned value to UTC or local time, use
std::gmtime()orstd::localtime()respectively.Throws: if
-!exists(ph)-
template<class Path> void last_write_time( const Path & ph, std::time_t new_time );-Effects: Asks the operating system to set the last write time to
new_time, or to the current time ifnew_time==std::time_t().Throws: if
@@ -472,7 +460,6 @@ new_time, or to the current time if!exists(ph)new_time==std::time_t(). as a postcondition because the times may differ somewhat on some operating systems.create_directory
@@ -781,7 +768,7 @@ by a prior program run by the command processor.
template<class Path> bool create_directory( const Path & directory_ph );
Revised -20 June, 2005
+12 July, 2005© Copyright Beman Dawes, 2002