// 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 // 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 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, -1 ) ); 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; recur_dir_itr_imp() : m_level(0), m_no_push(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 ); 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; } 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 -------------------// // constructor 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 ) ); } // 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 ( m_imp->m_stack.top()->is_directory() ) { m_imp->m_stack.push( 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" ); m_imp->m_stack.pop(); --m_imp->m_level; } // what() basic_filesystem_error_decoder -------------------------------// namespace detail { inline void decode_system_message( system_error_type ec, std::string & target ) { system_message( ec, target ); } # if defined(BOOST_WINDOWS_API) && !defined(BOOST_FILESYSTEM_NARROW_ONLY) inline void decode_system_message( system_error_type ec, std::wstring & target ) { system_message( ec, target ); } # endif template void decode_system_message( system_error_type ec, String & target ) { std::string temp; system_message( ec, temp ); for ( const char * p = temp.c_str(); *p != 0; ++p ) { target += static_cast( *p ); } } } template typename Path::string_type what( const basic_filesystem_error & ex ) { typename Path::string_type s; for ( const char * p = ex.what(); *p != 0; ++p ) { s += static_cast( *p ); } if ( !ex.path1().empty() ) { s += static_cast( ':' ); s += static_cast( ' ' ); s += static_cast( '\"' ); s += ex.path1().file_string(); s += static_cast( '\"' ); } if ( !ex.path2().empty() ) { s += static_cast( ',' ); s += static_cast( ' ' ); s += static_cast( '\"' ); s += ex.path2().file_string(); s += static_cast( '\"' ); } if ( ex.system_error() ) { s += static_cast( ' ' ); detail::decode_system_message( ex.system_error(), s ); } return s; } } // namespace filesystem } // namespace boost #undef BOOST_FS_FUNC_STRING #undef BOOST_FS_FUNC #include // pops abi_prefix.hpp pragmas #endif // BOOST_FILESYSTEM_CONVENIENCE_HPP