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