Sponsored Link •
|
Defines a const_iterator
for readdir_sequence
/* ///////////////////////////////////////////////////////////// * Extract from unixstl_readdir_sequence.h * * www: http://www.synesis.com.au/unixstl * http://www.unixstl.org/ * * Copyright (C) 2002-2004, Synesis Software Pty Ltd. * (Licensed under the Synesis Software Standard Source License: * http://www.synesis.com.au/licenses/ssssl.html) * ////////////////////////////////////////////////////////// */ ... // Includes (as shown in Listing 3) class readdir_sequence::const_iterator : public stlsoft::iterator_base < std::input_iterator_tag , readdir_sequence::value_type , ptrdiff_t , readdir_sequence::value_type* , readdir_sequence::value_type& > { private: typedef readdir_sequence::string_type string_type; public: typedef const_iterator class_type; typedef readdir_sequence::value_type value_type; // Construction private: friend class readdir_sequence; const_iterator(DIR *dir, string_type const &directory, unsigned flags); public: const_iterator(); const_iterator(class_type const &rhs); ~const_iterator(); class_type const &operator =(class_type const &rhs); // Accessors public: value_type operator *() const; class_type &operator ++(); class_type operator ++(int); bool operator ==(class_type const &rhs) const; bool operator !=(class_type const &rhs) const; // Members private: struct rds_shared_handle; rds_shared_handle *m_handle; // The DIR handle, shared with other iterator instances struct dirent *m_entry; // The current entry unsigned m_flags; // flags. (Only non-const, to allow copy assignment) string_type m_scratch; // Holds the directory, and is a scratch area size_type m_dirLen; // The length of the directory }; struct readdir_sequence::const_iterator::rds_shared_handle { public: typedef rds_shared_handle class_type; // Members public: DIR *dir; private: int cRefs; public: explicit rds_shared_handle(DIR *d); void AddRef(); void Release(); #if defined(__GNUC__) /* Silly old "helpful" GCC! */ protected: #else /* ? __GNUC__ */ private: #endif /* __GNUC__ */ ~rds_shared_handle(); private: rds_shared_handle(class_type const &); class_type &operator =(class_type const &); }; /* ///////////////////////////////////////////////////////////////////////////// * Implementation */ inline readdir_sequence::const_iterator::const_iterator(DIR *dir , readdir_sequence::string_type const &directory , unsigned flags) : m_handle(new rds_shared_handle(dir)) , m_entry(NULL) , m_flags(flags) , m_scratch(directory) , m_dirLen(directory.length()) { unixstl_assert(0 != traits_type::has_dir_end(stlsoft_ns_qual(c_str_ptr)(m_scratch))); if(NULL != m_handle) { operator ++(); } } inline readdir_sequence::const_iterator::const_iterator() : m_handle(NULL) , m_entry(NULL) , m_dirLen(0) {} inline readdir_sequence::const_iterator::const_iterator(class_type const &rhs) : m_handle(rhs.m_handle) , m_entry(rhs.m_entry) , m_scratch(rhs.m_scratch) , m_dirLen(rhs.m_dirLen) { if(NULL != m_handle) { m_handle->AddRef(); } } inline readdir_sequence::const_iterator::~const_iterator() { if(NULL != m_handle) { m_handle->Release(); } } inline readdir_sequence::const_iterator const &readdir_sequence::const_iterator::operator =(readdir_sequence::const_iterator const &rhs) { if(NULL != m_handle) { m_handle->Release(); } m_handle = rhs.m_handle; m_entry = rhs.m_entry; m_flags = rhs.m_flags; m_scratch = rhs.m_scratch; m_dirLen = rhs.m_dirLen; if(NULL != m_handle) { m_handle->AddRef(); } return *this; } inline readdir_sequence::const_iterator::value_type readdir_sequence::const_iterator::operator *() const { unixstl_message_assert( "Dereferencing invalid iterator", NULL != m_entry); return m_entry; } inline readdir_sequence::const_iterator &readdir_sequence::const_iterator::operator ++() { unixstl_message_assert( "Incrementing invalid iterator", NULL != m_handle); for(;;) { m_entry = readdir(m_handle->dir); if(NULL != m_entry) { unixstl_assert(NULL != m_entry->d_name); if(0 == (m_flags & includeDots)) { if(traits_type::is_dots(m_entry->d_name)) { continue; // Don't want dots; skip it } } if((m_flags & (directories | files)) != (directories | files)) { // Now need to process the file, by using stat struct stat st; // Truncate the scratch to the directory path, ... m_scratch.resize(m_dirLen); // ... and add the file m_scratch += m_entry->d_name; if(0 != stat(stlsoft_ns_qual(c_str_ptr)(m_scratch), &st)) { // Failed to get info from entry. Must assume it is // dead, so skip it continue; } else { if(m_flags & directories) // Want directories { if(S_IFDIR == (st.st_mode & S_IFDIR)) { // It is a directory, so accept it break; } } if(m_flags & files) // Want files { if(S_IFREG == (st.st_mode & S_IFREG)) { // It is a file, so accept it break; } } continue; // Not a match, so skip this entry } } } break; // No entries left, so break out } if(NULL == m_entry) { unixstl_assert(NULL != m_handle); m_handle->Release(); m_handle = NULL; } return *this; } inline readdir_sequence::const_iterator readdir_sequence::const_iterator::operator ++(int) { class_type ret(*this); operator ++(); return ret; } inline bool readdir_sequence::const_iterator::operator ==(readdir_sequence::const_iterator const &rhs) const { unixstl_assert(NULL == m_handle || NULL == rhs.m_handle || m_handle->dir == rhs.m_handle->dir); return m_entry == rhs.m_entry; } inline bool readdir_sequence::const_iterator::operator !=(readdir_sequence::const_iterator const &rhs) const { return !operator ==(rhs); } inline /* explicit */ readdir_sequence::const_iterator::rds_shared_handle::rds_shared_handle(DIR *d) : dir(d) , cRefs(1) {} inline void readdir_sequence::const_iterator::rds_shared_handle::AddRef() { ++cRefs; } inline void readdir_sequence::const_iterator::rds_shared_handle::Release() { if(0 == --cRefs) { delete this; } } inline readdir_sequence::const_iterator::rds_shared_handle::~rds_shared_handle() { unixstl_message_assert( "Shared handle destroyed with outstanding references!" , 0 == cRefs); if(NULL != dir) { closedir(dir); } }
Sponsored Links
|