mirror of
https://github.com/ONLYOFFICE/core.git
synced 2026-07-11 06:22:44 +08:00
1356 lines
28 KiB
C++
1356 lines
28 KiB
C++
|
|
#pragma once
|
|
|
|
#include <Structures.h>
|
|
#include <Base64.h>
|
|
|
|
#ifdef USE_ATL_CSTRING
|
|
|
|
namespace Strings
|
|
{
|
|
static BOOL NotEquals(const CString& strValue1, const CString& strValue2)
|
|
{
|
|
// ýòà ôóíêöèÿ çàíèìàåòñÿ ìàêñèìàëüíî áûñòðûì ñðàâíåíèåì ñòðîê (íå íåñîâïàäåíèå)
|
|
// íå íàäî çäåñü íè÷åãî "áîëåå êðóòîãî" implement'èòü...
|
|
|
|
// TODO:
|
|
|
|
return (strValue1 != strValue2);
|
|
}
|
|
static CString ToLower(const CString& strValue)
|
|
{
|
|
CString s = strValue;
|
|
|
|
s.MakeLower();
|
|
|
|
return s;
|
|
}
|
|
static CString ToUpper(const CString& strValue)
|
|
{
|
|
CString s = strValue;
|
|
|
|
s.MakeUpper();
|
|
|
|
return s;
|
|
}
|
|
static CString Substring(const CString& strValue, int nFirst, int nCount)
|
|
{
|
|
if (nCount < 1)
|
|
return "";
|
|
|
|
return strValue.Mid(nFirst, nCount);
|
|
}
|
|
static int IndexOf(const CString& strValue, const CString& strSubstring, int nStart = 0)
|
|
{
|
|
return strValue.Find(strSubstring, nStart);
|
|
}
|
|
static int LastIndexOf(const CString& strValue, const CString& strSubstring)
|
|
{
|
|
CString strValueReverse = strValue;
|
|
CString strSubstringReverse = strSubstring;
|
|
|
|
strValueReverse.MakeReverse();
|
|
strSubstringReverse.MakeReverse();
|
|
|
|
int nIndex = IndexOf(strValueReverse, strSubstringReverse);
|
|
|
|
if (nIndex < 0)
|
|
return -1;
|
|
|
|
return strValue.GetLength() - nIndex - strSubstring.GetLength();
|
|
}
|
|
static int Split(const CString& strValue, const CString& strSplitter, Templates::CArray<CString>& arrSubstrings)
|
|
{
|
|
if (strSplitter.GetLength() < 1)
|
|
{
|
|
arrSubstrings.Add(strValue);
|
|
return arrSubstrings.GetCount();
|
|
}
|
|
|
|
int nStart = 0;
|
|
|
|
int nIndex = IndexOf(strValue, strSplitter, nStart);
|
|
|
|
while (nIndex >= 0)
|
|
{
|
|
CString strPart = Substring(strValue, nStart, nIndex - nStart);
|
|
|
|
if (strPart.GetLength() > 0)
|
|
arrSubstrings.Add(strPart);
|
|
|
|
nStart = nIndex + strSplitter.GetLength();
|
|
|
|
nIndex = IndexOf(strValue, strSplitter, nStart);
|
|
}
|
|
|
|
CString strLastPart = Substring(strValue, nStart, strValue.GetLength() - nStart);
|
|
|
|
if (strLastPart.GetLength() > 0)
|
|
arrSubstrings.Add(strLastPart);
|
|
|
|
return arrSubstrings.GetCount();
|
|
}
|
|
static BOOL StartsWith(const CString& strValue, const CString& strSubstring)
|
|
{
|
|
return (IndexOf(strValue, strSubstring) == 0);
|
|
}
|
|
static BOOL EndsWith(const CString& strValue, const CString& strSubstring)
|
|
{
|
|
return (LastIndexOf(strValue, strSubstring) == strValue.GetLength() - strSubstring.GetLength());
|
|
}
|
|
|
|
static int ToDigit(char c)
|
|
{
|
|
if (c >= '0' && c <= '9')
|
|
return (int)(c - '0');
|
|
if (c >= 'a' && c <= 'f')
|
|
return 10 + (int)(c - 'a');
|
|
if (c >= 'A' && c <= 'F')
|
|
return 10 + (int)(c - 'A');
|
|
|
|
return 0;
|
|
}
|
|
static COLORREF ToColor(const CString& strValue)
|
|
{
|
|
// variables
|
|
int blue = 0;
|
|
int green = 0;
|
|
int red = 0;
|
|
|
|
CString color = strValue; color = color.Trim();
|
|
|
|
if (color.Find("0x")!=-1)
|
|
color.Delete(0,2);
|
|
if (color.Find("#")!=-1)
|
|
color.Delete(0,1);
|
|
|
|
while (color.GetLength() < 6)
|
|
color = "0" + color;
|
|
|
|
red = 16*ToDigit(color[0]) + ToDigit(color[1]);
|
|
green = 16*ToDigit(color[2]) + ToDigit(color[3]);
|
|
blue = 16*ToDigit(color[4]) + ToDigit(color[5]);
|
|
|
|
return RGB(red, green, blue);
|
|
}
|
|
static void ToColor(const CString& strValue, int& nR, int& nG, int& nB, int& nA)
|
|
{
|
|
CString color = strValue; color = color.Trim();
|
|
|
|
if (color.Find("0x")!=-1)
|
|
color.Delete(0,2);
|
|
if (color.Find("#")!=-1)
|
|
color.Delete(0,1);
|
|
|
|
while (color.GetLength() < 8)
|
|
color = "0" + color;
|
|
|
|
nA = 16*ToDigit(color[0]) + ToDigit(color[1]);
|
|
nR = 16*ToDigit(color[2]) + ToDigit(color[3]);
|
|
nG = 16*ToDigit(color[4]) + ToDigit(color[5]);
|
|
nB = 16*ToDigit(color[6]) + ToDigit(color[7]);
|
|
}
|
|
static BOOL ToBoolean(const CString& strValue)
|
|
{
|
|
CString s = strValue;
|
|
|
|
s.MakeLower();
|
|
|
|
return (s == "true");
|
|
}
|
|
static int ToInteger(const CString& strValue)
|
|
{
|
|
return atoi(strValue);
|
|
}
|
|
static double ToDouble(const CString& strValue)
|
|
{
|
|
double d = 0;
|
|
|
|
sscanf(strValue, " %lf", &d);
|
|
|
|
return d;
|
|
}
|
|
static BOOL ToBinary(const CString& strValue, BYTE*& pData, int& nSizeAllocated, int& nSizeArray)
|
|
{
|
|
pData = NULL;
|
|
nSizeArray = 0;
|
|
nSizeAllocated = Base64::Base64DecodeGetRequiredLength(strValue.GetLength());
|
|
|
|
if (nSizeAllocated < 1)
|
|
return FALSE;
|
|
|
|
pData = new BYTE[nSizeAllocated];
|
|
if (!pData)
|
|
return FALSE;
|
|
|
|
nSizeArray = nSizeAllocated;
|
|
|
|
if (!Base64::Base64Decode((LPCSTR)strValue, strValue.GetLength(), pData, &nSizeArray))
|
|
{
|
|
delete[] pData;
|
|
pData = NULL;
|
|
nSizeArray = 0;
|
|
nSizeAllocated = 0;
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static CString FromInteger(int Value, int Base = 10)
|
|
{
|
|
CString str;
|
|
|
|
str.Format("%d", Value);
|
|
|
|
return str;
|
|
}
|
|
static CString FromDouble(double Value)
|
|
{
|
|
CString str;
|
|
|
|
str.Format("%lf", Value);
|
|
|
|
return str;
|
|
}
|
|
static CString FromBoolean(BOOL Value)
|
|
{
|
|
if (Value)
|
|
return "true";
|
|
|
|
return "false";
|
|
}
|
|
static CString FromBinary(const BYTE* pData, long lSize)
|
|
{
|
|
if ((NULL == pData) || (0 == lSize))
|
|
return "";
|
|
|
|
CString sResult;
|
|
int nStrSize = Base64::Base64EncodeGetRequiredLength(lSize);
|
|
|
|
LPSTR pStrData = sResult.GetBuffer(nStrSize + 1);
|
|
BOOL bSuccess = Base64::Base64Encode(pData, lSize, pStrData, &nStrSize);
|
|
|
|
pStrData[nStrSize] = '\0';
|
|
sResult.ReleaseBuffer();
|
|
return sResult;
|
|
}
|
|
|
|
static CString FromVariant(VARIANT val)
|
|
{
|
|
CString sVal = "";
|
|
switch (VT_TYPEMASK & val.vt)
|
|
{
|
|
case VT_EMPTY:
|
|
break;
|
|
case VT_NULL:
|
|
sVal = "";
|
|
break;
|
|
case VT_I2:
|
|
sVal.Format("%d", val.iVal);
|
|
break;
|
|
case VT_I4:
|
|
sVal.Format("%d", val.lVal);
|
|
break;
|
|
case VT_R4:
|
|
sVal.Format("%f", val.fltVal);
|
|
break;
|
|
case VT_R8:
|
|
sVal.Format("%f", val.dblVal);
|
|
break;
|
|
case VT_DATE:
|
|
sVal.Format("%f", val.date);
|
|
break;
|
|
case VT_BSTR:
|
|
sVal = val.bstrVal;
|
|
break;
|
|
case VT_BOOL:
|
|
sVal = (VARIANT_TRUE == val.boolVal) ? "1" : "0";
|
|
break;
|
|
case VT_VARIANT:
|
|
sVal = "";
|
|
break;
|
|
case VT_UNKNOWN:
|
|
sVal = "";
|
|
//ìîæíî ñîõðàíÿòü ïûòàÿñü ïîëó÷èòü IDispatch èíòåðôåéñ, íî âðîäå íàì îí íå íàäî
|
|
break;
|
|
case VT_I1:
|
|
sVal.Format("%d", val.cVal);
|
|
break;
|
|
case VT_UI1:
|
|
sVal.Format("%d", val.bVal);
|
|
break;
|
|
case VT_UI2:
|
|
sVal.Format("%d", val.uiVal);
|
|
break;
|
|
case VT_UI4:
|
|
sVal.Format("%d", val.ulVal);
|
|
break;
|
|
case VT_I8:
|
|
sVal.Format("%d", val.llVal);
|
|
break;
|
|
case VT_UI8:
|
|
sVal.Format("%d", val.ullVal);
|
|
break;
|
|
case VT_INT:
|
|
sVal.Format("%d", val.intVal);
|
|
break;
|
|
case VT_UINT:
|
|
sVal.Format("%d", val.uintVal);
|
|
break;
|
|
case VT_DECIMAL:
|
|
case VT_CY:
|
|
case VT_SAFEARRAY:
|
|
case VT_VOID:
|
|
case VT_HRESULT:
|
|
case VT_CARRAY:
|
|
case VT_USERDEFINED:
|
|
case VT_LPSTR:
|
|
case VT_LPWSTR:
|
|
case VT_RECORD:
|
|
case VT_INT_PTR:
|
|
case VT_UINT_PTR:
|
|
case VT_FILETIME:
|
|
case VT_BLOB:
|
|
case VT_STREAM:
|
|
case VT_STORAGE:
|
|
case VT_STREAMED_OBJECT:
|
|
case VT_STORED_OBJECT:
|
|
case VT_BLOB_OBJECT:
|
|
case VT_CF:
|
|
case VT_CLSID:
|
|
case VT_VERSIONED_STREAM:
|
|
case VT_BSTR_BLOB:
|
|
sVal = "";
|
|
break;
|
|
}
|
|
|
|
return sVal;
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef USE_EXTENDED_STRINGS
|
|
|
|
#ifdef USE_MFC_STRING
|
|
|
|
class CMfcString
|
|
{
|
|
CString m_string;
|
|
|
|
public:
|
|
|
|
CMfcString()
|
|
{
|
|
m_string.Empty();
|
|
}
|
|
CMfcString(const CMfcString& str)
|
|
{
|
|
operator= (str);
|
|
}
|
|
CMfcString(const TCHAR ch)
|
|
{
|
|
operator= (ch);
|
|
}
|
|
CMfcString(const TCHAR* pch)
|
|
{
|
|
operator= (pch);
|
|
}
|
|
CMfcString(const _bstr_t& bstr_t)
|
|
{
|
|
operator= (bstr_t);
|
|
}
|
|
CMfcString(const CString& str)
|
|
{
|
|
operator= (str);
|
|
}
|
|
|
|
CMfcString& operator= (const CMfcString& str)
|
|
{
|
|
m_string = str.m_string;
|
|
|
|
return *this;
|
|
}
|
|
CMfcString& operator= (const TCHAR ch)
|
|
{
|
|
m_string = ch;
|
|
|
|
return *this;
|
|
}
|
|
CMfcString& operator= (const TCHAR* pch)
|
|
{
|
|
m_string = pch;
|
|
|
|
return *this;
|
|
}
|
|
CMfcString& operator= (const _bstr_t& bstr_t)
|
|
{
|
|
m_string = (TCHAR*)bstr_t;
|
|
|
|
return *this;
|
|
}
|
|
CMfcString& operator= (const CString& str)
|
|
{
|
|
m_string = str;
|
|
|
|
return *this;
|
|
}
|
|
|
|
CMfcString& operator += (const CMfcString& str)
|
|
{
|
|
m_string += str.m_string;
|
|
|
|
return *this;
|
|
}
|
|
CMfcString& operator += (const TCHAR ch)
|
|
{
|
|
CMfcString str(ch);
|
|
|
|
return operator += (str);
|
|
}
|
|
CMfcString& operator += (const TCHAR* pch)
|
|
{
|
|
CMfcString str(pch);
|
|
|
|
return operator += (str);
|
|
}
|
|
CMfcString& operator += (const _bstr_t& bstr_t)
|
|
{
|
|
CMfcString str(bstr_t);
|
|
|
|
return operator += (str);
|
|
}
|
|
CMfcString& operator += (const CString& str)
|
|
{
|
|
m_string += str;
|
|
|
|
return *this;
|
|
}
|
|
|
|
friend CMfcString operator+ (const CMfcString& str1, const CMfcString& str2)
|
|
{
|
|
CMfcString str(str1);
|
|
|
|
str += str2;
|
|
|
|
return str;
|
|
}
|
|
friend BOOL operator== (const CMfcString& str1, const CMfcString& str2)
|
|
{
|
|
return (str1.m_string.Compare(str2.m_string) == 0);
|
|
}
|
|
friend BOOL operator!= (const CMfcString& str1, const CMfcString& str2)
|
|
{
|
|
return !operator== (str1, str2);
|
|
}
|
|
|
|
TCHAR operator[] (int index) const
|
|
{
|
|
return m_string[index];
|
|
}
|
|
operator TCHAR*() const
|
|
{
|
|
return (TCHAR*)m_string;
|
|
}
|
|
operator _bstr_t() const
|
|
{
|
|
_bstr_t strResult(m_string);
|
|
|
|
return strResult;
|
|
}
|
|
operator CString()
|
|
{
|
|
return m_string;
|
|
}
|
|
|
|
int GetLength() const
|
|
{
|
|
return (int)m_string.GetLength();
|
|
}
|
|
TCHAR* GetBuffer(int nSize)
|
|
{
|
|
return m_string.GetBuffer(nSize);
|
|
}
|
|
BOOL IsEmpty()
|
|
{
|
|
return m_string.IsEmpty();
|
|
}
|
|
void Reserve(int size)
|
|
{
|
|
m_string.Preallocate(size);
|
|
}
|
|
void Clear()
|
|
{
|
|
m_string = "";
|
|
}
|
|
void Delete(int index, int count)
|
|
{
|
|
m_string.Delete(index, count);
|
|
}
|
|
void MakeLower()
|
|
{
|
|
m_string.MakeLower();
|
|
}
|
|
void MakeUpper()
|
|
{
|
|
m_string.MakeUpper();
|
|
}
|
|
void Append(const CMfcString& str)
|
|
{
|
|
m_string.Append(str.m_string);
|
|
}
|
|
void Replace(const CMfcString& strOld, const CMfcString& strNew)
|
|
{
|
|
m_string.Replace(strOld.m_string, strNew.m_string);
|
|
}
|
|
void Insert(int index, const CMfcString& str)
|
|
{
|
|
m_string.Insert(index, str.m_string);
|
|
}
|
|
void TrimLeft()
|
|
{
|
|
m_string.TrimLeft();
|
|
}
|
|
void TrimRight()
|
|
{
|
|
m_string.TrimRight();
|
|
}
|
|
void Trim()
|
|
{
|
|
TrimLeft();
|
|
TrimRight();
|
|
}
|
|
|
|
CMfcString Left(int count) const
|
|
{
|
|
return Substring(0, count);
|
|
}
|
|
CMfcString Right(int count) const
|
|
{
|
|
return Substring(m_string.GetLength() - count, count);
|
|
}
|
|
CMfcString Substring(int index, int count) const
|
|
{
|
|
CMfcString strResult;
|
|
|
|
strResult.m_string = m_string.Mid(index, count);
|
|
|
|
return strResult;
|
|
}
|
|
|
|
void Format(const TCHAR* strFormat,...)
|
|
{
|
|
va_list args;
|
|
|
|
va_start(args, strFormat);
|
|
|
|
m_string.Format(strFormat, args);
|
|
|
|
va_end(args);
|
|
}
|
|
|
|
int Compare(const CMfcString& str)
|
|
{
|
|
return m_string.Compare(str.m_string);
|
|
}
|
|
int CompareNoCase(const CMfcString& str)
|
|
{
|
|
return m_string.CompareNoCase(str.m_string);
|
|
}
|
|
int IndexOf(TCHAR ch, int start) const
|
|
{
|
|
return (int)m_string.Find(ch, start);
|
|
}
|
|
int IndexOf(const CMfcString& str, int start) const
|
|
{
|
|
return (int)m_string.Find(str.m_string, start);
|
|
}
|
|
int LastIndexOf(TCHAR ch) const
|
|
{
|
|
return (int)m_string.ReverseFind(ch);
|
|
}
|
|
int LastIndexOf(const CMfcString& str) const
|
|
{
|
|
CString strValueReverse = m_string;
|
|
CString strSubstringReverse = str;
|
|
|
|
strValueReverse.MakeReverse();
|
|
strSubstringReverse.MakeReverse();
|
|
|
|
int nIndex = IndexOf(strSubstringReverse, 0);
|
|
|
|
if (nIndex < 0)
|
|
return -1;
|
|
|
|
return GetLength() - nIndex - str.GetLength();
|
|
}
|
|
BOOL StartsWith(const CMfcString& str) const
|
|
{
|
|
return (IndexOf(str, 0) == 0);
|
|
}
|
|
BOOL StartsWith(TCHAR ch) const
|
|
{
|
|
return (IndexOf(ch, 0) == 0);
|
|
}
|
|
BOOL EndsWith(const CMfcString& str) const
|
|
{
|
|
return (LastIndexOf(str) == (m_string.GetLength() - str.m_string.GetLength()));
|
|
}
|
|
BOOL EndsWith(TCHAR ch) const
|
|
{
|
|
return (m_string.ReverseFind(ch) == (m_string.GetLength() - 1));
|
|
}
|
|
};
|
|
|
|
#undef String
|
|
#define String CMfcString
|
|
|
|
#endif
|
|
|
|
#ifdef USE_STD_STRING
|
|
|
|
#include <string>
|
|
#include <vector>
|
|
#include <algorithm>
|
|
|
|
typedef std::basic_string<TCHAR> TStdString;
|
|
|
|
namespace std
|
|
{
|
|
class Tokenizer
|
|
{
|
|
protected:
|
|
|
|
size_t m_Offset;
|
|
const TStdString m_String;
|
|
TStdString m_Token;
|
|
TStdString m_Delimiters;
|
|
|
|
public:
|
|
|
|
Tokenizer(const TStdString& str)
|
|
: m_String(str)
|
|
, m_Offset(0)
|
|
, m_Delimiters(" \t\n\r")
|
|
{
|
|
}
|
|
Tokenizer(const TStdString& str, const TStdString& delimiters)
|
|
: m_String(str)
|
|
, m_Offset(0)
|
|
, m_Delimiters(delimiters)
|
|
{
|
|
}
|
|
|
|
BOOL nextToken()
|
|
{
|
|
return nextToken(m_Delimiters);
|
|
}
|
|
BOOL nextToken(const TStdString& delimiters)
|
|
{
|
|
// find the start charater of the next token.
|
|
size_t i = m_String.find_first_not_of(delimiters, m_Offset);
|
|
|
|
if (i == TStdString::npos)
|
|
{
|
|
m_Offset = m_String.length();
|
|
return FALSE;
|
|
}
|
|
|
|
// find the end of the token.
|
|
size_t j = m_String.find_first_of(delimiters, i);
|
|
if (j == TStdString::npos)
|
|
{
|
|
m_Token = m_String.substr(i);
|
|
m_Offset = m_String.length();
|
|
return TRUE;
|
|
}
|
|
|
|
// to intercept the token and save current position
|
|
m_Token = m_String.substr(i, j - i);
|
|
m_Offset = j;
|
|
|
|
return TRUE;
|
|
}
|
|
const TStdString getToken() const
|
|
{
|
|
return m_Token;
|
|
}
|
|
|
|
// to reset the tokenizer. After reset it, the tokenizer can get the tokens from the first token.
|
|
void reset()
|
|
{
|
|
m_Offset = 0;
|
|
}
|
|
};
|
|
|
|
std::vector<TStdString> split(const TStdString& str, const TStdString& delimiters)
|
|
{
|
|
std::vector<TStdString> ss;
|
|
|
|
Tokenizer tokenizer(str, delimiters);
|
|
|
|
while (tokenizer.nextToken())
|
|
ss.push_back(tokenizer.getToken());
|
|
|
|
return ss;
|
|
}
|
|
}
|
|
|
|
class CStdString
|
|
{
|
|
TStdString m_string;
|
|
|
|
public:
|
|
|
|
CStdString()
|
|
{
|
|
m_string.clear();
|
|
}
|
|
CStdString(const CStdString& str)
|
|
{
|
|
operator= (str);
|
|
}
|
|
CStdString(const TCHAR ch)
|
|
{
|
|
operator= (ch);
|
|
}
|
|
CStdString(const TCHAR* pch)
|
|
{
|
|
operator= (pch);
|
|
}
|
|
CStdString(const BSTR bstr)
|
|
{
|
|
operator= (bstr);
|
|
}
|
|
CStdString(const TStdString& str)
|
|
{
|
|
operator= (str);
|
|
}
|
|
|
|
CStdString& operator= (const CStdString& str)
|
|
{
|
|
m_string = str.m_string;
|
|
|
|
return *this;
|
|
}
|
|
CStdString& operator= (const TCHAR ch)
|
|
{
|
|
m_string = ch;
|
|
|
|
return *this;
|
|
}
|
|
CStdString& operator= (const TCHAR* pch)
|
|
{
|
|
m_string = pch;
|
|
|
|
return *this;
|
|
}
|
|
CStdString& operator= (const BSTR bstr)
|
|
{
|
|
m_string = (TCHAR*)bstr;
|
|
|
|
return *this;
|
|
}
|
|
CStdString& operator= (const TStdString& str)
|
|
{
|
|
m_string = str;
|
|
|
|
return *this;
|
|
}
|
|
|
|
CStdString& operator += (const CStdString& str)
|
|
{
|
|
m_string += str.m_string;
|
|
|
|
return *this;
|
|
}
|
|
CStdString& operator += (const TCHAR ch)
|
|
{
|
|
CStdString str(ch);
|
|
|
|
return operator += (str);
|
|
}
|
|
CStdString& operator += (const TCHAR* pch)
|
|
{
|
|
CStdString str(pch);
|
|
|
|
return operator += (str);
|
|
}
|
|
CStdString& operator += (const BSTR bstr)
|
|
{
|
|
CStdString str(bstr);
|
|
|
|
return operator += (str);
|
|
}
|
|
CStdString& operator += (const TStdString& str)
|
|
{
|
|
m_string += str;
|
|
|
|
return *this;
|
|
}
|
|
|
|
friend CStdString operator+ (const CStdString& str1, const CStdString& str2)
|
|
{
|
|
CStdString str(str1);
|
|
|
|
str += str2;
|
|
|
|
return str;
|
|
}
|
|
friend BOOL operator== (const CStdString& str1, const CStdString& str2)
|
|
{
|
|
return (str1.m_string.compare(str2.m_string) == 0);
|
|
}
|
|
friend BOOL operator!= (const CStdString& str1, const CStdString& str2)
|
|
{
|
|
return !operator== (str1, str2);
|
|
}
|
|
|
|
TCHAR operator[] (int index) const
|
|
{
|
|
return m_string[index];
|
|
}
|
|
operator BSTR() const
|
|
{
|
|
return (BSTR)m_string.c_str();
|
|
}
|
|
operator TStdString()
|
|
{
|
|
return m_string;
|
|
}
|
|
operator TCHAR*() const
|
|
{
|
|
return (TCHAR*)m_string.data();
|
|
}
|
|
|
|
|
|
int GetLength() const
|
|
{
|
|
return (int)m_string.length();
|
|
}
|
|
TCHAR* GetBuffer(int nSize)
|
|
{
|
|
if (nSize > 0)
|
|
Reserve(nSize);
|
|
|
|
return (TCHAR*)m_string.data();
|
|
}
|
|
BOOL IsEmpty()
|
|
{
|
|
return m_string.empty();
|
|
}
|
|
void Reserve(int size)
|
|
{
|
|
m_string.reserve(size);
|
|
}
|
|
void Clear()
|
|
{
|
|
m_string.clear();
|
|
}
|
|
void Delete(int index, int count)
|
|
{
|
|
m_string.erase(index, count);
|
|
}
|
|
void MakeLower()
|
|
{
|
|
std::transform(m_string.begin(), m_string.end(), m_string.begin(), tolower);
|
|
}
|
|
void MakeUpper()
|
|
{
|
|
std::transform(m_string.begin(), m_string.end(), m_string.begin(), toupper);
|
|
}
|
|
void Append(const CStdString& str)
|
|
{
|
|
m_string.append(str.m_string);
|
|
}
|
|
void Replace(const CStdString& strOld, const CStdString& strNew)
|
|
{
|
|
if (strOld.m_string.empty())
|
|
return;
|
|
|
|
size_t nPos = 0;
|
|
|
|
for (;;)
|
|
{
|
|
nPos = m_string.find(strOld.m_string, nPos);
|
|
|
|
if (nPos == m_string.npos)
|
|
break;
|
|
|
|
m_string.replace(nPos, strOld.m_string.size(), strNew.m_string);
|
|
|
|
nPos += strNew.m_string.size();
|
|
}
|
|
}
|
|
void Insert(int index, const CStdString& str)
|
|
{
|
|
m_string.insert(index, str.m_string);
|
|
}
|
|
void TrimLeft()
|
|
{
|
|
TStdString::iterator oIterator;
|
|
|
|
for (oIterator = m_string.begin(); oIterator != m_string.end(); ++oIterator)
|
|
if (!isspace(*oIterator))
|
|
break;
|
|
|
|
if (oIterator == m_string.end())
|
|
m_string.clear();
|
|
else
|
|
m_string.erase(m_string.begin(), oIterator);
|
|
}
|
|
void TrimRight()
|
|
{
|
|
if (m_string.begin() == m_string.end())
|
|
return;
|
|
|
|
TStdString::iterator oIterator;
|
|
|
|
for (oIterator = m_string.end() - 1; ; --oIterator)
|
|
{
|
|
if (!isspace(*oIterator))
|
|
{
|
|
m_string.erase(oIterator + 1, m_string.end());
|
|
break;
|
|
}
|
|
|
|
if (oIterator == m_string.begin())
|
|
{
|
|
m_string.clear();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
void Trim()
|
|
{
|
|
TrimLeft();
|
|
TrimRight();
|
|
}
|
|
|
|
CStdString Left(int count) const
|
|
{
|
|
CStdString strResult;
|
|
|
|
strResult.m_string = m_string.substr(0, count);
|
|
|
|
return strResult;
|
|
}
|
|
CStdString Right(int count) const
|
|
{
|
|
CStdString strResult;
|
|
|
|
strResult.m_string = m_string.substr(m_string.length() - count, count);
|
|
|
|
return strResult;
|
|
}
|
|
CStdString Substring(int index, int count) const
|
|
{
|
|
CStdString strResult;
|
|
|
|
strResult.m_string = m_string.substr(index, count);
|
|
|
|
return strResult;
|
|
}
|
|
|
|
int Format(const TCHAR* strFormat,...)
|
|
{
|
|
int nMaxChars = 4096; // TODO: const ?
|
|
|
|
std::vector<TCHAR> _buffer(nMaxChars);
|
|
|
|
va_list argList;
|
|
va_start(argList, strFormat);
|
|
|
|
//int ret = _vsnprintf_s(&_buffer[0], nMaxChars, nMaxChars, strFormat, argList);
|
|
int ret = _vsnprintf(&_buffer[0], nMaxChars, strFormat, argList);
|
|
|
|
|
|
va_end(argList);
|
|
|
|
m_string.assign(&_buffer[0], ret);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int Compare(const CStdString& str)
|
|
{
|
|
return m_string.compare(str.m_string);
|
|
}
|
|
int CompareNoCase(const CStdString& str)
|
|
{
|
|
TStdString::const_iterator oIterator1 = m_string.begin();
|
|
TStdString::const_iterator oIterator2 = str.m_string.begin();
|
|
|
|
// stop when either string's end has been reached
|
|
while ( (oIterator1 != m_string.end()) && (oIterator2 != str.m_string.end()) )
|
|
{
|
|
// letters differ?
|
|
if (::toupper(*oIterator1) != ::toupper(*oIterator2))
|
|
return (::toupper(*oIterator1) < ::toupper(*oIterator2)) ? -1 : 1; // return -1 to indicate smaller than, 1 otherwise
|
|
|
|
// proceed to the next character in each string
|
|
++oIterator1;
|
|
++oIterator2;
|
|
}
|
|
|
|
// cache lengths
|
|
size_t size1 = m_string.size();
|
|
size_t size2 = str.m_string.size();
|
|
|
|
// return -1, 0 or 1 according to strings' lengths
|
|
if (size1 == size2)
|
|
return 0;
|
|
|
|
return (size1 < size2) ? -1 : 1;
|
|
}
|
|
int IndexOf(TCHAR ch, int start) const
|
|
{
|
|
return (int)m_string.find(ch, start);
|
|
}
|
|
int IndexOf(const CStdString& str, int start) const
|
|
{
|
|
return (int)m_string.find(str.m_string, start);
|
|
}
|
|
int LastIndexOf(TCHAR ch) const
|
|
{
|
|
return (int)m_string.rfind(ch);
|
|
}
|
|
int LastIndexOf(const CStdString& str) const
|
|
{
|
|
return (int)m_string.rfind(str.m_string);
|
|
}
|
|
BOOL StartsWith(const CStdString& str) const
|
|
{
|
|
return (m_string.find(str.m_string, 0) == 0);
|
|
}
|
|
BOOL StartsWith(TCHAR ch) const
|
|
{
|
|
return (m_string.find(ch, 0) == 0);
|
|
}
|
|
BOOL EndsWith(const CStdString& str) const
|
|
{
|
|
return (m_string.rfind(str.m_string) == (m_string.length() - str.m_string.length()));
|
|
}
|
|
BOOL EndsWith(TCHAR ch) const
|
|
{
|
|
return (m_string.rfind(ch) == (m_string.length() - 1));
|
|
}
|
|
};
|
|
|
|
#undef String
|
|
#define String CStdString
|
|
|
|
#endif
|
|
|
|
namespace Strings
|
|
{
|
|
static BOOL NotEquals(const TCHAR* pszValue1, const TCHAR* pszValue2)
|
|
{
|
|
// ýòà ôóíêöèÿ çàíèìàåòñÿ ìàêñèìàëüíî áûñòðûì ñðàâíåíèåì ñòðîê (íå íåñîâïàäåíèå)
|
|
// íå íàäî çäåñü íè÷åãî "áîëåå êðóòîãî" implement'èòü...
|
|
|
|
// TODO:
|
|
|
|
String strValue1 = pszValue1;
|
|
String strValue2 = pszValue2;
|
|
|
|
return (strValue1 != strValue2);
|
|
}
|
|
static String ToLower(const String& strValue)
|
|
{
|
|
String s = strValue;
|
|
|
|
s.MakeLower();
|
|
|
|
return s;
|
|
}
|
|
static String ToUpper(const String& strValue)
|
|
{
|
|
String s = strValue;
|
|
|
|
s.MakeUpper();
|
|
|
|
return s;
|
|
}
|
|
static String Substring(const String& strValue, int nFirst, int nCount)
|
|
{
|
|
if (nCount < 1)
|
|
return "";
|
|
|
|
return strValue.Substring(nFirst, nCount);
|
|
}
|
|
static int IndexOf(const String& strValue, const String& strSubstring, int nStart = 0)
|
|
{
|
|
return strValue.IndexOf(strSubstring, nStart);
|
|
}
|
|
static int LastIndexOf(const String& strValue, const String& strSubstring)
|
|
{
|
|
return strValue.LastIndexOf(strSubstring);
|
|
}
|
|
static int Split(const TCHAR* pszValue, const TCHAR* pszSplitter, Templates::CArray<String>& arrSubstrings)
|
|
{
|
|
String strValue = pszValue;
|
|
String strSplitter = pszSplitter;
|
|
|
|
if (strSplitter.GetLength() < 1)
|
|
{
|
|
arrSubstrings.Add(strValue);
|
|
return arrSubstrings.GetCount();
|
|
}
|
|
|
|
int nStart = 0;
|
|
|
|
int nIndex = IndexOf(strValue, strSplitter, nStart);
|
|
|
|
while (nIndex >= 0)
|
|
{
|
|
String strPart = Substring(strValue, nStart, nIndex - nStart);
|
|
|
|
if (strPart.GetLength() > 0)
|
|
arrSubstrings.Add(strPart);
|
|
|
|
nStart = nIndex + strSplitter.GetLength();
|
|
|
|
nIndex = IndexOf(strValue, strSplitter, nStart);
|
|
}
|
|
|
|
String strLastPart = Substring(strValue, nStart, strValue.GetLength() - nStart);
|
|
|
|
if (strLastPart.GetLength() > 0)
|
|
arrSubstrings.Add(strLastPart);
|
|
|
|
return arrSubstrings.GetCount();
|
|
}
|
|
static BOOL StartsWith(const String& strValue, const String& strSubstring)
|
|
{
|
|
return strValue.StartsWith(strSubstring);
|
|
}
|
|
static BOOL EndsWith(const String& strValue, const String& strSubstring)
|
|
{
|
|
return strValue.EndsWith(strSubstring);
|
|
}
|
|
|
|
static int ToDigit(char c)
|
|
{
|
|
if (c >= '0' && c <= '9')
|
|
return (int)(c - '0');
|
|
if (c >= 'a' && c <= 'f')
|
|
return 10 + (int)(c - 'a');
|
|
if (c >= 'A' && c <= 'F')
|
|
return 10 + (int)(c - 'A');
|
|
|
|
return 0;
|
|
}
|
|
static COLORREF ToColor(const TCHAR* strValue)
|
|
{
|
|
// variables
|
|
int blue = 0;
|
|
int green = 0;
|
|
int red = 0;
|
|
|
|
String color = strValue;
|
|
|
|
color.Trim();
|
|
|
|
if (color.IndexOf("0x", 0) != -1)
|
|
color.Delete(0, 2);
|
|
if (color.IndexOf("#", 0) != -1)
|
|
color.Delete(0, 1);
|
|
|
|
while (color.GetLength() < 6)
|
|
color = String("0") + color;
|
|
|
|
red = 16*ToDigit(color[0]) + ToDigit(color[1]);
|
|
green = 16*ToDigit(color[2]) + ToDigit(color[3]);
|
|
blue = 16*ToDigit(color[4]) + ToDigit(color[5]);
|
|
|
|
return RGB(red, green, blue);
|
|
}
|
|
static BOOL ToBoolean(const TCHAR* strValue)
|
|
{
|
|
String s = strValue;
|
|
|
|
s.MakeLower();
|
|
|
|
return (s == String("true"));
|
|
}
|
|
static int ToInteger(const TCHAR* strValue)
|
|
{
|
|
int nValue = 0;
|
|
|
|
sscanf(strValue, " %d", &nValue);
|
|
|
|
return nValue;
|
|
}
|
|
static double ToDouble(const TCHAR* strValue)
|
|
{
|
|
double dValue = 0;
|
|
|
|
sscanf(strValue, " %lf", &dValue);
|
|
|
|
return dValue;
|
|
}
|
|
static BOOL ToBinary(const TCHAR* pszValue, BYTE*& pData, int& nSizeAllocated, int& nSizeArray)
|
|
{
|
|
String strValue = pszValue;
|
|
|
|
pData = NULL;
|
|
nSizeArray = 0;
|
|
nSizeAllocated = Base64::Base64DecodeGetRequiredLength(strValue.GetLength());
|
|
|
|
if (nSizeAllocated < 1)
|
|
return FALSE;
|
|
|
|
pData = new BYTE[nSizeAllocated];
|
|
if (!pData)
|
|
return FALSE;
|
|
|
|
nSizeArray = nSizeAllocated;
|
|
|
|
if (!Base64::Base64Decode(pszValue, strValue.GetLength(), pData, &nSizeArray))
|
|
{
|
|
delete[] pData;
|
|
pData = NULL;
|
|
nSizeArray = 0;
|
|
nSizeAllocated = 0;
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static String FromInteger(int nValue, int Base = 10)
|
|
{
|
|
String str;
|
|
|
|
str.Format("%d", nValue);
|
|
|
|
return str;
|
|
}
|
|
static String FromDouble(double dValue)
|
|
{
|
|
String str;
|
|
|
|
str.Format("%lf", dValue);
|
|
|
|
return str;
|
|
}
|
|
static String FromBoolean(BOOL bValue)
|
|
{
|
|
if (bValue)
|
|
return "true";
|
|
|
|
return "false";
|
|
}
|
|
static String FromBinary(const BYTE* pData, long lSize)
|
|
{
|
|
if ((NULL == pData) || (0 == lSize))
|
|
return "";
|
|
|
|
String sResult;
|
|
int nStrSize = Base64::Base64EncodeGetRequiredLength(lSize);
|
|
|
|
LPSTR pStrData = sResult.GetBuffer(nStrSize + 1);
|
|
BOOL bSuccess = Base64::Base64Encode(pData, lSize, pStrData, &nStrSize);
|
|
|
|
pStrData[nStrSize] = '\0';
|
|
sResult.Clear();
|
|
return sResult;
|
|
}
|
|
|
|
static String FromVariant(VARIANT val)
|
|
{
|
|
String sVal = "";
|
|
switch (VT_TYPEMASK & val.vt)
|
|
{
|
|
case VT_EMPTY:
|
|
break;
|
|
case VT_NULL:
|
|
sVal = "";
|
|
break;
|
|
case VT_I2:
|
|
sVal.Format("%d", val.iVal);
|
|
break;
|
|
case VT_I4:
|
|
sVal.Format("%d", val.lVal);
|
|
break;
|
|
case VT_R4:
|
|
sVal.Format("%f", val.fltVal);
|
|
break;
|
|
case VT_R8:
|
|
sVal.Format("%f", val.dblVal);
|
|
break;
|
|
case VT_DATE:
|
|
sVal.Format("%f", val.date);
|
|
break;
|
|
case VT_BSTR:
|
|
sVal = val.bstrVal;
|
|
break;
|
|
case VT_BOOL:
|
|
sVal = (VARIANT_TRUE == val.boolVal) ? "1" : "0";
|
|
break;
|
|
case VT_VARIANT:
|
|
sVal = "";
|
|
break;
|
|
case VT_UNKNOWN:
|
|
sVal = "";
|
|
//ìîæíî ñîõðàíÿòü ïûòàÿñü ïîëó÷èòü IDispatch èíòåðôåéñ, íî âðîäå íàì îí íå íàäî
|
|
break;
|
|
case VT_I1:
|
|
sVal.Format("%d", val.cVal);
|
|
break;
|
|
case VT_UI1:
|
|
sVal.Format("%d", val.bVal);
|
|
break;
|
|
case VT_UI2:
|
|
sVal.Format("%d", val.uiVal);
|
|
break;
|
|
case VT_UI4:
|
|
sVal.Format("%d", val.ulVal);
|
|
break;
|
|
case VT_I8:
|
|
sVal.Format("%d", val.llVal);
|
|
break;
|
|
case VT_UI8:
|
|
sVal.Format("%d", val.ullVal);
|
|
break;
|
|
case VT_INT:
|
|
sVal.Format("%d", val.intVal);
|
|
break;
|
|
case VT_UINT:
|
|
sVal.Format("%d", val.uintVal);
|
|
break;
|
|
case VT_DECIMAL:
|
|
case VT_CY:
|
|
case VT_SAFEARRAY:
|
|
case VT_VOID:
|
|
case VT_HRESULT:
|
|
case VT_CARRAY:
|
|
case VT_USERDEFINED:
|
|
case VT_LPSTR:
|
|
case VT_LPWSTR:
|
|
case VT_RECORD:
|
|
case VT_INT_PTR:
|
|
case VT_UINT_PTR:
|
|
case VT_FILETIME:
|
|
case VT_BLOB:
|
|
case VT_STREAM:
|
|
case VT_STORAGE:
|
|
case VT_STREAMED_OBJECT:
|
|
case VT_STORED_OBJECT:
|
|
case VT_BLOB_OBJECT:
|
|
case VT_CF:
|
|
case VT_CLSID:
|
|
case VT_VERSIONED_STREAM:
|
|
case VT_BSTR_BLOB:
|
|
sVal = "";
|
|
break;
|
|
}
|
|
|
|
return sVal;
|
|
}
|
|
}
|
|
|
|
#endif
|