Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/boost/filesystem/convenience.hpp @ 33

Last change on this file since 33 was 29, checked in by landauf, 17 years ago

updated boost from 1_33_1 to 1_34_1

File size: 10.5 KB
RevLine 
[29]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
35namespace 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
Note: See TracBrowser for help on using the repository browser.