⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 filesystem_traits.hpp

📁 新版本TR1的stl
💻 HPP
📖 第 1 页 / 共 4 页
字号:
    {
        return false;
    }
    static bool_type is_readonly(fstat_data_type const* stat_data)
    {
        return FILE_ATTRIBUTE_READONLY == (stat_data->dwFileAttributes & FILE_ATTRIBUTE_READONLY);
    }

#ifdef STLSOFT_CF_64BIT_INT_SUPPORT
    static ws_uint64_t  get_file_size(file_handle_type h)
    {
        DWORD   dwHigh;
        DWORD   dwLow   =   ::GetFileSize(h, &dwHigh);

        if( 0xFFFFFFFF == dwLow &&
            ERROR_SUCCESS != ::GetLastError())
        {
            dwHigh = 0xFFFFFFFF;
        }

        return (static_cast<ws_uint64_t>(dwHigh) << 32) | dwLow;
    }
#endif /* STLSOFT_CF_64BIT_INT_SUPPORT */
};

STLSOFT_TEMPLATE_SPECIALISATION
struct filesystem_traits<ws_char_a_t>
    : public system_traits<ws_char_a_t>
{
public:
    typedef ws_char_a_t                             char_type;
    typedef ws_size_t                               size_type;
    typedef ws_ptrdiff_t                            difference_type;
    typedef WIN32_FIND_DATAA                        find_data_type;
    typedef WIN32_FIND_DATAA                        stat_data_type;
    typedef BY_HANDLE_FILE_INFORMATION              fstat_data_type;
    typedef filesystem_traits<char_type>            class_type;
    typedef ws_int_t                                int_type;
    typedef ws_bool_t                               bool_type;
    typedef HANDLE                                  file_handle_type;
    typedef HINSTANCE                               module_type;
    typedef DWORD                                   error_type;
private:
#if !defined(STLSOFT_COMPILER_IS_MSVC) || \
    _MSC_VER >= 1200
    typedef stlsoft_ns_qual(auto_buffer)<char_type> buffer_type_;
#endif /* compiler */
public:

    enum
    {
        maxPathLength   =   1 + _MAX_PATH       //!< The maximum length of a path for the current file system
    };

public:
    static char_type *ensure_dir_end(char_type *dir)
    {
        WINSTL_ASSERT(NULL != dir);

        char_type   *end    =   str_end(dir);

        if( dir < end &&
            !is_path_name_separator(*(end - 1)))
        {
            *end        =   path_name_separator();
            *(end + 1)  =   '\0';
        }

        return dir;
    }

    static char_type *remove_dir_end(char_type *dir)
    {
        WINSTL_ASSERT(NULL != dir);

        // Don't trim drive roots ...
        if( isalpha(dir[0]) &&
            ':' == dir[1] &&
            is_path_name_separator(dir[2]) &&
            '\0' == dir[3])
        {
            return dir;
        }

        // ... or UNC roots
        if( '\\' == dir[0] &&
            '\\' == dir[1] &&
            '\0' == dir[3])
        {
            return dir;
        }

        char_type   *end    =   str_end(dir);

        if( dir < end &&
            is_path_name_separator(*(end - 1)))
        {
            *(end - 1)  =   '\0';
        }

        return dir;
    }

    static bool_type has_dir_end(char_type const* dir)
    {
        WINSTL_ASSERT(NULL != dir);

        size_type len = str_len(dir);

        return (0 < len) && is_path_name_separator(dir[len - 1]);
    }

    static bool_type is_dots(char_type const* dir)
    {
        WINSTL_ASSERT(NULL != dir);

        return  dir[0] == '.' &&
                (   dir[1] == '\0' ||
                    (    dir[1] == '.' &&
                        dir[2] == '\0'));
    }

    static bool_type is_path_rooted(char_type const* path)
    {
        WINSTL_ASSERT(NULL != path);

        return is_path_name_separator(*path) || is_path_absolute(path);
    }

    static bool_type is_path_absolute(char_type const* path)
    {
        WINSTL_ASSERT(NULL != path);

        size_type len = str_len(path);

        return  is_path_UNC(path) ||
                (   (2 < len) &&
                    (':' == path[1]) &&
                    is_path_name_separator(path[2]));
    }

    static bool_type is_path_UNC(char_type const* path)
    {
        WINSTL_ASSERT(NULL != path);

        return ('\\' == path[0] && '\\' == path[1]);
    }

private:
    static bool_type is_root_drive_(char_type const* path)
    {
        if( isalpha(path[0]) &&
            ':' == path[1] &&
            is_path_name_separator(path[2]) &&
            '\0' == path[3])
        {
            return true;
        }

        return false;
    }
    static bool_type is_root_UNC_(char_type const* path)
    {
        if(is_path_UNC(path))
        {
            char_type const* sep = str_pbrk(path + 2, "\\/");

            if( NULL == sep ||
                '\0' == sep[1])
            {
                return true;
            }
        }

        return false;
    }
    static bool_type is_root_directory_(char_type const* path)
    {
        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<ws_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<ws_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
                        {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -