📄 glob_sequence.hpp
字号:
else
{
return false;
}
}
}
return false;
}
inline us_size_t glob_sequence::init_glob_(glob_sequence::char_type const* directory, glob_sequence::char_type const* pattern)
{
UNIXSTL_MESSAGE_ASSERT("Null pattern given to glob_sequence", NULL != pattern);
us_int_t glob_flags = 0;
basic_file_path_buffer<char_type> scratch_; // Scratch buffer for directory / pattern
#ifndef STLSOFT_CF_EXCEPTION_SUPPORT
if(0 == scratch_.size())
{
m_base = NULL;
return 0;
}
#endif /* !STLSOFT_CF_EXCEPTION_SUPPORT */
if( NULL == directory &&
absolutePath == (m_flags & absolutePath))
{
static const char_type s_thisDir[] = { '.', '\0' };
directory = s_thisDir;
}
// If a directory is given, then ...
if( NULL != directory &&
'\0' != *directory)
{
us_size_t dirLen;
// ... optionally turn it into an absolute directory, ...
if(absolutePath == (m_flags & absolutePath))
{
dirLen = traits_type::get_full_path_name(directory, scratch_.size(), &scratch_[0]);
}
else
{
traits_type::str_copy(&scratch_[0], directory);
dirLen = traits_type::str_len(scratch_.c_str());
}
// ... ensure that it has a trailing path name-separator, and ...
traits_type::ensure_dir_end(&scratch_[0] + (dirLen ? dirLen - 1 : 0));
// ... prefix directory onto pattern.
traits_type::str_cat(&scratch_[0] + dirLen, pattern);
pattern = scratch_.c_str();
}
if(m_flags & noSort)
{
// Don't bother sorting
glob_flags |= GLOB_NOSORT;
}
if(m_flags & markDirs)
{
// Ask for trailing slashes on directories
glob_flags |= GLOB_MARK;
}
#ifdef GLOB_ONLYDIR // If this is not defined, we rely on stat
if(directories == (m_flags & (directories | files)))
{
// Ask for only directories
glob_flags |= GLOB_ONLYDIR;
}
#endif /* GLOB_ONLYDIR */
#ifdef GLOB_ONLYFILE // If this is not defined, we rely on stat
if(files == (m_flags & (directories | files)))
{
// Ask for only files
glob_flags |= GLOB_ONLYFILE;
}
#endif /* GLOB_ONLYFILE */
#ifdef GLOB_ERR
if(m_flags & breakOnError)
{
glob_flags |= GLOB_ERR;
}
#endif /* GLOB_ERR */
#ifdef GLOB_NOESCAPE
if(m_flags & noEscape)
{
glob_flags |= GLOB_NOESCAPE;
}
#endif /* GLOB_NOESCAPE */
#ifdef GLOB_PERIOD
if(m_flags & matchPeriod)
{
glob_flags |= GLOB_PERIOD;
}
#endif /* GLOB_PERIOD */
#ifdef GLOB_BRACE
if(m_flags & bracePatterns)
{
glob_flags |= GLOB_BRACE;
}
#endif /* GLOB_BRACE */
#ifdef GLOB_TILDE
if(m_flags & expandTilde)
{
glob_flags |= GLOB_TILDE;
}
#endif /* GLOB_TILDE */
int gr = ::glob(pattern, glob_flags, NULL, &m_glob);
if(0 != gr)
{
#ifdef STLSOFT_CF_EXCEPTION_SUPPORT
# ifdef GLOB_NOMATCH
// When GLOB_NOMATCH is not defined, we can reasonably infer that
// there is no replacement value, so throwing on a non-zero
// return from glob() is appropriate
if(GLOB_NOMATCH != gr)
# endif /* GLOB_NOMATCH */
{
STLSOFT_THROW_X(glob_sequence_exception(gr, 0));
}
#endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
m_base = NULL;
return 0;
}
else
{
// Sink the glob_t instance into a local scoped_handle, to invoke
// ::globfree() automatically if we encounter any problems during
// the processing. At the end we'll call detach(), to "give it"
// to the glob_sequence instance.
stlsoft_ns_qual(scoped_handle)<glob_t*> cleanup(&m_glob, ::globfree);
char_type **base = m_glob.gl_pathv;
us_size_t cItems = static_cast<us_size_t>(m_glob.gl_pathc);
// This section performs a COW on the entry pointers, into
// the m_buffer member, if any of the following hold:
//
// 1. we're eliding dots
// 2. we want directories only, and so will need to
// remove files, AND we do not trust GLOB_ONLYDIR
// 3. we want files only, and so will need
// to remove directories
//
if( 0 == (m_flags & includeDots) || // 1
#ifndef UNIXSTL_GLOB_SEQUENCE_TRUST_ONLYDIR
directories == (m_flags & (directories | files)) || // 2
#endif /* !UNIXSTL_GLOB_SEQUENCE_TRUST_ONLYDIR */
files == (m_flags & (directories | files))) // 3
{
if(!m_buffer.resize(cItems))
{
#ifndef STLSOFT_CF_EXCEPTION_SUPPORT
m_base = NULL;
return 0;
#endif /* !STLSOFT_CF_EXCEPTION_SUPPORT */
}
UNIXSTL_ASSERT(m_buffer.size() == cItems);
base = static_cast<char_type**>(memcpy(&m_buffer[0], base, m_buffer.size() * sizeof(char_type*)));
}
// This section elides dots directories.
if(0 == (m_flags & includeDots))
{
// Now remove the dots. If located at the start of
// the gl buffer, then simply increment m_base to
// be above that. If not then rearrange the base
// two pointers such that they are there.
us_bool_t bFoundDot1 = false;
us_bool_t bFoundDot2 = false;
char_type **begin = base;
char_type **end = begin + cItems;
for(; begin != end; ++begin)
{
us_bool_t bTwoDots = false;
if(is_dots_maybe_slashed_(*begin, bTwoDots))
{
// Swap with whatever is at base[0]
if(begin != base)
{
unixstl_ns_qual_std(swap)(*begin, *base);
}
++base;
--cItems;
// We're only going to get one "." and one ".."
(bTwoDots ? bFoundDot2 : bFoundDot1) = true;
if( bFoundDot1 &&
bFoundDot2)
{
break;
}
}
}
}
// This section performs the filtering, if any of the following
// hold:
//
// 1. we want directories only, and so will need to
// remove files, AND we do not trust GLOB_ONLYDIR
// 2. we want files only, and so will need
// to remove directories
//
#ifndef UNIXSTL_GLOB_SEQUENCE_TRUST_ONLYDIR
if((m_flags & (directories | files)) != (directories | files)) // 1 & 2
#else /* ? UNIXSTL_GLOB_SEQUENCE_TRUST_ONLYDIR */
if((m_flags & (directories | files)) == files) // 2
#endif /* !UNIXSTL_GLOB_SEQUENCE_TRUST_ONLYDIR */
{
// Declare a path buffer which will be used as a scratch area
// in case we need to remove trailing path name separators to
// perform stat() on a (suspected) directory entry
basic_file_path_buffer<char_type> buffer;
char_type **begin = base;
char_type **end = begin + cItems;
#ifndef STLSOFT_CF_EXCEPTION_SUPPORT
if(0 == buffer.size())
{
m_base = NULL;
return 0;
}
#endif /* !STLSOFT_CF_EXCEPTION_SUPPORT */
// This loop enumerates through the list of entries, and attempts
// to match each with the requested file type.
//
// 1. If we're wanting to return only files, then markDirs (GLOB_MARK)
// will have been applied by validate_flags_(), so we test that
// first
// 2. If we're wanting to return only directories, then we must not
// be trusting GLOB_ONLYDIR. Either:
// 2.1. The user specified markDirs (GLOB_MARK), so use that, or
// 2.2. The user did not specify, and we must stat()
//
for(; begin != end; ++begin)
{
// Now need to process the file, by using stat
struct stat st;
int res;
char_type const* entry = *begin;
// 1.
if(files == (m_flags & (directories | files)))
{
UNIXSTL_ASSERT(markDirs == (m_flags & markDirs));
if(!traits_type::has_dir_end(entry))
{
continue; // A non-marked entry, hence a file, so accept
}
#ifndef UNIXSTL_GLOB_SEQUENCE_DONT_TRUST_MARK
else
{
res = ::stat(entry, &st);
if(0 != res)
{
// We could throw an exception here, but it might just be
// the case that a file has been deleted subsequent to its
// having been included in the glob list. As such, it makes
// more sense to just kick it from the list
}
else
{ // stat() succeeded
if(S_IFREG == (st.st_mode & S_IFREG))
{
continue; // A file, so accept it
}
}
}
#endif /* !UNIXSTL_GLOB_SEQUENCE_DONT_TRUST_MARK */
}
else // 2.
{
UNIXSTL_ASSERT(directories == (m_flags & (directories | files)));
#ifdef UNIXSTL_GLOB_SEQUENCE_TRUST_ONLYDIR
UNIXSTL_MESSAGE_ASSERT("Cannot get here, since trusting GLOB_ONLYDIR", 0);
#endif /* UNIXSTL_GLOB_SEQUENCE_TRUST_ONLYDIR */
if(markDirs == (m_flags & markDirs))
{
if(traits_type::has_dir_end(entry))
{
continue; // A marked entry, hence a directory, so accept
}
}
#ifndef UNIXSTL_GLOB_SEQUENCE_DONT_TRUST_MARK
else
#endif /* !UNIXSTL_GLOB_SEQUENCE_DONT_TRUST_MARK */
{
// Now we must stat()
res = stat(entry, &st);
if(0 != res)
{
// We could throw an exception here, but it might just be
// the case that a file has been deleted subsequent to its
// having been included in the glob list. As such, it makes
// more sense to just kick it from the list
}
else
{ // stat() succeeded
if(S_IFDIR == (st.st_mode & S_IFDIR))
{
continue; // A directory, so accept it
}
}
}
}
// This section elides the entry from the list
//
// Note that there is no test here to determine whether or not
// begin == base. It is assumed that most cases of file elision
// will involve several files - how many directories have just
// one file in them? - so the test would actually be a
// pessimisation
// Swap with whatever is at base[0]
unixstl_ns_qual_std(swap)(*begin, *base);
++base;
--cItems;
}
}
// Ensure we've not corrupted the sort order
if( 0 == (m_flags & noSort) &&
cItems != static_cast<us_size_t>(m_glob.gl_pathc))
{
unixstl_ns_qual_std(sort)(base, base + cItems);
}
// Set m_base and m_cItems to the correct values, with
// or without dots. m_base is cast here to remove the
// need for const-casting throughout the rest of the
// class
m_base = const_cast<char_type const**>(base);
// Everything has succeeded, so give ownership over to the
// glob_sequence instance
cleanup.detach();
return cItems;
}
}
#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_GLOB_SEQUENCE */
/* ////////////////////////////////////////////////////////////////////// */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -