// 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_FILESYSTEM_CONVENIENCE_HPP #define BOOST_FILESYSTEM_CONVENIENCE_HPP #include #include #include #include #include // must be the last #include # ifndef BOOST_FILESYSTEM_NARROW_ONLY # define BOOST_FS_FUNC(BOOST_FS_TYPE) \ template typename boost::enable_if, \ 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 filesystem { 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( "boost::filesystem::create_directories", ph, make_error_code( boost::system::posix::file_exists ) ) ); return false; } // First create branch, by calling ourself recursively create_directories(ph.branch_path()); // Now that parent's path exists, create the directory create_directory(ph); return true; } BOOST_FS_FUNC_STRING extension(const Path& ph) { typedef BOOST_FS_TYPENAME Path::string_type string_type; string_type leaf = ph.leaf(); BOOST_FS_TYPENAME string_type::size_type n = leaf.rfind('.'); if (n != string_type::npos) return leaf.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 leaf = ph.leaf(); BOOST_FS_TYPENAME string_type::size_type n = leaf.rfind('.'); return leaf.substr(0, n); } BOOST_FS_FUNC(Path) change_extension( const Path & ph, const BOOST_FS_TYPENAME Path::string_type & new_extension ) { return ph.branch_path() / (basename(ph) + new_extension); } # ifndef BOOST_FILESYSTEM_NARROW_ONLY // "do-the-right-thing" overloads ---------------------------------------// inline bool create_directories(const path& ph) { return create_directories(ph); } inline bool create_directories(const wpath& ph) { return create_directories(ph); } inline std::string extension(const path& ph) { return extension(ph); } inline std::wstring extension(const wpath& ph) { return extension(ph); } inline std::string basename(const path& ph) { return basename( ph ); } inline std::wstring basename(const wpath& ph) { return basename( ph ); } inline path change_extension( const path & ph, const std::string& new_ex ) { return change_extension( ph, new_ex ); } inline wpath change_extension( const wpath & ph, const std::wstring& new_ex ) { return change_extension( ph, new_ex ); } # 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, basic_directory_entry, 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, basic_directory_entry, 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 recursive_directory_iterator; # ifndef BOOST_FILESYSTEM_NARROW_ONLY typedef basic_recursive_directory_iterator wrecursive_directory_iterator; # endif // basic_recursive_directory_iterator implementation -------------------// // constructors template basic_recursive_directory_iterator:: basic_recursive_directory_iterator( const Path & dir_path ) : m_imp( new detail::recur_dir_itr_imp ) { m_imp->m_stack.push( basic_directory_iterator( dir_path ) ); if ( m_imp->m_stack.top () == basic_directory_iterator() ) { m_imp.reset (); } } template basic_recursive_directory_iterator:: basic_recursive_directory_iterator( const Path & dir_path, system::error_code & ec ) : m_imp( new detail::recur_dir_itr_imp ) { m_imp->m_no_throw = true; m_imp->m_stack.push( basic_directory_iterator( dir_path, ec ) ); if ( m_imp->m_stack.top () == basic_directory_iterator() ) { m_imp.reset (); } } // increment template void basic_recursive_directory_iterator::increment() { BOOST_ASSERT( m_imp.get() && "increment on end iterator" ); static const basic_directory_iterator 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; m_imp->m_stack.push( m_imp->m_no_throw ? basic_directory_iterator( *m_imp->m_stack.top(), ec ) : basic_directory_iterator( *m_imp->m_stack.top() ) ); 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 void basic_recursive_directory_iterator::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 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 filesystem } // namespace boost #undef BOOST_FS_FUNC_STRING #undef BOOST_FS_FUNC #include // pops abi_prefix.hpp pragmas #endif // BOOST_FILESYSTEM_CONVENIENCE_HPP