1 // boost/filesystem/convenience.hpp ----------------------------------------//
\r
3 // Copyright Beman Dawes, 2002-2005
\r
4 // Copyright Vladimir Prus, 2002
\r
5 // Use, modification, and distribution is subject to the Boost Software
\r
6 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
\r
7 // http://www.boost.org/LICENSE_1_0.txt)
\r
9 // See library home page at http://www.boost.org/libs/filesystem
\r
11 //----------------------------------------------------------------------------//
\r
13 #ifndef BOOST_FILESYSTEM_CONVENIENCE_HPP
\r
14 #define BOOST_FILESYSTEM_CONVENIENCE_HPP
\r
16 #include <boost/filesystem/operations.hpp>
\r
17 #include <boost/system/error_code.hpp>
\r
21 #include <boost/config/abi_prefix.hpp> // must be the last #include
\r
23 # ifndef BOOST_FILESYSTEM_NARROW_ONLY
\r
24 # define BOOST_FS_FUNC(BOOST_FS_TYPE) \
\r
25 template<class Path> typename boost::enable_if<is_basic_path<Path>, \
\r
26 BOOST_FS_TYPE>::type
\r
27 # define BOOST_FS_FUNC_STRING BOOST_FS_FUNC(typename Path::string_type)
\r
28 # define BOOST_FS_TYPENAME typename
\r
30 # define BOOST_FS_FUNC(BOOST_FS_TYPE) inline BOOST_FS_TYPE
\r
31 typedef boost::filesystem::path Path;
\r
32 # define BOOST_FS_FUNC_STRING inline std::string
\r
33 # define BOOST_FS_TYPENAME
\r
38 namespace filesystem
\r
41 BOOST_FS_FUNC(bool) create_directories(const Path& ph)
\r
43 if (ph.empty() || exists(ph))
\r
45 if ( !ph.empty() && !is_directory(ph) )
\r
46 boost::throw_exception( basic_filesystem_error<Path>(
\r
47 "boost::filesystem::create_directories", ph,
\r
48 make_error_code( boost::system::posix::file_exists ) ) );
\r
52 // First create branch, by calling ourself recursively
\r
53 create_directories(ph.parent_path());
\r
54 // Now that parent's path exists, create the directory
\r
55 create_directory(ph);
\r
59 # ifndef BOOST_FILESYSTEM_NO_DEPRECATED
\r
61 BOOST_FS_FUNC_STRING extension(const Path& ph)
\r
63 typedef BOOST_FS_TYPENAME Path::string_type string_type;
\r
64 string_type filename = ph.filename();
\r
66 BOOST_FS_TYPENAME string_type::size_type n = filename.rfind('.');
\r
67 if (n != string_type::npos)
\r
68 return filename.substr(n);
\r
70 return string_type();
\r
73 BOOST_FS_FUNC_STRING basename(const Path& ph)
\r
75 typedef BOOST_FS_TYPENAME Path::string_type string_type;
\r
76 string_type filename = ph.filename();
\r
77 BOOST_FS_TYPENAME string_type::size_type n = filename.rfind('.');
\r
78 return filename.substr(0, n);
\r
82 BOOST_FS_FUNC(Path) change_extension( const Path & ph,
\r
83 const BOOST_FS_TYPENAME Path::string_type & new_extension )
\r
84 { return ph.parent_path() / (basename(ph) + new_extension); }
\r
88 # ifndef BOOST_FILESYSTEM_NARROW_ONLY
\r
90 // "do-the-right-thing" overloads ---------------------------------------//
\r
92 inline bool create_directories(const path& ph)
\r
93 { return create_directories<path>(ph); }
\r
94 inline bool create_directories(const wpath& ph)
\r
95 { return create_directories<wpath>(ph); }
\r
97 # ifndef BOOST_FILESYSTEM_NO_DEPRECATED
\r
98 inline std::string extension(const path& ph)
\r
99 { return extension<path>(ph); }
\r
100 inline std::wstring extension(const wpath& ph)
\r
101 { return extension<wpath>(ph); }
\r
103 inline std::string basename(const path& ph)
\r
104 { return basename<path>( ph ); }
\r
105 inline std::wstring basename(const wpath& ph)
\r
106 { return basename<wpath>( ph ); }
\r
108 inline path change_extension( const path & ph, const std::string& new_ex )
\r
109 { return change_extension<path>( ph, new_ex ); }
\r
110 inline wpath change_extension( const wpath & ph, const std::wstring& new_ex )
\r
111 { return change_extension<wpath>( ph, new_ex ); }
\r
117 // basic_recursive_directory_iterator helpers --------------------------//
\r
121 template< class Path >
\r
122 struct recur_dir_itr_imp
\r
124 typedef basic_directory_iterator< Path > element_type;
\r
125 std::stack< element_type, std::vector< element_type > > m_stack;
\r
130 recur_dir_itr_imp() : m_level(0), m_no_push(false), m_no_throw(false) {}
\r
133 } // namespace detail
\r
135 // basic_recursive_directory_iterator ----------------------------------//
\r
137 template< class Path >
\r
138 class basic_recursive_directory_iterator
\r
139 : public boost::iterator_facade<
\r
140 basic_recursive_directory_iterator<Path>,
\r
141 basic_directory_entry<Path>,
\r
142 boost::single_pass_traversal_tag >
\r
145 typedef Path path_type;
\r
147 basic_recursive_directory_iterator(){} // creates the "end" iterator
\r
149 explicit basic_recursive_directory_iterator( const Path & dir_path );
\r
150 basic_recursive_directory_iterator( const Path & dir_path,
\r
151 system::error_code & ec );
\r
153 int level() const { return m_imp->m_level; }
\r
158 BOOST_ASSERT( m_imp.get() && "attempt to no_push() on end iterator" );
\r
159 m_imp->m_no_push = true;
\r
162 file_status status() const
\r
164 BOOST_ASSERT( m_imp.get()
\r
165 && "attempt to call status() on end recursive_iterator" );
\r
166 return m_imp->m_stack.top()->status();
\r
169 file_status symlink_status() const
\r
171 BOOST_ASSERT( m_imp.get()
\r
172 && "attempt to call symlink_status() on end recursive_iterator" );
\r
173 return m_imp->m_stack.top()->symlink_status();
\r
178 // shared_ptr provides shallow-copy semantics required for InputIterators.
\r
179 // m_imp.get()==0 indicates the end iterator.
\r
180 boost::shared_ptr< detail::recur_dir_itr_imp< Path > > m_imp;
\r
182 friend class boost::iterator_core_access;
\r
184 typename boost::iterator_facade<
\r
185 basic_recursive_directory_iterator<Path>,
\r
186 basic_directory_entry<Path>,
\r
187 boost::single_pass_traversal_tag >::reference
\r
188 dereference() const
\r
190 BOOST_ASSERT( m_imp.get() && "attempt to dereference end iterator" );
\r
191 return *m_imp->m_stack.top();
\r
196 bool equal( const basic_recursive_directory_iterator & rhs ) const
\r
197 { return m_imp == rhs.m_imp; }
\r
201 typedef basic_recursive_directory_iterator<path> recursive_directory_iterator;
\r
202 # ifndef BOOST_FILESYSTEM_NARROW_ONLY
\r
203 typedef basic_recursive_directory_iterator<wpath> wrecursive_directory_iterator;
\r
206 // basic_recursive_directory_iterator implementation -------------------//
\r
209 template<class Path>
\r
210 basic_recursive_directory_iterator<Path>::
\r
211 basic_recursive_directory_iterator( const Path & dir_path )
\r
212 : m_imp( new detail::recur_dir_itr_imp<Path> )
\r
214 m_imp->m_stack.push( basic_directory_iterator<Path>( dir_path ) );
\r
215 if ( m_imp->m_stack.top () == basic_directory_iterator<Path>() )
\r
216 { m_imp.reset (); }
\r
219 template<class Path>
\r
220 basic_recursive_directory_iterator<Path>::
\r
221 basic_recursive_directory_iterator( const Path & dir_path,
\r
222 system::error_code & ec )
\r
223 : m_imp( new detail::recur_dir_itr_imp<Path> )
\r
225 m_imp->m_no_throw = true;
\r
226 m_imp->m_stack.push( basic_directory_iterator<Path>( dir_path, ec ) );
\r
227 if ( m_imp->m_stack.top () == basic_directory_iterator<Path>() )
\r
228 { m_imp.reset (); }
\r
232 template<class Path>
\r
233 void basic_recursive_directory_iterator<Path>::increment()
\r
235 BOOST_ASSERT( m_imp.get() && "increment on end iterator" );
\r
237 static const basic_directory_iterator<Path> end_itr;
\r
239 if ( m_imp->m_no_push )
\r
240 { m_imp->m_no_push = false; }
\r
241 else if ( is_directory( m_imp->m_stack.top()->status() ) )
\r
243 system::error_code ec;
\r
244 #if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x610))
\r
245 if( m_imp->m_no_throw ) {
\r
246 m_imp->m_stack.push(
\r
247 basic_directory_iterator<Path>( *m_imp->m_stack.top(), ec )
\r
251 m_imp->m_stack.push(
\r
252 basic_directory_iterator<Path>( *m_imp->m_stack.top() )
\r
256 m_imp->m_stack.push(
\r
258 ? basic_directory_iterator<Path>( *m_imp->m_stack.top(), ec )
\r
259 : basic_directory_iterator<Path>( *m_imp->m_stack.top() ) );
\r
261 if ( m_imp->m_stack.top() != end_itr )
\r
266 m_imp->m_stack.pop();
\r
269 while ( !m_imp->m_stack.empty()
\r
270 && ++m_imp->m_stack.top() == end_itr )
\r
272 m_imp->m_stack.pop();
\r
276 if ( m_imp->m_stack.empty() ) m_imp.reset(); // done, so make end iterator
\r
280 template<class Path>
\r
281 void basic_recursive_directory_iterator<Path>::pop()
\r
283 BOOST_ASSERT( m_imp.get() && "pop on end iterator" );
\r
284 BOOST_ASSERT( m_imp->m_level > 0 && "pop with level < 1" );
\r
286 static const basic_directory_iterator<Path> end_itr;
\r
290 m_imp->m_stack.pop();
\r
293 while ( !m_imp->m_stack.empty()
\r
294 && ++m_imp->m_stack.top() == end_itr );
\r
296 if ( m_imp->m_stack.empty() ) m_imp.reset(); // done, so make end iterator
\r
299 } // namespace filesystem
\r
300 } // namespace boost
\r
302 #undef BOOST_FS_FUNC_STRING
\r
303 #undef BOOST_FS_FUNC
\r
305 #include <boost/config/abi_suffix.hpp> // pops abi_prefix.hpp pragmas
\r
306 #endif // BOOST_FILESYSTEM_CONVENIENCE_HPP
\r