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;
}
}