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);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 StrToIntint64_t StrToInt(const _tstring& str, int radix = 10);
#endifstd::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);// 分割字符串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::string FromFileA(const std::string& strFile);std::wstring FromFileW(const std::wstring& strFile);_tstring FromFile(const _tstring& strFile);// 字符串保存到文件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) BiteUT_Kb, // (2 ^ 010) BiteUT_Mb, // (2 ^ 020) BiteUT_Gb, // (2 ^ 030) BiteUT_Tb, // (2 ^ 040) BiteUT_Pb, // (2 ^ 050) BiteUT_Eb, // (2 ^ 060) BiteUT_Zb, // (2 ^ 070) BiteUT_Yb, // (2 ^ 080) BiteUT_Bb, // (2 ^ 090) BiteUT_Nb, // (2 ^ 100) BiteUT_Db, // (2 ^ 110) BiteUT_Cb, // (2 ^ 120) BiteUT_Xb, // (2 ^ 130) BiteUT_B, // Byte 2 ^ 000 ByteeUT_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 ByteeUT_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 tableunsigned 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 tableunsigned 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 _UNICODEreturn str;
#elsereturn _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 _UNICODEreturn _MultiStrToWStr(CP_ACP, str);
#elsereturn 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 _UNICODEreturn _MultiStrToWStr(CP_UTF8, str);
#elsereturn WStrToAStr(U8StrToWStr(str));
#endif}std::string TStrToAStr(const _tstring& str){
#ifdef _UNICODEreturn _WStrToMultiStr(CP_ACP, str);
#elsereturn str;
#endif}std::wstring TStrToWStr(const _tstring& str){
#ifdef _UNICODEreturn str;
#elsereturn AStrToWStr(str);
#endif}std::string TStrToU8Str(const _tstring& str){
#ifdef _UNICODEreturn WStrToU8Str(str);
#elsereturn 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 - 0xFEif (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){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;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;cp32 = ch & 0x1F;}else if (ch >= 0xE0 && ch <= 0xEF){byte_count = 3;cp32 = ch & 0x0F;}else if (ch >= 0xF0 && ch <= 0xF7){byte_count = 4;cp32 = ch & 0x07;}else if (ch >= 0xF8 && ch <= 0xFB){byte_count = 5;cp32 = ch & 0x03;}else if (ch >= 0xFC && ch <= 0xFD){byte_count = 6;cp32 = 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) && (0xFEFF != code_point)){char_count++;}}}data_pos++;if (-1 != size_count){size_count--;}}if (!result_flag){return -1;}return char_count;}int32_t GetUtf16Count(const void* data_ptr, size_t size/* = -1*/){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;}}while ((0 != *data_pos) && (0 != size_count)){code_point_tmp = *data_pos;// 检查字节序if (0xFFFE == code_point_tmp || 0xFEFF == code_point_tmp){if (0 == byte_count){// 小端序if (0xFFFE == code_point_tmp){big_endian_flag = true;}// 大端序if (0xFEFF == code_point_tmp){little_endian_flag = true;}}else{result_flag = false;break;}// 不可能同时存在小端序和大端序if (big_endian_flag && little_endian_flag){result_flag = false;break;}data_pos++;if (-1 != size_count){size_count -= 2;}continue;}//字节序转换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){return -1;}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 _UNICODEreturn GetUpperStrW(str);
#elsereturn 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 _UNICODEreturn GetLowerStrW(str);
#elsereturn 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 _UNICODEreturn ToUpperStrW(str);
#elsereturn 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 _UNICODEreturn ToLowerStrW(str);
#elsereturn 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 StrToIntint64_t StrToInt(const _tstring& str, int radix/* = 10*/){return ::_tcstoll(str.c_str(), nullptr, radix);}
#endifstd::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()){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);} 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()){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);} while (false);return findPos;}size_t FindNoCase(const _tstring& strMain, const _tstring& strSub, size_t offset/* = 0*/){
#ifdef _UNICODEreturn FindNoCaseW(strMain, strSub, offset);
#elsereturn 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 _UNICODEreturn FindFirstNotOfNoCaseW(strMain, strSub, offset);
#elsereturn 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 _UNICODEreturn CompareNoCaseW(strSrc, strDest);
#elsereturn 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);}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);}return FindNoCaseW(strMain, strSub, offset);}size_t Find(const _tstring& strMain, const _tstring& strSub, size_t offset/* = 0*/, bool fCase/* = false*/){
#ifdef _UNICODEreturn FindW(strMain, strSub, offset, fCase);
#elsereturn 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 _UNICODEreturn ReplaceNoCaseW(strMain, strSub, strTarget);
#elsereturn 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 _UNICODEreturn ReplaceW(strMain, strSub, strTarget, fCase);
#elsereturn 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 _UNICODEreturn CompareW(strSrc, strDest, fCase);
#elsereturn CompareA(strSrc, strDest, fCase);
#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 _UNICODEreturn SplitStrW(str, delim, fCase);
#elsereturn SplitStrA(str, delim, fCase);
#endif}std::string FromFileA(const std::string& strFile){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 (GetUtf8Count(strBuffer.data(), nSize) > 0){// UTF8 -> ANSIstd::string strUtf8((const char*)strBuffer.data(), nSize);// 去除字节序标识while (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 -> ANSIstd::wstring strUtf16((const wchar_t*)strBuffer.data(), nSize / sizeof(wchar_t));// 去除字节序标识while (!strUtf16.empty() && 0xFEFF == strUtf16[0]){strUtf16 = strUtf16.substr(1);}strContent = WStrToAStr(strUtf16);}else{strContent = strBuffer;}return strContent;}std::wstring FromFileW(const std::wstring& strFile){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 (GetUtf8Count(strBuffer.data(), nSize) > 0){// UTF8 -> UTF16std::string strUtf8((const char*)strBuffer.data(), nSize);strContent = U8StrToWStr(strUtf8);}else if (GetUtf16Count(strBuffer.data(), nSize) < 0){// ANSI -> UTF16std::string strAnsi((const char*)strBuffer.data(), nSize);strContent = AStrToWStr(strAnsi);}else{strContent = std::wstring((wchar_t*)strBuffer.data(), strBuffer.size() / sizeof(wchar_t));}// 去除字节序标识while (!strContent.empty() && 0xFEFF == strContent[0]){strContent = strContent.substr(1);}return strContent;}_tstring FromFile(const _tstring& strFile){
#ifdef _UNICODEreturn FromFileW(strFile);
#elsereturn FromFileA(strFile);
#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[0]){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 _UNICODEreturn ToFileW(str, strFile);
#elsereturn 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 Stringint 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 _UNICODEreturn GetErrorMessageW(dwMessageId, dwLanguageId);
#elsereturn 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;}
}