/***********************************//** * @file SimpleString.h * @copyright China Merchants Bank Co.,Ltd All rights reserved * @brief * @details * replace char with CHAR and wchar_t with WCHAR for linux compaticity. **************************************/ #ifndef _RVC_SIMPLESTRING_H_ #define _RVC_SIMPLESTRING_H_ #pragma once #include #include "AutoArray.h" #ifndef _WIN32 #include #include #include #include #include #include #include #include #endif //NOT _WIN32 #define WTAG "rvc.tools.simplestring" template class CSimpleStringT; typedef CSimpleStringT CSimpleStringA; typedef CSimpleStringT CSimpleString; #if defined(_MSC_VER) #define SPCHAR WCHAR #else #define SPCHAR wchar_t #endif //_MSC_VER typedef CSimpleStringT CSimpleStringW; static inline CSimpleStringW CSimpleStringA2W(CSimpleStringA str); static inline CSimpleStringA CSimpleStringW2A(CSimpleStringW wstr); #ifndef _WIN32 typedef CSimpleStringT CSimpleString16Bit; static inline CSimpleStringA CSimpleString16Bit2A(CSimpleString16Bit wstr); static inline CSimpleString16Bit CSimpleStringA216Bit(CSimpleStringA str); static inline CSimpleStringW CSimpleString16Bit2W(CSimpleString16Bit wstr); static inline CSimpleString16Bit CSimpleStringW216Bit(CSimpleStringW wstr); #endif //NOT _WIN32 template class CSimpleStringT { public: CSimpleStringT() {} CSimpleStringT(const T* pString) { if (pString != NULL) { m_StringBuf.Copy(pString, 0, CalculateStringToBufferLength(pString)); } } CSimpleStringT(const T* pString, size_t n) { if (n > 0 && pString != NULL) { if (pString[n - 1]) { // not end with NULL m_StringBuf.Init(n + 1); memcpy(&m_StringBuf[0], pString, sizeof(T) * n); m_StringBuf[n] = 0; } else { m_StringBuf.Copy(pString, 0, n); } } } CSimpleStringT(const CSimpleStringT& String) :m_StringBuf(String.m_StringBuf) {} CSimpleStringT(T ch, size_t n) : m_StringBuf(n + 1) { for (size_t i = 0; i < n; ++i) m_StringBuf[i] = ch; m_StringBuf[n] = 0; } CSimpleStringT(bool bEmptyString) { if (bEmptyString) { m_StringBuf.Init(1); m_StringBuf[0] = 0; } } static CSimpleStringT Format(const T* pszFormat, ...) { if (pszFormat == NULL) { return CSimpleStringT(); } CSimpleStringT strRet; va_list args; va_start(args, pszFormat); int nLen = _CalFormatStrLen(pszFormat, args); strRet.m_StringBuf.Init(nLen + 1); _FormatString(strRet.m_StringBuf.GetWriteableArray(), nLen + 1, pszFormat, args); va_end(args); return strRet; } CSimpleStringT SubString(int nIndex, int nCount = 0) { if (nIndex < 0 || nIndex >= GetLength() || nCount < 0) return CSimpleStringT(); if (nCount == 0) nCount = GetLength() - nIndex; else if (nIndex + nCount > GetLength()) nCount = GetLength() - nIndex; CSimpleStringT strRet; strRet.m_StringBuf.Init(nCount + 1); memcpy_s(&strRet.m_StringBuf[0], (nCount + 1) * sizeof(T), &m_StringBuf[nIndex], nCount * sizeof(T)); strRet.m_StringBuf[nCount] = 0; return strRet; } CSimpleStringT& operator=(const T* pString) { int m_nStringLen = CalculateStringToBufferLength(pString); if (m_nStringLen == 0) { m_StringBuf.Init(0); return *this; } m_StringBuf.Init(m_nStringLen); memcpy_s(m_StringBuf.GetWriteableArray(), m_nStringLen * sizeof(T), pString, m_nStringLen * sizeof(T)); return *this; } CSimpleStringT& operator=(const CSimpleStringT& String) { m_StringBuf = String.m_StringBuf; return *this; } bool operator ==(const CSimpleStringT& String)const { if (m_StringBuf == String.m_StringBuf) return true; if (GetLength() == String.GetLength()) return Compare(String) == 0; else return false; } bool operator == (const T* pString) const { if (pString == NULL) return false; return Compare(pString) == 0; } bool operator !=(const CSimpleStringT& String)const { return !(operator==(String)); } operator const T* ()const { return m_StringBuf; } CSimpleStringT operator + (const CSimpleStringT& RightString)const { int nRightLen = RightString.GetLength(); if (nRightLen == 0) return *this; int nLeftLen = GetLength(); if (nLeftLen == 0) return RightString; // bugfix [3/18/2020 15:34 Gifur] //CSimpleStringA ResultString; CSimpleStringT ResultString; int nResultSize = nLeftLen + nRightLen + 1; ResultString.m_StringBuf.Init(nResultSize); T* pTargetString = ResultString.m_StringBuf.GetWriteableArray(); memcpy_s(pTargetString, nResultSize * sizeof(T), m_StringBuf, nLeftLen * sizeof(T)); //memcpy_s(pTargetString+nLeftLen,(nRightLen+1)*sizeof(T),RightString,nRightLen+1); // {bug} memcpy_s(pTargetString + nLeftLen, (nRightLen + 1) * sizeof(T), RightString, (nRightLen + 1) * sizeof(T)); return ResultString; } CSimpleStringT& operator +=(const T* pString) { int nRightLen = CalculateStringToBufferLength(pString); if (nRightLen == 0) return *this; int nLeftLen = GetLength(); if (nLeftLen == 0) return operator=(pString); //int nResultSize=nLeftLen+nRightLen+1; // {bug} since nRightLen == strlen(pString)+1, no need +1 again! //m_StringBuf.EnlargeArray(nResultSize); //memcpy_s(m_StringBuf.GetWriteableArray()+nLeftLen,(nRightLen+1)*sizeof(T),pString,(nRightLen+1)*sizeof(T)); int nResultSize = nLeftLen + nRightLen; m_StringBuf.EnlargeArray(nResultSize); memcpy_s(m_StringBuf.GetWriteableArray() + nLeftLen, (nRightLen) * sizeof(T), pString, (nRightLen) * sizeof(T)); return *this; } CSimpleStringT& operator +=(const CSimpleStringT& RightString) { int nRigthLen = RightString.GetLength(); if (nRigthLen == 0) return *this; int nLeftLen = GetLength(); if (nLeftLen == 0) return operator=(RightString); int nResultSize = nLeftLen + nRigthLen + 1; m_StringBuf.EnlargeArray(nResultSize); memcpy_s(m_StringBuf.GetWriteableArray() + nLeftLen, (nRigthLen + 1) * sizeof(T), RightString, (nRigthLen + 1) * sizeof(T)); return *this; } const T operator[](int nIndex)const { return m_StringBuf[nIndex]; } T& operator[](int nIndex) { return m_StringBuf[nIndex]; } const T* GetData() const { return &m_StringBuf[0]; } int GetLength()const { int nLen = m_StringBuf.GetCount(); return nLen == 0 ? nLen : _CalStringLen(m_StringBuf); } int GetCapability()const { int nLen = m_StringBuf.GetCount(); return nLen == 0 ? nLen : nLen - 1; //to keep the '\0' CHAR } void Clear() { m_StringBuf.Init(0); } CAutoArray> Split(T ch) { CAutoArray> ret; const T* pData = GetData(); int nStringSize = GetLength(); int nBegin(0), nEnd(0); while (nEnd < nStringSize) { if (pData[nEnd] == ch || nEnd == nStringSize - 1) { int nSize = pData[nEnd] == ch ? nEnd - nBegin : nEnd - nBegin + 1; if (nSize > 0) { int nNewSize = ret.GetCount() + 1; ret.EnlargeArray(nNewSize); ret[nNewSize - 1] = CSimpleStringT(pData + nBegin, nSize).Trim(); } nBegin = nEnd + 1; nEnd++; } else { nEnd++; } } return ret; } CSimpleStringT Trim() { int nBegin = 0; while (nBegin < GetLength() && ((int)m_StringBuf[nBegin]) == 0x20) nBegin++; int nEnd = GetLength() - 1; while (nEnd >= 0 && ((int)m_StringBuf[nEnd]) == 0x20) nEnd--; if (nBegin > nEnd) return CSimpleStringT(true); else return SubString(nBegin, nEnd - nBegin + 1); } bool IsStartWith(const T* pStr, bool bIgnoreCase = false) { int nLen = _CalStringLen(pStr); if (nLen == 0) return false; else if (GetLength() < nLen) return false; CSimpleStringT strComp = SubString(0, nLen); return _CompareString(pStr, strComp, bIgnoreCase) == 0; } bool IsEndWith(const T* pStr, bool bIgnoreCase = false) { int nLen = _CalStringLen(pStr); if (nLen == 0) return false; else if (GetLength() < nLen) return false; int nStart = GetLength() - nLen; CSimpleStringT strComp = SubString(nStart, nLen); return _CompareString(pStr, strComp, bIgnoreCase) == 0; } int IndexOf(const T* pStr) { if (pStr == NULL) return -1; int nCompLen = _CalStringLen(pStr); int nDataLen = GetLength(); if (nCompLen == 0 || nDataLen < nCompLen) return -1; for (int i = 0; i <= nDataLen - nCompLen; i++) { if (_CompareStringN(&m_StringBuf[i], pStr, nCompLen) == 0) return i; } return -1; } CSimpleStringT& Append(const T* pString) { int nRightLen = CalculateStringToBufferLength(pString); if (nRightLen == 0) return *this; int nLeftLen = GetLength(); if (nLeftLen == 0) return operator=(pString); //m_StringBuf.EnlargeArray(nLeftLen+nRightLen+1); // {bug} CalculateStringToBufferLength already includes null //memcpy_s(m_StringBuf.GetWriteableArray()+nLeftLen,(nRightLen+1)*sizeof(T),pString,(nRightLen+1)*sizeof(T)); m_StringBuf.EnlargeArray(nLeftLen + nRightLen); memcpy_s(m_StringBuf.GetWriteableArray() + nLeftLen, (nRightLen) * sizeof(T), pString, (nRightLen) * sizeof(T)); return *this; } CSimpleStringT& Append(const T* pString, int iCount) { if (iCount <= 0) return *this; int nRightLen = CalculateStringToBufferLength(pString); if (nRightLen < iCount) return *this; nRightLen = iCount; int nLeftLen = GetLength(); int nResultSize = nLeftLen + nRightLen; m_StringBuf.EnlargeArray(nResultSize + 1); // include null-terminated CHAR memcpy_s(m_StringBuf.GetWriteableArray() + nLeftLen, nRightLen * sizeof(T), pString, nRightLen * sizeof(T)); *(m_StringBuf.GetWriteableArray() + nResultSize) = 0; return *this; } bool IsNullOrEmpty() const { return GetLength() == 0; } void Resize(int n) { m_StringBuf.Init(n); } int Compare(const T* p) const { if (p == GetData()) return 0; return _CompareString(m_StringBuf, p); } int Compare(const T* p, bool bIgnoreCase) const { if (p == GetData()) return 0; return _CompareString(m_StringBuf, p, bIgnoreCase); } int Compare(const CSimpleStringT& str) const { return Compare(str.GetData()); } int Compare(const CSimpleStringT& str, bool bIgnoreCase) const { return Compare(str.GetData(), bIgnoreCase); } private: static inline int _CompareString(const CHAR* pStr1, const CHAR* pStr2, bool bIgnoreCase = false) { if (pStr2 == NULL || pStr1 == NULL) { if (pStr2 == NULL && pStr1 == NULL) return 0; return 1; } if (bIgnoreCase) return _stricmp(pStr1, pStr2); else return strcmp(pStr1, pStr2); } static inline int _CompareString(const WCHAR* pStr1, const WCHAR* pStr2, bool bIgnoreCase = false) { if (pStr2 == NULL || pStr1 == NULL) { if (pStr2 == NULL && pStr1 == NULL) return 0; return 1; } if (bIgnoreCase) return _wcsicmp(pStr1, pStr2); else #if defined(_MSC_VER) return wcscmp(pStr1, pStr2); #else return _wcscmp(pStr1, pStr2); #endif //_MSC_VER } #ifndef _WIN32 static inline int _CompareString(const wchar_t* pStr1, const wchar_t* pStr2, bool bIgnoreCase = false) { if (pStr2 == NULL || pStr1 == NULL) { if (pStr2 == NULL && pStr1 == NULL) return 0; return 1; } if (bIgnoreCase) return wcscasecmp(pStr1, pStr2); else return wcscmp(pStr1, pStr2); } #endif //NOT _WIN32 static inline int _CompareStringN(const CHAR* pStr1, const CHAR* pStr2, int nCompLen, bool bIgnoreCase = false) { if (bIgnoreCase) return _strnicmp(pStr1, pStr2, nCompLen); else return strncmp(pStr1, pStr2, nCompLen); } static inline int _CompareStringN(const WCHAR* pStr1, const WCHAR* pStr2, int nCompLen, bool bIgnoreCase = false) { if (bIgnoreCase) return _wcsnicmp(pStr1, pStr2, nCompLen); else #ifdef _WIN32 return wcsncmp(pStr1, pStr2, nCompLen); #else return _wcsncmp(pStr1, pStr2, nCompLen); #endif //_WIN32 } #ifndef _WIN32 static inline int _CompareStringN(const wchar_t* pStr1, const wchar_t* pStr2, int nCompLen, bool bIgnoreCase = false) { if (bIgnoreCase) return wcsncasecmp(pStr1, pStr2, nCompLen); else return wcsncmp(pStr1, pStr2, nCompLen); } #endif //NOT _WIN32 static inline int _CalStringLen(const CHAR* pString) { return strlen(pString); } static inline int _CalStringLen(const WCHAR* pString) { #if defined(_MSC_VER) return wcslen(pString); #else return _wcslen(pString); #endif //_MSC_VER } #ifndef _WIN32 static inline int _CalStringLen(const wchar_t* pString) { return wcslen(pString); } #endif //NOT _WIN32 static inline int _CalFormatStrLen(const CHAR* pFormat, va_list ArgList) { return _vscprintf(pFormat, ArgList); } static inline int _CalFormatStrLen(const WCHAR* pFormat, va_list ArgList) { return _vscwprintf(pFormat, ArgList); } #ifndef _WIN32 static inline int _CalFormatStrLen(const wchar_t* pFormat, va_list ArgList) { int buf_size = 1024; int result = -1; while (buf_size < 1024 * 1024) { va_list args; va_copy(args, ArgList); wchar_t buffer[buf_size]; int fmt_size = vswprintf(buffer, sizeof(buffer) / sizeof(wchar_t), pFormat, args); va_end(args); if (fmt_size >= 0) { result = fmt_size; break; } buf_size *= 2; } return result; //return vwprintf(pFormat, ArgList); } #endif static inline int _FormatString(CHAR* pBuffer, int nBufLen, const CHAR* pFormat, va_list ArgList) { return _vsnprintf_s(pBuffer, nBufLen, _TRUNCATE, pFormat, ArgList); } static inline int _FormatString(WCHAR* pBuffer, int nBufLen, const WCHAR* pFormat, va_list ArgList) { //bugFix: _vsnwprintf replace with _vsnwprintf_s [3/18/2020 15:36 Gifur] return _vsnwprintf_s(pBuffer, nBufLen, _TRUNCATE, pFormat, ArgList); } #ifndef _WIN32 static inline int _FormatString(wchar_t* pBuffer, int nBufLen, const wchar_t* pFormat, va_list ArgList) { return vswprintf(pBuffer, nBufLen, pFormat, ArgList); } #endif //NOT _WIN32 static int CalculateStringToBufferLength(const T* pString) { if (pString == NULL) return 0; int nLen = _CalStringLen(pString); return nLen + 1; } CAutoArray m_StringBuf; /* * fixed compiled error: 'static' is invalid in friend declarations * a function first declared in a friend declaration has external linkage. otherwise the function * retains its previous linkage. [3/18/2020 13:30 Gifur] */ friend /*static*/ inline CSimpleStringW CSimpleStringA2W(CSimpleStringA str); friend /*static*/ inline CSimpleStringA CSimpleStringW2A(CSimpleStringW str); #ifndef _WIN32 friend /*static*/ CSimpleStringA CSimpleString16Bit2A(CSimpleString16Bit wstr); friend /*static*/ CSimpleString16Bit CSimpleStringA216Bit(CSimpleStringA str); friend /*static*/ CSimpleStringW CSimpleString16Bit2W(CSimpleString16Bit wstr); friend /*static*/ CSimpleString16Bit CSimpleStringW216Bit(CSimpleStringW wstr); #endif //NOT _WIN32 }; template bool operator<(const CSimpleStringT& lhs, const CSimpleStringT& rhs) { return lhs.Compare(rhs) < 0; } static inline CSimpleStringW CSimpleStringA2W(CSimpleStringA str) { #if defined(_MSC_VER) CSimpleStringW wstr; int n = ::MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0); if (n > 0) { wstr.m_StringBuf.Init(n); ::MultiByteToWideChar(CP_ACP, 0, str, -1, &wstr[0], n); } return wstr; #else if (str.IsNullOrEmpty()) return CSimpleStringW(true); int len = mbstowcs(NULL, str, 0); WLog_DBG(WTAG, ">>> %s: origin locale: %s, data: %s(%d): error:%d, %s", __FUNCTION__, setlocale(LC_CTYPE, NULL), str.GetData(), len, errno, strerror(errno)); if (len == -1) { return CSimpleStringW(true); } len += 1; wchar_t* p = new wchar_t[len]; wmemset(p, 0, len); size_t ret = mbstowcs(p, str, len); if (ret == (size_t)-1) { delete[] p; return CSimpleStringW(true); } CSimpleStringW result(p); delete[] p; WLog_DBG(WTAG, "<<< %s: data: %ls(%d)", __FUNCTION__, result.GetData(), ret); return result; #endif //_MSC_VER } static inline CSimpleStringA CSimpleStringW2A(CSimpleStringW wstr) { #if defined(_MSC_VER) CSimpleStringA str; int n = ::WideCharToMultiByte(CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL); if (n > 0) { str.m_StringBuf.Init(n); ::WideCharToMultiByte(CP_ACP, 0, wstr, -1, &str[0], n, NULL, NULL); } return str; #else if (wstr.IsNullOrEmpty()) return CSimpleStringA(true); int len = wcstombs(NULL, wstr, 0); WLog_DBG(WTAG, ">>> %s: origin locale: %s, data: %ls(%d)", __FUNCTION__, setlocale(LC_CTYPE, NULL), wstr.GetData(), len); if (len == -1) { return CSimpleStringA(true); } len += 1; char* p = new char[len]; memset(p, 0, len * sizeof(char)); size_t ret = wcstombs(p, wstr, len); if (ret == (size_t)-1) { delete[] p; return CSimpleStringA(true); } CSimpleStringA result(p); delete[] p; WLog_DBG(WTAG, "<<< %s: data: %s(%d)", __FUNCTION__, result.GetData(), ret); return result; #endif //_MSC_VER } #ifndef _WIN32 static inline CSimpleStringA CSimpleString16Bit2A(CSimpleString16Bit wstr) { CSimpleStringA str; int n = ::WideCharToMultiByte(CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL); if (n > 0) { str.m_StringBuf.Init(n); ::WideCharToMultiByte(CP_ACP, 0, wstr, -1, &str[0], n, NULL, NULL); } return str; } static inline CSimpleString16Bit CSimpleStringA216Bit(CSimpleStringA str) { CSimpleString16Bit wstr; int n = ::MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0); if (n > 0) { wstr.m_StringBuf.Init(n); ::MultiByteToWideChar(CP_ACP, 0, str, -1, &wstr[0], n); } return wstr; } static inline CSimpleStringW CSimpleString16Bit2W(CSimpleString16Bit wstr) { CSimpleStringA str = CSimpleString16Bit2A(wstr); return CSimpleStringA2W(str); } static inline CSimpleString16Bit CSimpleStringW216Bit(CSimpleStringW wstr) { CSimpleStringA str = CSimpleStringW2A(wstr); return CSimpleStringA216Bit(str); } #endif //NOT _WIN32 #endif //_RVC_SIMPLESTRING_H_