Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/boost/filesystem/directory.hpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 //  boost/filesystem/directory.hpp  ---------------------------------------------------//
0002 
0003 //  Copyright Beman Dawes 2002-2009
0004 //  Copyright Jan Langer 2002
0005 //  Copyright Dietmar Kuehl 2001
0006 //  Copyright Vladimir Prus 2002
0007 //  Copyright Andrey Semashev 2019, 2022
0008 
0009 //  Distributed under the Boost Software License, Version 1.0.
0010 //  See http://www.boost.org/LICENSE_1_0.txt
0011 
0012 //  Library home page: http://www.boost.org/libs/filesystem
0013 
0014 //--------------------------------------------------------------------------------------//
0015 
0016 #ifndef BOOST_FILESYSTEM_DIRECTORY_HPP
0017 #define BOOST_FILESYSTEM_DIRECTORY_HPP
0018 
0019 #include <boost/filesystem/config.hpp>
0020 #include <boost/filesystem/path.hpp>
0021 #include <boost/filesystem/file_status.hpp>
0022 #include <boost/filesystem/detail/path_traits.hpp>
0023 
0024 #include <cstddef>
0025 #include <string>
0026 #include <vector>
0027 
0028 #include <boost/assert.hpp>
0029 #include <boost/detail/bitmask.hpp>
0030 #include <boost/system/error_code.hpp>
0031 #include <boost/smart_ptr/intrusive_ptr.hpp>
0032 #include <boost/smart_ptr/intrusive_ref_counter.hpp>
0033 #include <boost/iterator/iterator_facade.hpp>
0034 #include <boost/iterator/iterator_categories.hpp>
0035 
0036 #include <boost/filesystem/detail/header.hpp> // must be the last #include
0037 
0038 //--------------------------------------------------------------------------------------//
0039 
0040 namespace boost {
0041 namespace filesystem {
0042 
0043 enum class directory_options : unsigned int
0044 {
0045     none = 0u,
0046     skip_permission_denied = 1u,         // if a directory cannot be opened because of insufficient permissions, pretend that the directory is empty
0047     follow_directory_symlink = 1u << 1u, // recursive_directory_iterator: follow directory symlinks
0048     skip_dangling_symlinks = 1u << 2u,   // non-standard extension for recursive_directory_iterator: don't follow dangling directory symlinks,
0049     pop_on_error = 1u << 3u,             // non-standard extension for recursive_directory_iterator: instead of producing an end iterator on errors,
0050                                          // repeatedly invoke pop() until it succeeds or the iterator becomes equal to end iterator
0051     _detail_no_follow = 1u << 4u,        // internal use only
0052     _detail_no_push = 1u << 5u           // internal use only
0053 };
0054 
0055 BOOST_BITMASK(directory_options)
0056 
0057 class directory_iterator;
0058 class recursive_directory_iterator;
0059 
0060 namespace detail {
0061 
0062 struct directory_iterator_params;
0063 
0064 BOOST_FILESYSTEM_DECL void directory_iterator_construct(directory_iterator& it, path const& p, directory_options opts, directory_iterator_params* params, system::error_code* ec);
0065 BOOST_FILESYSTEM_DECL void directory_iterator_increment(directory_iterator& it, system::error_code* ec);
0066 
0067 struct recur_dir_itr_imp;
0068 
0069 BOOST_FILESYSTEM_DECL void recursive_directory_iterator_construct(recursive_directory_iterator& it, path const& dir_path, directory_options opts, system::error_code* ec);
0070 BOOST_FILESYSTEM_DECL void recursive_directory_iterator_increment(recursive_directory_iterator& it, system::error_code* ec);
0071 BOOST_FILESYSTEM_DECL void recursive_directory_iterator_pop(recursive_directory_iterator& it, system::error_code* ec);
0072 
0073 } // namespace detail
0074 
0075 //--------------------------------------------------------------------------------------//
0076 //                                                                                      //
0077 //                                 directory_entry                                      //
0078 //                                                                                      //
0079 //--------------------------------------------------------------------------------------//
0080 
0081 //  GCC has a problem with a member function named path within a namespace or
0082 //  sub-namespace that also has a class named path. The workaround is to always
0083 //  fully qualify the name path when it refers to the class name.
0084 
0085 class directory_entry
0086 {
0087     friend BOOST_FILESYSTEM_DECL void detail::directory_iterator_construct(directory_iterator& it, path const& p, directory_options opts, detail::directory_iterator_params* params, system::error_code* ec);
0088     friend BOOST_FILESYSTEM_DECL void detail::directory_iterator_increment(directory_iterator& it, system::error_code* ec);
0089 
0090     friend BOOST_FILESYSTEM_DECL void detail::recursive_directory_iterator_increment(recursive_directory_iterator& it, system::error_code* ec);
0091 
0092 public:
0093     typedef boost::filesystem::path::value_type value_type; // enables class path ctor taking directory_entry
0094 
0095     directory_entry() noexcept {}
0096 
0097     explicit directory_entry(boost::filesystem::path const& p);
0098 
0099 #if BOOST_FILESYSTEM_VERSION >= 4
0100     directory_entry(boost::filesystem::path const& p, system::error_code& ec) :
0101         m_path(p)
0102     {
0103         refresh_impl(&ec);
0104         if (ec)
0105             m_path.clear();
0106     }
0107 #else
0108     directory_entry(boost::filesystem::path const& p, file_status st, file_status symlink_st = file_status()) :
0109         m_path(p), m_status(st), m_symlink_status(symlink_st)
0110     {
0111     }
0112 #endif
0113 
0114     directory_entry(directory_entry const& rhs) :
0115         m_path(rhs.m_path), m_status(rhs.m_status), m_symlink_status(rhs.m_symlink_status)
0116     {
0117     }
0118 
0119     directory_entry& operator=(directory_entry const& rhs)
0120     {
0121         m_path = rhs.m_path;
0122         m_status = rhs.m_status;
0123         m_symlink_status = rhs.m_symlink_status;
0124         return *this;
0125     }
0126 
0127     directory_entry(directory_entry&& rhs) noexcept :
0128         m_path(static_cast< boost::filesystem::path&& >(rhs.m_path)),
0129         m_status(static_cast< file_status&& >(rhs.m_status)),
0130         m_symlink_status(static_cast< file_status&& >(rhs.m_symlink_status))
0131     {
0132     }
0133 
0134     directory_entry& operator=(directory_entry&& rhs) noexcept
0135     {
0136         m_path = static_cast< boost::filesystem::path&& >(rhs.m_path);
0137         m_status = static_cast< file_status&& >(rhs.m_status);
0138         m_symlink_status = static_cast< file_status&& >(rhs.m_symlink_status);
0139         return *this;
0140     }
0141 
0142     void assign(boost::filesystem::path&& p);
0143 
0144 #if BOOST_FILESYSTEM_VERSION >= 4
0145     void assign(boost::filesystem::path&& p, system::error_code& ec)
0146     {
0147         m_path = static_cast< boost::filesystem::path&& >(p);
0148         refresh_impl(&ec);
0149     }
0150 #else
0151     void assign(boost::filesystem::path&& p, file_status st, file_status symlink_st = file_status())
0152     {
0153         assign_with_status(static_cast< boost::filesystem::path&& >(p), st, symlink_st);
0154     }
0155 #endif
0156 
0157     void assign(boost::filesystem::path const& p);
0158 
0159 #if BOOST_FILESYSTEM_VERSION >= 4
0160     void assign(boost::filesystem::path const& p, system::error_code& ec)
0161     {
0162         m_path = p;
0163         refresh_impl(&ec);
0164     }
0165 #else
0166     void assign(boost::filesystem::path const& p, file_status st, file_status symlink_st = file_status())
0167     {
0168         assign_with_status(p, st, symlink_st);
0169     }
0170 #endif
0171 
0172     void replace_filename(boost::filesystem::path const& p);
0173 
0174 #if BOOST_FILESYSTEM_VERSION >= 4
0175     void replace_filename(boost::filesystem::path const& p, system::error_code& ec)
0176     {
0177         m_path.replace_filename(p);
0178         refresh_impl(&ec);
0179     }
0180 #else
0181     void replace_filename(boost::filesystem::path const& p, file_status st, file_status symlink_st = file_status())
0182     {
0183         replace_filename_with_status(p, st, symlink_st);
0184     }
0185 
0186     BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use directory_entry::replace_filename() instead")
0187     void replace_leaf(boost::filesystem::path const& p, file_status st, file_status symlink_st)
0188     {
0189         replace_filename_with_status(p, st, symlink_st);
0190     }
0191 #endif
0192 
0193     boost::filesystem::path const& path() const noexcept { return m_path; }
0194     operator boost::filesystem::path const&() const noexcept { return m_path; }
0195 
0196     void refresh() { refresh_impl(); }
0197     void refresh(system::error_code& ec) noexcept { refresh_impl(&ec); }
0198 
0199     file_status status() const
0200     {
0201         if (!filesystem::status_known(m_status))
0202             refresh_impl();
0203         return m_status;
0204     }
0205 
0206     file_status status(system::error_code& ec) const noexcept
0207     {
0208         ec.clear();
0209 
0210         if (!filesystem::status_known(m_status))
0211             refresh_impl(&ec);
0212         return m_status;
0213     }
0214 
0215     file_status symlink_status() const
0216     {
0217         if (!filesystem::status_known(m_symlink_status))
0218             refresh_impl();
0219         return m_symlink_status;
0220     }
0221 
0222     file_status symlink_status(system::error_code& ec) const noexcept
0223     {
0224         ec.clear();
0225 
0226         if (!filesystem::status_known(m_symlink_status))
0227             refresh_impl(&ec);
0228         return m_symlink_status;
0229     }
0230 
0231     filesystem::file_type file_type() const
0232     {
0233         if (!filesystem::type_present(m_status))
0234             refresh_impl();
0235         return m_status.type();
0236     }
0237 
0238     filesystem::file_type file_type(system::error_code& ec) const noexcept
0239     {
0240         ec.clear();
0241 
0242         if (!filesystem::type_present(m_status))
0243             refresh_impl(&ec);
0244         return m_status.type();
0245     }
0246 
0247     filesystem::file_type symlink_file_type() const
0248     {
0249         if (!filesystem::type_present(m_symlink_status))
0250             refresh_impl();
0251         return m_symlink_status.type();
0252     }
0253 
0254     filesystem::file_type symlink_file_type(system::error_code& ec) const noexcept
0255     {
0256         ec.clear();
0257 
0258         if (!filesystem::type_present(m_symlink_status))
0259             refresh_impl(&ec);
0260         return m_symlink_status.type();
0261     }
0262 
0263     bool exists() const
0264     {
0265         filesystem::file_type ft = this->file_type();
0266         return ft != filesystem::status_error && ft != filesystem::file_not_found;
0267     }
0268 
0269     bool exists(system::error_code& ec) const noexcept
0270     {
0271         filesystem::file_type ft = this->file_type(ec);
0272         return ft != filesystem::status_error && ft != filesystem::file_not_found;
0273     }
0274 
0275     bool is_regular_file() const
0276     {
0277         return this->file_type() == filesystem::regular_file;
0278     }
0279 
0280     bool is_regular_file(system::error_code& ec) const noexcept
0281     {
0282         return this->file_type(ec) == filesystem::regular_file;
0283     }
0284 
0285     bool is_directory() const
0286     {
0287         return this->file_type() == filesystem::directory_file;
0288     }
0289 
0290     bool is_directory(system::error_code& ec) const noexcept
0291     {
0292         return this->file_type(ec) == filesystem::directory_file;
0293     }
0294 
0295     bool is_symlink() const
0296     {
0297         return this->symlink_file_type() == filesystem::symlink_file;
0298     }
0299 
0300     bool is_symlink(system::error_code& ec) const noexcept
0301     {
0302         return this->symlink_file_type(ec) == filesystem::symlink_file;
0303     }
0304 
0305     bool is_block_file() const
0306     {
0307         return this->file_type() == filesystem::block_file;
0308     }
0309 
0310     bool is_block_file(system::error_code& ec) const noexcept
0311     {
0312         return this->file_type(ec) == filesystem::block_file;
0313     }
0314 
0315     bool is_character_file() const
0316     {
0317         return this->file_type() == filesystem::character_file;
0318     }
0319 
0320     bool is_character_file(system::error_code& ec) const noexcept
0321     {
0322         return this->file_type(ec) == filesystem::character_file;
0323     }
0324 
0325     bool is_fifo() const
0326     {
0327         return this->file_type() == filesystem::fifo_file;
0328     }
0329 
0330     bool is_fifo(system::error_code& ec) const noexcept
0331     {
0332         return this->file_type(ec) == filesystem::fifo_file;
0333     }
0334 
0335     bool is_socket() const
0336     {
0337         return this->file_type() == filesystem::socket_file;
0338     }
0339 
0340     bool is_socket(system::error_code& ec) const noexcept
0341     {
0342         return this->file_type(ec) == filesystem::socket_file;
0343     }
0344 
0345     bool is_reparse_file() const
0346     {
0347         return this->symlink_file_type() == filesystem::reparse_file;
0348     }
0349 
0350     bool is_reparse_file(system::error_code& ec) const noexcept
0351     {
0352         return this->symlink_file_type(ec) == filesystem::reparse_file;
0353     }
0354 
0355     bool is_other() const
0356     {
0357         filesystem::file_type ft = this->file_type();
0358         return ft != filesystem::status_error && ft != filesystem::file_not_found &&
0359             ft != filesystem::regular_file && ft != filesystem::directory_file;
0360     }
0361 
0362     bool is_other(system::error_code& ec) const noexcept
0363     {
0364         filesystem::file_type ft = this->file_type(ec);
0365         return ft != filesystem::status_error && ft != filesystem::file_not_found &&
0366             ft != filesystem::regular_file && ft != filesystem::directory_file;
0367     }
0368 
0369     bool operator==(directory_entry const& rhs) const { return m_path == rhs.m_path; }
0370     bool operator!=(directory_entry const& rhs) const { return m_path != rhs.m_path; }
0371     bool operator<(directory_entry const& rhs) const { return m_path < rhs.m_path; }
0372     bool operator<=(directory_entry const& rhs) const { return m_path <= rhs.m_path; }
0373     bool operator>(directory_entry const& rhs) const { return m_path > rhs.m_path; }
0374     bool operator>=(directory_entry const& rhs) const { return m_path >= rhs.m_path; }
0375 
0376 private:
0377     BOOST_FILESYSTEM_DECL void refresh_impl(system::error_code* ec = nullptr) const;
0378 
0379     void assign_with_status(boost::filesystem::path&& p, file_status st, file_status symlink_st)
0380     {
0381         m_path = static_cast< boost::filesystem::path&& >(p);
0382         m_status = static_cast< file_status&& >(st);
0383         m_symlink_status = static_cast< file_status&& >(symlink_st);
0384     }
0385 
0386     void assign_with_status(boost::filesystem::path const& p, file_status st, file_status symlink_st)
0387     {
0388         m_path = p;
0389         m_status = static_cast< file_status&& >(st);
0390         m_symlink_status = static_cast< file_status&& >(symlink_st);
0391     }
0392 
0393     void replace_filename_with_status(boost::filesystem::path const& p, file_status st, file_status symlink_st)
0394     {
0395         m_path.replace_filename(p);
0396         m_status = static_cast< file_status&& >(st);
0397         m_symlink_status = static_cast< file_status&& >(symlink_st);
0398     }
0399 
0400 private:
0401     boost::filesystem::path m_path;
0402     mutable file_status m_status;         // stat()-like
0403     mutable file_status m_symlink_status; // lstat()-like
0404 };
0405 
0406 #if !defined(BOOST_FILESYSTEM_SOURCE)
0407 
0408 inline directory_entry::directory_entry(boost::filesystem::path const& p) :
0409     m_path(p)
0410 {
0411 #if BOOST_FILESYSTEM_VERSION >= 4
0412     refresh_impl();
0413 #endif
0414 }
0415 
0416 inline void directory_entry::assign(boost::filesystem::path&& p)
0417 {
0418     m_path = static_cast< boost::filesystem::path&& >(p);
0419 #if BOOST_FILESYSTEM_VERSION >= 4
0420     refresh_impl();
0421 #else
0422     m_status = file_status();
0423     m_symlink_status = file_status();
0424 #endif
0425 }
0426 
0427 inline void directory_entry::assign(boost::filesystem::path const& p)
0428 {
0429     m_path = p;
0430 #if BOOST_FILESYSTEM_VERSION >= 4
0431     refresh_impl();
0432 #else
0433     m_status = file_status();
0434     m_symlink_status = file_status();
0435 #endif
0436 }
0437 
0438 inline void directory_entry::replace_filename(boost::filesystem::path const& p)
0439 {
0440     m_path.replace_filename(p);
0441 #if BOOST_FILESYSTEM_VERSION >= 4
0442     refresh_impl();
0443 #else
0444     m_status = file_status();
0445     m_symlink_status = file_status();
0446 #endif
0447 }
0448 
0449 #endif // !defined(BOOST_FILESYSTEM_SOURCE)
0450 
0451 namespace detail {
0452 namespace path_traits {
0453 
0454 // Dispatch function for integration with path class
0455 template< typename Callback >
0456 BOOST_FORCEINLINE typename Callback::result_type dispatch(directory_entry const& de, Callback cb, const codecvt_type* cvt, directory_entry_tag)
0457 {
0458     boost::filesystem::path::string_type const& source = de.path().native();
0459     return cb(source.data(), source.data() + source.size(), cvt);
0460 }
0461 
0462 } // namespace path_traits
0463 } // namespace detail
0464 
0465 //--------------------------------------------------------------------------------------//
0466 //                                                                                      //
0467 //                            directory_entry overloads                                 //
0468 //                                                                                      //
0469 //--------------------------------------------------------------------------------------//
0470 
0471 //  Without these functions, calling (for example) 'is_directory' with a 'directory_entry' results in:
0472 //  - a conversion to 'path' using 'operator boost::filesystem::path const&()',
0473 //  - then a call to 'is_directory(path const& p)' which recomputes the status with 'detail::status(p)'.
0474 //
0475 //  These functions avoid a costly recomputation of the status if one calls 'is_directory(e)' instead of 'is_directory(e.status())'
0476 
0477 inline file_status status(directory_entry const& e)
0478 {
0479     return e.status();
0480 }
0481 
0482 inline file_status status(directory_entry const& e, system::error_code& ec) noexcept
0483 {
0484     return e.status(ec);
0485 }
0486 
0487 inline file_status symlink_status(directory_entry const& e)
0488 {
0489     return e.symlink_status();
0490 }
0491 
0492 inline file_status symlink_status(directory_entry const& e, system::error_code& ec) noexcept
0493 {
0494     return e.symlink_status(ec);
0495 }
0496 
0497 inline bool type_present(directory_entry const& e)
0498 {
0499     return e.file_type() != filesystem::status_error;
0500 }
0501 
0502 inline bool type_present(directory_entry const& e, system::error_code& ec) noexcept
0503 {
0504     return e.file_type(ec) != filesystem::status_error;
0505 }
0506 
0507 inline bool status_known(directory_entry const& e)
0508 {
0509     return filesystem::status_known(e.status());
0510 }
0511 
0512 inline bool status_known(directory_entry const& e, system::error_code& ec) noexcept
0513 {
0514     return filesystem::status_known(e.status(ec));
0515 }
0516 
0517 inline bool exists(directory_entry const& e)
0518 {
0519     return e.exists();
0520 }
0521 
0522 inline bool exists(directory_entry const& e, system::error_code& ec) noexcept
0523 {
0524     return e.exists(ec);
0525 }
0526 
0527 inline bool is_regular_file(directory_entry const& e)
0528 {
0529     return e.is_regular_file();
0530 }
0531 
0532 inline bool is_regular_file(directory_entry const& e, system::error_code& ec) noexcept
0533 {
0534     return e.is_regular_file(ec);
0535 }
0536 
0537 inline bool is_directory(directory_entry const& e)
0538 {
0539     return e.is_directory();
0540 }
0541 
0542 inline bool is_directory(directory_entry const& e, system::error_code& ec) noexcept
0543 {
0544     return e.is_directory(ec);
0545 }
0546 
0547 inline bool is_symlink(directory_entry const& e)
0548 {
0549     return e.is_symlink();
0550 }
0551 
0552 inline bool is_symlink(directory_entry const& e, system::error_code& ec) noexcept
0553 {
0554     return e.is_symlink(ec);
0555 }
0556 
0557 inline bool is_block_file(directory_entry const& e)
0558 {
0559     return e.is_block_file();
0560 }
0561 
0562 inline bool is_block_file(directory_entry const& e, system::error_code& ec) noexcept
0563 {
0564     return e.is_block_file(ec);
0565 }
0566 
0567 inline bool is_character_file(directory_entry const& e)
0568 {
0569     return e.is_character_file();
0570 }
0571 
0572 inline bool is_character_file(directory_entry const& e, system::error_code& ec) noexcept
0573 {
0574     return e.is_character_file(ec);
0575 }
0576 
0577 inline bool is_fifo(directory_entry const& e)
0578 {
0579     return e.is_fifo();
0580 }
0581 
0582 inline bool is_fifo(directory_entry const& e, system::error_code& ec) noexcept
0583 {
0584     return e.is_fifo(ec);
0585 }
0586 
0587 inline bool is_socket(directory_entry const& e)
0588 {
0589     return e.is_socket();
0590 }
0591 
0592 inline bool is_socket(directory_entry const& e, system::error_code& ec) noexcept
0593 {
0594     return e.is_socket(ec);
0595 }
0596 
0597 inline bool is_reparse_file(directory_entry const& e)
0598 {
0599     return e.is_reparse_file();
0600 }
0601 
0602 inline bool is_reparse_file(directory_entry const& e, system::error_code& ec) noexcept
0603 {
0604     return e.is_reparse_file(ec);
0605 }
0606 
0607 inline bool is_other(directory_entry const& e)
0608 {
0609     return e.is_other();
0610 }
0611 
0612 inline bool is_other(directory_entry const& e, system::error_code& ec) noexcept
0613 {
0614     return e.is_other(ec);
0615 }
0616 
0617 //--------------------------------------------------------------------------------------//
0618 //                                                                                      //
0619 //                            directory_iterator helpers                                //
0620 //                                                                                      //
0621 //--------------------------------------------------------------------------------------//
0622 
0623 namespace detail {
0624 
0625 struct dir_itr_imp :
0626     public boost::intrusive_ref_counter< dir_itr_imp >
0627 {
0628 #ifdef BOOST_WINDOWS_API
0629     bool close_handle;
0630     unsigned char extra_data_format;
0631     std::size_t current_offset;
0632 #endif
0633     directory_entry dir_entry;
0634     void* handle;
0635 
0636     dir_itr_imp() noexcept :
0637 #ifdef BOOST_WINDOWS_API
0638         close_handle(false),
0639         extra_data_format(0u),
0640         current_offset(0u),
0641 #endif
0642         handle(nullptr)
0643     {
0644     }
0645     BOOST_FILESYSTEM_DECL ~dir_itr_imp() noexcept;
0646 
0647     BOOST_FILESYSTEM_DECL static void* operator new(std::size_t class_size, std::size_t extra_size) noexcept;
0648     BOOST_FILESYSTEM_DECL static void operator delete(void* p, std::size_t extra_size) noexcept;
0649     BOOST_FILESYSTEM_DECL static void operator delete(void* p) noexcept;
0650 };
0651 
0652 } // namespace detail
0653 
0654 //--------------------------------------------------------------------------------------//
0655 //                                                                                      //
0656 //                                directory_iterator                                    //
0657 //                                                                                      //
0658 //--------------------------------------------------------------------------------------//
0659 
0660 class directory_iterator :
0661     public boost::iterator_facade<
0662         directory_iterator,
0663         directory_entry,
0664         boost::single_pass_traversal_tag
0665     >
0666 {
0667     friend class boost::iterator_core_access;
0668 
0669     friend BOOST_FILESYSTEM_DECL void detail::directory_iterator_construct(directory_iterator& it, path const& p, directory_options opts, detail::directory_iterator_params* params, system::error_code* ec);
0670     friend BOOST_FILESYSTEM_DECL void detail::directory_iterator_increment(directory_iterator& it, system::error_code* ec);
0671 
0672     friend BOOST_FILESYSTEM_DECL void detail::recursive_directory_iterator_increment(recursive_directory_iterator& it, system::error_code* ec);
0673 
0674 public:
0675     directory_iterator() noexcept {} // creates the "end" iterator
0676 
0677     // iterator_facade derived classes don't seem to like implementations in
0678     // separate translation unit dll's, so forward to detail functions
0679     explicit directory_iterator(path const& p, directory_options opts = directory_options::none)
0680     {
0681         detail::directory_iterator_construct(*this, p, opts, nullptr, nullptr);
0682     }
0683 
0684     directory_iterator(path const& p, system::error_code& ec) noexcept
0685     {
0686         detail::directory_iterator_construct(*this, p, directory_options::none, nullptr, &ec);
0687     }
0688 
0689     directory_iterator(path const& p, directory_options opts, system::error_code& ec) noexcept
0690     {
0691         detail::directory_iterator_construct(*this, p, opts, nullptr, &ec);
0692     }
0693 
0694     directory_iterator(directory_iterator const&) = default;
0695     directory_iterator& operator=(directory_iterator const&) = default;
0696 
0697     directory_iterator(directory_iterator&& that) noexcept :
0698         m_imp(static_cast< boost::intrusive_ptr< detail::dir_itr_imp >&& >(that.m_imp))
0699     {
0700     }
0701 
0702     directory_iterator& operator=(directory_iterator&& that) noexcept
0703     {
0704         m_imp = static_cast< boost::intrusive_ptr< detail::dir_itr_imp >&& >(that.m_imp);
0705         return *this;
0706     }
0707 
0708     directory_iterator& increment(system::error_code& ec) noexcept
0709     {
0710         detail::directory_iterator_increment(*this, &ec);
0711         return *this;
0712     }
0713 
0714 private:
0715     boost::iterator_facade<
0716         directory_iterator,
0717         directory_entry,
0718         boost::single_pass_traversal_tag
0719     >::reference dereference() const
0720     {
0721         BOOST_ASSERT_MSG(!is_end(), "attempt to dereference end directory iterator");
0722         return m_imp->dir_entry;
0723     }
0724 
0725     void increment() { detail::directory_iterator_increment(*this, nullptr); }
0726 
0727     bool equal(directory_iterator const& rhs) const noexcept
0728     {
0729         return m_imp == rhs.m_imp || (is_end() && rhs.is_end());
0730     }
0731 
0732     bool is_end() const noexcept
0733     {
0734         // Note: The check for handle is needed because the iterator can be copied and the copy
0735         // can be incremented to end while the original iterator still refers to the same dir_itr_imp.
0736         return !m_imp || !m_imp->handle;
0737     }
0738 
0739 private:
0740     // intrusive_ptr provides the shallow-copy semantics required for single pass iterators
0741     // (i.e. InputIterators). The end iterator is indicated by is_end().
0742     boost::intrusive_ptr< detail::dir_itr_imp > m_imp;
0743 };
0744 
0745 //  enable directory_iterator C++11 range-based for statement use  --------------------//
0746 
0747 // begin() and end() are only used by a range-based for statement in the context of
0748 // auto - thus the top-level const is stripped - so returning const is harmless and
0749 // emphasizes begin() is just a pass through.
0750 inline directory_iterator const& begin(directory_iterator const& iter) noexcept
0751 {
0752     return iter;
0753 }
0754 
0755 inline directory_iterator end(directory_iterator const&) noexcept
0756 {
0757     return directory_iterator();
0758 }
0759 
0760 // enable C++14 generic accessors for range const iterators
0761 inline directory_iterator const& cbegin(directory_iterator const& iter) noexcept
0762 {
0763     return iter;
0764 }
0765 
0766 inline directory_iterator cend(directory_iterator const&) noexcept
0767 {
0768     return directory_iterator();
0769 }
0770 
0771 //  enable directory_iterator BOOST_FOREACH  -----------------------------------------//
0772 
0773 inline directory_iterator& range_begin(directory_iterator& iter) noexcept
0774 {
0775     return iter;
0776 }
0777 
0778 inline directory_iterator range_begin(directory_iterator const& iter) noexcept
0779 {
0780     return iter;
0781 }
0782 
0783 inline directory_iterator range_end(directory_iterator&) noexcept
0784 {
0785     return directory_iterator();
0786 }
0787 
0788 inline directory_iterator range_end(directory_iterator const&) noexcept
0789 {
0790     return directory_iterator();
0791 }
0792 
0793 } // namespace filesystem
0794 
0795 //  namespace boost template specializations
0796 template< typename C, typename Enabler >
0797 struct range_mutable_iterator;
0798 
0799 template<>
0800 struct range_mutable_iterator< boost::filesystem::directory_iterator, void >
0801 {
0802     typedef boost::filesystem::directory_iterator type;
0803 };
0804 
0805 template< typename C, typename Enabler >
0806 struct range_const_iterator;
0807 
0808 template<>
0809 struct range_const_iterator< boost::filesystem::directory_iterator, void >
0810 {
0811     typedef boost::filesystem::directory_iterator type;
0812 };
0813 
0814 namespace filesystem {
0815 
0816 //--------------------------------------------------------------------------------------//
0817 //                                                                                      //
0818 //                      recursive_directory_iterator helpers                            //
0819 //                                                                                      //
0820 //--------------------------------------------------------------------------------------//
0821 
0822 namespace detail {
0823 
0824 struct recur_dir_itr_imp :
0825     public boost::intrusive_ref_counter< recur_dir_itr_imp >
0826 {
0827     typedef directory_iterator element_type;
0828     std::vector< element_type > m_stack;
0829     directory_options m_options;
0830 
0831     explicit recur_dir_itr_imp(directory_options opts) noexcept : m_options(opts) {}
0832 };
0833 
0834 } // namespace detail
0835 
0836 //--------------------------------------------------------------------------------------//
0837 //                                                                                      //
0838 //                           recursive_directory_iterator                               //
0839 //                                                                                      //
0840 //--------------------------------------------------------------------------------------//
0841 
0842 class recursive_directory_iterator :
0843     public boost::iterator_facade<
0844         recursive_directory_iterator,
0845         directory_entry,
0846         boost::single_pass_traversal_tag
0847     >
0848 {
0849     friend class boost::iterator_core_access;
0850 
0851     friend BOOST_FILESYSTEM_DECL void detail::recursive_directory_iterator_construct(recursive_directory_iterator& it, path const& dir_path, directory_options opts, system::error_code* ec);
0852     friend BOOST_FILESYSTEM_DECL void detail::recursive_directory_iterator_increment(recursive_directory_iterator& it, system::error_code* ec);
0853     friend BOOST_FILESYSTEM_DECL void detail::recursive_directory_iterator_pop(recursive_directory_iterator& it, system::error_code* ec);
0854 
0855 public:
0856     recursive_directory_iterator() noexcept {} // creates the "end" iterator
0857 
0858     explicit recursive_directory_iterator(path const& dir_path)
0859     {
0860         detail::recursive_directory_iterator_construct(*this, dir_path, directory_options::none, nullptr);
0861     }
0862 
0863     recursive_directory_iterator(path const& dir_path, system::error_code& ec)
0864     {
0865         detail::recursive_directory_iterator_construct(*this, dir_path, directory_options::none, &ec);
0866     }
0867 
0868     recursive_directory_iterator(path const& dir_path, directory_options opts)
0869     {
0870         detail::recursive_directory_iterator_construct(*this, dir_path, opts, nullptr);
0871     }
0872 
0873     recursive_directory_iterator(path const& dir_path, directory_options opts, system::error_code& ec)
0874     {
0875         detail::recursive_directory_iterator_construct(*this, dir_path, opts, &ec);
0876     }
0877 
0878     recursive_directory_iterator(recursive_directory_iterator const&) = default;
0879     recursive_directory_iterator& operator=(recursive_directory_iterator const&) = default;
0880 
0881     recursive_directory_iterator(recursive_directory_iterator&& that) noexcept :
0882         m_imp(static_cast< boost::intrusive_ptr< detail::recur_dir_itr_imp >&& >(that.m_imp))
0883     {
0884     }
0885 
0886     recursive_directory_iterator& operator=(recursive_directory_iterator&& that) noexcept
0887     {
0888         m_imp = static_cast< boost::intrusive_ptr< detail::recur_dir_itr_imp >&& >(that.m_imp);
0889         return *this;
0890     }
0891 
0892     recursive_directory_iterator& increment(system::error_code& ec) noexcept
0893     {
0894         detail::recursive_directory_iterator_increment(*this, &ec);
0895         return *this;
0896     }
0897 
0898     int depth() const noexcept
0899     {
0900         BOOST_ASSERT_MSG(!is_end(), "depth() on end recursive_directory_iterator");
0901         return static_cast< int >(m_imp->m_stack.size() - 1u);
0902     }
0903 
0904     bool recursion_pending() const noexcept
0905     {
0906         BOOST_ASSERT_MSG(!is_end(), "recursion_pending() on end recursive_directory_iterator");
0907         return (m_imp->m_options & directory_options::_detail_no_push) == directory_options::none;
0908     }
0909 
0910     void pop()
0911     {
0912         detail::recursive_directory_iterator_pop(*this, nullptr);
0913     }
0914 
0915     void pop(system::error_code& ec) noexcept
0916     {
0917         detail::recursive_directory_iterator_pop(*this, &ec);
0918     }
0919 
0920     void disable_recursion_pending(bool value = true) noexcept
0921     {
0922         BOOST_ASSERT_MSG(!is_end(), "disable_recursion_pending() on end recursive_directory_iterator");
0923         if (value)
0924             m_imp->m_options |= directory_options::_detail_no_push;
0925         else
0926             m_imp->m_options &= ~directory_options::_detail_no_push;
0927     }
0928 
0929     file_status status() const
0930     {
0931         BOOST_ASSERT_MSG(!is_end(), "status() on end recursive_directory_iterator");
0932         return m_imp->m_stack.back()->status();
0933     }
0934 
0935     file_status symlink_status() const
0936     {
0937         BOOST_ASSERT_MSG(!is_end(), "symlink_status() on end recursive_directory_iterator");
0938         return m_imp->m_stack.back()->symlink_status();
0939     }
0940 
0941 private:
0942     boost::iterator_facade<
0943         recursive_directory_iterator,
0944         directory_entry,
0945         boost::single_pass_traversal_tag
0946     >::reference dereference() const
0947     {
0948         BOOST_ASSERT_MSG(!is_end(), "dereference of end recursive_directory_iterator");
0949         return *m_imp->m_stack.back();
0950     }
0951 
0952     void increment() { detail::recursive_directory_iterator_increment(*this, nullptr); }
0953 
0954     bool equal(recursive_directory_iterator const& rhs) const noexcept
0955     {
0956         return m_imp == rhs.m_imp || (is_end() && rhs.is_end());
0957     }
0958 
0959     bool is_end() const noexcept
0960     {
0961         // Note: The check for m_stack.empty() is needed because the iterator can be copied and the copy
0962         // can be incremented to end while the original iterator still refers to the same recur_dir_itr_imp.
0963         return !m_imp || m_imp->m_stack.empty();
0964     }
0965 
0966 private:
0967     // intrusive_ptr provides the shallow-copy semantics required for single pass iterators
0968     // (i.e. InputIterators). The end iterator is indicated by is_end().
0969     boost::intrusive_ptr< detail::recur_dir_itr_imp > m_imp;
0970 };
0971 
0972 //  enable recursive directory iterator C++11 range-base for statement use  ----------//
0973 
0974 // begin() and end() are only used by a range-based for statement in the context of
0975 // auto - thus the top-level const is stripped - so returning const is harmless and
0976 // emphasizes begin() is just a pass through.
0977 inline recursive_directory_iterator const& begin(recursive_directory_iterator const& iter) noexcept
0978 {
0979     return iter;
0980 }
0981 
0982 inline recursive_directory_iterator end(recursive_directory_iterator const&) noexcept
0983 {
0984     return recursive_directory_iterator();
0985 }
0986 
0987 // enable C++14 generic accessors for range const iterators
0988 inline recursive_directory_iterator const& cbegin(recursive_directory_iterator const& iter) noexcept
0989 {
0990     return iter;
0991 }
0992 
0993 inline recursive_directory_iterator cend(recursive_directory_iterator const&) noexcept
0994 {
0995     return recursive_directory_iterator();
0996 }
0997 
0998 //  enable recursive directory iterator BOOST_FOREACH  -------------------------------//
0999 
1000 inline recursive_directory_iterator& range_begin(recursive_directory_iterator& iter) noexcept
1001 {
1002     return iter;
1003 }
1004 
1005 inline recursive_directory_iterator range_begin(recursive_directory_iterator const& iter) noexcept
1006 {
1007     return iter;
1008 }
1009 
1010 inline recursive_directory_iterator range_end(recursive_directory_iterator&) noexcept
1011 {
1012     return recursive_directory_iterator();
1013 }
1014 
1015 inline recursive_directory_iterator range_end(recursive_directory_iterator const&) noexcept
1016 {
1017     return recursive_directory_iterator();
1018 }
1019 
1020 } // namespace filesystem
1021 
1022 //  namespace boost template specializations
1023 template<>
1024 struct range_mutable_iterator< boost::filesystem::recursive_directory_iterator, void >
1025 {
1026     typedef boost::filesystem::recursive_directory_iterator type;
1027 };
1028 
1029 template<>
1030 struct range_const_iterator< boost::filesystem::recursive_directory_iterator, void >
1031 {
1032     typedef boost::filesystem::recursive_directory_iterator type;
1033 };
1034 
1035 } // namespace boost
1036 
1037 #include <boost/filesystem/detail/footer.hpp>
1038 
1039 #endif // BOOST_FILESYSTEM_DIRECTORY_HPP