ossrv_pub/boost_apis/boost/filesystem/convenience.hpp
changeset 0 e4d67989cc36
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     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