]> git.lyx.org Git - lyx.git/blob - boost/boost/filesystem/convenience.hpp
* lib/doc/Makefile.am:
[lyx.git] / boost / boost / filesystem / convenience.hpp
1 //  boost/filesystem/convenience.hpp  ----------------------------------------//
2
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)
8
9 //  See library home page at http://www.boost.org/libs/filesystem
10
11 //----------------------------------------------------------------------------// 
12
13 #ifndef BOOST_FILESYSTEM_CONVENIENCE_HPP
14 #define BOOST_FILESYSTEM_CONVENIENCE_HPP
15
16 #include <boost/filesystem/operations.hpp>
17 #include <vector>
18 #include <stack>
19
20 #include <boost/config/abi_prefix.hpp> // must be the last #include
21
22 # ifndef BOOST_FILESYSTEM_NARROW_ONLY
23 #   define BOOST_FS_FUNC(BOOST_FS_TYPE) \
24       template<class Path> typename boost::enable_if<is_basic_path<Path>, \
25       BOOST_FS_TYPE>::type
26 #   define BOOST_FS_FUNC_STRING BOOST_FS_FUNC(typename Path::string_type)
27 #   define BOOST_FS_TYPENAME typename
28 # else
29 #   define BOOST_FS_FUNC(BOOST_FS_TYPE) inline BOOST_FS_TYPE 
30     typedef boost::filesystem::path Path;
31 #   define BOOST_FS_FUNC_STRING std::string
32 #   define BOOST_FS_TYPENAME
33 # endif
34
35 namespace boost
36 {
37   namespace filesystem
38   {
39
40     BOOST_FS_FUNC(bool) create_directories(const Path& ph)
41     {
42          if (ph.empty() || exists(ph))
43          {
44            if ( !ph.empty() && !is_directory(ph) )
45                boost::throw_exception( basic_filesystem_error<Path>(
46                  "boost::filesystem::create_directories", ph, -1 ) );
47            return false;
48          }
49
50          // First create branch, by calling ourself recursively
51          create_directories(ph.branch_path());
52          // Now that parent's path exists, create the directory
53          create_directory(ph);
54          return true;
55      }
56
57     BOOST_FS_FUNC_STRING extension(const Path& ph)
58     {
59       typedef BOOST_FS_TYPENAME Path::string_type string_type;
60       string_type leaf = ph.leaf();
61
62       BOOST_FS_TYPENAME string_type::size_type n = leaf.rfind('.');
63       if (n != string_type::npos)
64         return leaf.substr(n);
65       else
66         return string_type();
67     }
68
69     BOOST_FS_FUNC_STRING basename(const Path& ph)
70     {
71       typedef BOOST_FS_TYPENAME Path::string_type string_type;
72       string_type leaf = ph.leaf();
73       BOOST_FS_TYPENAME string_type::size_type n = leaf.rfind('.');
74       return leaf.substr(0, n);
75     }
76
77     BOOST_FS_FUNC(Path) change_extension( const Path & ph,
78       const BOOST_FS_TYPENAME Path::string_type & new_extension )
79       { return ph.branch_path() / (basename(ph) + new_extension); }
80
81 # ifndef BOOST_FILESYSTEM_NARROW_ONLY
82
83     // "do-the-right-thing" overloads  ---------------------------------------//
84
85     inline bool create_directories(const path& ph)
86       { return create_directories<path>(ph); }
87     inline bool create_directories(const wpath& ph)
88       { return create_directories<wpath>(ph); }
89
90     inline std::string extension(const path& ph)
91       { return extension<path>(ph); }
92     inline std::wstring extension(const wpath& ph)
93       { return extension<wpath>(ph); }
94
95     inline std::string basename(const path& ph)
96       { return basename<path>( ph ); }
97     inline std::wstring basename(const wpath& ph)
98       { return basename<wpath>( ph ); }
99
100     inline path change_extension( const path & ph, const std::string& new_ex )
101       { return change_extension<path>( ph, new_ex ); }
102     inline wpath change_extension( const wpath & ph, const std::wstring& new_ex )
103       { return change_extension<wpath>( ph, new_ex ); }
104
105 # endif
106
107
108     //  basic_recursive_directory_iterator helpers  --------------------------//
109
110     namespace detail
111     {
112       template< class Path >
113       struct recur_dir_itr_imp
114       {
115         typedef basic_directory_iterator< Path > element_type;
116         std::stack< element_type, std::vector< element_type > > m_stack;
117         int  m_level;
118         bool m_no_push;
119         bool m_no_throw;
120
121         recur_dir_itr_imp() : m_level(0), m_no_push(false), m_no_throw(false) {}
122       };
123
124     } // namespace detail
125
126     //  basic_recursive_directory_iterator  ----------------------------------//
127
128     template< class Path >
129     class basic_recursive_directory_iterator
130       : public boost::iterator_facade<
131           basic_recursive_directory_iterator<Path>,
132           basic_directory_entry<Path>,
133           boost::single_pass_traversal_tag >
134     {
135     public:
136       typedef Path path_type;
137
138       basic_recursive_directory_iterator(){}  // creates the "end" iterator
139
140       explicit basic_recursive_directory_iterator( const Path & dir_path );
141       basic_recursive_directory_iterator( const Path & dir_path, system_error_type & ec );
142
143       int level() const { return m_imp->m_level; }
144
145       void pop();
146       void no_push()
147       {
148         BOOST_ASSERT( m_imp.get() && "attempt to no_push() on end iterator" );
149         m_imp->m_no_push = true;
150       }
151
152       file_status status() const
153       {
154         BOOST_ASSERT( m_imp.get()
155           && "attempt to call status() on end recursive_iterator" );
156         return m_imp->m_stack.top()->status();
157       }
158
159       file_status symlink_status() const
160       {
161         BOOST_ASSERT( m_imp.get()
162           && "attempt to call symlink_status() on end recursive_iterator" );
163         return m_imp->m_stack.top()->symlink_status();
164       }
165
166     private:
167
168       // shared_ptr provides shallow-copy semantics required for InputIterators.
169       // m_imp.get()==0 indicates the end iterator.
170       boost::shared_ptr< detail::recur_dir_itr_imp< Path > >  m_imp;
171
172       friend class boost::iterator_core_access;
173
174       typename boost::iterator_facade< 
175         basic_recursive_directory_iterator<Path>,
176         basic_directory_entry<Path>,
177         boost::single_pass_traversal_tag >::reference
178       dereference() const 
179       {
180         BOOST_ASSERT( m_imp.get() && "attempt to dereference end iterator" );
181         return *m_imp->m_stack.top();
182       }
183
184       void increment();
185
186       bool equal( const basic_recursive_directory_iterator & rhs ) const
187         { return m_imp == rhs.m_imp; }
188     };
189
190     typedef basic_recursive_directory_iterator<path> recursive_directory_iterator;
191 # ifndef BOOST_FILESYSTEM_NARROW_ONLY
192     typedef basic_recursive_directory_iterator<wpath> wrecursive_directory_iterator;
193 # endif
194
195     //  basic_recursive_directory_iterator implementation  -------------------//
196
197     //  constructors
198     template<class Path>
199     basic_recursive_directory_iterator<Path>::
200       basic_recursive_directory_iterator( const Path & dir_path )
201       : m_imp( new detail::recur_dir_itr_imp<Path> )
202     {
203       m_imp->m_stack.push( basic_directory_iterator<Path>( dir_path ) );
204     }
205
206     template<class Path>
207     basic_recursive_directory_iterator<Path>::
208       basic_recursive_directory_iterator( const Path & dir_path, system_error_type & ec )
209       : m_imp( new detail::recur_dir_itr_imp<Path> )
210     {
211       m_imp->m_stack.push( basic_directory_iterator<Path>( dir_path, std::nothrow ) );
212       m_imp->m_no_throw = true;
213     }
214
215     //  increment
216     template<class Path>
217     void basic_recursive_directory_iterator<Path>::increment()
218     {
219       BOOST_ASSERT( m_imp.get() && "increment on end iterator" );
220       
221       static const basic_directory_iterator<Path> end_itr;
222
223       if ( m_imp->m_no_push ) m_imp->m_no_push = false;
224       else if ( is_directory( m_imp->m_stack.top()->status() ) )
225       {
226         system_error_type ec;
227         m_imp->m_stack.push(
228           m_imp->m_no_throw
229             ? basic_directory_iterator<Path>( *m_imp->m_stack.top(), ec )
230             : basic_directory_iterator<Path>( *m_imp->m_stack.top() )
231           );
232         if ( m_imp->m_stack.top() != end_itr )
233         {
234           ++m_imp->m_level;
235           return;
236         }
237         m_imp->m_stack.pop();
238       }
239
240       while ( !m_imp->m_stack.empty()
241         && ++m_imp->m_stack.top() == end_itr )
242       {
243         m_imp->m_stack.pop();
244         --m_imp->m_level;
245       }
246
247       if ( m_imp->m_stack.empty() ) m_imp.reset(); // done, so make end iterator
248     }
249
250     //  pop
251     template<class Path>
252     void basic_recursive_directory_iterator<Path>::pop()
253     {
254       BOOST_ASSERT( m_imp.get() && "pop on end iterator" );
255       BOOST_ASSERT( m_imp->m_level > 0 && "pop with level < 1" );
256
257       m_imp->m_stack.pop();
258       --m_imp->m_level;
259     }
260
261     //  what() basic_filesystem_error_decoder  -------------------------------//
262
263     namespace detail
264     {
265
266 #   if BOOST_WORKAROUND(__BORLANDC__,BOOST_TESTED_AT(0x581))
267       using boost::filesystem::system_message;
268 #   endif
269
270       inline void decode_system_message( system_error_type ec, std::string & target )
271       {
272         system_message( ec, target );
273       }
274
275 #   if defined(BOOST_WINDOWS_API) && !defined(BOOST_FILESYSTEM_NARROW_ONLY)
276       inline void decode_system_message( system_error_type ec, std::wstring & target )
277       {
278         system_message( ec, target );
279       }
280 #   endif
281
282       template<class String>
283       void decode_system_message( system_error_type ec, String & target )
284       {
285         std::string temp;
286         system_message( ec, temp );
287         for ( const char * p = temp.c_str(); *p != 0; ++p )
288           { target += static_cast<typename String::value_type>( *p ); }
289       }
290     }
291
292     template<class Path>
293     typename Path::string_type what( const basic_filesystem_error<Path> & ex )
294     {
295       typename Path::string_type s;
296       for ( const char * p = ex.what(); *p != 0; ++p )
297         { s += static_cast<typename Path::string_type::value_type>( *p ); }
298
299       if ( !ex.path1().empty() )
300       {
301         s += static_cast<typename Path::string_type::value_type>( ':' );
302         s += static_cast<typename Path::string_type::value_type>( ' ' );
303         s += static_cast<typename Path::string_type::value_type>( '\"' );
304         s += ex.path1().file_string();
305         s += static_cast<typename Path::string_type::value_type>( '\"' );
306       }
307       if ( !ex.path2().empty() )
308       {
309         s += static_cast<typename Path::string_type::value_type>( ',' );
310         s += static_cast<typename Path::string_type::value_type>( ' ' );
311         s += static_cast<typename Path::string_type::value_type>( '\"' );
312         s += ex.path2().file_string();
313         s += static_cast<typename Path::string_type::value_type>( '\"' );
314       }
315       if ( ex.system_error() )
316       {
317         s += static_cast<typename Path::string_type::value_type>( ' ' );
318
319         detail::decode_system_message( ex.system_error(), s );
320       }
321       return s;
322     }
323
324   } // namespace filesystem
325 } // namespace boost
326
327 #undef BOOST_FS_FUNC_STRING
328 #undef BOOST_FS_FUNC
329
330 #include <boost/config/abi_suffix.hpp> // pops abi_prefix.hpp pragmas
331 #endif // BOOST_FILESYSTEM_CONVENIENCE_HPP