From bb0fe7585c42d091784645b3ee3a76f34b62cfd5 Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Thu, 12 Jul 2012 13:53:17 +0000 Subject: [PATCH] Add BOOST_FOREACH support. Correct C++11 range-based for statement enabler signatures. Improve test coverage. Clears feature requests #5896 and #6521. [SVN r79451] --- doc/reference.html | 47 +++++++++++------ doc/release_history.html | 12 +++-- doc/src/build.bat | 3 ++ doc/src/hoist.bat | 5 ++ doc/src/source.html | 47 +++++++++++------ include/boost/filesystem/operations.hpp | 67 ++++++++++++++++++++++--- test/Jamfile.v2 | 2 +- test/operations_unit_test.cpp | 31 ++++++++++-- 8 files changed, 167 insertions(+), 47 deletions(-) create mode 100644 doc/src/hoist.bat diff --git a/doc/reference.html b/doc/reference.html index 57d6604..c3b9e36 100644 --- a/doc/reference.html +++ b/doc/reference.html @@ -134,7 +134,12 @@ del { background-color:#FFA0A0 } Class directory_iterator
    directory_iterator members
 directory_iterator + non-member functions
Class recursive_directory_iterator
+   + recursive_directory_iterator
+        non-member functions
Operational functions
     absolute
