#ifndef __COMUTILHPP__ #define __COMUTILHPP__ #pragma once #include #include #include #include #include #include template inline type clamp (const type& min,const type& x,const type& max) { if (x < min) return min; if (x>max) return max; return x; } #if 0 template type max(const type& a,const type& b) { return (((a) > (b)) ? (a) : (b)); } template type min(const type& a,const type& b) { return (((a) < (b)) ? (a) : (b)); } #endif inline bool IsAlNum(BYTE bChar) { #pragma warning (disable:4800) WORD wResult; BOOL bRc; bRc = GetStringTypeEx(LOCALE_SYSTEM_DEFAULT, CT_CTYPE1, (LPCTSTR)&bChar, 1, &wResult); assert(bRc); return (bool)(wResult & (C1_ALPHA | C1_DIGIT)); } inline bool IsSpace(BYTE bChar) { #pragma warning (disable:4800) WORD wResult; BOOL bRc; bRc = GetStringTypeEx(LOCALE_SYSTEM_DEFAULT, CT_CTYPE1, (LPCTSTR)&bChar, 1, &wResult); assert(bRc); return (bool)(wResult & (C1_SPACE)); } inline bool IsSpace(WORD bChar) { #pragma warning (disable:4800) WORD wResult; BOOL bRc; bRc = GetStringTypeEx(LOCALE_SYSTEM_DEFAULT, CT_CTYPE1, (LPCTSTR)&bChar, 2, &wResult); assert(bRc); return (bool)(wResult & (C1_SPACE)); } #define _countof(array) (sizeof(array)/sizeof(array[0])) #ifdef OLE2ANSI typedef LPSTR BSTR; #else typedef LPWSTR BSTR;// must (semantically) match typedef in oleauto.h #endif struct CCom_StringData { long nRefs; // reference count int nDataLength; int nAllocLength; // TCHAR data[nAllocLength] TCHAR* data() { return (TCHAR*)(this+1); } }; bool comline_AfxIsValidString(LPCWSTR lpsz, int nLength = -1); bool comline_AfxIsValidString(LPCSTR lpsz, int nLength = -1); bool comline_AfxIsValidAddress(const void* lp,UINT nBytes, bool bReadWrite = true); int comline_AfxLoadString(UINT nID, LPTSTR lpszBuf, UINT nMaxBuf,HINSTANCE inst); class CCom_String { public: // Constructors CCom_String(); CCom_String(const CCom_String& stringSrc); CCom_String(TCHAR ch, int nRepeat = 1); CCom_String(LPCTSTR lpsz); CCom_String(LPCWSTR lpsz); CCom_String(LPCTSTR lpch, int nLength); CCom_String(const unsigned char* psz); // Attributes & Operations // as an array of characters int GetLength() const; bool IsEmpty() const; void Empty(); // free up the data TCHAR GetAt(int nIndex) const; // 0 based TCHAR operator[](int nIndex) const; // same as GetAt void SetAt(int nIndex, TCHAR ch); operator LPCTSTR() const; // as a C string // overloaded assignment const CCom_String& operator=(const CCom_String& stringSrc); const CCom_String& operator=(TCHAR ch); #ifdef _UNICODE const CCom_String& operator=(char ch); #endif const CCom_String& operator=(LPCSTR lpsz); const CCom_String& operator=(LPCWSTR lpsz); const CCom_String& operator=(const unsigned char* psz); // string concatenation const CCom_String& operator+=(const CCom_String& string); const CCom_String& operator+=(TCHAR ch); #ifdef _UNICODE const CCom_String& operator+=(char ch); #endif const CCom_String& operator+=(LPCTSTR lpsz); friend CCom_String operator+(const CCom_String& string1, const CCom_String& string2); friend CCom_String operator+(const CCom_String& string, TCHAR ch); friend CCom_String operator+(TCHAR ch, const CCom_String& string); #ifdef _UNICODE friend CCom_String operator+(const CCom_String& string, char ch); friend CCom_String operator+(char ch, const CCom_String& string); #endif friend CCom_String operator+(const CCom_String& string, LPCTSTR lpsz); friend CCom_String operator+(LPCTSTR lpsz, const CCom_String& string); // string comparison int Compare(LPCTSTR lpsz) const; // straight character int CompareNoCase(LPCTSTR lpsz) const; // ignore case int Collate(LPCTSTR lpsz) const; // NLS aware // simple sub-string extraction CCom_String Mid(int nFirst, int nCount) const; CCom_String Mid(int nFirst) const; CCom_String Left(int nCount) const; CCom_String Right(int nCount) const; CCom_String SpanIncluding(LPCTSTR lpszCharSet) const; CCom_String SpanExcluding(LPCTSTR lpszCharSet) const; // upper/lower/reverse conversion void MakeUpper(); void MakeLower(); void MakeReverse(); // trimming whitespace (either side) void TrimRight(); void TrimLeft(); // searching (return starting index, or -1 if not found) // look for a single character match int Find(TCHAR ch) const; // like "C" strchr int ReverseFind(TCHAR ch) const; int FindOneOf(LPCTSTR lpszCharSet) const; // advanced manipulation int Replace(TCHAR chOld, TCHAR chNew); int Replace(LPCTSTR lpszOld, LPCTSTR lpszNew); int Remove(TCHAR chRemove); int Insert(int nIndex, TCHAR ch); int Insert(int nIndex, LPCTSTR pstr); int Delete(int nIndex, int nCount = 1); // look for a specific sub-string int Find(LPCTSTR lpszSub) const; // like "C" strstr // simple formatting void _cdecl Format(LPCTSTR lpszFormat, ...); void _cdecl Format(UINT nFormatID,HINSTANCE inst, ...); void _cdecl FormatHex (char *mem,int count); void FormatV(LPCTSTR lpszFormat, va_list argList); #ifndef _MAC // formatting for localization (uses FormatMessage API) void _cdecl FormatMessage(LPCTSTR lpszFormat, ...); void _cdecl FormatMessage(UINT nFormatID,HINSTANCE inst, ...); #endif // Windows support bool LoadString(UINT nID,HINSTANCE inst=NULL); // load from string resource // 255 chars max #ifndef _UNICODE // ANSI <-> OEM support (convert string in place) void AnsiToOem(); void OemToAnsi(); #endif #ifndef _AFX_NO_BSTR_SUPPORT // OLE BSTR support (use for OLE automation) BSTR AllocSysString() const; BSTR SetSysString(BSTR* pbstr) const; #endif // Access to string implementation buffer as "C" character array LPTSTR GetBuffer(int nMinBufLength); void ReleaseBuffer(int nNewLength = -1); LPTSTR GetBufferSetLength(int nNewLength); void FreeExtra(); // Use LockBuffer/UnlockBuffer to turn refcounting off LPTSTR LockBuffer(); void UnlockBuffer(); // Implementation public: ~CCom_String(); int GetAllocLength() const; protected: LPTSTR m_pchData; // pointer to ref counted string data // implementation helpers CCom_StringData* GetData() const; void Init(); void AllocCopy(CCom_String& dest, int nCopyLen, int nCopyIndex, int nExtraLen) const; void AllocBuffer(int nLen); void AssignCopy(int nSrcLen, LPCTSTR lpszSrcData); void ConcatCopy(int nSrc1Len, LPCTSTR lpszSrc1Data, int nSrc2Len, LPCTSTR lpszSrc2Data); void ConcatInPlace(int nSrcLen, LPCTSTR lpszSrcData); void CopyBeforeWrite(); void AllocBeforeWrite(int nLen); void Release(); static void PASCAL Release(CCom_StringData* pData); static int PASCAL SafeStrlen(LPCTSTR lpsz); }; // Compare helpers bool operator==(const CCom_String& s1, const CCom_String& s2); bool operator==(const CCom_String& s1, LPCTSTR s2); bool operator==(LPCTSTR s1, const CCom_String& s2); bool operator!=(const CCom_String& s1, const CCom_String& s2); bool operator!=(const CCom_String& s1, LPCTSTR s2); bool operator!=(LPCTSTR s1, const CCom_String& s2); bool operator<(const CCom_String& s1, const CCom_String& s2); bool operator<(const CCom_String& s1, LPCTSTR s2); bool operator<(LPCTSTR s1, const CCom_String& s2); bool operator>(const CCom_String& s1, const CCom_String& s2); bool operator>(const CCom_String& s1, LPCTSTR s2); bool operator>(LPCTSTR s1, const CCom_String& s2); bool operator<=(const CCom_String& s1, const CCom_String& s2); bool operator<=(const CCom_String& s1, LPCTSTR s2); bool operator<=(LPCTSTR s1, const CCom_String& s2); bool operator>=(const CCom_String& s1, const CCom_String& s2); bool operator>=(const CCom_String& s1, LPCTSTR s2); bool operator>=(LPCTSTR s1, const CCom_String& s2); // conversion helpers int _cdecl _wcstombsz(char* mbstr, const wchar_t* wcstr, size_t count); int _cdecl _mbstowcsz(wchar_t* wcstr, const char* mbstr, size_t count); // Globals extern TCHAR comline_afxChNil; const CCom_String& comline_AfxGetEmptyString(); #define comline_afxEmptyString comline_AfxGetEmptyString() // CCom_String inline CCom_StringData* CCom_String::GetData() const { assert(m_pchData != NULL); return ((CCom_StringData*)m_pchData)-1; } inline void CCom_String::Init() { m_pchData = comline_afxEmptyString.m_pchData; } inline CCom_String::CCom_String(const unsigned char* lpsz) { Init(); *this = (LPCSTR)lpsz; } inline const CCom_String& CCom_String::operator=(const unsigned char* lpsz) { *this = (LPCSTR)lpsz; return *this; } #ifdef _UNICODE inline const CCom_String& CCom_String::operator+=(char ch) { *this += (TCHAR)ch; return *this; } inline const CCom_String& CCom_String::operator=(char ch) { *this = (TCHAR)ch; return *this; } inline CCom_String operator+(const CCom_String& string, char ch) { return string + (TCHAR)ch; } inline CCom_String operator+(char ch, const CCom_String& string) { return (TCHAR)ch + string; } #endif inline int CCom_String::GetLength() const { return GetData()->nDataLength; } inline int CCom_String::GetAllocLength() const { return GetData()->nAllocLength; } inline bool CCom_String::IsEmpty() const { return GetData()->nDataLength == 0; } inline CCom_String::operator LPCTSTR() const { return m_pchData; } inline int PASCAL CCom_String::SafeStrlen(LPCTSTR lpsz) { return (lpsz == NULL) ? 0 : lstrlen(lpsz); } // CCom_String support (windows specific) inline int CCom_String::Compare(LPCTSTR lpsz) const { return _tcscmp(m_pchData, lpsz); } // MBCS/Unicode aware inline int CCom_String::CompareNoCase(LPCTSTR lpsz) const { return _tcsicmp(m_pchData, lpsz); } // MBCS/Unicode aware // CCom_String::Collate is often slower than Compare but is MBSC/Unicode // aware as well as locale-sensitive with respect to sort order. inline int CCom_String::Collate(LPCTSTR lpsz) const { return _tcscoll(m_pchData, lpsz); } // locale sensitive inline TCHAR CCom_String::GetAt(int nIndex) const { assert(nIndex >= 0); assert(nIndex < GetData()->nDataLength); return m_pchData[nIndex]; } inline TCHAR CCom_String::operator[](int nIndex) const { // same as GetAt assert(nIndex >= 0); assert(nIndex < GetData()->nDataLength); return m_pchData[nIndex]; } inline bool operator==(const CCom_String& s1, const CCom_String& s2) { return s1.Compare(s2) == 0; } inline bool operator==(const CCom_String& s1, LPCTSTR s2) { return s1.Compare(s2) == 0; } inline bool operator==(LPCTSTR s1, const CCom_String& s2) { return s2.Compare(s1) == 0; } inline bool operator!=(const CCom_String& s1, const CCom_String& s2) { return s1.Compare(s2) != 0; } inline bool operator!=(const CCom_String& s1, LPCTSTR s2) { return s1.Compare(s2) != 0; } inline bool operator!=(LPCTSTR s1, const CCom_String& s2) { return s2.Compare(s1) != 0; } inline bool operator<(const CCom_String& s1, const CCom_String& s2) { return s1.Compare(s2) < 0; } inline bool operator<(const CCom_String& s1, LPCTSTR s2) { return s1.Compare(s2) < 0; } inline bool operator<(LPCTSTR s1, const CCom_String& s2) { return s2.Compare(s1) > 0; } inline bool operator>(const CCom_String& s1, const CCom_String& s2) { return s1.Compare(s2) > 0; } inline bool operator>(const CCom_String& s1, LPCTSTR s2) { return s1.Compare(s2) > 0; } inline bool operator>(LPCTSTR s1, const CCom_String& s2) { return s2.Compare(s1) < 0; } inline bool operator<=(const CCom_String& s1, const CCom_String& s2) { return s1.Compare(s2) <= 0; } inline bool operator<=(const CCom_String& s1, LPCTSTR s2) { return s1.Compare(s2) <= 0; } inline bool operator<=(LPCTSTR s1, const CCom_String& s2) { return s2.Compare(s1) >= 0; } inline bool operator>=(const CCom_String& s1, const CCom_String& s2) { return s1.Compare(s2) >= 0; } inline bool operator>=(const CCom_String& s1, LPCTSTR s2) { return s1.Compare(s2) >= 0; } inline bool operator>=(LPCTSTR s1, const CCom_String& s2) { return s2.Compare(s1) <= 0; } #endif