📄 glob_sequence.hpp
字号:
#elif defined(GLOB_SEQUENCE_CTOR_ALT_FORM)
template<ss_typename_param_k S>
ss_explicit_k glob_sequence(S const& pattern)
: m_flags(validate_flags_())
, m_buffer(1)
{
m_cItems = init_glob_(NULL, stlsoft_ns_qual(c_str_ptr)(pattern));
UNIXSTL_ASSERT(is_valid());
}
template<ss_typename_param_k S>
glob_sequence(S const& pattern, us_int_t flags /* = noSort */)
: m_flags(validate_flags_(flags))
, m_buffer(1)
{
m_cItems = init_glob_(NULL, stlsoft_ns_qual(c_str_ptr)(pattern));
UNIXSTL_ASSERT(is_valid());
}
glob_sequence(char_type const* directory, char_type const* pattern, us_int_t flags = noSort);
template<ss_typename_param_k S>
glob_sequence(S const& directory, char const* pattern, us_int_t flags = noSort)
: m_flags(validate_flags_(flags))
, m_buffer(1)
{
m_cItems = init_glob_(stlsoft_ns_qual(c_str_ptr)(directory), stlsoft_ns_qual(c_str_ptr)(pattern));
UNIXSTL_ASSERT(is_valid());
}
template<ss_typename_param_k S>
glob_sequence(S const& directory, S const& pattern, us_int_t flags = noSort)
: m_flags(validate_flags_(flags))
, m_buffer(1)
{
m_cItems = init_glob_(stlsoft_ns_qual(c_str_ptr)(directory), stlsoft_ns_qual(c_str_ptr)(pattern));
UNIXSTL_ASSERT(is_valid());
}
#elif defined(GLOB_SEQUENCE_CTOR_OLD_FORM)
ss_explicit_k glob_sequence(char_type const* pattern, us_int_t flags = noSort);
glob_sequence(char_type const* directory, char_type const* pattern, us_int_t flags = noSort);
#else /* ? constructor form */
# error Constructor form not recognised
#endif /* constructor form */
#if 0
/// \brief Constructs a sequence according to the given criteria
///
/// The constructor initialises a glob_sequence instance on the given
/// pattern with the given flags.
///
/// \param directory The directory in which the pattern is located
/// \param pattern The pattern against which to match the file-system contents
/// \param flags Flags to alter the behaviour of the search
///
/// \note If exceptions are supported, then this will throw a glob_sequence_exception
/// on failure of any underlying functions
glob_sequence(char_type const* directory, char_type const* pattern, char_type delim, us_int_t flags = noSort);
#endif /* 0 */
/// \brief Releases any acquired resources
~glob_sequence() stlsoft_throw_0();
/// @}
/// \name Attributes
/// @{
public:
/// \brief Returns the number of elements in the sequence
us_size_t size() const;
/// \brief Indicates whether the search sequence is empty
us_bool_t empty() const;
/// @}
/// \name Element Access
/// @{
public:
/// \brief Returns the value corresponding to the given index
///
/// \note In debug-mode a runtime assert is applied to enforce that the index is valid. There is <b>no</b> release-time checking on the index validity!
const_reference operator [](size_type index) const;
/// @}
/// \name Iteration
/// @{
public:
/// \brief Begins the iteration
///
/// \return An iterator representing the start of the sequence
const_iterator begin() const;
/// \brief Ends the iteration
///
/// \return An iterator representing the end of the sequence
const_iterator end() const;
#ifdef STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT
/// \brief Begins the reverse iteration
///
/// \return An iterator representing the start of the reverse sequence
const_reverse_iterator rbegin() const;
/// \brief Ends the reverse iteration
///
/// \return An iterator representing the end of the reverse sequence
const_reverse_iterator rend() const;
#endif /* STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT */
/// @}
/// \name Implementation
/// @{
private:
// Tests the class invariant
us_bool_t is_valid() const;
// Validates the flags, and sets up defaults
static us_int_t validate_flags_(us_int_t flags = noSort);
// Returns true if pch is a path separator "/" (or "\\"); false otherwise
static us_bool_t is_path_separator_(char_type ch);
// Returns true if pch == "" or "/" (or "\\"); false otherwise
static us_bool_t is_end_of_path_elements_(char_type const* pch, difference_type index);
// Returns true if s points to a path that is a dots directory; false otherwise
static us_bool_t is_dots_maybe_slashed_(char_type const* s, us_bool_t &bTwoDots);
// Calls glob() and process the results
us_size_t init_glob_(char_type const* directory, char_type const* pattern);
/// @}
/// \name Members
/// @{
private:
typedef stlsoft_ns_qual(auto_buffer_old)< char_type const*
, allocator_type
, 128
> buffer_type_;
us_int_t const m_flags;
char_type const** m_base;
us_size_t m_cItems;
buffer_type_ m_buffer;
glob_t m_glob;
/// @}
/// \name Not to be implemented
/// @{
private:
glob_sequence(class_type const&);
class_type const& operator =(class_type const&);
/// @}
};
////////////////////////////////////////////////////////////////////////////
// Unit-testing
#ifdef STLSOFT_UNITTEST
# include "./unittest/glob_sequence_unittest_.h"
#endif /* STLSOFT_UNITTEST */
/* /////////////////////////////////////////////////////////////////////////
* Implementation
*/
#ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
#if defined(GLOB_SEQUENCE_CTOR_OLD_FORM)
inline /* ss_explicit_k */ glob_sequence::glob_sequence(glob_sequence::char_type const* pattern, us_int_t flags /* = noSort */)
: m_flags(validate_flags_(flags))
, m_buffer(1)
{
m_cItems = init_glob_(NULL, pattern);
UNIXSTL_ASSERT(is_valid());
}
#endif /* GLOB_SEQUENCE_CTOR_OLD_FORM */
#if defined(GLOB_SEQUENCE_CTOR_OLD_FORM) || \
defined(GLOB_SEQUENCE_CTOR_ALT_FORM)
inline glob_sequence::glob_sequence(glob_sequence::char_type const* directory, glob_sequence::char_type const* pattern, us_int_t flags /* = noSort */)
: m_flags(validate_flags_(flags))
, m_buffer(1)
{
m_cItems = init_glob_(directory, pattern);
UNIXSTL_ASSERT(is_valid());
}
#endif /* GLOB_SEQUENCE_CTOR_OLD_FORM || GLOB_SEQUENCE_CTOR_ALT_FORM */
#if 0
template< ss_typename_param_k S1
, ss_typename_param_k S2
>
inline glob_sequence::glob_sequence(S1 const& directory, S2 const& pattern, us_int_t flags /* = noSort */)
: m_flags(validate_flags_(flags))
, m_buffer(1)
{
m_cItems = init_glob_(stlsoft_ns_qual(c_str_ptr)(directory), stlsoft_ns_qual(c_str_ptr)(pattern));
UNIXSTL_ASSERT(is_valid());
}
#endif /* 0 */
#if 0
inline glob_sequence::glob_sequence(char_type const* directory, char_type const* pattern, char_type delim, us_int_t flags /* = noSort */)
: m_flags(validate_flags_(flags))
, m_buffer(1)
{
m_cItems = init_glob_(NULL, pattern);
UNIXSTL_ASSERT(is_valid());
}
#endif /* 0 */
inline glob_sequence::~glob_sequence() stlsoft_throw_0()
{
UNIXSTL_ASSERT(is_valid());
if(NULL != m_base)
{
::globfree(&m_glob);
}
}
inline us_size_t glob_sequence::size() const
{
return m_cItems;
}
inline us_bool_t glob_sequence::empty() const
{
return 0 == size();
}
inline glob_sequence::const_reference glob_sequence::operator [](glob_sequence::size_type index) const
{
UNIXSTL_MESSAGE_ASSERT("index access out of range in glob_sequence", index < 1 + size()); // Has to be +1, since legitimate to take address of one-past-the-end
return m_base[index];
}
inline glob_sequence::const_iterator glob_sequence::begin() const
{
return m_base;
}
inline glob_sequence::const_iterator glob_sequence::end() const
{
return m_base + m_cItems;
}
#ifdef STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT
inline glob_sequence::const_reverse_iterator glob_sequence::rbegin() const
{
return const_reverse_iterator(end());
}
inline glob_sequence::const_reverse_iterator glob_sequence::rend() const
{
return const_reverse_iterator(begin());
}
#endif /* STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT */
inline us_bool_t glob_sequence::is_valid() const
{
if((0 != m_cItems) && (NULL == m_base))
{
return false;
}
return true;
}
inline /* static */ us_int_t glob_sequence::validate_flags_(us_int_t flags)
{
const us_int_t validFlags = 0
| includeDots
| directories
| files
| noSort
| markDirs
| absolutePath
| breakOnError
| noEscape
#ifdef GLOB_PERIOD
| matchPeriod
#endif /* GLOB_PERIOD */
#ifdef GLOB_BRACE
| bracePatterns
#endif /* GLOB_BRACE */
#ifdef GLOB_TILDE
| expandTilde
#endif /* GLOB_TILDE */
| 0;
UNIXSTL_MESSAGE_ASSERT("Specification of unrecognised/unsupported flags", flags == (flags & validFlags));
STLSOFT_SUPPRESS_UNUSED(validFlags);
if(0 == (flags & (directories | files)))
{
flags |= (directories | files);
}
#ifndef UNIXSTL_GLOB_SEQUENCE_DONT_TRUST_MARK
// If we're not searching for directories, then we can optimise the
// subsequent filtering by asking for the dots directories (so we
// skip that filtering) and asking for directories to be marked (so
// we can detect the mark rather than making a system call (stat())
if(0 == (flags & directories))
{
// It's more efficient to not bother doing a separate dots check if all
// directories are being elided.
flags |= includeDots;
// Since we're not going to be returning directories to the caller, and
// it's more efficient to believe the glob() directory marking rather
// than calling stat, we add the markDirs flag here.
flags |= markDirs;
}
#endif /* !UNIXSTL_GLOB_SEQUENCE_DONT_TRUST_MARK */
return flags;
}
inline /* static */ us_bool_t glob_sequence::is_path_separator_(glob_sequence::char_type ch)
{
return ch == '/'
#if defined(_UNIXSTL_COMPILER_IS_UNKNOWN) && \
!defined(_UNIXSTL_GLOB_SEQUENCE_NO_BACK_SLASH_TERMINATOR)
|| ch == '\\' /* Allow for testing on Win32 systems */
#endif /* _UNIXSTL_COMPILER_IS_UNKNOWN && !_UNIXSTL_GLOB_SEQUENCE_NO_BACK_SLASH_TERMINATOR */
;
}
inline /* static */ us_bool_t glob_sequence::is_end_of_path_elements_(glob_sequence::char_type const* pch, glob_sequence::difference_type index)
{
return pch[index] == '\0' ||
( pch[index + 1] == '\0' &&
is_path_separator_(pch[index]));
}
inline /* static */ us_bool_t glob_sequence::is_dots_maybe_slashed_(glob_sequence::char_type const* s, us_bool_t &bTwoDots)
{
UNIXSTL_ASSERT(NULL != s);
// This must match all patterns like the following:
//
// "." l=1, s[0] = .
// ".." l=2, s[0] = ., s[1] = .
// "./" l=2, s[0] = ., s[1] = sep
// "../" l=3, s[0] = ., s[1] = ., s[2] = sep
// "abc/."
// "abc/.."
// "abc/./"
// "abc/../"
const us_size_t len = traits_type::str_len(s);
us_size_t lastNameChar = len -1;
UNIXSTL_ASSERT(len > 0);
if(is_path_separator_(s[lastNameChar]))
{
--lastNameChar;
}
if( 0 < lastNameChar &&
'.' == s[lastNameChar])
{
--lastNameChar;
if( 0 == lastNameChar ||
is_path_separator_(s[lastNameChar]))
{
bTwoDots = false;
return true;
}
else if( 0 < lastNameChar &&
'.' == s[lastNameChar])
{
--lastNameChar;
if( 0 == lastNameChar ||
is_path_separator_(s[lastNameChar]))
{
bTwoDots = true;
return true;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -