/* TCString.cpp - TCString class Copyright (c) 2005-2008 Chervov Dmitry This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "Common.h" #include "CString.h" #define STR_GROWBY 64 #define min(a,b) (((a) < (b)) ? (a) : (b)) template void TString::Empty() { nBufSize = 1; SetAllocSize(STR_GROWBY); pBuf[0] = 0; } template void TString::Free() { // HeapFree(GetProcessHeap(), 0, pBuf); free(pBuf); pBuf = NULL; nBufSize = 0; nAllocSize = 0; } template T *TString::GetBuffer(int nNewLen) { if (nNewLen != -1) { SetBufSize(nNewLen + 1); } _ASSERT(pBuf); return pBuf; } template void TString::ReleaseBuffer(int nNewLen) { if (nNewLen == -1) { nBufSize = My_lstrlen(pBuf) + 1; } else { nBufSize = nNewLen + 1; pBuf[nNewLen] = 0; _ASSERT(My_lstrlen(pBuf) == nNewLen); } _ASSERT(nBufSize <= nAllocSize); // prevent buffer overruns } template void TString::SetAllocSize(int nNewAllocSize) { _ASSERT(nNewAllocSize > 0); T *pNewBuf = /*(char *)HeapAlloc(GetProcessHeap(), 0, sizeof(char) * nNewAllocSize);*/ (T *)malloc(sizeof(T) * nNewAllocSize); if (pBuf) { memcpy(pNewBuf, pBuf, sizeof(T) * min(nBufSize, nNewAllocSize)); //HeapFree(GetProcessHeap(), 0, pBuf); free(pBuf); } pBuf = pNewBuf; nAllocSize = nNewAllocSize; } template void TString::SetBufSize(int nNewBufSize) { _ASSERT(nNewBufSize >= 0); if (nNewBufSize < nBufSize) { _ASSERT(pBuf); pBuf[nNewBufSize - 1] = 0; } if ((unsigned)(nAllocSize - nNewBufSize) / STR_GROWBY) { SetAllocSize((nNewBufSize + STR_GROWBY - 1) - (nNewBufSize + STR_GROWBY - 1) % STR_GROWBY); } nBufSize = nNewBufSize; } template TString& TString::Cat(const T *pStr) { _ASSERT(pBuf && pStr); int StrLen = My_lstrlen(pStr); SetAllocSize(nBufSize + StrLen); My_lstrcpy(GetBuffer() + GetLen(), pStr); ReleaseBuffer(nBufSize + StrLen - 1); return *this; } template TString& TString::Cat(const T c) { _ASSERT(pBuf); SetAllocSize(nBufSize + 1); int CurLen = GetLen(); T *p = GetBuffer(); p[CurLen] = c; p[CurLen + 1] = '\0'; ReleaseBuffer(nBufSize); return *this; } template TString& TString::DiffCat(const T *pStart, const T *pEnd) { _ASSERT(pBuf && pStart && pEnd); int StrLen = pEnd - pStart; SetAllocSize(nBufSize + StrLen); My_strncpy(GetBuffer() + GetLen(), pStart, StrLen); ReleaseBuffer(nBufSize + StrLen - 1); return *this; } template TString& TString::Replace(const T *szFind, const T *szReplaceBy) { if (!pBuf) { return *this; } T *pCurPos = pBuf; int FindLen = My_lstrlen(szFind); T *p; TString Result; Result.GetBuffer(1)[0] = '\0'; Result.ReleaseBuffer(0); // set the string to ""; we can't do it in a usual way (using a constructor or an assignment) because we don't know whether "" needs to be unicode or ansi while (p = ( T* )My_strstr(pCurPos, szFind)) { Result.DiffCat(pCurPos, p); Result += szReplaceBy; pCurPos = p + FindLen; } Result += pCurPos; *this = Result; return *this; } template TString& TString::Replace(int nIndex, int nCount, const T *szReplaceBy) { if (!pBuf || !szReplaceBy || nIndex < 0 || nCount < 0) { return *this; } TString Result; Result.GetBuffer(1)[0] = '\0'; Result.ReleaseBuffer(0); // set the string to ""; we can't do it in a usual way (using a constructor or an assignment) because we don't know whether "" needs to be unicode or ansi if (nIndex > GetLen()) { nIndex = GetLen(); } if (nIndex + nCount > GetLen()) { nCount = GetLen() - nIndex; } Result.DiffCat(pBuf, pBuf + nIndex); Result += szReplaceBy; Result += pBuf + nIndex + nCount; *this = Result; return *this; } template TString TString::Left(int nCount) const { _ASSERT(nCount >= 0); TString Result(*this); Result.SetBufSize(nCount + 1); return Result; } template TString TString::Right(int nCount) const { _ASSERT(nCount >= 0); if (nCount < GetLen()) { return &pBuf[GetLen() - nCount]; } else { return *this; } } template TString TString::SubStr(int nIndex, int nCount) const { _ASSERT(nIndex >= 0 && nCount >= 0); TString Result; if (nIndex < GetLen()) { My_strncpy(Result.GetBuffer(nCount), &pBuf[nIndex], nCount); Result.ReleaseBuffer(); } else { Result.GetBuffer(1)[0] = '\0'; Result.ReleaseBuffer(0); } return Result; } template TString TString::ToLower() const { TString Result(*this); if (!pBuf) { return Result; // return NULL string } My_strlwr((T*)Result); return Result; } template TString& TString::operator = (const T *pStr) { if (pStr) { int StrLen = My_lstrlen(pStr); SetBufSize(StrLen + 1); My_lstrcpy(GetBuffer(), pStr); ReleaseBuffer(StrLen); } else { Free(); } return *this; } /*TCString& TCString::Format(char *pszFormat, ...) { va_list argList; va_start(argList, pszFormat); int StrLen = _vscprintf(pszFormat, argList); // it's stupidity. in some versions of msvcrt.dll there's no _vscprintf function, so there's no any way to determine needed string length. so actually I can't use _vsnprintf too. _vsnprintf(GetBuffer(StrLen), StrLen, pszFormat, argList); ReleaseBuffer(StrLen); va_end(argList); return *this; } */ template class TString; template class TString; template class TString; CString DBGetContactSettingString(HANDLE hContact, const char *szModule, const char *szSetting, const char *szDefaultValue) { DBVARIANT dbv = {0}; DBCONTACTGETSETTING dbcgs; dbcgs.szModule = szModule; dbcgs.pValue = &dbv; dbcgs.szSetting = szSetting; int iRes = CallService(MS_DB_CONTACT_GETSETTING, (WPARAM)hContact, (LPARAM)&dbcgs); CString Result; if (!iRes && dbv.type == DBVT_ASCIIZ) { Result = dbv.pszVal; } else { Result = szDefaultValue; } if (!iRes) { CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv); } return Result; } TCString DBGetContactSettingString(HANDLE hContact, const char *szModule, const char *szSetting, const TCHAR *szDefaultValue) { DBVARIANT dbv = {0}; DBCONTACTGETSETTING dbcgs; dbcgs.szModule = szModule; dbcgs.pValue = &dbv; dbcgs.szSetting = szSetting; dbv.type = DBVT_WCHAR; int iRes = CallService(MS_DB_CONTACT_GETSETTING_STR, (WPARAM)hContact, (LPARAM)&dbcgs); TCString Result; if (!iRes && dbv.type == DBVT_WCHAR) { Result = dbv.ptszVal; } else { Result = szDefaultValue; } if (!iRes) { CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv); } return Result; } int DBGetContactSettingString(HANDLE hContact, const char *szModule, const char *szSetting, DBVARIANT *dbv) { #ifdef _DEBUG return db_get_s(hContact, szModule, szSetting, dbv, DBVT_ASCIIZ); #else return db_get_s(hContact, szModule, szSetting, dbv, DBVT_ASCIIZ); #endif } TCString DBGetContactSettingAsString(HANDLE hContact, const char *szModule, const char *szSetting, const TCHAR *szDefaultValue) { // also converts numeric values to a string DBVARIANT dbv = {0}; DBCONTACTGETSETTING dbcgs; dbcgs.szModule = szModule; dbcgs.pValue = &dbv; dbcgs.szSetting = szSetting; dbv.type = DBVT_WCHAR; int iRes = CallService(MS_DB_CONTACT_GETSETTING_STR, (WPARAM)hContact, (LPARAM)&dbcgs); TCString Result; if (!iRes && (dbv.type == DBVT_ASCIIZ || dbv.type == DBVT_WCHAR)) { Result = dbv.ptszVal; } else if (dbv.type == DBVT_BYTE || dbv.type == DBVT_WORD || dbv.type == DBVT_DWORD) { long value = (dbv.type == DBVT_DWORD) ? dbv.dVal : (dbv.type == DBVT_WORD ? dbv.wVal : dbv.bVal); _ultot(value, Result.GetBuffer(64), 10); Result.ReleaseBuffer(); } else { Result = szDefaultValue; } if (!iRes) { CallService(MS_DB_CONTACT_FREEVARIANT, 0, (LPARAM)&dbv); } return Result; }