| // boost/filesystem/convenience.hpp ----------------------------------------// |
| |
| // Copyright Beman Dawes, 2002-2005 |
| // Copyright Vladimir Prus, 2002 |
| // Use, modification, and distribution is subject to the Boost Software |
| // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at |
| // http://www.boost.org/LICENSE_1_0.txt) |
| |
| // See library home page at http://www.boost.org/libs/filesystem |
| |
| //----------------------------------------------------------------------------// |
| |
| #ifndef BOOST_FILESYSTEM2_CONVENIENCE_HPP |
| #define BOOST_FILESYSTEM2_CONVENIENCE_HPP |
| |
| #include <boost/filesystem/operations.hpp> |
| #include <boost/system/error_code.hpp> |
| #include <vector> |
| #include <stack> |
| |
| #include <boost/config/abi_prefix.hpp> // must be the last #include |
| |
| # ifndef BOOST_FILESYSTEM2_NARROW_ONLY |
| # define BOOST_FS_FUNC(BOOST_FS_TYPE) \ |
| template<class Path> typename boost::enable_if<is_basic_path<Path>, \ |
| BOOST_FS_TYPE>::type |
| # define BOOST_FS_FUNC_STRING BOOST_FS_FUNC(typename Path::string_type) |
| # define BOOST_FS_TYPENAME typename |
| # else |
| # define BOOST_FS_FUNC(BOOST_FS_TYPE) inline BOOST_FS_TYPE |
| typedef boost::filesystem::path Path; |
| # define BOOST_FS_FUNC_STRING inline std::string |
| # define BOOST_FS_TYPENAME |
| # endif |
| |
| namespace boost |
| { |
| namespace filesystem2 |
| { |
| |
| BOOST_FS_FUNC(bool) create_directories(const Path& ph) |
| { |
| if (ph.empty() || exists(ph)) |
| { |
| if ( !ph.empty() && !is_directory(ph) ) |
| boost::throw_exception( basic_filesystem_error<Path>( |
| "boost::filesystem::create_directories", ph, |
| make_error_code( boost::system::errc::file_exists ) ) ); |
| return false; |
| } |
| |
| // First create branch, by calling ourself recursively |
| create_directories(ph.parent_path()); |
| // Now that parent's path exists, create the directory |
| create_directory(ph); |
| return true; |
| } |
| |
| # ifndef BOOST_FILESYSTEM_NO_DEPRECATED |
| |
| BOOST_FS_FUNC_STRING extension(const Path& ph) |
| { |
| typedef BOOST_FS_TYPENAME Path::string_type string_type; |
| string_type filename = ph.filename(); |
| |
| BOOST_FS_TYPENAME string_type::size_type n = filename.rfind('.'); |
| if (n != string_type::npos) |
| return filename.substr(n); |
| else |
| return string_type(); |
| } |
| |
| BOOST_FS_FUNC_STRING basename(const Path& ph) |
| { |
| typedef BOOST_FS_TYPENAME Path::string_type string_type; |
| string_type filename = ph.filename(); |
| BOOST_FS_TYPENAME string_type::size_type n = filename.rfind('.'); |
| return filename.substr(0, n); |
| } |
| |
| |
| BOOST_FS_FUNC(Path) change_extension( const Path & ph, |
| const BOOST_FS_TYPENAME Path::string_type & new_extension ) |
| { |
| # if !defined(_STLPORT_VERSION) |
| return ph.parent_path() / (basename(ph) + new_extension); |
| # else |
| typedef BOOST_FS_TYPENAME Path::string_type string_type; |
| string_type filename = basename(ph) + new_extension; |
| return ph.parent_path() / filename; |
| # endif |
| } |
| # endif |
| |
| # ifndef BOOST_FILESYSTEM2_NARROW_ONLY |
| |
| // "do-the-right-thing" overloads ---------------------------------------// |
| |
| inline bool create_directories(const path& ph) |
| { return create_directories<path>(ph); } |
| inline bool create_directories(const wpath& ph) |
| { return create_directories<wpath>(ph); } |
| |
| # ifndef BOOST_FILESYSTEM_NO_DEPRECATED |
| inline std::string extension(const path& ph) |
| { return extension<path>(ph); } |
| inline std::wstring extension(const wpath& ph) |
| { return extension<wpath>(ph); } |
| |
| inline std::string basename(const path& ph) |
| { return basename<path>( ph ); } |
| inline std::wstring basename(const wpath& ph) |
| { return basename<wpath>( ph ); } |
| |
| inline path change_extension( const path & ph, const std::string& new_ex ) |
| { return change_extension<path>( ph, new_ex ); } |
| inline wpath change_extension( const wpath & ph, const std::wstring& new_ex ) |
| { return change_extension<wpath>( ph, new_ex ); } |
| # endif |
| |
| # endif |
| |
| |
| // basic_recursive_directory_iterator helpers --------------------------// |
| |
| namespace detail |
| { |
| template< class Path > |
| struct recur_dir_itr_imp |
| { |
| typedef basic_directory_iterator< Path > element_type; |
| std::stack< element_type, std::vector< element_type > > m_stack; |
| int m_level; |
| bool m_no_push; |
| bool m_no_throw; |
| |
| recur_dir_itr_imp() : m_level(0), m_no_push(false), m_no_throw(false) {} |
| }; |
| |
| } // namespace detail |
| |
| // basic_recursive_directory_iterator ----------------------------------// |
| |
| template< class Path > |
| class basic_recursive_directory_iterator |
| : public boost::iterator_facade< |
| basic_recursive_directory_iterator<Path>, |
| basic_directory_entry<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 ); |
| basic_recursive_directory_iterator( const Path & dir_path, |
| system::error_code & ec ); |
| |
| int level() const { return m_imp->m_level; } |
| |
| void pop(); |
| void no_push() |
| { |
| BOOST_ASSERT( m_imp.get() && "attempt to no_push() on end iterator" ); |
| m_imp->m_no_push = true; |
| } |
| |
| file_status status() const |
| { |
| BOOST_ASSERT( m_imp.get() |
| && "attempt to call status() on end recursive_iterator" ); |
| return m_imp->m_stack.top()->status(); |
| } |
| |
| file_status symlink_status() const |
| { |
| BOOST_ASSERT( m_imp.get() |
| && "attempt to call symlink_status() on end recursive_iterator" ); |
| return m_imp->m_stack.top()->symlink_status(); |
| } |
| |
| private: |
| |
| // shared_ptr provides shallow-copy semantics required for InputIterators. |
| // m_imp.get()==0 indicates the end iterator. |
| boost::shared_ptr< detail::recur_dir_itr_imp< Path > > m_imp; |
| |
| friend class boost::iterator_core_access; |
| |
| typename boost::iterator_facade< |
| basic_recursive_directory_iterator<Path>, |
| basic_directory_entry<Path>, |
| boost::single_pass_traversal_tag >::reference |
| dereference() const |
| { |
| BOOST_ASSERT( m_imp.get() && "attempt to dereference end iterator" ); |
| return *m_imp->m_stack.top(); |
| } |
| |
| void increment(); |
| |
| bool equal( const basic_recursive_directory_iterator & rhs ) const |
| { return m_imp == rhs.m_imp; } |
| |
| }; |
| |
| typedef basic_recursive_directory_iterator<path> recursive_directory_iterator; |
| # ifndef BOOST_FILESYSTEM2_NARROW_ONLY |
| typedef basic_recursive_directory_iterator<wpath> wrecursive_directory_iterator; |
| # endif |
| |
| // basic_recursive_directory_iterator implementation -------------------// |
| |
| // constructors |
| template<class Path> |
| basic_recursive_directory_iterator<Path>:: |
| basic_recursive_directory_iterator( const Path & dir_path ) |
| : m_imp( new detail::recur_dir_itr_imp<Path> ) |
| { |
| m_imp->m_stack.push( basic_directory_iterator<Path>( dir_path ) ); |
| if ( m_imp->m_stack.top () == basic_directory_iterator<Path>() ) |
| { m_imp.reset (); } |
| } |
| |
| template<class Path> |
| basic_recursive_directory_iterator<Path>:: |
| basic_recursive_directory_iterator( const Path & dir_path, |
| system::error_code & ec ) |
| : m_imp( new detail::recur_dir_itr_imp<Path> ) |
| { |
| m_imp->m_no_throw = true; |
| m_imp->m_stack.push( basic_directory_iterator<Path>( dir_path, ec ) ); |
| if ( m_imp->m_stack.top () == basic_directory_iterator<Path>() ) |
| { m_imp.reset (); } |
| } |
| |
| // increment |
| template<class Path> |
| void basic_recursive_directory_iterator<Path>::increment() |
| { |
| BOOST_ASSERT( m_imp.get() && "increment on end iterator" ); |
| |
| static const basic_directory_iterator<Path> end_itr; |
| |
| if ( m_imp->m_no_push ) |
| { m_imp->m_no_push = false; } |
| else if ( is_directory( m_imp->m_stack.top()->status() ) ) |
| { |
| system::error_code ec; |
| #if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x610)) |
| if( m_imp->m_no_throw ) { |
| m_imp->m_stack.push( |
| basic_directory_iterator<Path>( *m_imp->m_stack.top(), ec ) |
| ); |
| } |
| else { |
| m_imp->m_stack.push( |
| basic_directory_iterator<Path>( *m_imp->m_stack.top() ) |
| ); |
| } |
| #else |
| m_imp->m_stack.push( |
| m_imp->m_no_throw |
| ? basic_directory_iterator<Path>( *m_imp->m_stack.top(), ec ) |
| : basic_directory_iterator<Path>( *m_imp->m_stack.top() ) ); |
| #endif |
| if ( m_imp->m_stack.top() != end_itr ) |
| { |
| ++m_imp->m_level; |
| return; |
| } |
| m_imp->m_stack.pop(); |
| } |
| |
| while ( !m_imp->m_stack.empty() |
| && ++m_imp->m_stack.top() == end_itr ) |
| { |
| m_imp->m_stack.pop(); |
| --m_imp->m_level; |
| } |
| |
| if ( m_imp->m_stack.empty() ) m_imp.reset(); // done, so make end iterator |
| } |
| |
| // pop |
| template<class Path> |
| void basic_recursive_directory_iterator<Path>::pop() |
| { |
| BOOST_ASSERT( m_imp.get() && "pop on end iterator" ); |
| BOOST_ASSERT( m_imp->m_level > 0 && "pop with level < 1" ); |
| |
| static const basic_directory_iterator<Path> end_itr; |
| |
| do |
| { |
| m_imp->m_stack.pop(); |
| --m_imp->m_level; |
| } |
| while ( !m_imp->m_stack.empty() |
| && ++m_imp->m_stack.top() == end_itr ); |
| |
| if ( m_imp->m_stack.empty() ) m_imp.reset(); // done, so make end iterator |
| } |
| |
| } // namespace filesystem2 |
| } // namespace boost |
| |
| #undef BOOST_FS_FUNC_STRING |
| #undef BOOST_FS_FUNC |
| |
| //----------------------------------------------------------------------------// |
| |
| namespace boost |
| { |
| namespace filesystem |
| { |
| using filesystem2::create_directories; |
| using filesystem2::basic_recursive_directory_iterator; |
| using filesystem2::recursive_directory_iterator; |
| |
| # ifndef BOOST_FILESYSTEM_NO_DEPRECATED |
| using filesystem2::extension; |
| using filesystem2::basename; |
| using filesystem2::change_extension; |
| # endif |
| |
| # ifndef BOOST_FILESYSTEM2_NARROW_ONLY |
| using filesystem2::wrecursive_directory_iterator; |
| # endif |
| |
| } |
| } |
| |
| //----------------------------------------------------------------------------// |
| |
| #include <boost/config/abi_suffix.hpp> // pops abi_prefix.hpp pragmas |
| #endif // BOOST_FILESYSTEM2_CONVENIENCE_HPP |