字符串编码转换与常用操作(Win32,C++)

CStrUtils.h

#pragma once

#include <string>
#include <vector>
#include <windows.h>
#include <tchar.h>

#ifdef _UNICODE
using _tstring = std::wstring;
#else
using _tstring = std::string;
#endif

// 字符串转换实用工具
namespace CStrUtils
{
    // 宽字符串转换
    std::string WStrToU8Str(const std::wstring& str);
    std::string WStrToAStr(const std::wstring& str);
    _tstring WStrToTStr(const std::wstring& str);

    // ANSI字符串转换
    std::wstring AStrToWStr(const std::string& str);
    std::string AStrToU8Str(const std::string& str);
    _tstring AStrToTStr(const std::string& str);

    // UTF-8字符串转换
    std::wstring U8StrToWStr(const std::string& str);
    std::string U8StrToAStr(const std::string& str);
    _tstring U8StrToTStr(const std::string& str);

    // 中立字符串转换
    std::string TStrToAStr(const _tstring& str);
    std::wstring TStrToWStr(const _tstring& str);
    std::string TStrToU8Str(const _tstring& str);

    // 获取字符个数
    int GetGbkCount(const void* pData, size_t size = -1);
    int GetUtf8Count(const void* data_ptr, size_t size = -1);
    int GetUtf16Count(const void* data_ptr, size_t size = -1, bool* big_endian_ptr = nullptr);

    int GetGbkCount(const std::string& str);
    int GetUtf8Count(const std::string& str);
    int GetUtf16Count(const std::wstring& str);

    // 获取大写字符串
    std::string GetUpperStrA(const std::string& str);
    std::wstring GetUpperStrW(const std::wstring& str);
    _tstring GetUpperStr(const _tstring& str);

    // 获取小写字符串
    std::string GetLowerStrA(const std::string& str);
    std::wstring GetLowerStrW(const std::wstring& str);
    _tstring GetLowerStr(const _tstring& str);

    // 转换为大写字符串
    std::string& ToUpperStrA(const std::string& str);
    std::wstring& ToUpperStrW(const std::wstring& str);
    _tstring& ToUpperStr(const _tstring& str);

    // 转换为小写字符串
    std::string& ToLowerStrA(const std::string& str);
    std::wstring& ToLowerStrW(const std::wstring& str);
    _tstring& ToLowerStr(const _tstring& str);

    // 浮点数转换
    double StrToDoubleA(const std::string& str);
    double StrToDoubleW(const std::wstring& str);
    double StrToDouble(const _tstring& str);
    std::string DoubleToStrA(double val);
    std::wstring DoubleToStrW(double val);
    _tstring DoubleToStr(double val);

    // 整数转换
    int64_t StrToIntA(const std::string& str, int radix = 10);
    int64_t StrToIntW(const std::wstring& str, int radix = 10);

    // shlwapi.h 含有 StrToInt 宏定义, 此处检查防止冲突
#ifndef StrToInt
    int64_t StrToInt(const _tstring& str, int radix = 10);
#endif

    std::string IntToStrA(int64_t val, int radix = 10);
    std::wstring IntToStrW(int64_t val, int radix = 10);
    _tstring IntToStr(int64_t val, int radix = 10);

    // 无符号整数转换
    uint64_t StrToUIntA(const std::string& str, int radix = 10);
    uint64_t StrToUIntW(const std::wstring& str, int radix = 10);
    uint64_t StrToUInt(const _tstring& str, int radix = 10);
    std::string UIntToStrA(uint64_t val, int radix = 10);
    std::wstring UIntToStrW(uint64_t val, int radix = 10);
    _tstring UIntToStr(uint64_t val, int radix = 10);

    // 查找字符串位置(忽略大小写)
    size_t FindNoCaseA(const std::string& strMain, const std::string& strSub, size_t offset = 0);
    size_t FindNoCaseW(const std::wstring& strMain, const std::wstring& strSub, size_t offset = 0);
    size_t FindNoCase(const _tstring& strMain, const _tstring& strSub, size_t offset = 0);

    size_t FindFirstNotOfNoCaseA(const std::string& strMain, const std::string& strSub, size_t offset = 0);
    size_t FindFirstNotOfNoCaseW(const std::wstring& strMain, const std::wstring& strSub, size_t offset = 0);
    size_t FindFirstNotOfNoCase(const _tstring& strMain, const _tstring& strSub, size_t offset = 0);

    // 替换字符串(忽略大小写)
    std::string& ReplaceNoCaseA(std::string& strMain, const std::string& strSub, const std::string& strTarget);
    std::wstring& ReplaceNoCaseW(std::wstring& strMain, const std::wstring& strSub, const std::wstring& strTarget);
    _tstring& ReplaceNoCase(_tstring& strMain, const _tstring& strSub, const _tstring& strTarget);

    // 比较字符串(忽略大小写)
    int CompareNoCaseA(const std::string& strSrc, const std::string& strDest);
    int CompareNoCaseW(const std::wstring& strSrc, const std::wstring& strDest);
    int CompareNoCase(const _tstring& strSrc, const _tstring& strDest);

    // 查找字符串
    size_t FindA(const std::string& strMain, const std::string& strSub, size_t offset = 0, bool fCase = false);
    size_t FindW(const std::wstring& strMain, const std::wstring& strSub, size_t offset = 0, bool fCase = false);
    size_t Find(const _tstring& strMain, const _tstring& strSub, size_t offset = 0, bool fCase = false);

    // 替换字符串
    std::string& ReplaceA(std::string& strSrc, const std::string& strFind, const std::string& strReplace, bool fCase = false);
    std::wstring& ReplaceW(std::wstring& strSrc, const std::wstring& strFind, const std::wstring& strReplace, bool fCase = false);
    _tstring& Replace(_tstring& strSrc, const _tstring& strFind, const _tstring& strReplace, bool fCase = false);

    // 比较字符串
    int CompareA(const std::string& strSrc, const std::string& strDest, bool fCase = true);
    int CompareW(const std::wstring& strSrc, const std::wstring& strDest, bool fCase = true);
    int Compare(const _tstring& strSrc, const _tstring& strDest, bool fCase = true);

    bool IsOctStringA(const std::string& strSrc);
    bool IsOctStringW(const std::wstring& strSrc);
    bool IsOctString(const _tstring& strSrc);

    bool IsDecStringA(const std::string& strSrc);
    bool IsDecStringW(const std::wstring& strSrc);
    bool IsDecString(const _tstring& strSrc);

    bool IsHexStringA(const std::string& strSrc);
    bool IsHexStringW(const std::wstring& strSrc);
    bool IsHexString(const _tstring& strSrc);

    // 分割字符串
    std::vector<std::string> SplitStrA(const std::string& str, const std::string& delim, bool fCase = true);
    std::vector<std::wstring> SplitStrW(const std::wstring& str, const std::wstring& delim, bool fCase = true);
    std::vector<_tstring> SplitStr(const _tstring& str, const _tstring& delim, bool fCase = true);

    // 按行拆分字符串
    std::vector<std::string> SplitLinesA(const std::string& str);
    std::vector<std::wstring> SplitLinesW(const std::wstring& str);
    std::vector<_tstring> SplitLines(const _tstring& str);

    // 合并字符串
    std::string ConcatStringsA(const std::vector<std::string>& strList, const std::string& strReturn = "");
    std::wstring ConcatStringsW(const std::vector<std::wstring>& strList, const std::wstring& strReturn = L"");
    _tstring ConcatStrings(const std::vector<_tstring>& strList, const _tstring& strReturn = _T(""));

    // 移除前后空格
    std::string RemoveSpacesA(const std::string& strValue, bool fLeft = true, bool fRight = true);
    std::wstring RemoveSpacesW(const std::wstring& strValue, bool fLeft = true, bool fRight = true);
    _tstring RemoveSpaces(const _tstring& strValue, bool fLeft = true, bool fRight = true);

    // 从文件载入字符串
    std::string FromFileA(const std::string& strFile, bool fAutoEncoding = false);
    std::wstring FromFileW(const std::wstring& strFile, bool fAutoEncoding = false);
    _tstring FromFile(const _tstring& strFile, bool fAutoEncoding = false);

    // 字符串保存到文件
    bool ToFileA(const std::string& str, const std::string& strFile);
    bool ToFileW(const std::wstring& str, const std::wstring& strFile);
    bool ToFile(const _tstring& str, const _tstring& strFile);

    // 格式化字符串
    std::string FormatA(LPCSTR pFormat, ...);
    std::wstring FormatW(LPCWSTR pFormat, ...);
    _tstring Format(LPCTSTR pFormat, ...);

    // 输出调试字符串
    void OutputDebugA(LPCSTR pFormat, ...);
    void OutputDebugW(LPCWSTR pFormat, ...);
    void OutputDebug(LPCTSTR pFormat, ...);

    // 控制台输出
    void ConsoleClear(SHORT nStartLine = -1, SHORT nCount = -1);
    void ConsoleSetPos(SHORT x = 0, SHORT y = 0);
    void ConsolePrintf(LPCTSTR pFormat, ...);
    void ConsoleOutputA(LPCSTR pFormat, ...);
    void ConsoleOutputW(LPCWSTR pFormat, ...);
    void ConsoleOutput(LPCTSTR pFormat, ...);

