📄 findfile_sequence.hpp
字号:
shared_handle *this_handle = m_handle;
m_handle = rhs.m_handle;
m_data = rhs.m_data;
m_subpath = rhs.m_subpath;
m_subPathLen = rhs.m_subPathLen;
m_pattern0 = rhs.m_pattern0;
m_pattern1 = rhs.m_pattern1;
m_delim = rhs.m_delim;
m_flags = rhs.m_flags;
if(NULL != m_handle)
{
m_handle->AddRef();
}
if(NULL != this_handle)
{
this_handle->Release();
}
return *this;
}
template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k V>
inline basic_findfile_sequence_const_input_iterator<C, T, V>::~basic_findfile_sequence_const_input_iterator() stlsoft_throw_0()
{
if(NULL != m_handle)
{
m_handle->Release();
}
}
template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k V>
inline ss_typename_type_k basic_findfile_sequence_const_input_iterator<C, T, V>::class_type &basic_findfile_sequence_const_input_iterator<C, T, V>::operator ++()
{
// Pre-condition enforcements
WINSTL_MESSAGE_ASSERT("Attempting to increment an invalid iterator!", '\0' != *m_pattern0);
WINSTL_ASSERT(NULL != m_pattern0);
WINSTL_ASSERT(NULL != m_pattern1);
enum
{
#ifdef FILE_ATTRIBUTE_REPARSE_POINT
reparsePointConstant = FILE_ATTRIBUTE_REPARSE_POINT
#else /* ? FILE_ATTRIBUTE_REPARSE_POINT */
reparsePointConstant = 0x00000400
#endif /* FILE_ATTRIBUTE_REPARSE_POINT */
};
STLSOFT_STATIC_ASSERT(reparsePointConstant); // Suppress silly Borland's warnings
for(; '\0' != *m_pattern0 || '\0' != *m_pattern1;)
{
if(NULL == m_handle)
{
// Walk through the patterns
while(stlsoft_ns_qual(find_next_token)(m_pattern0, m_pattern1, m_delim))
{
WINSTL_ASSERT(m_pattern0 <= m_pattern1);
if(m_pattern1 != m_pattern0) // Will return m_pattern0 == m_pattern1 for empty tokens
{
// We now have a non-empty pattern, so we need to concatenate
// it with the directory to form a search-spec for
// FindFirstFile()
//
// From this path we must also determine the sub-path for any items retrieved from
// this search, since WIN32_FIND_DATA will contain only the file-name. Since the
// sequence is tolerant of both slashes and backslashes, we need to find the last
// of each and take the end-most.
file_path_buffer_type_ search; // Buffer in which to prepare the search-spec for FindFirstFile()
size_type cch; // Used to make the strrchr operations faster
if(traits_type::is_path_rooted(m_pattern0))
{
search[0] = '\0';
cch = 0;
}
else
{
traits_type::str_n_copy(&search[0], m_list->get_directory(), search.size());
cch = traits_type::str_len(&search[0]);
WINSTL_ASSERT(cch > 0);
--cch; // Directory is always trailing a path name separator
traits_type::ensure_dir_end(&search[(cch > 1) ? (cch - 2) : 0]);
}
traits_type::str_n_cat(&search[0] + cch, m_pattern0, static_cast<ws_size_t>(m_pattern1 - m_pattern0));
// Note: At this point, cch may be 1 under, because ensure_dir_end() may have added
// a character that we've not counted. But that's ok, because we don't use it as an
// exact value, just a minimum value
char_type const* slash = traits_type::str_rchr(&search[0] + cch, '/');
char_type const* bslash = traits_type::str_rchr(&search[0] + cch, '\\');
WINSTL_ASSERT(!traits_type::is_path_rooted(m_pattern0) || ((NULL != slash) || (NULL != bslash)));
if( NULL != slash &&
slash >= m_pattern1)
{
slash = NULL;
}
if( NULL != bslash &&
bslash >= m_pattern1)
{
bslash = NULL;
}
if( NULL != slash ||
NULL != bslash)
{
if(NULL == slash)
{
slash = bslash;
}
else if(NULL != bslash &&
slash < bslash)
{
slash = bslash;
}
const ws_size_t n = static_cast<ws_size_t>(slash - &search[0]);
traits_type::str_n_copy(&m_subpath[0], &search[0], n);
m_subPathLen = n;
m_subpath[n] = '\0';
}
HANDLE hSrch = find_first_file_(search.c_str(), m_flags, &m_data);
if(INVALID_HANDLE_VALUE != hSrch)
{
#if defined(STLSOFT_COMPILER_IS_MSVC) && \
_MSC_VER < 1200
stlsoft_ns_qual(scoped_handle)<HANDLE> cleanup(hSrch, (void (STLSOFT_STDCALL *)(HANDLE))&::FindClose, INVALID_HANDLE_VALUE);
#else /* ? compiler */
stlsoft_ns_qual(scoped_handle)<HANDLE> cleanup(hSrch, ::FindClose, INVALID_HANDLE_VALUE);
#endif /* compiler */
// Special case, where the pattern specified is either "." or ".."
// the API will return the directory name, but we want to keep the
// dot name.
if( '.' == m_pattern0[0] &&
( m_pattern1 == m_pattern0 + 1 ||
( '.' == m_pattern0[1] &&
m_pattern1 == m_pattern0 + 2)))
{
const ws_size_t n = static_cast<ws_size_t>(m_pattern1 - m_pattern0);
traits_type::str_n_copy(&m_data.cFileName[0], m_pattern0, n);
m_data.cFileName[n] = '\0';
}
m_handle = new shared_handle(hSrch);
if(NULL != m_handle)
{
cleanup.detach();
}
return *this;
}
else
{
#ifdef _DEBUG
DWORD dwErr = ::GetLastError();
STLSOFT_SUPPRESS_UNUSED(dwErr);
#endif /* _DEBUG */
}
}
}
}
if(NULL != m_handle)
{
for(; INVALID_HANDLE_VALUE != m_handle->hSrch; )
{
if(!traits_type::find_next_file(m_handle->hSrch, &m_data))
{
m_handle->Release();
m_handle = NULL;
break;
}
else
{
if( traits_type::is_file(&m_data) &&
( 0 == (m_flags & sequence_type::skipHiddenFiles) ||
0 == (m_data.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)))
{
// A file, and files requested, so break
if(m_flags & sequence_type::files)
{
return *this;
}
}
else
{
if( 0 == (m_flags & sequence_type::skipHiddenDirs) ||
0 == (m_data.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN))
{
if(traits_type::is_dots(m_data.cFileName))
{
if(m_flags & sequence_type::includeDots)
{
// A dots file, and dots are requested
return *this;
}
}
else if(m_flags & sequence_type::directories)
{
// A directory, and directories requested
if( 0 == (m_flags & sequence_type::skipReparseDirs) ||
0 == (m_data.dwFileAttributes & reparsePointConstant))
{
// Either not requested to skip reparse points, or not a reparse point
return *this;
}
}
}
}
}
}
}
}
return *this;
}
template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k V>
inline ss_typename_type_k basic_findfile_sequence_const_input_iterator<C, T, V>::class_type basic_findfile_sequence_const_input_iterator<C, T, V>::operator ++(int)
{
class_type ret(*this);
operator ++();
return ret;
}
template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k V>
inline const ss_typename_type_k basic_findfile_sequence_const_input_iterator<C, T, V>::value_type basic_findfile_sequence_const_input_iterator<C, T, V>::operator *() const
{
WINSTL_MESSAGE_ASSERT("Dereferencing end()-valued iterator", NULL != m_handle);
WINSTL_ASSERT(m_subPathLen == traits_type::str_len(m_subpath.c_str()));
if(0 == m_subPathLen)
{
return value_type(m_data, m_list->get_directory(), traits_type::str_len(m_list->get_directory()));
}
else
{
return value_type(m_data, m_subpath.c_str(), m_subPathLen);
}
}
template <ss_typename_param_k C, ss_typename_param_k T, ss_typename_param_k V>
inline ws_bool_t basic_findfile_sequence_const_input_iterator<C, T, V>::equal(basic_findfile_sequence_const_input_iterator<C, T, V> const& rhs) const
{
// Should only be comparing iterators from same container
WINSTL_MESSAGE_ASSERT("Comparing iterators from separate sequences", m_list == rhs.m_list || NULL == m_list || NULL == rhs.m_list);
return m_handle == rhs.m_handle;
}
#endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
/* ////////////////////////////////////////////////////////////////////// */
#ifndef _WINSTL_NO_NAMESPACE
# if defined(_STLSOFT_NO_NAMESPACE) || \
defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
} // namespace winstl
# else
} // namespace winstl_project
} // namespace stlsoft
# endif /* _STLSOFT_NO_NAMESPACE */
#endif /* !_WINSTL_NO_NAMESPACE */
/* /////////////////////////////////////////////////////////////////////////
* Namespace
*
* The string access shims exist either in the stlsoft namespace, or in the
* global namespace. This is required by the lookup rules.
*
*/
#ifndef _WINSTL_NO_NAMESPACE
# if !defined(_STLSOFT_NO_NAMESPACE) && \
!defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
namespace stlsoft
{
# else /* ? _STLSOFT_NO_NAMESPACE */
/* There is no stlsoft namespace, so must define in the global namespace */
# endif /* !_STLSOFT_NO_NAMESPACE */
using ::winstl::c_str_len;
using ::winstl::c_str_len_a;
using ::winstl::c_str_len_w;
using ::winstl::c_str_data;
using ::winstl::c_str_data_a;
using ::winstl::c_str_data_w;
using ::winstl::c_str_ptr;
using ::winstl::c_str_ptr_a;
using ::winstl::c_str_ptr_w;
using ::winstl::c_str_ptr_null;
using ::winstl::c_str_ptr_null_a;
using ::winstl::c_str_ptr_null_w;
#ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
using ::winstl::is_empty;
#endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
# if !defined(_STLSOFT_NO_NAMESPACE) && \
!defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
} // namespace stlsoft
# else /* ? _STLSOFT_NO_NAMESPACE */
/* There is no stlsoft namespace, so must define in the global namespace */
# endif /* !_STLSOFT_NO_NAMESPACE */
#endif /* !_WINSTL_NO_NAMESPACE */
/* ////////////////////////////////////////////////////////////////////// */
#endif /* WINSTL_INCL_WINSTL_FILESYSTEM_HPP_FINDFILE_SEQUENCE */
/* ////////////////////////////////////////////////////////////////////// */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -