#ifndef STRING__H_ #define STRING__H_ #ifdef _WIN32 #pragma once #endif #include #include #include #ifndef _WIN32 #include #endif class HString : public std::string { public: static int ReadOneLine(HString * pstrDst, const char * pszSrc, int nStartOffset) { const char * p = pszSrc + nStartOffset; int i, nResult = -1; for (i = 0; *p != '\0' ; i++) { if (*p == '\r') { nResult = nStartOffset + i + 1; if (*(p + 1) == '\n') nResult++; pstrDst->Assign(pszSrc + nStartOffset, i); break; } else if (*p == '\n') { nResult = nStartOffset + i + 1; pstrDst->Assign(pszSrc + nStartOffset, i); break; } p++; } if (nResult == -1 && i > 0) { nResult = nStartOffset + i; pstrDst->Assign(pszSrc + nStartOffset, i); } return nResult; } public: HString() {} HString(char ch) { operator=(ch); } //HString(const char * psz) : std::string(psz) {} HString(const char * psz) { if (psz) std::string::operator=(psz); } HString(const char * p, size_t nSize) : std::string(p, nSize) {} HString(const std::string & str) : std::string(str) {} HString(short num) { operator=(num); } //??? HString * pstr = NULL; pstr ? *pstr : NULL HString(unsigned short num) { operator=(num); } HString(int num) { operator=(num); } HString(unsigned int num) { operator=(num); } HString(long num) { operator=(num); } HString(unsigned long num) { operator=(num); } HString(float num) { operator=(num); } HString(double num) { operator=(num); } #ifdef _WIN32 HString(time_t num) { operator=(num); } #endif ~HString() {} inline std::string & operator=(char ch) { return std::string::operator=(ch); } inline std::string & operator=(const char * psz) { if (psz) return std::string::operator=(psz); return std::string::operator=(""); } inline std::string & operator=(short num) //... { char szBuf[16]; sprintf(szBuf, "%d", num); return std::string::operator=(szBuf); } inline std::string & operator=(unsigned short num) //... { char szBuf[16]; sprintf(szBuf, "%hd", num); return std::string::operator=(szBuf); } inline std::string & operator=(int num) //... { char szBuf[32]; sprintf(szBuf, "%d", num); return std::string::operator=(szBuf); } inline std::string & operator=(unsigned int num) //... { char szBuf[32]; sprintf(szBuf, "%u", num); return std::string::operator=(szBuf); } inline std::string & operator=(long num) //... { char szBuf[64]; sprintf(szBuf, "%ld", num); return std::string::operator=(szBuf); } inline std::string & operator=(unsigned long num) //... { char szBuf[64]; sprintf(szBuf, "%lu", num); return std::string::operator=(szBuf); } inline std::string & operator=(float num) //... { char szBuf[64]; sprintf(szBuf, "%f", num); return std::string::operator=(szBuf); } inline std::string & operator=(double num) //... { char szBuf[64]; sprintf(szBuf, "%lf", num); return std::string::operator=(szBuf); } #ifdef _WIN32 inline std::string & operator=(time_t num) //... { char szBuf[64]; sprintf(szBuf, "%lld", num); return std::string::operator=(szBuf); } #endif inline std::string & operator+=(char ch) { return std::string::operator+=(ch); } inline std::string & operator+=(const char * psz) { if (psz == NULL) return *this; return std::string::operator+=(psz); } inline std::string & operator+=(const std::string & str) { return std::string::operator+=(str); } inline std::string & operator+=(short num) //... { char szBuf[16]; sprintf(szBuf, "%d", num); return append(szBuf); } inline std::string & operator+=(unsigned short num) //... { char szBuf[16]; sprintf(szBuf, "%hd", num); return append(szBuf); } inline std::string & operator+=(int num) //... { char szBuf[32]; sprintf(szBuf, "%d", num); return append(szBuf); } inline std::string & operator+=(unsigned int num) //... { char szBuf[32]; sprintf(szBuf, "%u", num); return append(szBuf); } inline std::string & operator+=(long num) //... { char szBuf[64]; sprintf(szBuf, "%ld", num); return append(szBuf); } inline std::string & operator+=(unsigned long num) //... { char szBuf[64]; sprintf(szBuf, "%lu", num); return append(szBuf); } inline std::string & operator+=(float num) //... { char szBuf[64]; sprintf(szBuf, "%f", num); return append(szBuf); } inline std::string & operator+=(double num) //... { char szBuf[64]; sprintf(szBuf, "%lf", num); return append(szBuf); } #ifdef _WIN32 inline std::string & operator+=(time_t num) //... { char szBuf[64]; sprintf(szBuf, "%lld", num); return append(szBuf); } #endif inline operator const char *() const { return c_str(); } inline operator short() const { return atoi(c_str()); } inline operator unsigned short() const { return atoi(c_str()); } inline operator int() const { return atoi(c_str()); } inline operator unsigned int() const { return atoi(c_str()); } inline operator long() const { return atol(c_str()); } inline operator unsigned long() const { return atol(c_str()); } inline const char * psz() const { return c_str(); } inline size_t GetLength() const { return length(); } inline bool IsEmpty() const { return empty(); } inline void Reserve(size_t nSize) { reserve(nSize); } inline std::string & Assign(const char * psz, size_t nOffset) { return assign(psz, nOffset); } inline size_t Copy(char * psz, size_t len, size_t pos = 0) const { return copy(psz, len, pos); } inline HString SubStr(const size_t pos, size_t len) const { return substr(pos, len); } inline int StrNCmp(const char * psz, unsigned int nCount) { return ::strncmp(c_str(), psz, nCount); } inline int StrNICmp(const char * psz, unsigned int nCount) { return ::strnicmp(c_str(), psz, nCount); } inline const char * StrNStr(const char * psz, int nCount = -1) const { return ::StrNStr(c_str(), psz, nCount); } inline const char * StrNIStr(const char * psz, int nCount = -1) const { return ::StrNIStr(c_str(), psz, nCount); } inline const char * ToUpper() { char * pszDst = (char *)malloc(GetLength() + 1); char * pszOffset = pszDst; const char * pszSrc = psz(); while (*pszSrc) { *pszOffset++ = toupper(*pszSrc++); } *pszOffset = '\0'; std::string::operator=(pszDst); free(pszDst); return c_str(); } inline const char * ToLower() { char * pszDst = (char *)malloc(GetLength() + 1); char * pszOffset = pszDst; const char * pszSrc = psz(); while (*pszSrc) { *pszOffset++ = tolower(*pszSrc++); } *pszOffset = '\0'; std::string::operator=(pszDst); free(pszDst); return c_str(); } inline int CompareNoCase(const char * p) const { return stricmp(psz(), p); } inline char GetLast() const { if (empty()) return -1; return psz()[GetLength() - 1]; } #ifdef _WIN32 #pragma warning(disable:4267) #endif inline long Find(const HString & str, size_t pos = 0) const { size_t nResult = find(str, pos); if (nResult == std::string::npos) return -1; return nResult; } inline long Find(const char * psz, size_t pos = 0) const { size_t nResult = find(psz, pos); if (nResult == std::string::npos) return -1; return nResult; } inline long Find(const char * psz, size_t pos, size_t n) const { size_t nResult = find(psz, pos, n); if (nResult == std::string::npos) return -1; return nResult; } inline long Find(char c, size_t pos = 0) const { size_t nResult = find(c, pos); if (nResult == std::string::npos) return -1; return nResult; } #ifdef _WIN32 #pragma warning(default:4267) #endif void Trim(bool bRemoveFront, bool bRemoveRear) { char * pszBuffer = (char *)malloc(GetLength() + 1); char * pszDst = pszBuffer; strcpy(pszDst, psz()); StrTrim(&pszDst, GetLength(), bRemoveFront, bRemoveRear); std::string::operator=(pszDst); free(pszBuffer); } bool Replace(const char * pszKeyword, const char * pszReplace, int nMode = 0, int nCount = -1) // nMode : 0 = case sensitive, 1 = no case, 2 = keyword { if (nCount == 0) return false; const char * (*fnStrStr)(const char *, const char *); if (nMode == 0) fnStrStr = (const char*(*)(const char*, const char*))strstr; else if (nMode == 1) fnStrStr = stristr; else fnStrStr = StrIKeyword; int nRepeatCount = nCount; size_t nKeywordLength = strlen(pszKeyword); const char * pszNext = psz(); int nKeywordCount = 0; for (;;) { if ((pszNext = fnStrStr(pszNext, pszKeyword)) == NULL) break; nKeywordCount++; if (nRepeatCount > -1 && --nRepeatCount == 0) break; pszNext += nKeywordLength; } if (nKeywordCount == 0) return false; size_t nReplaceLength = strlen(pszReplace); size_t nTextLength = GetLength(); size_t nNewTextLength = nTextLength + (nReplaceLength - nKeywordLength) * nKeywordCount; char * pszNewText = (char *)malloc(nNewTextLength + 1); size_t nCopySize; size_t nRemainSize = nTextLength; char * pszNewTextOffset = pszNewText; const char * pszTextOffset = psz(); nRepeatCount = nCount; for (;;) { if ((pszNext = fnStrStr(pszTextOffset, pszKeyword)) == NULL) break; nCopySize = pszNext - pszTextOffset; memcpy(pszNewTextOffset, pszTextOffset, nCopySize); memcpy(pszNewTextOffset + nCopySize, pszReplace, nReplaceLength); pszTextOffset += nCopySize + nKeywordLength; pszNewTextOffset += nCopySize + nReplaceLength; nRemainSize -= nCopySize + nKeywordLength; if (nRepeatCount > -1 && --nRepeatCount == 0) break; } if (nRemainSize > 0) memcpy(pszNewTextOffset, pszTextOffset, nRemainSize); pszNewText[nNewTextLength] = '\0'; std::string::operator=(pszNewText); free(pszNewText); return true; } // " a b c " --> " a b c " void RemoveRedundancyChar(const char * pszSrc, size_t nLength, char ch) { *this = ""; if (pszSrc == NULL || nLength == 0) return; for (size_t i = 0; i < nLength; i++) { if (pszSrc[i] == ch && pszSrc[i + 1] == ch) continue; *this += pszSrc[i]; } } void RemoveRedundancyRow(const char * pszSrc, size_t nLength) { *this = ""; if (pszSrc == NULL || nLength == 0) return; for (size_t i = 0; i < nLength; i++) { if (pszSrc[i] == '\r' && pszSrc[i + 1] == '\n' && pszSrc[i + 2] == '\r' && pszSrc[i + 3] == '\n') { i++; continue; } *this += pszSrc[i]; } } void Cut(char chDelimiter) { char * p = (char *)psz(); size_t nLength = GetLength(); for (size_t i = 0; i < nLength; i++) { if (p[i] == chDelimiter) { p[i] = '\0'; break; } } } void PartAssign(const char * psz, char chDelimiter) { size_t i = 0; for (; psz[i]; i++) { if (psz[i] == chDelimiter) break; } if (i == 0) return; Assign(psz, i); } /*int Tokenize(const char * psz, size_t nSize, char chDelimiter) { for (size_t i = 0; i < nSize; i++) { if (psz[i] == ' ') { if (i > 0) Assign(psz, i); return (int)(i + 1); } } return -1; }*/ // 2019-11-01 0:02 -> YYYY-MM-DD HH:MM void ConvertDateTime() { if (GetLength() == 15) { HString str(psz(), 11); str += "0"; str += this->SubStr(11, 4); *this = str; } } }; /////////////////////////////////////// class HStringTokenizer : public HObject { public: HStringTokenizer(const HString & str, const char cDelimiter) { Tokenize(str, cDelimiter); } HStringTokenizer(const char * psz, const char cDelimiter) { HString str = psz; Tokenize(str, cDelimiter); } ~HStringTokenizer() { if (m_arr) delete [] m_arr; } inline size_t GetCount() { return m_nCount; } //inline HString & operator [] (int nIndex) inline HString & operator [] (size_t nIndex) { return m_arr[nIndex]; } protected: // |a|b - fail inline void Tokenize(const HString & str, const char cDelimiter) { if (str.IsEmpty()) { m_arr = NULL; m_nCount = 0; return; } m_nCount = std::count(str.begin(), str.end(), cDelimiter) + 1; m_arr = new HString[m_nCount]; std::istringstream stream(str); std::string token; int i = 0; while (std::getline(stream, token, cDelimiter)) { m_arr[i++] = token; } } private: HString * m_arr; size_t m_nCount; }; /////////////////////////////////////// class HUtf16ToUtf8 { public: HUtf16ToUtf8() { #ifndef _WIN32 m_iconv = iconv_open("UTF-8", "UTF-16LE"); #endif m_pUtf8 = NULL; } ~HUtf16ToUtf8() { if (m_pUtf8) free(m_pUtf8); #ifndef _WIN32 iconv_close(m_iconv); #endif } char * Convert(const char * pSrc, int nLen) { if (m_pUtf8) free(m_pUtf8); #ifndef _WIN32 size_t nDstLen = nLen * 2; m_pUtf8 = (char *)calloc(nDstLen + 1, 1); char * pSrc2 = (char *)calloc(nLen + 1, 1); memcpy(pSrc2, pSrc, nLen + 1); char * pUtf16 = pSrc2; char * pDst = m_pUtf8; iconv(m_iconv, &pUtf16, (size_t *)&nLen, &pDst, &nDstLen); free(pSrc2); #else int nDstLen = WideCharToMultiByte(CP_UTF8, 0, (const wchar_t *)pSrc, (int)nLen, NULL, 0, NULL, NULL); if (nDstLen > 0) { m_pUtf8 = (char *)malloc(nDstLen + 1); WideCharToMultiByte(CP_UTF8, 0, (const wchar_t *)pSrc, (int)nLen, m_pUtf8, nDstLen, NULL, NULL); m_pUtf8[nDstLen] = '\0'; } #endif return m_pUtf8; } protected: #ifndef _WIN32 iconv_t m_iconv; #endif char * m_pUtf8; }; class HUtf8ToEucKr { public: HUtf8ToEucKr() { #ifndef _WIN32 m_iconv = iconv_open("EUC-KR", "UTF-8"); #endif m_pEucKr = NULL; } ~HUtf8ToEucKr() { if (m_pEucKr) free(m_pEucKr); #ifndef _WIN32 iconv_close(m_iconv); #endif } char * Convert(const char * pSrc, int nLen) { if (pSrc == NULL || pSrc[0] == '\0' || nLen <= 0) return ""; if (m_pEucKr) free(m_pEucKr); #ifndef _WIN32 size_t nDstLen = nLen * 2; m_pEucKr = (char *)calloc(nDstLen + 1, 1); char * pSrc2 = (char *)calloc(nLen + 1, 1); strcpy(pSrc2, pSrc); char * pUtf8 = pSrc2; char * pDst = m_pEucKr; iconv(m_iconv, &pUtf8, (size_t *)&nLen, &pDst, &nDstLen); free(pSrc2); #else int nLength = MultiByteToWideChar(CP_UTF8, 0, pSrc, nLen + 1, NULL, NULL); BSTR bstrWide = SysAllocStringLen(NULL, nLength); MultiByteToWideChar(CP_UTF8, 0, pSrc, nLen + 1, bstrWide, nLength); nLength = WideCharToMultiByte(CP_ACP, 0, bstrWide, -1, NULL, 0, NULL, NULL); m_pEucKr = (char *)malloc(nLength); WideCharToMultiByte(CP_ACP, 0, bstrWide, -1, m_pEucKr, nLength, NULL, NULL); SysFreeString(bstrWide); #endif return m_pEucKr; } protected: #ifndef _WIN32 iconv_t m_iconv; #endif char * m_pEucKr; }; class HEucKrToUtf8 { public: HEucKrToUtf8() { #ifndef _WIN32 m_iconv = iconv_open("UTF-8", "EUC-KR"); #endif m_pUtf8 = NULL; } ~HEucKrToUtf8() { if (m_pUtf8) free(m_pUtf8); #ifndef _WIN32 iconv_close(m_iconv); #endif } char * Convert(const char * pSrc, int nLen) { if (m_pUtf8) free(m_pUtf8); #ifndef _WIN32 size_t nDstLen = nLen * 4; m_pUtf8 = (char *)calloc(nDstLen + 1, 1); char * pSrc2 = (char *)calloc(nLen + 1, 1); strcpy(pSrc2, pSrc); char * pUtf16 = pSrc2; char * pDst = m_pUtf8; iconv(m_iconv, &pUtf16, (size_t *)&nLen, &pDst, &nDstLen); free(pSrc2); #else int nLength = MultiByteToWideChar(CP_ACP, 0, pSrc, nLen, NULL, NULL); BSTR bstrCode = SysAllocStringLen(NULL, nLength); MultiByteToWideChar(CP_ACP, 0, pSrc, nLen, bstrCode, nLength); int nLength2 = WideCharToMultiByte(CP_UTF8, 0, bstrCode, -1, m_pUtf8, 0, NULL, NULL); m_pUtf8 = (char*)malloc(nLength2 + 1); WideCharToMultiByte(CP_UTF8, 0, bstrCode, -1, m_pUtf8, nLength2, NULL, NULL); SysFreeString(bstrCode); #endif return m_pUtf8; } protected: #ifndef _WIN32 iconv_t m_iconv; #endif char * m_pUtf8; }; /////////////////////////////////////// extern inline void RemoveTagElement(HString * pstrDst, const char * pszSrc, size_t nLength, const char * pszTag) { *pstrDst = ""; if (pszSrc == NULL || nLength == 0) return; HString strFrontTag = "<"; strFrontTag += pszTag; HString strRearTag = ""; bool bSkip = false; for (size_t i = 0; i < nLength; i++, pszSrc++) { if (bSkip) { if (strnicmp(pszSrc, strRearTag, strRearTag.GetLength()) == 0) { bSkip = false; i += strRearTag.GetLength() - 1; pszSrc += strRearTag.GetLength() - 1; } continue; } else if (strnicmp(pszSrc, strFrontTag, strFrontTag.GetLength()) == 0) { bSkip = true; i += strFrontTag.GetLength() - 1; pszSrc += strFrontTag.GetLength() - 1; continue; } *pstrDst += *pszSrc; } } extern inline void RemoveMarkupTag(HString * pstrDst, const char * pszSrc, size_t nLength) { *pstrDst = ""; if (pszSrc == NULL || nLength == 0) return; int nSkipMode = 0; // 0 : no skip, 1 : normal tag, 2 : comment tag for (size_t i = 0; i < nLength; i++) { if (nSkipMode == 1) { if (pszSrc[i] == '>') nSkipMode = 0; continue; } else if (nSkipMode == 2) { if (pszSrc[i] == '-' && pszSrc[i + 1] == '-' && pszSrc[i + 2] == '>') { i += 2; nSkipMode = 0; } continue; } else if (pszSrc[i] == '<') { if (pszSrc[i + 1] == '!' && pszSrc[i + 2] == '-' && pszSrc[i + 3] == '-') { i += 2; nSkipMode = 2; } else nSkipMode = 1; continue; } *pstrDst += pszSrc[i]; } } extern inline size_t ClearSpaceAndRow(HString * pstrDst, const char * pszSrc, size_t nLength, bool bRemoveRow) { size_t nRowCount = 0; *pstrDst = ""; if (pszSrc == NULL || nLength == 0) return nRowCount; char * pNextLine = (char *)pszSrc; char * pOneLine; do { pOneLine = pNextLine; pNextLine = StrSlice(pOneLine); StrTrim(&pOneLine, strlen(pOneLine), true, true); if (pOneLine[0] == '\0') continue; *pstrDst += pOneLine; nRowCount++; if (bRemoveRow == false) *pstrDst += "\r\n"; } while (pNextLine); return nRowCount; } extern inline void StrRemoveRow(HString * pstrDst, const char * pszSrc, const char * pszKeyword) { *pstrDst = ""; if (pszSrc == NULL || pszKeyword == NULL) return; char * pNextLine = (char *)pszSrc; char * pOneLine; do { pOneLine = pNextLine; pNextLine = StrSlice(pOneLine); StrTrim(&pOneLine, strlen(pOneLine), true, true); if (pOneLine[0] == '\0' || stristr(pOneLine, pszKeyword)) continue; *pstrDst += pOneLine; *pstrDst += "\r\n"; } while (pNextLine); } // nMode = 0 : between, 1 : with front, 2 : with rear, 3 : both remove extern inline void StrBetweenRemove(HString * pstrDst, const char * pszSrc, const char * pszFront, const char * pszRear, int nMode) { *pstrDst = ""; if (pszSrc == NULL || pszFront == NULL || pszRear == NULL) return; char * pszStart, * pszEnd; if ((pszStart = (char *)strstr(pszSrc, pszFront)) == NULL) return; size_t nFrontSize = strlen(pszFront); pszStart += nFrontSize; if ((pszEnd = strstr(pszStart, pszRear)) == NULL) return; if (nMode == 1 || nMode == 3) pszStart -= nFrontSize; pstrDst->Assign(pszSrc, pszStart - pszSrc); if (nMode == 2 || nMode == 3) *pstrDst += (pszEnd + strlen(pszRear)); else *pstrDst += pszEnd; } #endif // STRING__H_