    // 获取GetLastError()的错误信息文本
    std::string GetErrorMessageA(DWORD dwMessageId, DWORD dwLanguageId = MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT));
    std::wstring GetErrorMessageW(DWORD dwMessageId, DWORD dwLanguageId = MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT));
    _tstring GetErrorMessage(DWORD dwMessageId, DWORD dwLanguageId = MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT));

    // 数据单位
    enum eUnitType
    {
        eUT_Auto,   // 自动
        eUT_b,      // (2 ^ 000) Bit
        eUT_Kb,     // (2 ^ 010) Bit
        eUT_Mb,     // (2 ^ 020) Bit
        eUT_Gb,     // (2 ^ 030) Bit
        eUT_Tb,     // (2 ^ 040) Bit
        eUT_Pb,     // (2 ^ 050) Bit
        eUT_Eb,     // (2 ^ 060) Bit
        eUT_Zb,     // (2 ^ 070) Bit
        eUT_Yb,     // (2 ^ 080) Bit
        eUT_Bb,     // (2 ^ 090) Bit
        eUT_Nb,     // (2 ^ 100) Bit
        eUT_Db,     // (2 ^ 110) Bit
        eUT_Cb,     // (2 ^ 120) Bit
        eUT_Xb,     // (2 ^ 130) Bit

        eUT_B,      // Byte          2 ^ 000 Byte
        eUT_KB,     // Kilobyte      2 ^ 010 Byte 
        eUT_MB,     // Megabyte      2 ^ 020 Byte 
        eUT_GB,     // Gigabyte      2 ^ 030 Byte 
        eUT_TB,     // Terabyte      2 ^ 040 Byte 
        eUT_PB,     // Petabyte      2 ^ 050 Byte 
        eUT_EB,     // Exabyte       2 ^ 060 Byte 
        eUT_ZB,     // Zettabyte     2 ^ 070 Byte 
        eUT_YB,     // Yottabyte     2 ^ 080 Byte 
        eUT_BB,     // Brontobyte    2 ^ 090 Byte 
        eUT_NB,     // NonaByte      2 ^ 100 Byte 
        eUT_DB,     // DoggaByte     2 ^ 110 Byte 
        eUT_CB,     // corydonbyte   2 ^ 120 Byte 
        eUT_XB,     // Xerobyte      2 ^ 130 Byte
        eUT_Max
    };

    // 数据单位信息
    typedef struct _DATA_UNIT_INFO
    {
        double value;           // 数值
        eUnitType eUnit;        // 单位
        _tstring strUnitStr;    // 单位字符串
        _tstring strOutput;     // 内容(数值 + 单位字符串)
        _DATA_UNIT_INFO() : value(0.0f), eUnit(eUnitType::eUT_Auto) {}
    }DATA_UNIT_INFO;

    // 数据单位转换
    DATA_UNIT_INFO FormatByteSize(
        double nBytesSize,                                      // 输入值
        eUnitType eSrcUnit = eUnitType::eUT_Auto,               // 原始单位
        eUnitType eDestUnit = eUnitType::eUT_Auto,              // 目标单位
        bool fHasUnits = true,                                  // 结果字符串数值添加单位
        bool fSpace = true,                                     // 结果字符串数值与单位之间添加空格
        int nInteger = 1,                                       // 整数部分长度
        int nPrecision = 3                                      // 小数部分长度
    );
}

CStrUtils.cpp

#include "CStrUtils.h"
#include <fstream>
#include <tchar.h>

// ANSI GBK 编码标准
// 
// 汉字区
// GBK/2:0XBOA1-F7FE 收录 GB 2312 汉字 6763 个,按原序排列
// GBK/3:0X8140-AOFE,收录 CJK 汉字 6080 个
// GBK/4:0XAA40-FEAO,收录 CJK 汉字和增补的汉字 8160 个
// 
// 图形符号区
// GBK/1:0XA1A1-A9FE,除 GB 2312 的符号外,还增补了其它符号
// GBK/5:0XA840-A9AO,扩除非汉字区
// 
// 用户自定义区
// GBK 区域中的空白区,用户可以自己定义字符

// UTF-8 编码标准
// 
// 1字节 U+0000000 - U+0000007F 0xxxxxxx
// 2字节 U+0000080 - U+000007FF 110xxxxx 10xxxxxx
// 3字节 U+0000800 - U+0000FFFF 1110xxxx 10xxxxxx 10xxxxxx
// 4字节 U+0010000 - U+001FFFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
// 5字节 U+0200000 - U+03FFFFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
// 6字节 U+4000000 - U+7FFFFFFF 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

// UTF16 编码标准
// 
// 基本多语言平面(U+0000 - U+FFFF)
// 
// 辅助平面(U+10000 - U+10FFFF)
// 1.码位减去 0x10000,得到20位的代理值(0x00 - 0xFFFFF)
// 2.高10位(范围0 - 0x3FF)加 0xD800 得到高位代理(0xD800 - 0xDBFF)
// 3.低10位(范围0 - 0x3FF)加 0xDC00 得到低位代理(0xDC00 - 0xDFFF)

namespace CStrUtils
{
    const int FORMAT_COUNT_MAX = (1024 * 1024 * 64);

    // UTF-8 Byte count table
    unsigned char g_utf8_bytes_count_table[0x100] = {
        0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
        0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
        0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
        0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
        0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
        0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
        0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
        0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
        0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
        0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
        0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
        0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x05,0x05,0x05,0x05,0x06,0x06,0x00,0x00,
    };

    // UTF-8 Data mask table
    unsigned char g_utf8_data_mask_table[0x100] = {
        0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
        0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
        0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
        0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
        0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
        0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
        0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
        0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
        0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
        0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
        0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,
        0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x03,0x03,0x03,0x03,0x01,0x01,0x00,0x00,
    };

    std::string _WStrToMultiStr(UINT CodePage, const std::wstring& str)
    {
        //计算缓冲区所需的字节长度
        int cbMultiByte = ::WideCharToMultiByte(CodePage, 0, str.c_str(), -1, NULL, 0, NULL, NULL);
        std::string strResult(cbMultiByte, 0);

        //成功则返回写入到指示的缓冲区的字节数
        size_t nConverted = ::WideCharToMultiByte(CodePage, 0, str.c_str(), (int)str.size(), &strResult[0], (int)strResult.size(), NULL, NULL);

        //调整内容长度
        strResult.resize(nConverted);
        return strResult;
    }

    std::wstring _MultiStrToWStr(UINT CodePage, const std::string& str)
    {
        //计算缓冲区所需的字符长度
        int cchWideChar = ::MultiByteToWideChar(CodePage, 0, str.c_str(), -1, NULL, 0);
        std::wstring strResult(cchWideChar, 0);

        //成功则返回写入到指示的缓冲区的字符数
        size_t nConverted = ::MultiByteToWideChar(CodePage, 0, str.c_str(), (int)str.size(), &strResult[0], (int)strResult.size());

        //调整内容长度
        strResult.resize(nConverted);
        return strResult;
    }

    std::string WStrToAStr(const std::wstring& str)
    {
        return _WStrToMultiStr(CP_ACP, str);
    }

    std::string WStrToU8Str(const std::wstring& str)
    {
        return _WStrToMultiStr(CP_UTF8, str);
    }

    _tstring WStrToTStr(const std::wstring& str)
    {
#ifdef _UNICODE
        return str;
#else
        return _WStrToMultiStr(CP_ACP, str);
#endif
    }

    std::wstring AStrToWStr(const std::string& str)
    {
        return _MultiStrToWStr(CP_ACP, str);
    }

    std::string AStrToU8Str(const std::string& str)
    {
        return WStrToU8Str(AStrToWStr(str));
    }

    _tstring AStrToTStr(const std::string& str)
    {
#ifdef _UNICODE
        return _MultiStrToWStr(CP_ACP, str);
#else
        return str;
#endif
    }

    std::wstring U8StrToWStr(const std::string& str)
    {
        return _MultiStrToWStr(CP_UTF8, str);
    }

    std::string U8StrToAStr(const std::string& str)
    {
        return WStrToAStr(U8StrToWStr(str));
    }

    _tstring U8StrToTStr(const std::string& str)
    {
#ifdef _UNICODE
        return _MultiStrToWStr(CP_UTF8, str);
#else
        return WStrToAStr(U8StrToWStr(str));
#endif
    }

    std::string TStrToAStr(const _tstring& str)
    {
#ifdef _UNICODE
        return _WStrToMultiStr(CP_ACP, str);
#else
        return str;
#endif
    }

    std::wstring TStrToWStr(const _tstring& str)
    {
#ifdef _UNICODE
        return str;
#else
        return AStrToWStr(str);
#endif
    }

    std::string TStrToU8Str(const _tstring& str)
    {
#ifdef _UNICODE
        return WStrToU8Str(str);
#else
        return WStrToU8Str(AStrToWStr(str));
#endif
    }

    int32_t _GetGbkCount(const void* pData, size_t size/* = -1*/, std::string* pGbk/* = nullptr*/)
    {
        const uint8_t* pCpData = (const uint8_t*)pData;
        std::string strOutGbk;      // 输出字符编码
        uint16_t gbkCode = 0;       // GBK编码
        int32_t nByteCount = 0;     // 字节计数
        int32_t nChCount = 0;       // 字符计数
        bool fResult = true;        // 操作结果

        while ((0 != *pCpData) && (0 != size))
        {
            uint8_t ch = *pCpData;

            // ASCII编码 兼容
            if (ch <= 0x7F)
            {
                gbkCode = ch;
                nChCount++;
            }
            else
            {
                // 高字节范围: 0x81 - 0xFE
                if (0 == nByteCount)
                {
                    gbkCode = 0;
                    if (ch >= 0x81 && ch <= 0xFE)
                    {
                        gbkCode = ch;
                        nByteCount = 1;
                    }
                    else
                    {
                        fResult = false;
                        break;
                    }
                }
                else
                {
                    // 低字节范围: 0x40 - 0xFE (不包括0x7F)
                    if (1 == nByteCount)
                    {
                        if (!(ch >= 0x40 && ch <= 0xFE) || 0x7F == ch)
                        {
                            fResult = false;
                            break;
                        }
                    }

                    gbkCode = gbkCode << 8;
                    gbkCode |= ch;

                    nByteCount--;

                    if (0 == nByteCount)
                    {
                        nChCount++;
                    }
                }
            }

            if (0 == nByteCount)
            {
                if (gbkCode <= 0x7F)
                {
                    strOutGbk.push_back((uint8_t)gbkCode);
                }
                else
                {
                    strOutGbk.push_back(gbkCode >> 8);
                    strOutGbk.push_back(gbkCode & 0xFF);
                }
            }

            pCpData++;

            if (-1 != size)
            {
                size--;
            }
        }

        if (!fResult || (-1 != size && size > 0))
        {
            return -1;
        }

        if (pGbk)
        {
            *pGbk = std::move(strOutGbk);
        }

        return nChCount;
    }

    int GetGbkCount(const void* pData, size_t size/* = -1*/)
    {
        return _GetGbkCount(pData, size, nullptr);
    }

    int GetUtf8Count(const void* data_ptr, size_t size/* = -1*/)
    {
        const uint8_t* data_pos = (const uint8_t*)data_ptr;
        size_t size_count = size;
        uint32_t code_point = 0;
        int32_t byte_count = 0;
        int32_t char_count = 0;
        bool result_flag = true;

        // 字节序检查
        if ((0xEF == data_pos[0]) && (0xBB == data_pos[1]) && (0xBF == data_pos[2]))
        {
            data_pos += 3;

            if (-1 != size_count)
            {
                size_count -= 3;
            }
        }

        while ((0 != *data_pos) && (0 != size_count))
        {
            uint8_t ch = *data_pos;

            // ASCII 范围
            if (ch < 0x7F)
            {
                code_point = ch;
                char_count++;
            }
            else
            {
                if (0 == byte_count)
                {
                    code_point = 0;
                    if (ch >= 0xC0)
                    {
                        // 获取字符编码字节数
                        byte_count = g_utf8_bytes_count_table[ch];

                        // 获取首字节码点
                        code_point = ch & g_utf8_data_mask_table[ch];

                        /*
                        if (ch >= 0xC0 && ch <= 0xDF)
                        {
                            byte_count = 2;
                            code_point = ch & 0x1F;
                        }
                        else if (ch >= 0xE0 && ch <= 0xEF)
                        {
                            byte_count = 3;
                            code_point = ch & 0x0F;
                        }
                        else if (ch >= 0xF0 && ch <= 0xF7)
                        {
                            byte_count = 4;
                            code_point = ch & 0x07;
                        }
                        else if (ch >= 0xF8 && ch <= 0xFB)
                        {
                            byte_count = 5;
                            code_point = ch & 0x03;
                        }
                        else if (ch >= 0xFC && ch <= 0xFD)
                        {
                            byte_count = 6;
                            code_point = ch & 0x01;
                        }
                        */

                        if (0 == byte_count)
                        {
                            result_flag = false;
                            break;
                        }

                        byte_count--;
                    }
                    else
                    {
                        result_flag = false;
                        break;
                    }
                }
                else
                {
                    // 非首字节码点字节掩码检查
                    if (0x80 != (ch & 0xC0))
                    {
                        result_flag = false;
                        break;
                    }

                    // 码点组合
                    code_point = code_point << 6;
                    code_point |= ch & 0x3F;

                    byte_count--;

                    // 统计字符计数, 忽略字节顺序标记(BOM)
                    if (0 == byte_count)
                    {
                        char_count++;
                    }
                }
            }

            data_pos++;

            if (-1 != size_count)
            {
                size_count--;
            }
        }

        if (!result_flag || (-1 != size_count && size_count > 0))
        {
            return -1;
        }

        return char_count;
    }

    int32_t GetUtf16Count(const void* data_ptr, size_t size/* = -1*/, bool* big_endian_ptr/* = nullptr*/)
    {
        const uint16_t* data_pos = (const uint16_t*)data_ptr;
        size_t size_count = size;
        uint32_t code_point = 0;
        uint16_t code_point_high = 0;
        uint16_t code_point_low = 0;
        uint16_t code_point_tmp = 0;
        int32_t byte_count = 0;
        int32_t char_count = 0;
        bool big_endian_flag = false;
        bool little_endian_flag = false;
        bool result_flag = true;

        if (-1 != size_count)
        {
            if ((size_count < 2) || (0 != (size_count % 2)))
            {
                return -1;
            }
        }

        code_point_tmp = *data_pos;

        // 字节序检查
        if (0xFFFE == code_point_tmp || 0xFEFF == code_point_tmp)
        {
            // 大端序
            if (0xFFFE == code_point_tmp)
            {
                big_endian_flag = true;
            }

            // 小端序
            if (0xFEFF == code_point_tmp)
            {
                little_endian_flag = true;
            }

            data_pos++;

            if (-1 != size_count)
            {
                size_count -= 2;
            }
        }

        while ((0 != *data_pos) && (0 != size_count))
        {
            code_point_tmp = *data_pos;

            //字节序转换
            if (big_endian_flag)
            {
                code_point_tmp = ((code_point_tmp >> 8) | (code_point_tmp << 8));
            }

            // 代理区检查
            if (!(code_point_tmp >= 0xD800 && code_point_tmp <= 0xDFFF))
            {
                if (code_point_high > 0)
                {
                    result_flag = false;
                    break;
                }

                code_point = code_point_tmp;
                char_count++;
            }
            else
            {
                if (0 == byte_count)
                {
                    // 高位代理(高10位)
                    if (code_point_tmp >= 0xD800 && code_point_tmp <= 0xDBFF)
                    {
                        code_point_high = (code_point_tmp - 0xD800);
                        byte_count = 1;
                    }
                    else
                    {
                        result_flag = false;
                        break;
                    }
                }
                else
                {
                    if (1 == byte_count)
                    {
                        // 低位代理(低10位)
                        if ((code_point_tmp >= 0xDC00) && (code_point_tmp <= 0xDFFF))
                        {
                            code_point_low = (code_point_tmp - 0xDC00);
                            code_point = 0x10000 + ((uint32_t)code_point_high << 10 | code_point_low);
                            code_point_low = 0;
                            code_point_high = 0;
                        }
                        else
                        {
                            result_flag = false;
                            break;
                        }
                    }

                    byte_count--;

                    if (0 == byte_count)
                    {
                        char_count++;
                    }
                }
            }

            data_pos++;

            if (-1 != size_count)
            {
                size_count -= 2;
            }
        }

        if (!result_flag || (-1 != size_count && size_count > 0))
        {
            return -1;
        }

        if (big_endian_ptr)
        {
            *big_endian_ptr = big_endian_flag;
        }

        return char_count;
    }

    int GetGbkCount(const std::string& str)
    {
        return _GetGbkCount(str.c_str(), str.size(), nullptr);
    }

    int GetUtf8Count(const std::string& str)
    {
        return GetUtf8Count(str.c_str(), str.size());
    }

    int GetUtf16Count(const std::wstring& str)
    {
        return GetUtf16Count(str.c_str(), str.size() * sizeof(wchar_t));
    }

    std::string GetUpperStrA(const std::string& str)
    {
        std::string strResult = str;
        for (auto& item : strResult)
        {
            if (item >= _T('a') && item <= _T('z')) item -= 0x20;
        }

        return strResult;
    }

    std::wstring GetUpperStrW(const std::wstring& str)
    {
        std::wstring strResult = str;
        for (auto& item : strResult)
        {
            if (item >= _T('a') && item <= _T('z')) item -= 0x20;
        }

        return strResult;
    }

    _tstring GetUpperStr(const _tstring& str)
    {
#ifdef _UNICODE
        return GetUpperStrW(str);
#else
        return GetUpperStrA(str);
#endif
    }

    std::string GetLowerStrA(const std::string& str)
    {
        std::string strResult = str;
        for (auto& item : strResult)
        {
            if (item >= _T('A') && item <= _T('Z')) item += 0x20;
        }

        return strResult;
    }

    std::wstring GetLowerStrW(const std::wstring& str)
    {
        std::wstring strResult = str;
        for (auto& item : strResult)
        {
            if (item >= _T('A') && item <= _T('Z')) item += 0x20;
        }

        return strResult;
    }

    _tstring GetLowerStr(const _tstring& str)
    {
#ifdef _UNICODE
        return GetLowerStrW(str);
#else
        return GetLowerStrA(str);
#endif
    }

    std::string& ToUpperStrA(std::string& str)
    {
        for (auto& item : str)
        {
            if (item >= _T('a') && item <= _T('z')) item -= 0x20;
        }

        return str;
    }

    std::wstring& ToUpperStrW(std::wstring& str)
    {
        for (auto& item : str)
        {
            if (item >= _T('a') && item <= _T('z')) item -= 0x20;
        }

        return str;
    }

    _tstring& ToUpperStr(_tstring& str)
    {
#ifdef _UNICODE
        return ToUpperStrW(str);
#else
        return ToUpperStrA(str);
#endif
    }

    std::string& ToLowerStrA(std::string& str)
    {
        for (auto& item : str)
        {
            if (item >= _T('A') && item <= _T('Z')) item += 0x20;
        }

        return str;
    }

    std::wstring& ToLowerStrW(std::wstring& str)
    {
        for (auto& item : str)
        {
            if (item >= _T('A') && item <= _T('Z')) item += 0x20;
        }

        return str;
    }

    _tstring& ToLowerStr(_tstring& str)
    {
#ifdef _UNICODE
        return ToLowerStrW(str);
#else
        return ToLowerStrA(str);
#endif
    }

    double StrToDoubleA(const std::string& str)
    {
        return ::strtod(str.c_str(), nullptr);
    }

    double StrToDoubleW(const std::wstring& str)
    {
        return ::wcstod(str.c_str(), nullptr);
    }

    double StrToDouble(const _tstring& str)
    {
        return ::_tcstod(str.c_str(), nullptr);
    }

    std::string DoubleToStrA(double val)
    {
        char szBuf[MAX_PATH] = { 0 };
        ::sprintf_s(szBuf, _countof(szBuf), "%g", val);
        return szBuf;
    }

    std::wstring DoubleToStrW(double val)
    {
        wchar_t szBuf[MAX_PATH] = { 0 };
        ::swprintf_s(szBuf, _countof(szBuf), L"%g", val);
        return szBuf;
    }

    _tstring DoubleToStr(double val)
    {
        TCHAR szBuf[MAX_PATH] = { 0 };
        ::_stprintf_s(szBuf, _countof(szBuf), _T("%g"), val);
        return szBuf;
    }

    int64_t StrToIntA(const std::string& str, int radix/* = 10*/)
    {
        return ::strtoll(str.c_str(), nullptr, radix);
    }

    int64_t StrToIntW(const std::wstring& str, int radix/* = 10*/)
    {
        return ::wcstoll(str.c_str(), nullptr, radix);
    }

#ifndef StrToInt
    int64_t StrToInt(const _tstring& str, int radix/* = 10*/)
    {
        return ::_tcstoll(str.c_str(), nullptr, radix);
    }
#endif

    std::string IntToStrA(int64_t val, int radix/* = 10*/)
    {
        char szBuf[MAX_PATH] = { 0 };
        ::_i64toa_s(val, szBuf, _countof(szBuf), radix);
        return szBuf;
    }

    std::wstring IntToStrW(int64_t val, int radix/* = 10*/)
    {
        wchar_t szBuf[MAX_PATH] = { 0 };
        ::_i64tow_s(val, szBuf, _countof(szBuf), radix);
        return szBuf;
    }

    _tstring IntToStr(int64_t val, int radix/* = 10*/)
    {
        TCHAR szBuf[MAX_PATH] = { 0 };
        ::_i64tot_s(val, szBuf, _countof(szBuf), radix);
        return szBuf;
    }

    uint64_t StrToUIntA(const std::string& str, int radix/* = 10*/)
    {
        return ::strtoull(str.c_str(), nullptr, radix);
    }

    uint64_t StrToUIntW(const std::wstring& str, int radix/* = 10*/)
    {
        return ::wcstoull(str.c_str(), nullptr, radix);
    }

    uint64_t StrToUInt(const _tstring& str, int radix/* = 10*/)
    {
        return ::_tcstoull(str.c_str(), nullptr, radix);
    }

    std::string UIntToStrA(uint64_t val, int radix/* = 10*/)
    {
        char szBuf[MAX_PATH] = { 0 };
        ::_ui64toa_s(val, szBuf, _countof(szBuf), radix);
        return szBuf;
    }

    std::wstring UIntToStrW(uint64_t val, int radix/* = 10*/)
    {
        wchar_t szBuf[MAX_PATH] = { 0 };
        ::_ui64tow_s(val, szBuf, _countof(szBuf), radix);
        return szBuf;
    }

    _tstring UIntToStr(uint64_t val, int radix/* = 10*/)
    {
        TCHAR szBuf[MAX_PATH] = { 0 };
        ::_ui64tot_s(val, szBuf, _countof(szBuf), radix);
        return szBuf;
    }

    size_t FindNoCaseA(const std::string& strMain, const std::string& strSub, size_t offset/* = 0*/)
    {
        size_t findPos = std::string::npos;

        do
        {
            // 主串长度比字串小, 不需要比较
            if (strMain.size() < strSub.size() || offset > (strMain.size() - 1))
            {
                break;
            }

            std::string strMainTmp = strMain;
            std::string strSubTmp = strSub;

            // 转换大小写
            for (auto& item : strMainTmp)
            {
                if (item >= _T('A') && item <= _T('Z')) item += 0x20;
            }

            for (auto& item : strSubTmp)
            {
                if (item >= _T('A') && item <= _T('Z')) item += 0x20;
            }

            //findPos = strMainTmp.find(strSubTmp, offset);
            const char* pFind = std::strstr(strMainTmp.c_str() + offset, strSubTmp.c_str());
            findPos = pFind ? pFind - strMainTmp.c_str() : findPos;

        } while (false);

        return findPos;
    }

    size_t FindNoCaseW(const std::wstring& strMain, const std::wstring& strSub, size_t offset/* = 0*/)
    {
        size_t findPos = std::wstring::npos;

        do
        {
            // 主串长度比字串小, 不需要比较
            if (strMain.size() < strSub.size() || offset > (strMain.size() - 1))
            {
                break;
            }

            std::wstring strMainTmp = strMain;
            std::wstring strSubTmp = strSub;

            // 转换大小写
            for (auto& item : strMainTmp)
            {
                if (item >= _T('A') && item <= _T('Z')) item += 0x20;
            }

            for (auto& item : strSubTmp)
            {
                if (item >= _T('A') && item <= _T('Z')) item += 0x20;
            }

            //findPos = strMainTmp.find(strSubTmp, offset);
            const wchar_t* pFind = std::wcsstr(strMainTmp.c_str() + offset, strSubTmp.c_str());
            findPos = pFind ? pFind - strMainTmp.c_str() : findPos;

        } while (false);

        return findPos;
    }

    size_t FindNoCase(const _tstring& strMain, const _tstring& strSub, size_t offset/* = 0*/)
    {
#ifdef _UNICODE
        return FindNoCaseW(strMain, strSub, offset);
#else
        return FindNoCaseA(strMain, strSub, offset);
#endif
    }

    size_t FindFirstNotOfNoCaseA(const std::string& strMain, const std::string& strSub, size_t offset/* = 0*/)
    {
        size_t findPos = std::string::npos;

        do
        {
            // 主串长度比字串小, 不需要比较
            if (strMain.size() < strSub.size())
            {
                break;
            }

            std::string strMainTmp = strMain;
            std::string strSubTmp = strSub;

            // 转换大小写
            for (auto& item : strMainTmp)
            {
                if (item >= _T('A') && item <= _T('Z')) item += 0x20;
            }

            for (auto& item : strSubTmp)
            {
                if (item >= _T('A') && item <= _T('Z')) item += 0x20;
            }

            findPos = strMainTmp.find_first_not_of(strSubTmp, offset);

        } while (false);

        return findPos;
    }

    size_t FindFirstNotOfNoCaseW(const std::wstring& strMain, const std::wstring& strSub, size_t offset/* = 0*/)
    {
        size_t findPos = std::wstring::npos;

        do
        {
            // 主串长度比字串小, 不需要比较
            if (strMain.size() < strSub.size())
            {
                break;
            }

            std::wstring strMainTmp = strMain;
            std::wstring strSubTmp = strSub;

            // 转换大小写
            for (auto& item : strMainTmp)
            {
                if (item >= _T('A') && item <= _T('Z')) item += 0x20;
            }

            for (auto& item : strSubTmp)
            {
                if (item >= _T('A') && item <= _T('Z')) item += 0x20;
            }

            findPos = strMainTmp.find_first_not_of(strSubTmp, offset);

        } while (false);

        return findPos;
    }

    size_t FindFirstNotOfNoCase(const _tstring& strMain, const _tstring& strSub, size_t offset/* = 0*/)
    {
#ifdef _UNICODE
        return FindFirstNotOfNoCaseW(strMain, strSub, offset);
#else
        return FindFirstNotOfNoCaseA(strMain, strSub, offset);
#endif
    }

    int CompareNoCaseA(const std::string& strSrc, const std::string& strDest)
    {
        return _stricmp(strSrc.c_str(), strDest.c_str());
    }

    int CompareNoCaseW(const std::wstring& strSrc, const std::wstring& strDest)
    {
        return _wcsicmp(strSrc.c_str(), strDest.c_str());
    }

    int CompareNoCase(const _tstring& strSrc, const _tstring& strDest)
    {
#ifdef _UNICODE
        return CompareNoCaseW(strSrc, strDest);
#else
        return CompareNoCaseA(strSrc, strDest);
#endif
    }

    size_t FindA(const std::string& strMain, const std::string& strSub, size_t offset/* = 0*/, bool fCase/* = false*/)
    {
        if (fCase)
        {
            //return strMain.find(strSub, offset);

            if (offset <= (strMain.size() - 1))
            {
                const char* pFind = std::strstr(strMain.c_str() + offset, strSub.c_str());
                if (pFind)
                {
                    return pFind - strMain.c_str();
                }
            }

            return std::wstring::npos;
        }

        return FindNoCaseA(strMain, strSub, offset);
    }

    size_t FindW(const std::wstring& strMain, const std::wstring& strSub, size_t offset/* = 0*/, bool fCase/* = false*/)
    {
        if (fCase)
        {
            //return strMain.find(strSub, offset);

            if (offset <= (strMain.size() - 1))
            {
                const wchar_t* pFind = std::wcsstr(strMain.c_str() + offset, strSub.c_str());
                if (pFind)
                {
                    return pFind - strMain.c_str();
                }
            }

            return std::wstring::npos;
        }

        return FindNoCaseW(strMain, strSub, offset);
    }

    size_t Find(const _tstring& strMain, const _tstring& strSub, size_t offset/* = 0*/, bool fCase/* = false*/)
    {
#ifdef _UNICODE
        return FindW(strMain, strSub, offset, fCase);
#else
        return FindA(strMain, strSub, offset, fCase);
#endif
    }

    std::string& ReplaceNoCaseA(std::string& strMain, const std::string& strSub, const std::string& strTarget)
    {
        if (strSub.empty())
        {
            return strMain;
        }

        size_t nFind = 0;
        while (_tstring::npos != (nFind = FindNoCaseA(strMain, strSub, nFind)))
        {
            strMain.replace(nFind, strSub.size(), strTarget);
            nFind += strTarget.size();
        };

        return strMain;
    }

    std::wstring& ReplaceNoCaseW(std::wstring& strMain, const std::wstring& strSub, const std::wstring& strTarget)
    {
        if (strSub.empty())
        {
            return strMain;
        }

        size_t nFind = 0;
        while (_tstring::npos != (nFind = FindNoCaseW(strMain, strSub, nFind)))
        {
            strMain.replace(nFind, strSub.size(), strTarget);
            nFind += strTarget.size();
        };

        return strMain;
    }

    _tstring& ReplaceNoCase(_tstring& strMain, const _tstring& strSub, const _tstring& strTarget)
    {
#ifdef _UNICODE
        return ReplaceNoCaseW(strMain, strSub, strTarget);
#else
        return ReplaceNoCaseA(strMain, strSub, strTarget);
#endif
    }

    std::string& ReplaceA(std::string& strMain, const std::string& strSub, const std::string& strTarget, bool fCase/* = false*/)
    {
        if (strSub.empty())
        {
            return strMain;
        }

        if (fCase)
        {
            size_t nFind = 0;
            while (std::string::npos != (nFind = strMain.find(strSub, nFind)))
            {
                strMain.replace(nFind, strSub.size(), strTarget);
                nFind += strTarget.size();
            }
        }
        else
        {
            return ReplaceNoCaseA(strMain, strSub, strTarget);
        }

        return strMain;
    }

    std::wstring& ReplaceW(std::wstring& strMain, const std::wstring& strSub, const std::wstring& strTarget, bool fCase/* = false*/)
    {
        if (strSub.empty())
        {
            return strMain;
        }

        if (fCase)
        {
            size_t nFind = 0;
            while (std::wstring::npos != (nFind = strMain.find(strSub, nFind)))
            {
                strMain.replace(nFind, strSub.size(), strTarget);
                nFind += strTarget.size();
            };
        }
        else
        {
            return ReplaceNoCaseW(strMain, strSub, strTarget);
        }

        return strMain;
    }

    _tstring& Replace(_tstring& strMain, const _tstring& strSub, const _tstring& strTarget, bool fCase/* = false*/)
    {
#ifdef _UNICODE
        return ReplaceW(strMain, strSub, strTarget, fCase);
#else
        return ReplaceA(strMain, strSub, strTarget, fCase);
#endif
    }

    int CompareA(const std::string& strSrc, const std::string& strDest, bool fCase /* = true*/)
    {
        if (fCase)
        {
            return strcmp(strSrc.c_str(), strDest.c_str());
        }

        return _stricmp(strSrc.c_str(), strDest.c_str());
    }

    int CompareW(const std::wstring& strSrc, const std::wstring& strDest, bool fCase /* = true*/)
    {
        if (fCase)
        {
            return wcscmp(strSrc.c_str(), strDest.c_str());
        }

        return _wcsicmp(strSrc.c_str(), strDest.c_str());
    }

    int Compare(const _tstring& strSrc, const _tstring& strDest, bool fCase /* = true*/)
    {
#ifdef _UNICODE
        return CompareW(strSrc, strDest, fCase);
#else
        return CompareA(strSrc, strDest, fCase);
#endif
    }

    bool IsOctStringA(const std::string& strSrc)
    {
        size_t index = 0;
        for (const auto& ch : strSrc)
        {
            if (!(ch >= '0' && ch <= '7'))
            {
                return false;
            }

            index++;
        }

        return true;
    }

    bool IsOctStringW(const std::wstring& strSrc)
    {
        size_t index = 0;
        for (const auto& ch : strSrc)
        {
            if (!(ch >= '0' && ch <= '7'))
            {
                return false;
            }

            index++;
        }

        return true;
    }

    bool IsOctString(const _tstring& strSrc)
    {
#ifdef _UNICODE
        return IsOctStringW(strSrc);
#else
        return IsOctStringA(strSrc);
#endif
    }


    bool IsDecStringA(const std::string& strSrc)
    {
        size_t index = 0;
        for (const auto& ch : strSrc)
        {
            if (!(ch >= '0' && ch <= '9'))
            {
                if (('=' == ch || '-' == ch) && 0 == index)
                {
                    if (1 == strSrc.size())
                    {
                        return false;
                    }

                    index++;
                    continue;
                }

                return false;
            }

            index++;
        }

        return true;
    }

    bool IsDecStringW(const std::wstring& strSrc)
    {
        size_t index = 0;
        for (const auto& ch : strSrc)
        {
            if (!(ch >= '0' && ch <= '9'))
            {
                if (('=' == ch || '-' == ch) && 0 == index)
                {
                    if (1 == strSrc.size())
                    {
                        return false;
                    }

                    index++;
                    continue;
                }

                return false;
            }

            index++;
        }

        return true;
    }

    bool IsDecString(const _tstring& strSrc)
    {
#ifdef _UNICODE
        return IsDecStringW(strSrc);
#else
        return IsDecStringA(strSrc);
#endif
    }

    bool IsHexStringA(const std::string& strSrc)
    {
        bool fPrefix = false;
        size_t index = 0;
        for (const auto& ch : strSrc)
        {
            if (!((ch >= '0' && ch <= '9') || 
                (ch >= 'a' && ch <= 'f') || 
                (ch >= 'A' && ch <= 'F')))
            {
                if (('x' == ch || 'X' == ch) && 1 == index && 0 == strSrc[0])
                {
                    index++;
                    continue;
                }

                return false;
            }

            index++;
        }

        return true;
    }

    bool IsHexStringW(const std::wstring& strSrc)
    {
        bool fPrefix = false;
        size_t index = 0;
        for (const auto& ch : strSrc)
        {
            if (!((ch >= '0' && ch <= '9') ||
                (ch >= 'a' && ch <= 'f') ||
                (ch >= 'A' && ch <= 'F')))
            {
                if (('x' == ch || 'X' == ch) && 1 == index && 0 == strSrc[0])
                {
                    index++;
                    continue;
                }

                return false;
            }

            index++;
        }

        return true;
    }

    bool IsHexString(const _tstring& strSrc)
    {
#ifdef _UNICODE
        return IsHexStringW(strSrc);
#else
        return IsHexStringA(strSrc);
#endif
    }

    std::vector<std::string> SplitStrA(const std::string& str, const std::string& delim, bool fCase /* = true*/)
    {
        std::vector<std::string> vectorOut;
        size_t iStart = 0;
        size_t iEnd = 0;

        if (delim.empty())
        {
            vectorOut.push_back(str);
        }
        else
        {
            if (fCase)
            {
                while ((iStart = str.find_first_not_of(delim, iEnd)) != std::string::npos)
                {
                    iEnd = str.find(delim, iStart);
                    vectorOut.push_back(str.substr(iStart, iEnd - iStart));
                }
            }
            else
            {
                while ((iStart = FindFirstNotOfNoCaseA(str, delim, iEnd)) != std::string::npos)
                {
                    iEnd = FindNoCaseA(str, delim, iStart);
                    vectorOut.push_back(str.substr(iStart, iEnd - iStart));
                }
            }
        }

        return vectorOut;
    }

    std::vector<std::wstring> SplitStrW(const std::wstring& str, const std::wstring& delim, bool fCase /* = true*/)
    {
        std::vector<std::wstring> vectorOut;
        size_t iStart = 0;
        size_t iEnd = 0;

        if (delim.empty())
        {
            vectorOut.push_back(str);
        }
        else
        {
            if (fCase)
            {
                while ((iStart = str.find_first_not_of(delim, iEnd)) != std::wstring::npos)
                {
                    iEnd = str.find(delim, iStart);
                    vectorOut.push_back(str.substr(iStart, iEnd - iStart));
                }
            }
            else
            {
                while ((iStart = FindFirstNotOfNoCaseW(str, delim, iEnd)) != std::string::npos)
                {
                    iEnd = FindNoCaseW(str, delim, iStart);
                    vectorOut.push_back(str.substr(iStart, iEnd - iStart));
                }
            }
        }

        return vectorOut;
    }

    std::vector<_tstring> SplitStr(const _tstring& str, const _tstring& delim, bool fCase /* = true*/)
    {
#ifdef _UNICODE
        return SplitStrW(str, delim, fCase);
#else
        return SplitStrA(str, delim, fCase);
#endif
    }

    std::vector<std::string> SplitLinesA(const std::string& str)
    {
        std::vector<std::string> splitOut;
        std::string m_strCRLF = "\r\n";

        if (std::string::npos != str.find("\r\n"))
        {
            m_strCRLF = "\r\n";
        }
        else if (std::string::npos != str.find("\r"))
        {
            m_strCRLF = "\r";
        }
        else if (std::string::npos != str.find("\n"))
        {
            m_strCRLF = "\n";
        }

        size_t iStart = 0;
        size_t iEnd = 0;

        while (std::string::npos != (iEnd = str.find(m_strCRLF, iEnd)))
        {
            std::string strLine = str.substr(iStart, iEnd - iStart);
            splitOut.push_back(strLine);
            iEnd += m_strCRLF.size();
            iStart = iEnd;
        }

        if (iStart != iEnd)
        {
            std::string strLine = str.substr(iStart, iEnd - iStart);
            if (!strLine.empty() && '\r' == strLine.back())
            {
                strLine.resize(strLine.size() - 1);
            }

            splitOut.push_back(strLine);
        }

        return splitOut;
    }

    std::vector<std::wstring> SplitLinesW(const std::wstring& str)
    {
        std::vector<std::wstring> splitOut;
        std::wstring m_strCRLF = L"\r\n";

        if (std::wstring::npos != str.find(L"\r\n"))
        {
            m_strCRLF = L"\r\n";
        }
        else if (std::wstring::npos != str.find(L"\r"))
        {
            m_strCRLF = L"\r";
        }
        else if (std::wstring::npos != str.find(L"\n"))
        {
            m_strCRLF = L"\n";
        }

        size_t iStart = 0;
        size_t iEnd = 0;

        while (std::wstring::npos != (iEnd = str.find(m_strCRLF, iEnd)))
        {
            std::wstring strLine = str.substr(iStart, iEnd - iStart);
            splitOut.push_back(strLine);
            iEnd += m_strCRLF.size();
            iStart = iEnd;
        }

        if (iStart != iEnd)
        {
            std::wstring strLine = str.substr(iStart, iEnd - iStart);
            if (!strLine.empty() && '\r' == strLine.back())
            {
                strLine.resize(strLine.size() - 1);
            }

            splitOut.push_back(strLine);
        }

        return splitOut;
    }

    std::vector<_tstring> SplitLines(const _tstring& str)
    {
#ifdef _UNICODE
        return SplitLinesW(str);
#else
        return SplitLinesA(str);
#endif
    }

    std::wstring ConcatStringsW(const std::vector<std::wstring>& strList, const std::wstring& strReturn/* = L""*/)
    {
        std::wstring strResult;
        size_t nCount = strList.size();
        for (const auto& item : strList)
        {
            nCount--;
            if (item.empty() && nCount > 0)
            {
                strResult += strReturn;
            }
            else
            {
                strResult += item;
                if (nCount > 0)
                {
                    strResult += strReturn;
                }
            }
        }

        return strResult;
    }

    std::string ConcatStringsA(const std::vector<std::string>& strList, const std::string& strReturn/* = ""*/)
    {
        std::string strResult;
        size_t nCount = strList.size();
        for (const auto& item : strList)
        {
            nCount--;
            if (item.empty() && nCount > 0)
            {
                strResult += strReturn;
            }
            else
            {
                strResult += item;
                if (nCount > 0)
                {
                    strResult += strReturn;
                }
            }
        }

        return strResult;
    }

    _tstring ConcatStrings(const std::vector<_tstring>& strList, const _tstring& strReturn/* = _T("")*/)
    {
#ifdef _UNICODE
        return ConcatStringsW(strList, strReturn);
#else
        return ConcatStringsA(strList, strReturn);
#endif
    }

    std::string RemoveSpacesA(const std::string& strValue, bool fLeft, bool fRight)
    {
        LPCSTR lpBegin = strValue.data();
        LPCSTR lpEnd = strValue.data() + strValue.size();

        if (fLeft)
        {
            while (lpBegin < lpEnd)
            {
                if (_T(' ') == *lpBegin)
                {
                    lpBegin++;
                }
                else
                {
                    break;
                }
            }
        }

        if (fRight)
        {
            while (lpEnd > lpBegin)
            {
                if (_T(' ') == *(lpEnd - 1))
                {
                    lpEnd--;
                }
                else
                {
                    break;
                }
            }
        }

        return std::string(lpBegin, lpEnd - lpBegin);
    }

    std::wstring RemoveSpacesW(const std::wstring& strValue, bool fLeft, bool fRight)
    {
        LPCWSTR lpBegin = strValue.data();
        LPCWSTR lpEnd = strValue.data() + strValue.size();

        if (fLeft)
        {
            while (lpBegin < lpEnd)
            {
                if (_T(' ') == *lpBegin)
                {
                    lpBegin++;
                }
                else
                {
                    break;
                }
            }
        }

        if (fRight)
        {
            while (lpEnd > lpBegin)
            {
                if (_T(' ') == *(lpEnd - 1))
                {
                    lpEnd--;
                }
                else
                {
                    break;
                }
            }
        }

        return std::wstring(lpBegin, lpEnd - lpBegin);
    }

    _tstring RemoveSpaces(const _tstring& strValue, bool fLeft, bool fRight)
    {
#ifdef _UNICODE
        return RemoveSpacesW(strValue, fLeft, fRight);
#else
        return RemoveSpacesA(strValue, fLeft, fRight);
#endif
    }

    std::string FromFileA(const std::string& strFile, bool fAutoEncoding/* = false*/)
    {
        std::string strContent;

        std::ifstream inputFile(strFile.c_str(), std::ios::binary | std::ios::in);
        if (!inputFile.is_open())
        {
            return strContent;
        }

        //获取文件大小
        inputFile.seekg(0, std::ios::end);
        std::streamoff nSize = inputFile.tellg();
        inputFile.seekg(0, std::ios::beg);

        std::string strBuffer(nSize, 0);
        inputFile.read(&strBuffer[0], nSize);
        size_t nByteSize = (size_t)inputFile.gcount();

        if (fAutoEncoding)
        {
            if (GetUtf8Count(strBuffer.data(), nSize) >= 0)
            {
                // UTF8 -> ANSI
                std::string strUtf8((const char*)strBuffer.data(), nSize);

                // 去除字节序标识
                if (strUtf8.size() >= 3 && (0xEF == (uint8_t)strUtf8[0] && 0xBB == (uint8_t)strUtf8[1] && 0xBF == (uint8_t)strUtf8[2]))
                {
                    strUtf8 = strUtf8.substr(3);
                }

                strContent = U8StrToAStr(strUtf8);
            }
            else if (GetUtf16Count(strBuffer.data(), nSize) >= 0)
            {
                // UTF16 -> ANSI
                std::wstring strUtf16((const wchar_t*)strBuffer.data(), nSize / sizeof(wchar_t));

                // 去除字节序标识
                if (!strUtf16.empty() && 0xFEFF == strUtf16.front())
                {
                    strUtf16 = strUtf16.substr(1);
                }

                strContent = WStrToAStr(strUtf16);
            }
            else
            {
                strContent = strBuffer;
            }
        }
        else
        {
            strContent = strBuffer;
        }

        return strContent;
    }

    std::wstring FromFileW(const std::wstring& strFile, bool fAutoEncoding/* = false*/)
    {
        std::wstring strContent;

        std::ifstream inputFile(strFile.c_str(), std::ios::binary | std::ios::in);
        if (!inputFile.is_open())
        {
            return strContent;
        }

        //获取文件大小
        inputFile.seekg(0, std::ios::end);
        std::streamoff nSize = inputFile.tellg();
        inputFile.seekg(0, std::ios::beg);

        std::string strBuffer(nSize, 0);
        inputFile.read((char*)&strBuffer[0], nSize);
        size_t nByteSize = (size_t)inputFile.gcount();

        inputFile.close();

        if (fAutoEncoding)
        {
            // 编码自动转换
            if (GetUtf8Count(strBuffer.data(), nSize) >= 0)
            {
                // UTF8 -> UTF16
                std::string strUtf8((const char*)strBuffer.data(), nSize);
                strContent = U8StrToWStr(strUtf8);
            }
            else if (GetUtf16Count(strBuffer.data(), nSize) < 0)
            {
                // ANSI -> UTF16
                std::string strAnsi((const char*)strBuffer.data(), nSize);
                strContent = AStrToWStr(strAnsi);
            }
            else
            {
                strContent = std::wstring((wchar_t*)strBuffer.data(), strBuffer.size() / sizeof(wchar_t));
            }

            // 去除字节序标识
            if (!strContent.empty() && 0xFEFF == strContent.front())
            {
                strContent = strContent.substr(1);
            }
        }
        else
        {
            strContent = std::wstring((wchar_t*)strBuffer.data(), strBuffer.size() / sizeof(wchar_t));
        }

        return strContent;
    }

    _tstring FromFile(const _tstring& strFile, bool fAutoEncoding/* = false*/)
    {
#ifdef _UNICODE
        return FromFileW(strFile, fAutoEncoding);
#else
        return FromFileA(strFile, fAutoEncoding);
#endif
    }

    bool ToFileA(const std::string& str, const std::string& strFile)
    {
        std::ofstream outputFile(strFile.c_str(), std::ios::binary | std::ios::out);
        if (!outputFile.is_open())
        {
            return false;
        }

        outputFile.write(str.c_str(), str.size());
        outputFile.close();

        return true;
    }

    bool ToFileW(const std::wstring& str, const std::wstring& strFile)
    {
        std::ofstream outputFile(strFile.c_str(), std::ios::binary | std::ios::out);
        if (!outputFile.is_open())
        {
            return false;
        }

        // 添加字节序标识
        if (!str.empty() && 0xFEFF != str.front())
        {
            std::wstring strContent;
            strContent += 0xFEFF;
            outputFile.write((const char*)strContent.c_str(), strContent.size() * sizeof(wchar_t));
        }

        outputFile.write((const char*)str.c_str(), str.size() * sizeof(wchar_t));
        outputFile.close();

        return true;
    }

