📄 filesystem_traits.hpp
字号:
{
if( is_path_name_separator(path[0]) &&
'\0' == path[1])
{
return true;
}
return false;
}
public:
static bool_type is_root_designator(char_type const *path)
{
WINSTL_ASSERT(NULL != path);
return is_root_directory_(path) || is_root_drive_(path) || is_root_UNC_(path);
}
static bool_type is_path_name_separator(char_type ch)
{
return '\\' == ch || '/' == ch;
}
static char_type path_separator()
{
return ';';
}
static char_type path_name_separator()
{
return '\\';
}
static char_type const *pattern_all()
{
return "*.*";
}
static size_type path_max()
{
return 1 + _MAX_PATH;
}
#if defined(STLSOFT_COMPILER_IS_MSVC) && \
_MSC_VER < 1200
static ws_dword_t get_full_path_name(char_type const *fileName, ws_dword_t cchBuffer, char_type *buffer, char_type **ppFile)
{
WINSTL_MESSAGE_ASSERT("GetFullPathNameW() will crash when the file-name and buffer parameters are the same, so it's not a good idea to do this for ANSI compilation", fileName != buffer);
if('"' == *fileName)
{
// This can only work if ...
const size_type len = class_type::str_len(fileName);
char_type const *const closing = class_type::str_chr(fileName + 1, '"');
// ... 1. the only other double quote is at the end of the string, and ...
if( NULL != closing &&
closing - fileName == static_cast<ptrdiff_t>(len - 1))
{
ws_dword_t res = class_type::get_full_path_name(fileName + 1, cchBuffer, buffer, ppFile);
// ... 2. the front-quote skipped string can be converted, and ...
if( 0 != res &&
res < cchBuffer)
{
WINSTL_ASSERT('\0' == buffer[res]);
char_type *const closing2 = class_type::str_chr(buffer, '"');
// ... 3. the front-quote skipped converted string contains a single trailing quote
if( NULL != closing2 &&
closing2 - buffer == static_cast<ptrdiff_t>(res - 1))
{
buffer[res-- - 1] = '\0';
return res;
}
}
}
}
return ::GetFullPathNameA(fileName, cchBuffer, buffer, ppFile);
}
#else /* ? compiler */
private:
static size_type get_full_path_name_impl2(char_type const *fileName, size_type len, char_type *buffer, size_type cchBuffer, char_type **ppFile)
{
size_type r = ::GetFullPathNameA(fileName, cchBuffer, buffer, ppFile);
if( 0 != r &&
NULL != buffer &&
r > cchBuffer)
{
buffer_type_ buffer_(1 + r);
if(0 == buffer_.size())
{
*ppFile = NULL;
return 0;
}
else
{
char_type *pFile2;
size_type r2 = get_full_path_name_impl2(fileName, len, &buffer_[0], buffer_.size(), &pFile2);
if(0 == r2)
{
return 0;
}
else
{
if(r2 > cchBuffer)
{
r2 = cchBuffer;
}
str_n_copy(&buffer[0], &buffer_[0], r2);
if( NULL != pFile2 &&
r2 == (r - 1) &&
static_cast<size_type>(pFile2 - &buffer_[0]) < r2)
{
*ppFile = &buffer[0] + (pFile2 - &buffer_[0]);
}
else
{
*ppFile = NULL;
}
return r2;
}
}
}
else
{
return r;
}
}
static size_type get_full_path_name_impl(char_type const *fileName, size_type len, char_type *buffer, size_type cchBuffer, char_type **ppFile)
{
WINSTL_ASSERT(len > 0);
if('\0' != fileName[len])
{
buffer_type_ fileName_(1 + (len - 1));
// May be being compiled absent exception support, so need to check the
// file path buffers. (This _could_ be done with a compile-time #ifdef,
// but it's best not, since some translators support exceptions but yet
// don't throw on mem exhaustion, and in any case a user could change
// ::new)
if(0 == fileName_.size())
{
set_last_error(ERROR_OUTOFMEMORY);
return 0;
}
else
{
fileName_[len] = '\0';
return get_full_path_name_impl( str_n_copy(&fileName_[0], fileName, len)
, len
, buffer
, cchBuffer
, ppFile);
}
}
else
{
return get_full_path_name_impl2(fileName, len, buffer, cchBuffer, ppFile);
}
}
public:
static size_type get_full_path_name(char_type const *fileName, size_type cchBuffer, char_type *buffer, char_type **ppFile)
{
WINSTL_MESSAGE_ASSERT("GetFullPathNameW() will crash when the file-name and buffer parameters are the same, so it's not a good idea to do this for ANSI compilation", fileName != buffer);
size_type n = 0;
const size_type len = class_type::str_len(fileName);
if(NULL != class_type::str_pbrk(fileName, "<>|*?"))
{
::SetLastError(ERROR_INVALID_NAME);
return 0;
}
if('"' == *fileName)
{
// This can only work if:
//
// - the only other double-quote is at the end of the string
// - the unquoted form successfully converts
char_type const *const closing = class_type::str_chr(fileName + 1, '"');
if( NULL == closing ||
static_cast<size_type>(closing - fileName) != len - 1)
{
set_last_error(ERROR_INVALID_DATA);
}
else
{
size_type r;
if(NULL == buffer)
{
r = get_full_path_name_impl(fileName, len, NULL, 0, ppFile);
if(0 != r)
{
n = 2 + r;
}
}
else if(cchBuffer == 0)
{
n = 0;
*ppFile = NULL;
}
else if(cchBuffer == 1)
{
// Have to check it's valid
r = get_full_path_name_impl(fileName, len, NULL, 0, ppFile);
if(0 != r)
{
buffer[0] = '"';
n = 1;
*ppFile = NULL;
}
}
else
{
r = get_full_path_name_impl(fileName + 1, len - 2, buffer + 1, cchBuffer - 1, ppFile);
if(0 != r)
{
// Write the first quote character into the buffer
buffer[0] = '"';
if(r + 1 < cchBuffer)
{
// There's enough space for the result and the closing quote
buffer[r + 1] = '"';
if(r + 2 < cchBuffer)
{
// There's enough space for the result and the closing quote and the nul-terminator
buffer[r + 2] = '\0';
n = r + 2;
}
else
{
n = r + 2;
}
}
else
{
n = r + 1;
}
}
}
}
}
else
{
n = get_full_path_name_impl(fileName, len, buffer, cchBuffer, ppFile);
}
// Paths that exceed _MAX_PATH cause GetFullPathNameA() to fail, but it
// does not (appear to) call SetLastError()
if( 0 == n &&
0 == ::GetLastError() &&
str_len(fileName) > _MAX_PATH)
{
::SetLastError(ERROR_FILENAME_EXCED_RANGE);
}
return n;
}
#endif /* compiler */
static size_type get_full_path_name(char_type const *fileName, size_type cchBuffer, char_type *buffer)
{
WINSTL_ASSERT(NULL != fileName);
char_type *pFile;
if('\0' == *fileName)
{
static const char s_dot[2] = { '.', '\0' };
fileName = s_dot;
}
return get_full_path_name(fileName, cchBuffer, buffer, &pFile);
}
static size_type get_short_path_name(char_type const *fileName, size_type cchBuffer, char_type *buffer)
{
return ::GetShortPathNameA(fileName, buffer, cchBuffer);
}
static size_type get_short_path_name(char_type const *fileName, char_type *buffer, size_type cchBuffer)
{
return ::GetShortPathNameA(fileName, buffer, cchBuffer);
}
// File-system enumeration
static HANDLE find_first_file(char_type const *spec, find_data_type *findData)
{
return ::FindFirstFileA(spec, findData);
}
#if defined(_WIN32_WINNT) && \
_WIN32_WINNT >= 0x0400
static HANDLE find_first_file_ex(char_type const *spec, FINDEX_SEARCH_OPS flags, find_data_type *findData)
{
return ::FindFirstFileExA(spec, FindExInfoStandard, findData, flags, NULL, 0);
}
#endif /* _WIN32_WINNT >= 0x0400 */
static bool_type find_next_file(HANDLE h, find_data_type *findData)
{
return ::FindNextFileA(h, findData) != FALSE;
}
static void find_file_close(HANDLE h)
{
WINSTL_ASSERT(INVALID_HANDLE_VALUE != h);
::FindClose(h);
}
#ifndef _WINSTL_NO_FINDVOLUME_API
static HANDLE find_first_volume(char_type *volume_name, size_type cch_volume_name)
{
return ::FindFirstVolumeA(volume_name, cch_volume_name);
}
static bool_type find_next_volume(HANDLE h, char_type *volume_name, size_type cch_volume_name)
{
return ::FindNextVolumeA(h, volume_name, cch_volume_name) != FALSE;
}
static void find_volume_close(HANDLE h)
{
WINSTL_ASSERT(INVALID_HANDLE_VALUE != h);
::FindVolumeClose(h);
}
#endif // !_WINSTL_NO_FINDVOLUME_API
// Modules
static size_type get_module_filename(HINSTANCE hModule, char_type *buffer, size_type cchBuffer)
{
return ::GetModuleFileNameA(hModule, buffer, cchBuffer);
}
static size_type get_system_directory(char_type *buffer, size_type cchBuffer)
{
return ::GetSystemDirectoryA(buffer, cchBuffer);
}
static size_type get_windows_directory(char_type *buffer, size_type cchBuffer)
{
return ::GetWindowsDirectoryA(buffer, cchBuffer);
}
// Dynamic Loading
static module_type load_library(char_type const *name)
{
return ::LoadLibraryA(name);
}
static bool_type free_library(module_type hModule)
{
return filesystem_traits_::free_library(hModule);
}
static FARPROC find_symbol(module_type hModule, char const *symbolName)
{
return filesystem_traits_::find_symbol(hModule, symbolName);
}
// File-system state
static bool_type set_current_directory(char_type const *dir)
{
return ::SetCurrentDirectoryA(dir) != FALSE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -