📄 readdir_sequence.hpp
字号:
ss_explicit_k shared_handle(handle_type h)
: m_dir(h)
, m_refCount(1)
{}
ss_sint32_t AddRef()
{
return ++m_refCount;
}
ss_sint32_t Release()
{
ss_sint32_t rc = --m_refCount;
if(0 == rc)
{
delete this;
}
return rc;
}
#if defined(STLSOFT_CF_COMPILER_WARNS_NO_PUBLIC_DTOR)
protected:
#else /* ? STLSOFT_CF_COMPILER_WARNS_NO_PUBLIC_DTOR */
private:
#endif /* STLSOFT_CF_COMPILER_WARNS_NO_PUBLIC_DTOR */
~shared_handle() stlsoft_throw_0()
{
UNIXSTL_MESSAGE_ASSERT("Shared search handle being destroyed with outstanding references!", 0 == m_refCount);
if(NULL != m_dir)
{
::closedir(m_dir);
}
}
/// @}
/// \name Not to be implemented
/// @{
private:
shared_handle(class_type const&);
class_type& operator =(class_type const&);
/// @}
};
#endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
////////////////////////////////////////////////////////////////////////////
// Operators
inline us_bool_t operator ==( readdir_sequence::const_iterator const& lhs
, readdir_sequence::const_iterator const& rhs)
{
return lhs.equal(rhs);
}
inline us_bool_t operator !=( readdir_sequence::const_iterator const& lhs
, readdir_sequence::const_iterator const& rhs)
{
return !lhs.equal(rhs);
}
////////////////////////////////////////////////////////////////////////////
// Unit-testing
#ifdef STLSOFT_UNITTEST
# include "./unittest/readdir_sequence_unittest_.h"
#endif /* STLSOFT_UNITTEST */
/* /////////////////////////////////////////////////////////////////////////
* Implementation
*/
#ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
// readdir_sequence
inline /* static */ readdir_sequence::flags_type readdir_sequence::validate_flags_(readdir_sequence::flags_type flags)
{
const flags_type validFlags = 0
| includeDots
| directories
| files
| fullPath
| absolutePath
| 0;
UNIXSTL_MESSAGE_ASSERT("Specification of unrecognised/unsupported flags", flags == (flags & validFlags));
STLSOFT_SUPPRESS_UNUSED(validFlags);
if(0 == (flags & (directories | files)))
{
flags |= (directories | files);
}
return flags;
}
inline /* static */ readdir_sequence::string_type readdir_sequence::prepare_directory_(char_type const* directory, readdir_sequence::flags_type flags)
{
if( NULL == directory ||
'\0' == *directory)
{
static const char_type s_thisDir[] = { '.', '\0' };
directory = s_thisDir;
}
basic_file_path_buffer<char_type> path;
size_type n;
if(absolutePath & flags)
{
n = traits_type::get_full_path_name(directory, path.size(), &path[0]);
if(0 == n)
{
#ifdef STLSOFT_CF_EXCEPTION_SUPPORT
STLSOFT_THROW_X(readdir_sequence_exception("Failed to enumerate directory", errno));
#else /* ? STLSOFT_CF_EXCEPTION_SUPPORT */
traits_type::str_n_copy(&path[0], directory, path.size());
#endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
}
}
else
{
n = traits_type::str_len(traits_type::str_n_copy(&path[0], directory, path.size()));
}
traits_type::ensure_dir_end(&path[n - 1]);
directory = path.c_str();
return directory;
}
inline readdir_sequence::const_iterator readdir_sequence::begin() const
{
DIR *dir = ::opendir(m_directory.c_str());
if(NULL == dir)
{
#ifdef STLSOFT_CF_EXCEPTION_SUPPORT
STLSOFT_THROW_X(readdir_sequence_exception("Failed to enumerate directory", errno));
#else /* ? STLSOFT_CF_EXCEPTION_SUPPORT */
return const_iterator();
#endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
}
#ifdef STLSOFT_CF_EXCEPTION_SUPPORT
try
{
#endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
return const_iterator(dir, m_directory, m_flags);
#ifdef STLSOFT_CF_EXCEPTION_SUPPORT
}
catch(...)
{
::closedir(dir);
throw;
}
#endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
}
inline readdir_sequence::const_iterator readdir_sequence::end() const
{
return const_iterator();
}
inline us_bool_t readdir_sequence::empty() const
{
return begin() != end();
}
inline readdir_sequence::string_type const& readdir_sequence::get_directory() const
{
return m_directory;
}
inline readdir_sequence::flags_type readdir_sequence::get_flags() const
{
return m_flags;
}
// readdir_sequence::const_iterator;
inline readdir_sequence::const_iterator::const_iterator(DIR *dir, readdir_sequence::string_type const& directory, readdir_sequence::flags_type flags)
: m_handle(new shared_handle(dir))
, m_entry(NULL)
, m_flags(flags)
, m_scratch(directory)
, m_dirLen(directory.length())
{
UNIXSTL_ASSERT(traits_type::has_dir_end(m_scratch.c_str()));
if(NULL == m_handle)
{
::closedir(dir);
}
else
{
operator ++();
}
}
inline readdir_sequence::const_iterator::const_iterator()
: m_handle(NULL)
, m_entry(NULL)
, m_flags(0)
, m_scratch()
, 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_flags(rhs.m_flags)
, m_scratch(rhs.m_scratch)
, m_dirLen(rhs.m_dirLen)
{
if(NULL != m_handle)
{
m_handle->AddRef();
}
}
inline readdir_sequence::const_iterator::~const_iterator() stlsoft_throw_0()
{
if(NULL != m_handle)
{
m_handle->Release();
}
}
inline readdir_sequence::const_iterator::class_type const& readdir_sequence::const_iterator::operator =(readdir_sequence::const_iterator::class_type const& rhs)
{
shared_handle *this_handle = m_handle;
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();
}
if(NULL != this_handle)
{
this_handle->Release();
}
return *this;
}
inline readdir_sequence::const_iterator::value_type readdir_sequence::const_iterator::operator *() const
{
UNIXSTL_MESSAGE_ASSERT( "Dereferencing invalid iterator", NULL != m_entry);
#if defined(UNIXSTL_READDIR_SEQUENCE_OLD_VALUE_TYPE)
return m_entry;
#else /* ? UNIXSTL_READDIR_SEQUENCE_OLD_VALUE_TYPE */
return (readdir_sequence::fullPath & m_flags) ? m_scratch.c_str() : m_entry->d_name;
#endif /* UNIXSTL_READDIR_SEQUENCE_OLD_VALUE_TYPE */
}
inline readdir_sequence::const_iterator::class_type &readdir_sequence::const_iterator::operator ++()
{
UNIXSTL_MESSAGE_ASSERT( "Incrementing invalid iterator", NULL != m_handle);
for(;;)
{
errno = 0;
m_entry = ::readdir(m_handle->m_dir);
if(NULL == m_entry)
{
if(0 != errno)
{
#ifdef STLSOFT_CF_EXCEPTION_SUPPORT
STLSOFT_THROW_X(readdir_sequence_exception("Partial failure of directory enumeration", errno));
#endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
}
}
else
{
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 either
//
// - eliding files or directories, or
// - requiring absolute path
//
// then need to construct it.
if((m_flags & (fullPath | directories | files)) != (directories | files))
{
// Truncate the scratch to the directory path, ...
m_scratch.resize(m_dirLen);
// ... and add the file
m_scratch += m_entry->d_name;
}
if((m_flags & (directories | files)) != (directories | files))
{
// Now need to process the file, by using stat
traits_type::stat_data_type st;
if(!traits_type::stat(m_scratch.c_str(), &st))
{
// Failed to get info from entry. Must assume it is
// dead, so skip it
continue;
}
else
{
if(m_flags & directories) // Want directories
{
if(traits_type::is_directory(&st))
{
// It is a directory, so accept it
break;
}
}
if(m_flags & files) // Want files
{
if(traits_type::is_file(&st))
{
// It is a file, so accept it
break;
}
}
continue; // Not a match, so skip this entry
}
}
}
break;
}
if(NULL == m_entry)
{
UNIXSTL_ASSERT(NULL != m_handle);
m_handle->Release();
m_handle = NULL;
}
return *this;
}
inline readdir_sequence::const_iterator::class_type readdir_sequence::const_iterator::operator ++(int)
{
class_type ret(*this);
operator ++();
return ret;
}
inline bool readdir_sequence::const_iterator::equal(readdir_sequence::const_iterator::class_type const& rhs) const
{
UNIXSTL_ASSERT(NULL == m_handle || NULL == rhs.m_handle || m_handle->m_dir == rhs.m_handle->m_dir);
return m_entry == rhs.m_entry;
}
#endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
/* ////////////////////////////////////////////////////////////////////// */
#ifndef _UNIXSTL_NO_NAMESPACE
# if defined(_STLSOFT_NO_NAMESPACE) || \
defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
} // namespace unixstl
# else
} // namespace unixstl_project
} // namespace stlsoft
# endif /* _STLSOFT_NO_NAMESPACE */
#endif /* !_UNIXSTL_NO_NAMESPACE */
/* ////////////////////////////////////////////////////////////////////// */
#endif /* !UNIXSTL_INCL_UNIXSTL_FILESYSTEM_HPP_READDIR_SEQUENCE */
/* ////////////////////////////////////////////////////////////////////// */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -