#define __INTERNAL__ #include "stdafx.h" #include "malloc.h" #ifdef _DEBUG #undef THIS_FILE static CHAR THIS_FILE[] = __FILE__; #define new DEBUG_NEW #define delete DEBUG_DELETE #endif #ifdef WIN32 #pragma pack(push, 1) #endif // WIN32 struct #ifdef WIN32 __declspec(novtable) #endif // WIN32 SStrDummy { #ifdef USE_STRLOCK WORD m_wRefCount; #endif // USE_STRLOCK CHAR m_sz[1]; }; #ifdef WIN32 #pragma pack(pop) #endif // WIN32 #define NIL_LOCKCOUNT 0x8000 #ifdef WIN32 #pragma data_seg(".SHARED_DATA") #endif // WIN32 // all data in this section must be INITIALIZED!!!!!!!!!!!!! static SStrDummy l_sz = { #ifdef USE_STRLOCK NIL_LOCKCOUNT, // WORD m_wRefCount; #endif // USE_STRLOCK { 0, }, // CHAR m_sz; }; #ifdef WIN32 #pragma data_seg() #pragma comment(linker, "/section:.SHARED_DATA,RWS") #endif // WIN32 #ifdef _DEBUG void CStrTestMain(); class s_CAutoRun { public: s_CAutoRun() { CStrTestMain(); } } s_a; #endif // _DEBUG #define l_SZ (&l_sz.m_sz[0]) #ifdef USE_STRLOCK #define STR_LOCKCOUNT STR_LOCKCOUNT2(m_psz) #define STR_LOCKCOUNT2(psz) ((WORD*)psz)[-1] static inline CHAR* str_alloc(int nMax) { CHAR* psz = (CHAR*)malloc(sizeof(WORD) + sizeof(CHAR) * nMax); *(WORD*)psz = 0; CHAR* p = (CHAR*)&((BYTE*)psz)[sizeof(WORD)]; p[0] = '\0'; return p; } static inline CHAR* str_realloc(CHAR* psz, int nMax) { return (CHAR*)&((BYTE*)realloc(&STR_LOCKCOUNT2(psz), sizeof(WORD) + sizeof(CHAR) * nMax))[sizeof(WORD)]; } static inline void str_free(CHAR* psz) { free(&STR_LOCKCOUNT2(psz)); } #else // !USE_STRLOCK #define STR_LOCKCOUNT ASSERT(FALSE) #define STR_LOCKCOUNT2(psz) ASSERT(FALSE) //#define str_alloc(nMax) ((CHAR*)malloc(sizeof(CHAR)*nMax)) static inline CHAR* str_alloc(int nMax) { CHAR* p = (CHAR*)malloc(sizeof(CHAR) * nMax); p[0] = '\0'; return p; } #define str_realloc(psz, nMax) ((CHAR*)realloc(psz,sizeof(CHAR)*nMax)) #define str_free(psz) (free(psz)) #endif // USE_STRLOCK #ifdef USE_STRLOCK #define IS_NIL(psz) (((const WORD*)psz)[-1] == NIL_LOCKCOUNT) // check m_wRefCount #else // !USE_STRLOCK #define IS_NIL(psz) ((psz) == l_SZ) // check pointer... #endif // USE_STRLOCK static BOOL LSTRS_IsValid(int c, const char* pcszVals); static BOOL LSTRS_IsValid(int c, const char* pcszVals) { if (pcszVals) { if (strchr(pcszVals, c)) { return TRUE; } } else { if ((' ' < c) && (c != 0x7f) && (c != 0xff)) { return TRUE; } } return FALSE; } int __cdecl str_memcmp(const void* elem1, const void* elem2) { const char* s1 = ((const CStr*)elem1)->String(); const char* s2 = ((const CStr*)elem2)->String(); int n1 = strlen(s1); int n2 = strlen(s2); if (n1 > n2) { n2 = n1; } return memcmp(s1, s2, n2); } #if !defined(WIN32) char* _strupr(char *string) { char c, *p = string; while((c = *p) != '\0') { if (('a' <= c) && (c <= 'z')) { c -= ('a' - 'A'); *p = c; } p++; } return string; } char* _strlwr(char *string) { char c, *p = string; while((c = *p) != '\0') { if (('A' <= c) && (c <= 'Z')) { c += ('a' - 'A'); *p = c; } p++; } return string; } #endif // !defined(WIN32) int __cdecl str_Compare(const void* elem1, const void* elem2) { return lstrcmp(((const CStr*)elem1)->String(), ((const CStr*)elem2)->String()); } int __cdecl str_CompareReverse(const void* elem1, const void* elem2) { return -lstrcmp(((const CStr*)elem1)->String(), ((const CStr*)elem2)->String()); } int __cdecl str_CompareIC(const void* elem1, const void* elem2) { return lstrcmpi(((const CStr*)elem1)->String(), ((const CStr*)elem2)->String()); } int __cdecl str_CompareICReverse(const void* elem1, const void* elem2) { return -lstrcmpi(((const CStr*)elem1)->String(), ((const CStr*)elem2)->String()); } CStr::CStr() { m_psz = l_SZ; } CStr::CStr(const CHAR* pcsz) { #ifdef _DEBUG m_psz = (CHAR*)l_SZ; #endif // _DEBUG AssignNoCheck(pcsz); } CStr::CStr(const CHAR* pcsz, int nLen) { #ifdef _DEBUG m_psz = (CHAR*)l_SZ; #endif // _DEBUG AssignNoCheck(pcsz, nLen); } CStr::CStr(CHAR c, int nLen) { ASSERT((c != '\0') && (nLen >= 0)); if ((c != '\0') && (nLen > 0)) { CHAR* psz = str_alloc(nLen + 1); memset(psz, c, nLen); psz[nLen] = '\0'; m_psz = psz; } else { m_psz = l_SZ; } } CStr::CStr(const CStr& that) { #ifdef _DEBUG m_psz = l_SZ; #endif // _DEBUG AssignNoCheck(that.m_psz); } CStr::CStr(int nMax) { ASSERT(nMax > 0); m_psz = str_alloc(nMax); } CStr::~CStr() { #ifdef USE_STRLOCK #ifdef _DEBUG if (!IS_NIL(m_psz) && (STR_LOCKCOUNT != 0)) { TRACE("CStr::~CStr() called for CStr Locked: %d times\n", (int)STR_LOCKCOUNT); } #endif // _DEBUG #endif // USE_STRLOCK if (!IS_NIL(m_psz)) { str_free(m_psz); } #ifdef _DEBUG m_psz = NULL; #endif } const CHAR* CStr::Empty() { if (!IS_NIL(m_psz)) { #ifdef USE_STRLOCK if (STR_LOCKCOUNT) { m_psz[0] = '\0'; return m_psz; } #endif // USE_STRLOCK str_free(m_psz); m_psz = l_SZ; } return l_SZ; } void CStr::Swap(CStr& that) { #ifdef _DEBUG #ifdef USE_STRLOCK if (IsLocked() || that.IsLocked()) TRACE("CStr::Swap() called for Locked CStr(s)\n"); #endif // USE_STRLOCK #endif // _DEBUG CHAR* psz = m_psz; m_psz = that.m_psz; that.m_psz = psz; } #ifdef USE_STRLOCK WORD CStr::IsLocked() const { ASSERT_VALIDSTRING(m_psz); if (!IS_NIL(m_psz)) return STR_LOCKCOUNT; return 0; } CHAR* CStr::LockBuffer() { ASSERT_VALIDSTRING(m_psz); if (!IS_NIL(m_psz)) { ++STR_LOCKCOUNT; } else { TRACE("Trying To Lock Empty String...\n"); } return m_psz; } WORD CStr::UnlockBuffer() { ASSERT_VALIDSTRING(m_psz); if (!IS_NIL(m_psz)) { ASSERT(STR_LOCKCOUNT != 0); WORD wRefCount = --STR_LOCKCOUNT; if (wRefCount == 0) { if (m_psz[0] == '\0') { Reset(); } } return wRefCount; } else { TRACE("Trying To Unlock Empty String...\n"); return 0; } } #endif // USE_STRLOCK const CHAR* CStr::Assign(const CHAR* pcsz, int nLen/* = -1*/) { ASSERT(this); ASSERT_VALIDSTRING(m_psz); #ifdef USE_STRLOCK if (IsLocked()) { if (nLen < 0) { if (!pcsz || ((nLen = strlen(pcsz)) <= 0)) { return ResetLocked(); } nLen++; memcpy(m_psz, pcsz, nLen); } else { if (nLen <= 0) { return ResetLocked(); } ASSERT(pcsz); ASSERT((UINT)nLen <= strlen(pcsz)); memcpy(m_psz, pcsz, nLen); m_psz[nLen] = '\0'; } } else { #endif // USE_STRLOCK if (IS_NIL(m_psz)) { return AssignNoCheck(pcsz, nLen); } if (nLen < 0) { if (!pcsz || ((nLen = strlen(pcsz)) <= 0)) { return Reset(); } nLen++; memcpy(m_psz = str_realloc(m_psz, nLen), pcsz, nLen); } else { if (nLen <= 0) { return Reset(); } ASSERT(pcsz); ASSERT((UINT)nLen <= strlen(pcsz)); int nAlloc = nLen + 1; memcpy(m_psz = str_realloc(m_psz, nAlloc), pcsz, nLen); m_psz[nLen] = '\0'; } #ifdef USE_STRLOCK } #endif // USE_STRLOCK return m_psz; } CStr CStr::operator + (const CHAR* pcsz) const { int nLen; if (pcsz && ((nLen = strlen(pcsz)) > 0)) { CHAR* psz = m_psz; if (psz[0] == '\0') { return CStr(pcsz, nLen); } else { int n = strlen(psz); CStr str(n + ++nLen); CHAR* p = str.m_psz; memcpy(p, psz, n); memcpy(&p[n], pcsz, nLen); return str; } } return *this; } CStr& CStr::operator += (const CHAR* pcsz) { int nLen; #ifdef USE_STRLOCK if (IsLocked()) { if (pcsz && ((nLen = strlen(pcsz)) > 0)) { CHAR* psz = m_psz; memcpy(&psz[strlen(psz)], pcsz, nLen + 1); } } else { #endif // USE_STRLOCK if (pcsz && ((nLen = strlen(pcsz)) > 0)) { CHAR* psz = m_psz; if (IS_NIL(psz)) { AssignNoCheck(pcsz, nLen); } else { nLen++; int n = strlen(psz); psz = str_realloc(psz, n + nLen); memcpy(&psz[n], pcsz, nLen); m_psz = psz; } } #ifdef USE_STRLOCK } #endif // USE_STRLOCK return *this; } CStr CStr::operator + (CHAR c) const { CHAR ca[2]; ca[0] = c; ca[1] = '\0'; return *this + ca; } CStr& CStr::operator += (CHAR c) { CHAR ca[2]; ca[0] = c; ca[1] = '\0'; return *this += ca; } void CStr::MakeReverse() { int nLen = strlen(m_psz); if (nLen >= 2) { CHAR* pszStart = m_psz; CHAR* pszEnd = &pszStart[nLen - 1]; nLen /= 2; while(nLen-- > 0) { CHAR c; c = *pszStart; *pszStart = *pszEnd; *pszEnd = c; pszStart++; pszEnd--; } } } const CHAR* CStr::Prune(const CHAR* pcszDELs/* = NULL*/) { if (!pcszDELs) { pcszDELs = "\t "; } ASSERT_VALIDSTRING(pcszDELs); ASSERT(pcszDELs[0]); CHAR* pszHead = m_psz; CHAR c; while((c = *pszHead) != '\0') { if (strchr(pcszDELs, c)) { CHAR* pszStart = pszHead; while((c = *++pszHead) != '\0') { if (!strchr(pcszDELs, c)) { strcpy(pszStart, pszHead); goto no_DELs; } } ASSERT(c == '\0'); pszStart[0] = '\0'; break; } else { no_DELs: pszHead++; } } ReleaseBuffer(); return m_psz; } const CHAR* CStr::TrimLeft() { CHAR* pszHead = m_psz; CHAR c; while((c = *pszHead) != '\0') { if ((c != ' ') && (c != '\t')) { if (m_psz != pszHead) strcpy(m_psz, pszHead); return m_psz; } pszHead++; } return Empty(); } const CHAR* CStr::TrimRight() { CHAR* pszHead = m_psz; CHAR c; CHAR* pszTail = &pszHead[strlen(pszHead)]; while(pszTail != pszHead) { c = *--pszTail; if ((c != ' ') && (c != '\t')) { pszTail[1] = '\0'; return m_psz; } } return Empty(); } const CHAR* CStr::TrimAll() { TrimLeft(); return TrimRight(); } void __cdecl CStr::Format(LPCTSTR lpszFormat, ...) { va_list marker; va_start(marker, lpszFormat); vFormat(lpszFormat, marker); va_end(marker); } void CStr::vFormat(LPCTSTR lpszFormat, va_list marker) { CHAR szBuf[512]; #ifdef _DEBUG int n = vsprintf(szBuf, lpszFormat, marker); ASSERT((0 <= n) && (n + 1 <= NOFA(szBuf))); #else // !_DEBUG vsprintf(szBuf, lpszFormat, marker); #endif // _DEBUG Assign(szBuf); } CHAR* CStr::GetBuffer(int nLen) { ASSERT(nLen >= 0); ASSERT_VALIDSTRING(m_psz); CHAR* psz = m_psz; #ifdef USE_STRLOCK if (!IsLocked()) { #endif // USE_STRLOCK int n = strlen(psz); if ((n -= nLen) < 0) { nLen++; psz = (IS_NIL(psz)) ? str_alloc(nLen): str_realloc(psz, nLen); m_psz = psz; } #ifdef USE_STRLOCK } #endif // USE_STRLOCK return psz; } const CHAR* CStr::ReleaseBuffer(int nLen/* = -1*/) { ASSERT_VALIDSTRING(m_psz); CHAR* psz = m_psz; #ifdef USE_STRLOCK if (IsLocked()) { if (nLen >= 0) { psz[nLen] = '\0'; } return psz; } else { #endif // USE_STRLOCK if (nLen >= 0) { #ifdef _DEBUG if (psz[nLen] != '\0') // when _DEBUG, (pcsz == const l_SZ) is possible #endif // _DEBUG psz[nLen] = '\0'; } else { nLen = strlen(psz); } if (nLen == 0) { return Reset(); } else { return m_psz = str_realloc(psz, nLen + 1); } #ifdef USE_STRLOCK } #endif // USE_STRLOCK } CHAR* CStr::GetBufferSetLength(int nLen) { ASSERT(nLen >= 0); #ifdef _DEBUG CHAR* p1 = GetBuffer(nLen); if (!IS_NIL(p1)) // when _DEBUG, (pcsz == const l_SZ) is possible m_psz[nLen] = '\0'; #else // !_DEBUG GetBuffer(nLen); #endif // _DEBUG return m_psz; } void CStr::ChangeChars(CHAR cBefore, CHAR cAfter) { ASSERT(cBefore && cAfter); CHAR* psz = m_psz; CHAR c; while((c = *psz) != '\0') { if (c == cBefore) { *psz = cAfter; } psz++; } } BOOL CStr::AsDirectory(BOOL bRemoveLastDEL/* = FALSE*/) { int nPos = rFindSet("/\\"); if (nPos != -1) { if (!bRemoveLastDEL) nPos++; ReleaseBuffer(nPos); return TRUE; } return FALSE; } BOOL CStr::AddDirDEL() { int nLen = GetLength(); if (nLen > 0) { CHAR c = m_psz[nLen - 1]; if ((c != '\\') && (c != '/')) { #ifdef _WINDOWS *this += '\\'; #else // !_WINDOWS *this += '/'; #endif // _WINDOWS return TRUE; } } return FALSE; } int CStr::FindExtPos() const { int nPos = rFind('.'); if (nPos != -1) { const CHAR* pcsz = &m_psz[nPos + 1]; if (strchr(pcsz, '\\') || strchr(pcsz, '/')) { return -1; } } return nPos; } const char* CStr::FindExt() const { int nPos = FindExtPos(); if (nPos != -1) { return &m_psz[nPos]; } return NULL; } BOOL CStr::ChangeExt(const char* pcszExt, BOOL bForce/* = TRUE*/) { ASSERT_VALIDSTRING(pcszExt); int nPos = FindExtPos(); if (nPos != -1) { if (bForce && strcmp(&m_psz[nPos], pcszExt)) { int nLen = nPos + strlen(pcszExt); CHAR* psz = GetBuffer(nLen); strcpy(&psz[nPos], pcszExt); return TRUE; } } else { if (*pcszExt) { *this += pcszExt; return TRUE; } } return FALSE; } const CHAR* CStr::Left(CStr& strLeft, int nCount) const { ASSERT(&strLeft); ASSERT(nCount >= 0); ASSERT_VALIDSTRING(strLeft); ASSERT_VALIDSTRING(m_psz); CHAR* psz = m_psz; int n = strlen(psz); if ((n -= nCount) < 0) { nCount += n; return strLeft.Assign(psz, nCount); } else { CHAR* p = strLeft.GetBuffer(nCount); memcpy(p, psz, nCount); return strLeft.ReleaseBuffer(nCount); } } const CHAR* CStr::Right(CStr& strRight, int nCount) const { ASSERT(&strRight); ASSERT(nCount >= 0); ASSERT_VALIDSTRING(strRight); ASSERT_VALIDSTRING(m_psz); CHAR* psz = m_psz; int n = strlen(psz); if ((n -= nCount) < 0) { nCount += n; } else { psz += n; } return strRight.Assign(psz, nCount); } const CHAR* CStr::Mid(CStr& strMid, int nFirst) const { ASSERT(&strMid); ASSERT(nFirst >= 0); ASSERT_VALIDSTRING(strMid); ASSERT_VALIDSTRING(m_psz); CHAR* psz = m_psz; int n = strlen(psz); if (nFirst > 0) { if ((n -= nFirst) <= 0) { strMid.Empty(); return l_SZ; } psz += nFirst; } return strMid.Assign(psz, n); } const CHAR* CStr::Mid(CStr& strMid, int nFirst, int nCount) const { ASSERT(&strMid); ASSERT(nFirst >= 0); ASSERT(nCount >= 0); ASSERT_VALIDSTRING(strMid); ASSERT_VALIDSTRING(m_psz); if (nCount <= 0) { return strMid.Empty(); } CHAR* psz = m_psz; int n = strlen(psz); if (nFirst > 0) { if ((n -= nFirst) <= 0) { return strMid.Empty(); } psz += nFirst; } if ((n -= nCount) <= 0) { nCount += n; return strMid.Assign(psz, nCount); } else { CHAR* p = strMid.GetBuffer(nCount); memcpy(p, psz, nCount); return strMid.ReleaseBuffer(nCount); } } CStr CStr::Left(int nCount) const { CStr str; Left(str, nCount); return str; } CStr CStr::Right(int nCount) const { CStr str; Right(str, nCount); return str; } CStr CStr::Mid(int nFirst) const { CStr str; Mid(str, nFirst); return str; } CStr CStr::Mid(int nFirst, int nCount) const { CStr str; Mid(str, nFirst, nCount); return str; } int CStr::FindNext(CHAR c, int nStart) const { ASSERT(c != '\0'); const CHAR* pcsz = m_psz; if (nStart < 0) nStart = 0; else { ASSERT(strlen(pcsz) >= nStart); pcsz = &pcsz[nStart]; if (*pcsz == '\0') return -1; pcsz++; nStart++; } const char* pcsz2 = strchr(pcsz, c); if (pcsz2) { return nStart + (pcsz2 - pcsz); } return -1; } int CStr::Find(CHAR c) const { ASSERT(c != '\0'); const CHAR* pcsz = strchr(m_psz, c); if (pcsz) { return pcsz - m_psz; } return -1; } int CStr::rFindNext(CHAR c, int nStart) const { ASSERT(c != '\0'); const CHAR* pcsz = m_psz; const CHAR* pcsz2 = pcsz; if (nStart < 0) { nStart = strlen(pcsz2); } else { ASSERT(strlen(pcsz2) >= nStart); } pcsz2 = &pcsz2[nStart]; while(--pcsz2 >= pcsz) { nStart--; if (*pcsz2 == c) { return nStart; } } return -1; } int CStr::rFind(CHAR c) const { ASSERT(c != '\0'); const CHAR* pcsz = strrchr(m_psz, c); if (pcsz) { return pcsz - m_psz; } return -1; } int CStr::Find(const CHAR* pcsz, int nStart) const { ASSERT_VALIDSTRING(pcsz); if (nStart < 0) nStart = 0; const CHAR* pcsz2 = m_psz; while(nStart > 0) { if (*pcsz2++ == '\0') return -1; nStart--; } pcsz = strstr(pcsz2, pcsz); if (pcsz) { return pcsz - m_psz; } return -1; } int CStr::Find(const CHAR* pcsz) const { ASSERT_VALIDSTRING(pcsz); pcsz = strstr(m_psz, pcsz); if (pcsz) { return pcsz - m_psz; } return -1; } int CStr::FindSet(const CHAR* pcszSet) const { ASSERT_VALIDSTRING(pcszSet); CHAR* psz = m_psz; CHAR c; while((c = *psz) != '\0') { if (strchr(pcszSet, c)) { return psz - m_psz; } psz++; } return -1; } int CStr::rFindSet(const CHAR* pcszSet) const { ASSERT_VALIDSTRING(pcszSet); CHAR* pszStart = m_psz; CHAR* psz = &pszStart[strlen(pszStart)]; while(psz-- > pszStart) { if (strchr(pcszSet, *psz)) { return psz - m_psz; } } return -1; } #if defined(WIN32) BOOL CStr::GetWindowText(HWND hWnd) { Empty(); if (IsWindow(hWnd)) { int nSize = SendMessage(hWnd, WM_GETTEXTLENGTH, 0, 0); if (nSize > 0) { nSize += 10; // for safety... char* p = GetBuffer(nSize + 1/*'\0'*/); SendMessage(hWnd, WM_GETTEXT, (WPARAM)nSize, (LPARAM)p); } return TRUE; } return FALSE; } #endif // defined(WIN32) const CHAR* CStr::AssignNoCheck(const CHAR* pcsz, int nLen/* = -1*/) { ASSERT(IS_NIL(m_psz)); // when !_DEBUG then m_psz is !initialized... CHAR* psz; if (nLen < 0) { if (!pcsz || ((nLen = strlen(pcsz)) <= 0)) { return m_psz = l_SZ; } nLen++; psz = str_alloc(nLen); memcpy(psz, pcsz, nLen); } else { if (nLen <= 0) { return m_psz = l_SZ; } ASSERT(pcsz); ASSERT((UINT)nLen <= strlen(pcsz)); int nAlloc = nLen + 1; psz = str_alloc(nAlloc); memcpy(psz, pcsz, nLen); psz[nLen] = '\0'; } return m_psz = psz; } CHAR* CStr::Reset() { #ifdef USE_STRLOCK ASSERT(!IsLocked()); #endif // USE_STRLOCK if (!IS_NIL(m_psz)) { str_free(m_psz); m_psz = l_SZ; } return l_SZ; } #ifdef USE_STRLOCK CHAR* CStr::ResetLocked() { ASSERT(IsLocked()); ASSERT(!IS_NIL(m_psz)); m_psz[0] = '\0'; return m_psz; } #endif // USE_STRLOCK #ifdef USE_CSTR_ISTREAM istream& operator >> (istream& s, CStr& str) { str.Empty(); int c; while((c = s.get()) != EOF) { if (!isspace(c)) { do { str += (char)c; if ((c = s.get()) == EOF) break; } while(!isspace(c)); break; } } return s; } #endif // USE_CSTR_ISTREAM int CStrArray::GetTotalLength() const { int nTotalLength; int i, nSize = GetSize(); nTotalLength = nSize; // nSize°³ÀÇ '\0' for(i = 0; i < nSize; i++) { nTotalLength += strlen(GetAt(i)); } return nTotalLength; } int CStrArray::Find(const char* pcsz) const { ASSERT(pcsz); int i, nSize = GetSize(); for(i = 0; i < nSize; i++) { if (strcmp(GetAt(i), pcsz) == 0) return i; } return -1; } int CStrArray::AddIfNotFound(const char* pcsz) { int nFound = Find(pcsz); if (nFound == -1) { Add() = pcsz; } return nFound; } int CStrArray::AddIfNotFound(const CStr astrs[], int nCount) { int nAdded = 0; for(int i = 0; i < nCount; i++) { if (AddIfNotFound(astrs[i]) == -1) nAdded++; } return nAdded; } void CStrArray::Sort(QSortCompareProc pQSortCompareProc/* = (QSortCompareProc)NULL*/) { int nSize = GetSize(); if (nSize > 0) { if (!pQSortCompareProc) pQSortCompareProc = str_Compare; qsort(&GetAt(0), nSize, sizeof(CStr), pQSortCompareProc); } } BOOL CStrArray::LoadStrs(const char* pcszFile, const char* pcszVals/* = NULL*/, UINT uFlags/* = 0*/) { BOOL bRet = FALSE; FILE* pFile = fopen(pcszFile, "rt"); if (pFile) { bRet = LoadStrs(pFile, pcszVals, uFlags); fclose(pFile); } return bRet; } BOOL CStrArray::LoadStrs(FILE* pFile, const char* pcszVals/* = NULL*/, UINT uFlags/* = 0*/) { if (pFile) { int c; CStr str; while((c = getc(pFile)) != EOF) { if (LSTRS_IsValid(c, pcszVals)) { str += (char)c; } else { LSTRS_CheckAdd(str, uFlags); } } LSTRS_CheckAdd(str, uFlags); if (uFlags & LSTRS_DOSORT) Sort(); return TRUE; } return FALSE; } void CStrArray::LSTRS_CheckAdd(CStr& str, UINT uFlags) { if (!str.IsEmpty()) { UINT uFlagsCase = uFlags & (LSTRS_TOLOWER | LSTRS_TOUPPER); if (uFlagsCase) { if (uFlagsCase & LSTRS_TOLOWER) { str.MakeLower(); if (uFlagsCase & LSTRS_TOUPPER) { str.SetAt(0, (CHAR)toupper(str.GetAt(0))); } } else { // LSTRS_TOUPPER str.MakeUpper(); } } if (uFlags & LSTRS_ALLOWDUP) Add() = str; else AddIfNotFound(str); str.Empty(); } } #ifdef _DEBUG BOOL IsValidString(const CHAR* pcszStr, int nLen/* = -1*/) { // nLen: maximum size of string return pcszStr && !::IsBadStringPtr(pcszStr, (UINT)nLen); } BOOL IsValidStringSafe(const CHAR* pcszStr, int nLen/* = -1*/) { // nLen: maximum size of string return !pcszStr || !::IsBadStringPtr(pcszStr, (UINT)nLen); } BOOL IsValidMemory(const void* pMem, UINT uBytes, BOOL bWriteCheck/* = TRUE*/) { return pMem && !(::IsBadReadPtr(pMem, uBytes) || (bWriteCheck && ::IsBadWritePtr((void*)pMem, uBytes))); } BOOL IsValidMemorySafe(const void* pMem, UINT uBytes, BOOL bWriteCheck/* = TRUE*/) { return !pMem || !(::IsBadReadPtr(pMem, uBytes) || (bWriteCheck && ::IsBadWritePtr((void*)pMem, uBytes))); } #endif // _DEBUG #ifdef _DEBUG void CStrTestMain() { const CHAR* g_pcsza[] = { (const CHAR*)NULL, "", "a", "abc ", " 123456789", " abCABD ", }; int i, nStrs = NOFA(g_pcsza); CStr k; TARRAYREF(CStr) aStrs; aStrs.Add(nStrs); for(i = 0; i < nStrs; i++) { BOOL bLocked = FALSE; if (rand() % 2) { aStrs.GetAt(i).GetBuffer(256); aStrs.GetAt(i).LockBuffer(); bLocked = TRUE; } CStr a(g_pcsza[i]); CStr b(a, a.GetLength()); CStr c((CHAR)(rand() % 254 + 1), rand() % 3); a += b; a += c; b = a; c = a; a += (const CHAR*)NULL; b += ""; c += "sl123KDFklsd "; a = c; b = c; a.MakeLower(); b.MakeUpper(); c.MakeReverse(); a += b; c = a + b; a.TrimLeft(); a.TrimRight(); b.TrimLeft(); b.TrimRight(); c.TrimLeft(); c.TrimRight(); aStrs[i] = c; a.Left(k, 1000); a.Right(k, 1000); a.Mid(k, 1); a.Mid(k, 100); a.Mid(k, 1, a.GetLength() / 2); b.Left(k, 1000); b.Right(k, 1000); b.Mid(k, 1); b.Mid(k, 100); b.Mid(k, 1, a.GetLength() / 2); c.Left(k, 1000); c.Right(k, 1000); c.Mid(k, 1); c.Mid(k, 100); c.Mid(k, 1, a.GetLength() / 2); if (bLocked) aStrs.GetAt(i).UnlockBuffer(); } } #endif // _DEBUG