    bool ToFile(const _tstring& str, const _tstring& strFile)
    {
#ifdef _UNICODE
        return ToFileW(str, strFile);
#else
        return ToFileA(str, strFile);
#endif
    }

    std::string FormatA(LPCSTR pFormat, ...)
    {
        size_t nCchCount = MAX_PATH;
        std::string strResult(nCchCount, 0);
        va_list args;

        va_start(args, pFormat);

        do
        {
            //成功则赋值字符串并终止循环
            int nSize = _vsnprintf_s(&strResult[0], nCchCount, _TRUNCATE, pFormat, args);
            if (-1 != nSize)
            {
                strResult.resize(nSize);
                break;
            }

            //缓冲大小超限终止
            if (nCchCount >= FORMAT_COUNT_MAX)
            {
                break;
            }

            //重新分配缓冲
            nCchCount *= 2;
            strResult.resize(nCchCount);

        } while (true);

        va_end(args);

        return strResult;
    }

    std::wstring FormatW(LPCWSTR pFormat, ...)
    {
        size_t nCchCount = MAX_PATH;
        std::wstring strResult(nCchCount, 0);
        va_list args;

        va_start(args, pFormat);

        do
        {
            //格式化输出字符串
            int nSize = _vsnwprintf_s(&strResult[0], nCchCount, _TRUNCATE, pFormat, args);
            if (-1 != nSize)
            {
                strResult.resize(nSize);
                break;
            }

            //缓冲大小超限终止
            if (nCchCount >= FORMAT_COUNT_MAX)
            {
                break;
            }

            //重新分配缓冲
            nCchCount *= 2;
            strResult.resize(nCchCount);

        } while (true);

        va_end(args);

        return strResult;
    }

    _tstring Format(LPCTSTR pFormat, ...)
    {
        size_t nCchCount = MAX_PATH;
        _tstring strResult(nCchCount, 0);
        va_list args;

        va_start(args, pFormat);

        do
        {
            //格式化输出字符串
            int nSize = _vsntprintf_s(&strResult[0], nCchCount, _TRUNCATE, pFormat, args);
            if (-1 != nSize)
            {
                strResult.resize(nSize);
                break;
            }

            //缓冲大小超限终止
            if (nCchCount >= FORMAT_COUNT_MAX)
            {
                break;
            }

            //重新分配缓冲
            nCchCount *= 2;
            strResult.resize(nCchCount);

        } while (true);

        va_end(args);

        return strResult;
    }

    void OutputDebugA(LPCSTR pFormat, ...)
    {
        size_t nCchCount = MAX_PATH;
        std::string strResult(nCchCount, 0);
        va_list args;

        va_start(args, pFormat);

        do
        {
            //格式化输出字符串
            int nSize = _vsnprintf_s(&strResult[0], nCchCount, _TRUNCATE, pFormat, args);
            if (-1 != nSize)
            {
                ::OutputDebugStringA(strResult.c_str());
                break;
            }

            //缓冲大小超限终止
            if (nCchCount >= FORMAT_COUNT_MAX)
            {
                break;
            }

            //重新分配缓冲
            nCchCount *= 2;
            strResult.resize(nCchCount);

        } while (true);

        va_end(args);
    }

    void OutputDebugW(LPCWSTR pFormat, ...)
    {
        size_t nCchCount = MAX_PATH;
        std::wstring strResult(nCchCount, 0);
        va_list args;

        va_start(args, pFormat);

        do
        {
            //格式化输出字符串
            int nSize = _vsnwprintf_s(&strResult[0], nCchCount, _TRUNCATE, pFormat, args);
            if (-1 != nSize)
            {
                ::OutputDebugStringW(strResult.c_str());
                break;
            }

            //缓冲大小超限终止
            if (nCchCount >= FORMAT_COUNT_MAX)
            {
                break;
            }

            //重新分配缓冲
            nCchCount *= 2;
            strResult.resize(nCchCount);

        } while (true);

        va_end(args);
    }

    void OutputDebug(LPCTSTR pFormat, ...)
    {
        size_t nCchCount = MAX_PATH;
        _tstring strResult(nCchCount, 0);
        va_list args;

        va_start(args, pFormat);

        do
        {
            //格式化输出字符串
            int nSize = _vsntprintf_s(&strResult[0], nCchCount, _TRUNCATE, pFormat, args);
            if (-1 != nSize)
            {
                ::OutputDebugString(strResult.c_str());
                break;
            }

            //缓冲大小超限终止
            if (nCchCount >= FORMAT_COUNT_MAX)
            {
                break;
            }

            //重新分配缓冲
            nCchCount *= 2;
            strResult.resize(nCchCount);

        } while (true);

        va_end(args);
    }

    void ConsoleClear(SHORT nStartLine/* = -1*/, SHORT nCount/* = -1*/)
    {
        HANDLE console = GetStdHandle(STD_OUTPUT_HANDLE);
        CONSOLE_SCREEN_BUFFER_INFOEX ScreenBuffer = { 0 };
        ScreenBuffer.cbSize = sizeof(CONSOLE_SCREEN_BUFFER_INFOEX);
        ::GetConsoleScreenBufferInfoEx(console, &ScreenBuffer);
        SHORT nClearCount = ScreenBuffer.dwMaximumWindowSize.Y;

        if (nStartLine >= 0)
        {
            ScreenBuffer.dwCursorPosition.Y = nStartLine;
        }

        if (nCount >= 0)
        {
            nClearCount = ScreenBuffer.dwCursorPosition.Y + nCount;
            if (nClearCount > ScreenBuffer.dwMaximumWindowSize.Y)
            {
                nClearCount = ScreenBuffer.dwMaximumWindowSize.Y;
            }
        }

        for (SHORT i = ScreenBuffer.dwCursorPosition.Y; i < nClearCount; i++)
        {
            DWORD dwNumberOfCharsWritten = 0;
            ::FillConsoleOutputCharacter(
                console,
                _T(' '),
                ScreenBuffer.dwMaximumWindowSize.X,
                { 0, i },
                &dwNumberOfCharsWritten
            );
        }
    }

    void ConsoleSetPos(SHORT x, SHORT y)
    {
        ::SetConsoleCursorPosition(::GetStdHandle(STD_OUTPUT_HANDLE), { x, y });
    }

    void ConsolePrintf(LPCTSTR pFormat, ...)
    {
        size_t nCchCount = MAX_PATH;
        _tstring strResult(nCchCount, 0);
        va_list args;

        va_start(args, pFormat);

        do
        {
            // Formatted String
            int nSize = _vsntprintf_s(&strResult[0], nCchCount, _TRUNCATE, pFormat, args);
            if (-1 != nSize)
            {
                HANDLE console = GetStdHandle(STD_OUTPUT_HANDLE);
                CONSOLE_SCREEN_BUFFER_INFOEX ScreenBuffer = { 0 };
                ScreenBuffer.cbSize = sizeof(CONSOLE_SCREEN_BUFFER_INFOEX);

                ::GetConsoleScreenBufferInfoEx(console, &ScreenBuffer);

                // If text is entered at the beginning of a line, the current line content is cleared first.
                if (0 == ScreenBuffer.dwCursorPosition.X)
                {
                    DWORD dwNumberOfCharsWritten = 0;
                    ::FillConsoleOutputCharacter(
                        console,
                        _T(' '),
                        ScreenBuffer.dwMaximumWindowSize.X,
                        { 0, ScreenBuffer.dwCursorPosition.Y },
                        &dwNumberOfCharsWritten
                    );
                }

                ::WriteConsole(console, strResult.c_str(), nSize, NULL, NULL);
                break;
            }

            if (nCchCount >= INT32_MAX)
            {
                break;
            }

            nCchCount *= 2;
            strResult.resize(nCchCount);

        } while (true);

        va_end(args);
    }

    void ConsoleOutputA(LPCSTR pFormat, ...)
    {
        size_t nCchCount = MAX_PATH;
        std::string strResult(nCchCount, 0);
        va_list args;

        va_start(args, pFormat);

        do
        {
            //格式化输出字符串
            int nSize = _vsnprintf_s(&strResult[0], nCchCount, _TRUNCATE, pFormat, args);
            if (-1 != nSize)
            {
                HANDLE console = ::GetStdHandle(STD_OUTPUT_HANDLE);
                ::WriteConsoleA(console, strResult.c_str(), nSize, NULL, NULL);
                break;
            }

            //缓冲大小超限终止
            if (nCchCount >= FORMAT_COUNT_MAX)
            {
                break;
            }

            //重新分配缓冲
            nCchCount *= 2;
            strResult.resize(nCchCount);

        } while (true);

        va_end(args);
    }

    void ConsoleOutputW(LPCWSTR pFormat, ...)
    {
        size_t nCchCount = MAX_PATH;
        std::wstring strResult(nCchCount, 0);
        va_list args;

        va_start(args, pFormat);

        do
        {
            //格式化输出字符串
            int nSize = _vsnwprintf_s(&strResult[0], nCchCount, _TRUNCATE, pFormat, args);
            if (-1 != nSize)
            {
                HANDLE console = ::GetStdHandle(STD_OUTPUT_HANDLE);
                ::WriteConsoleW(console, strResult.c_str(), nSize, NULL, NULL);
                break;
            }

            //缓冲大小超限终止
            if (nCchCount >= FORMAT_COUNT_MAX)
            {
                break;
            }

            //重新分配缓冲
            nCchCount *= 2;
            strResult.resize(nCchCount);

        } while (true);

        va_end(args);
    }

    void ConsoleOutput(LPCTSTR pFormat, ...)
    {
        size_t nCchCount = MAX_PATH;
        _tstring strResult(nCchCount, 0);
        va_list args;

        va_start(args, pFormat);

        do
        {
            //格式化输出字符串
            int nSize = _vsntprintf_s(&strResult[0], nCchCount, _TRUNCATE, pFormat, args);
            if (-1 != nSize)
            {
                HANDLE console = ::GetStdHandle(STD_OUTPUT_HANDLE);
                ::WriteConsole(console, strResult.c_str(), nSize, NULL, NULL);
                break;
            }

            //缓冲大小超限终止
            if (nCchCount >= FORMAT_COUNT_MAX)
            {
                break;
            }

            //重新分配缓冲
            nCchCount *= 2;
            strResult.resize(nCchCount);

        } while (true);

        va_end(args);
    }

    std::string GetErrorMessageA(DWORD dwMessageId, DWORD dwLanguageId/* = MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT)*/)
    {
        std::string strResult;

        LPSTR pBuffer = NULL;
        DWORD dwFlags =
            FORMAT_MESSAGE_ALLOCATE_BUFFER |    //函数分配一个足够大的缓冲区来保存格式化消息,并将指针放置在 pBuffer 指定的地址处分配的缓冲区
            FORMAT_MESSAGE_FROM_SYSTEM |        //函数应在系统消息表资源搜索请求的消息
            FORMAT_MESSAGE_IGNORE_INSERTS |     //将忽略消息定义中的插入序列(如 %1)
            FORMAT_MESSAGE_MAX_WIDTH_MASK;      //函数忽略消息定义文本中的常规

        ::FormatMessageA(
            dwFlags,            //格式设置选项以及如何解释 lpSource 参数
            NULL,               //消息定义的位置。 此参数的类型取决于 dwFlags 参数中的设置
            dwMessageId,        //请求的消息的消息标识符。 如果 dwFlags 包含 FORMAT_MESSAGE_FROM_STRING,则忽略此参数
            dwLanguageId,       //所请求消息 的语言标识符
            (LPSTR)&pBuffer,    //指向缓冲区的指针
            MAX_PATH,           //如果未设置 FORMAT_MESSAGE_ALLOCATE_BUFFER 标志,则此参数以 TCHAR 为单位指定输出缓冲区的大小。 如果设置了 FORMAT_MESSAGE_ALLOCATE_BUFFER ,则此参数指定要为输出缓冲区分配的最小 TCHAR 数
            NULL                //一个值数组,这些值用作格式化消息中的插入值。 格式字符串中的 %1 指示 Arguments 数组中的第一个值;%2 指示第二个参数;等等
        );

        if (NULL != pBuffer)
        {
            strResult = pBuffer;
            ::LocalFree(pBuffer);
        }

        return strResult;
    }

    std::wstring GetErrorMessageW(DWORD dwMessageId, DWORD dwLanguageId/* = MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT)*/)
    {
        std::wstring strResult;

        LPWSTR pBuffer = NULL;
        DWORD dwFlags =
            FORMAT_MESSAGE_ALLOCATE_BUFFER |    //函数分配一个足够大的缓冲区来保存格式化消息,并将指针放置在 pBuffer 指定的地址处分配的缓冲区
            FORMAT_MESSAGE_FROM_SYSTEM |        //函数应在系统消息表资源搜索请求的消息
            FORMAT_MESSAGE_IGNORE_INSERTS |     //将忽略消息定义中的插入序列(如 %1)
            FORMAT_MESSAGE_MAX_WIDTH_MASK;      //函数忽略消息定义文本中的常规

        ::FormatMessageW(
            dwFlags,            //格式设置选项以及如何解释 lpSource 参数
            NULL,               //消息定义的位置。 此参数的类型取决于 dwFlags 参数中的设置
            dwMessageId,        //请求的消息的消息标识符。 如果 dwFlags 包含 FORMAT_MESSAGE_FROM_STRING,则忽略此参数
            dwLanguageId,       //所请求消息 的语言标识符
            (LPWSTR)&pBuffer,   //指向缓冲区的指针
            MAX_PATH,           //如果未设置 FORMAT_MESSAGE_ALLOCATE_BUFFER 标志,则此参数以 TCHAR 为单位指定输出缓冲区的大小。 如果设置了 FORMAT_MESSAGE_ALLOCATE_BUFFER ,则此参数指定要为输出缓冲区分配的最小 TCHAR 数
            NULL                //一个值数组,这些值用作格式化消息中的插入值。 格式字符串中的 %1 指示 Arguments 数组中的第一个值;%2 指示第二个参数;等等
        );

        if (NULL != pBuffer)
        {
            strResult = pBuffer;
            ::LocalFree(pBuffer);
        }

        return strResult;
    }

    _tstring GetErrorMessage(DWORD dwMessageId, DWORD dwLanguageId/* = MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT)*/)
    {
#ifdef _UNICODE
        return GetErrorMessageW(dwMessageId, dwLanguageId);
#else
        return GetErrorMessageA(dwMessageId, dwLanguageId);
#endif
    }

    DATA_UNIT_INFO FormatByteSize(
        double nBytesSize,
        eUnitType eSrcUnit/* = eUnitType::eUT_Auto*/,
        eUnitType eDestUnit/* = eUnitType::eUT_Auto*/,
        bool fHasUnits/* = true*/,
        bool fSpace/* = true*/,
        int nInteger/* = 1*/,
        int nPrecision/* = 3*/
    )
    {
        TCHAR szFormatBuf[MAX_PATH] = { 0 };
        TCHAR szResultBuf[MAX_PATH] = { 0 };
        DATA_UNIT_INFO dataUnitInfo;
        bool fSrcBit = false;
        bool fDestBit = false;

        LPCTSTR strUnitByteName[] = {
            _T("B"),
            _T("KB"),
            _T("MB"),
            _T("GB"),
            _T("TB"),
            _T("PB"),
            _T("EB"),
            _T("ZB"),
            _T("YB"),
            _T("BB"),
            _T("NB"),
            _T("DB"),
            _T("CB"),
            _T("XB"),
        };

        LPCTSTR strUnitBitName[] = {
            _T("b"),
            _T("Kb"),
            _T("Mb"),
            _T("Gb"),
            _T("Tb"),
            _T("Pb"),
            _T("Eb"),
            _T("Zb"),
            _T("Yb"),
            _T("Bb"),
            _T("Nb"),
            _T("Db"),
            _T("Cb"),
            _T("Xb"),
        };

        // 原始单位 比特 -> 字节
        if (eSrcUnit >= eUnitType::eUT_b && eSrcUnit < eUnitType::eUT_B)
        {
            fSrcBit = true;
            eSrcUnit = (eUnitType)(eSrcUnit + (eUnitType::eUT_B - eUnitType::eUT_b));
        }

        // 目标单位 比特 -> 字节
        if (eDestUnit >= eUnitType::eUT_b && eDestUnit < eUnitType::eUT_B)
        {
            fDestBit = true;
            eDestUnit = (eUnitType)(eDestUnit + (eUnitType::eUT_B - eUnitType::eUT_b));
        }

        // 原始单位转换
        for (int i = eUnitType::eUT_B; i < eSrcUnit; i++)
        {
            nBytesSize *= 1024.0f;
        }

        // 自动
        int nUnitTypeIndex = eUnitType::eUT_B;
        if (eUnitType::eUT_Auto == eDestUnit)
        {
            double nCurUnitSize = 1.0f;
            double nNextUnitSize = 1024.0f;
            int nUnitTypeMaxIndex = eUnitType::eUT_Max - 1;
            for (int i = 0; i < _countof(strUnitByteName) && nUnitTypeIndex < nUnitTypeMaxIndex; i++)
            {
                if ((nBytesSize >= nCurUnitSize && nBytesSize < nNextUnitSize) || 0 == nNextUnitSize || 0 == nBytesSize)
                {
                    break;
                }

                nCurUnitSize *= 1024.0f;
                nNextUnitSize *= 1024.0f;
                nUnitTypeIndex++;
            }
            eDestUnit = (eUnitType)nUnitTypeIndex;
        }

        {
            ::_stprintf_s(szFormatBuf, _countof(szFormatBuf), _T("%%%d.%dlf"), nInteger + nPrecision + 1, nPrecision);
            double fUnitSize = 1.0f;
            for (int i = eUnitType::eUT_B; i < eDestUnit; i++)
            {
                fUnitSize *= 1024.0f;
            }

            if (fSrcBit)
            {
                fUnitSize *= 8.0f;
            }

            if (fDestBit)
            {
                nBytesSize *= 8.0f;
            }

            double lfResult = nBytesSize / fUnitSize;
            ::_stprintf_s(szResultBuf, _countof(szResultBuf), szFormatBuf, lfResult);
            dataUnitInfo.strOutput = szResultBuf;
            dataUnitInfo.value = lfResult;

            if (fHasUnits)
            {
                if (fSpace)
                {
                    dataUnitInfo.strOutput += _T(" ");
                }

                if (fDestBit)
                {
                    dataUnitInfo.strOutput += strUnitBitName[eDestUnit - eUnitType::eUT_B];
                    dataUnitInfo.strUnitStr = strUnitBitName[eDestUnit - eUnitType::eUT_B];
                    dataUnitInfo.eUnit = (eUnitType)(eDestUnit + (eUnitType::eUT_B - eUnitType::eUT_b));
                }
                else
                {
                    dataUnitInfo.strOutput += strUnitByteName[eDestUnit - eUnitType::eUT_B];
                    dataUnitInfo.strUnitStr = strUnitByteName[eDestUnit - eUnitType::eUT_B];
                    dataUnitInfo.eUnit = eDestUnit;
                }
            }
        }

        return dataUnitInfo;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值