// 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/v2/config.hpp> #include <boost/filesystem/v2/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