@@ -152,11 +157,11 @@ del { background-color:#FFA0A0 }      equivalent
     file_size
     hard_link_count
-      initial_path
-     is_directory
-     is_empty
+      initial_path -      is_other
+      is_directory
+     is_empty
+     is_other
     is_regular_file
     is_symlink
     last_write_time
@@ -402,14 +407,26 @@ void swap(path& lhs, path& rhs); class directory_iterator; - inline directory_iterator& begin(directory_iterator& iter); - inline directory_iterator end(const directory_iterator&); + // enable c++11 range-based for statements + const directory_iterator& begin(const directory_iterator& iter); + directory_iterator end(const directory_iterator&); + + // enable BOOST_FOREACH + directory_iterator& range_begin(directory_iterator& iter); + directory_iterator range_begin(const directory_iterator& iter); + directory_iterator range_end(const directory_iterator&); class recursive_directory_iterator; - inline recursive_directory_iterator& begin(recursive_directory_iterator& iter); - inline recursive_directory_iterator end(const recursive_directory_iterator&); + // enable c++11 range-based for statements + const recursive_directory_iterator& begin(const recursive_directory_iterator& iter); + recursive_directory_iterator end(const recursive_directory_iterator&); +    // enable BOOST_FOREACH +    recursive_directory_iterator& range_begin(recursive_directory_iterator& iter); +    recursive_directory_iterator range_begin(const recursive_directory_iterator& iter); +    recursive_directory_iterator range_end(const recursive_directory_iterator&); +  enum file_type { status_error, file_not_found, regular_file, directory_file, @@ -2045,12 +2062,12 @@ directory_iterator& increment(system::error_code& ec);

Throws: As specified in Error reporting.

-

directory_iterator non-member functions

-
inline directory_iterator& begin(directory_iterator& iter);
+

directory_iterator non-member functions

+
const directory_iterator& begin(const directory_iterator& iter);

Returns: iter.

-
inline directory_iterator end(const directory_iterator&);
+
directory_iterator end(const directory_iterator&);

Returns: directory_iterator().

@@ -2191,14 +2208,14 @@ is decremented and iteration of the parent directory resumes.

[Note: no_push() is used to prevent unwanted recursion into a directory. --end note]

-

recursive_directory_iterator non-member functions

-
inline recursive_directory_iterator& begin(recursive_directory_iterator& iter);
+

recursive_directory_iterator non-member functions

+
const recursive_directory_iterator& begin(const recursive_directory_iterator& iter);

Returns: iter.

-
inline recursive_directory_iterator end(const recursive_directory_iterator&);
+
recursive_directory_iterator end(const recursive_directory_iterator&);
-

Returns: recursive_directory_iterator().

+

Returns: recursive_directory_iterator().

Operational functions

Operational functions query or modify files, including directories, in external diff --git a/doc/release_history.html b/doc/release_history.html index 88d6803..0b6d5f8 100644 --- a/doc/release_history.html +++ b/doc/release_history.html @@ -39,8 +39,14 @@

1.51.0

  • Add begin() and end() non-member functions for directory_iterator and - recursive_directory_iterator so that C++11 range-based for statements now - work.
  • + recursive_directory_iterator so that C++11 range-based for statements work. + Suggested by feature requests + #5896 and + #6521, using the + #5896 approach. +
  • Add range_begin() and range_end() non-member functions for directory_iterator and + recursive_directory_iterator so that + BOOST_FOREACH works.

1.50.0

@@ -170,7 +176,7 @@

Revised -10 July, 2012

+12 July, 2012

© Copyright Beman Dawes, 2011

Use, modification, and distribution are subject to the Boost Software License, Version 1.0. See diff --git a/doc/src/build.bat b/doc/src/build.bat index b7615d0..95b7f40 100644 --- a/doc/src/build.bat +++ b/doc/src/build.bat @@ -1,5 +1,8 @@ @echo off +rem Copyright Beman Dawes 2012 +rem Distributed under the Boost Software License, Version 1.0. del tr2.html 2>nul mmp TARGET=TR2 source.html tr2.html del reference.html 2>nul mmp TARGET=BOOST source.html reference.html +echo run "hoist" to hoist reference.html to doc directory diff --git a/doc/src/hoist.bat b/doc/src/hoist.bat new file mode 100644 index 0000000..2d84c16 --- /dev/null +++ b/doc/src/hoist.bat @@ -0,0 +1,5 @@ +@echo off +rem Copyright Beman Dawes 2012 +rem Distributed under the Boost Software License, Version 1.0. +copy /y reference.html .. +echo reference.html copied to .. diff --git a/doc/src/source.html b/doc/src/source.html index e4d58f9..a629639 100644 --- a/doc/src/source.html +++ b/doc/src/source.html @@ -103,7 +103,12 @@ $endif Class directory_iterator
    directory_iterator members
 directory_iterator + non-member functions
Class recursive_directory_iterator
+   + recursive_directory_iterator
+        non-member functions
Operational functions
     absolute
@@ -121,11 +126,11 @@ $endif      equivalent
     file_size
     hard_link_count
-      initial_path
-     is_directory
-     is_empty
+      initial_path
-      is_other
+      is_directory
+     is_empty
+     is_other
     is_regular_file
     is_symlink
     last_write_time
@@ -364,14 +369,26 @@ $endif class directory_iterator; - inline directory_iterator& begin(directory_iterator& iter); - inline directory_iterator end(const directory_iterator&); + // enable c++11 range-based for statements + const directory_iterator& begin(const directory_iterator& iter); + directory_iterator end(const directory_iterator&); + + // enable BOOST_FOREACH + directory_iterator& range_begin(directory_iterator& iter); + directory_iterator range_begin(const directory_iterator& iter); + directory_iterator range_end(const directory_iterator&); class recursive_directory_iterator; - inline recursive_directory_iterator& begin(recursive_directory_iterator& iter); - inline recursive_directory_iterator end(const recursive_directory_iterator&); + // enable c++11 range-based for statements + const recursive_directory_iterator& begin(const recursive_directory_iterator& iter); + recursive_directory_iterator end(const recursive_directory_iterator&); +    // enable BOOST_FOREACH +    recursive_directory_iterator& range_begin(recursive_directory_iterator& iter); +    recursive_directory_iterator range_begin(const recursive_directory_iterator& iter); +    recursive_directory_iterator range_end(const recursive_directory_iterator&); +  enum file_type { status_error, file_not_found, regular_file, directory_file, @@ -1989,12 +2006,12 @@ directory_iterator& increment(system::error_code& ec);

Throws: As specified in Error reporting.

-

directory_iterator non-member functions

-
inline directory_iterator& begin(directory_iterator& iter);
+

directory_iterator non-member functions

+
const directory_iterator& begin(const directory_iterator& iter);

Returns: iter.

-
inline directory_iterator end(const directory_iterator&);
+
directory_iterator end(const directory_iterator&);

Returns: directory_iterator().

@@ -2131,14 +2148,14 @@ is decremented and iteration of the parent directory resumes.

[Note: no_push() is used to prevent unwanted recursion into a directory. --end note]

-

recursive_directory_iterator non-member functions

-
inline recursive_directory_iterator& begin(recursive_directory_iterator& iter);
+

recursive_directory_iterator non-member functions

+
const recursive_directory_iterator& begin(const recursive_directory_iterator& iter);

Returns: iter.

-
inline recursive_directory_iterator end(const recursive_directory_iterator&);
+
recursive_directory_iterator end(const recursive_directory_iterator&);
-

Returns: recursive_directory_iterator().

+

Returns: recursive_directory_iterator().

Operational functions

Operational functions query or modify files, including directories, in external diff --git a/include/boost/filesystem/operations.hpp b/include/boost/filesystem/operations.hpp index a9a3ff1..043481b 100644 --- a/include/boost/filesystem/operations.hpp +++ b/include/boost/filesystem/operations.hpp @@ -33,8 +33,9 @@ #include #include #include +#include +#include #include - #include #include // for pair #include @@ -721,14 +722,37 @@ namespace detail { return m_imp == rhs.m_imp; } }; - // enable range-base for statement use + // enable C++11 range-base for statement use ---------------------------------------// + // begin() and end() are only used by a range-based for statement in the context of + // auto - thus the top-level const is stripped - so returning const is harmless and + // emphasizes begin() is just a pass through. inline - directory_iterator& begin(directory_iterator& iter) {return iter;} - + const directory_iterator& begin(const directory_iterator& iter) {return iter;} inline directory_iterator end(const directory_iterator&) {return directory_iterator();} + // enable BOOST_FOREACH ------------------------------------------------------------// + + inline + directory_iterator& range_begin(directory_iterator& iter) {return iter;} + inline + directory_iterator range_begin(const directory_iterator& iter) {return iter;} + inline + directory_iterator range_end(const directory_iterator&) {return directory_iterator();} + } // namespace filesystem + + // namespace boost template specializations + template<> + struct range_mutable_iterator + { typedef boost::filesystem::directory_iterator type; }; + template<> + struct range_const_iterator + { typedef boost::filesystem::directory_iterator type; }; + +namespace filesystem +{ + //--------------------------------------------------------------------------------------// // // // recursive_directory_iterator helpers // @@ -975,14 +999,41 @@ namespace detail }; - // enable range-base for statement use + // enable C++11 range-base for statement use ---------------------------------------// + // begin() and end() are only used by a range-based for statement in the context of + // auto - thus the top-level const is stripped - so returning const is harmless and + // emphasizes begin() is just a pass through. inline - recursive_directory_iterator& begin(recursive_directory_iterator& iter) {return iter;} - + const recursive_directory_iterator& begin(const recursive_directory_iterator& iter) + {return iter;} inline recursive_directory_iterator end(const recursive_directory_iterator&) - {return recursive_directory_iterator();} + {return recursive_directory_iterator();} + + // enable BOOST_FOREACH ------------------------------------------------------------// + + inline + recursive_directory_iterator& range_begin(recursive_directory_iterator& iter) + {return iter;} + inline + recursive_directory_iterator range_begin(const recursive_directory_iterator& iter) + {return iter;} + inline + recursive_directory_iterator range_end(const recursive_directory_iterator&) + {return recursive_directory_iterator();} + } // namespace filesystem + + // namespace boost template specializations + template<> + struct range_mutable_iterator + { typedef boost::filesystem::recursive_directory_iterator type; }; + template<> + struct range_const_iterator + { typedef boost::filesystem::recursive_directory_iterator type; }; + +namespace filesystem +{ # if !defined(BOOST_FILESYSTEM_NO_DEPRECATED) typedef recursive_directory_iterator wrecursive_directory_iterator; diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index eafd255..5be791d 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -24,7 +24,7 @@ project [ run locale_info.cpp : : : always_show_run_output ] [ run operations_test.cpp : : : shared always_show_run_output ] [ run operations_test.cpp : : : static : operations_test_static ] - [ run operations_unit_test.cpp : : : shared ] + [ run operations_unit_test.cpp : : : shared always_show_run_output ] [ run path_test.cpp : : : shared ] [ run path_test.cpp : : : static : path_test_static ] [ run path_unit_test.cpp : : : shared ] diff --git a/test/operations_unit_test.cpp b/test/operations_unit_test.cpp index 7f78b5d..f82bc9f 100644 --- a/test/operations_unit_test.cpp +++ b/test/operations_unit_test.cpp @@ -155,14 +155,22 @@ namespace #ifndef BOOST_NO_CXX11_RANGE_BASED_FOR for (directory_entry& x : directory_iterator(".")) { + CHECK(!x.path().empty()); //cout << " " << x.path() << "\n"; } + const directory_iterator dir_itr("."); + for (directory_entry& x : dir_itr) + { + CHECK(!x.path().empty()); + //cout << " " << x.path() << "\n"; + } #endif - //BOOST_FOREACH(directory_entry& x, directory_iterator(".")) - //{ - // cout << " " << x.path() << "\n"; - //} + BOOST_FOREACH(directory_entry& x, directory_iterator(".")) + { + CHECK(!x.path().empty()); + //cout << " " << x.path() << "\n"; + } cout << "directory_iterator_test complete" << endl; } @@ -208,10 +216,23 @@ namespace #ifndef BOOST_NO_CXX11_RANGE_BASED_FOR for (directory_entry& x : recursive_directory_iterator("..")) { - cout << " " << x.path() << "\n"; + CHECK(!x.path().empty()); + //cout << " " << x.path() << "\n"; + } + const recursive_directory_iterator dir_itr(".."); + for (directory_entry& x : dir_itr) + { + CHECK(!x.path().empty()); + //cout << " " << x.path() << "\n"; } #endif + BOOST_FOREACH(directory_entry& x, recursive_directory_iterator("..")) + { + CHECK(!x.path().empty()); + //cout << " " << x.path() << "\n"; + } + cout << "recursive_directory_iterator_test complete" << endl; }