#pragma once #ifdef DSTRING_EXPORTS #define DSTRING_API _declspec(dllexport) #else #define DSTRING_API _declspec(dllimport) #endif #ifndef _OLEAUTO_H_ typedef LPWSTR BSTR;// must (semantically) match typedef in oleauto.h #endif struct WStringData { long nRefs; // reference count int nDataLength; // length of data (including terminator) int nAllocLength; // length of allocation // wchar_t data[nAllocLength] wchar_t * data () // wchar_t* to managed data { return (wchar_t *) (this+1); } }; class DSTRING_API WString { public: WString (); WString (const wchar_t * lpsz); WString (const BSTR bstr); // WString (const DString & From, UINT CodePage); explicit WString (const DString & From); explicit WString (const char * lpsz); WString (const WString & Src); WString (WString && Src); ~WString (); // 返回的是字符数, 而不是真正的长度 ! 真正的长度要乘以 2 int GetLength () const { return GetData ()->nDataLength; } int GetByteLength () const { return GetLength () << 1; } bool IsEmpty () const { return (GetData ()->nDataLength == 0); } void Empty (); void Release (); wchar_t GetAt (int nIndex) const { return m_pchData [nIndex]; } wchar_t operator [] (int nIndex) const { return GetAt (nIndex); } void SetAt (int nIndex, wchar_t ch); // Number of ch int Count (wchar_t ch) const; // Number of lpszSub int Count (const wchar_t * lpszSub) const; // ref-counted copy from another WString WString & operator = (const WString & stringSrc); WString & operator = (const DString & stringSrc); WString & operator = (wchar_t ch); WString & operator = (const wchar_t * lpsz); WString & operator = (WString && Src); // string concatenation WString & Append (const WString & string) { ConcatInPlace (string.GetData ()->nDataLength, string.m_pchData); return *this; } WString & Append (const DString & string) { return Append (WString (string)); } WString & Append (wchar_t ch) { ConcatInPlace (1, &ch); return *this; } WString & Append (const wchar_t * lpsz) { ConcatInPlace ((int)wcslen (lpsz), lpsz); return *this; } WString & operator += (const WString & string) { return Append (string); } WString & operator += (wchar_t ch) { return Append (ch); } WString & operator += (const wchar_t * lpsz) { return Append (lpsz); } WString & operator += (const DString & string) { return Append (WString (string)); } WString & operator << (const DString & string) { return Append (WString (string)); } WString & operator << (const char * string) { return Append (WString (string)); } WString & operator << (const WString & string) { return Append (string); } WString & operator << (wchar_t ch) { return Append (ch); } WString & operator << (const wchar_t * lpsz) { return Append (lpsz); } WString & operator << (short v) { return Append (From (v)); } WString & operator << (int v) { return Append (From (v)); } WString & operator << (long v) { return Append (From (v)); } WString & operator << (UINT16 v) { return Append (From (v)); } WString & operator << (UINT32 v) { return Append (From (v)); } #if 0 template WString & operator << (const T t) { return Append (WString::From (t)); } #endif DSTRING_API friend WString operator + (const WString & string1, const char * string2); DSTRING_API friend WString operator + (const WString & string1, const DString & string2); DSTRING_API friend WString operator + (const WString & string1, const WString & string2); DSTRING_API friend WString operator + (const WString & string, wchar_t ch); DSTRING_API friend WString operator + (wchar_t ch, const WString & string); DSTRING_API friend WString operator + (const WString & string, const wchar_t * lpsz); DSTRING_API friend WString operator + (const wchar_t * lpsz, const WString & string); // string comparison int Compare (const wchar_t * lpsz) const; int CompareNoCase (const wchar_t * lpsz) const; // simple sub-string extraction WString Mid (int nFirst, int nCount) const; WString Mid (int nFirst) const; WString Left (int nCount) const; WString Right (int nCount) const; // upper/lower/reverse conversion void MakeUpper (); void MakeLower (); void MakeReverse (); // trimming whitespace (either side) void TrimRight (); void TrimLeft (); void TrimRight (wchar_t chTarget); void TrimRight (const wchar_t * lpszTargets); void TrimLeft (wchar_t chTarget); void TrimLeft (const wchar_t * lpszTargets); WString Trim () const { WString copy = *this; copy.TrimRight (); copy.TrimLeft (); return copy; } // advanced manipulation int Replace (wchar_t chOld, wchar_t chNew); int Replace (const wchar_t * lpszOld, const wchar_t * lpszNew); int Remove (const wchar_t * lpszSub); int Remove (wchar_t chRemove); int RemoveSpace (); int RemovePunctuation (); int RemoveControl (); int NCRemove (const wchar_t * lpszSub); int NCRemove (wchar_t chRemove); // searching int Find (wchar_t ch) const; int ReverseFind (wchar_t ch) const; int Find (wchar_t ch, int nStart) const; int FindOneOf (const wchar_t * lpszCharSet) const; int Find (const wchar_t * lpszSub) const; int Find (const wchar_t * lpszSub, int nStart) const; int NCFind (wchar_t ch) const; int NCFind (const wchar_t * lpszSub) const; public: WString Elements (int start, int stop, wchar_t sep) const; WString Element (int i, wchar_t sep) const; public: // get pointer to modifiable buffer at least as long as nMinBufLength wchar_t * GetBuffer (int nMinBufLength); // release buffer, setting length to nNewLength (or to first nul if -1) void ReleaseBuffer (int nNewLength = -1); // get pointer to modifiable buffer exactly as long as nNewLength wchar_t * GetBufferSetLength (int nNewLength); // release memory allocated to but unused by string void FreeExtra (); public: int GetAllocLength () const { return GetData ()->nAllocLength; } public: double Double () const { return _wtof (m_pchData); } int Int () const { int i = _wtoi (m_pchData); if (i) return i; return wcstol (m_pchData, NULL, 16); } long Long () const { long l = _wtol (m_pchData); if (l) return l; return wcstol (m_pchData, NULL, 16); } wchar_t Char () const { return m_pchData[0]; } bool Bool () const; __int64 Int64 () const { __int64 i = _wtoi64 (m_pchData); if (i) return i; return _wcstoi64 (m_pchData, NULL, 16); } protected: static int __cdecl GetFormattedLength (const wchar_t * pszFormat, va_list argList); static int __cdecl VFormat (wchar_t * lpzBuffer, const wchar_t * pszFormat, va_list argList); public: static WString From (const int i); static WString From (const long i); static WString From (const unsigned int u); static WString From (const unsigned long u); static WString From (const __int64 i); static WString From (const unsigned __int64 u); static WString From (const double d); static WString FromCodePage (const DString & from, UINT CodePage); static WString FromCodePage (const char * from, UINT CodePage); // repeat a single character static WString FromRepeat (wchar_t ch, int nRepeat); protected: static WString _FromCodePage (const char * from, int len, UINT CodePage); protected: void FormatV (const wchar_t * lpszFormat, va_list argList); void AppendFormatV (const wchar_t * lpszFormat, va_list argList); protected: // 对于字符串,代码中很容易忘记 L 前缀, 导致传入的是 char *, 而期望的是 wchar_t * // 比如, 正确的写法是: Format ("%s", L"abcd"); 但是很容易写成 Format ("%s", "abcd"); // 为了避免出现这种 BUG, 把这几个函数改成 protected static WString FromFormat (const wchar_t * szFormat, ...); void Format (const wchar_t * lpszFormat, ...); void AppendFormat (const wchar_t * lpszFormat, ...); // Cast public: operator const wchar_t * () const { return m_pchData; } const wchar_t * constBuffer (void) const { return m_pchData; } DString ToDString () const; DString ToDString (UINT CodePage) const; // explicit operator const DString () const { return ToDString (); } operator const DString () const = delete; operator bool () const = delete; protected: wchar_t * m_pchData; // pointer to ref counted string data WStringData * WString::GetData() const { return ((WStringData *) m_pchData)-1; } void Init (); void AllocCopy (WString& dest, int nCopyLen, int nCopyIndex, int nExtraLen) const; void AllocBuffer (int nLen); void AssignCopy (int nSrcLen, const wchar_t * lpszSrcData); void ConcatCopy (int nSrc1Len, const wchar_t * lpszSrc1Data, int nSrc2Len, const wchar_t * lpszSrc2Data); void ConcatInPlace (int nSrcLen, const wchar_t * lpszSrcData); void CopyBeforeWrite (); void AllocBeforeWrite (int nLen); void MoveAssign (WString & Src); static void Release (WStringData * pData); static void FreeData (WStringData * pData); }; // Compare helpers DSTRING_API inline bool __stdcall operator == (const WString& s1, const WString& s2) { return s1.Compare (s2) == 0; } DSTRING_API inline bool __stdcall operator == (const WString& s1, const wchar_t * s2) { return s1.Compare (s2) == 0; } DSTRING_API inline bool __stdcall operator == (const wchar_t * s1 , const WString& s2) { return s2.Compare (s1) == 0; } DSTRING_API inline bool __stdcall operator != (const WString& s1, const WString& s2) { return s1.Compare (s2) != 0; } DSTRING_API inline bool __stdcall operator != (const WString& s1, const wchar_t * s2) { return s1.Compare (s2) != 0; } DSTRING_API inline bool __stdcall operator != (const wchar_t * s1 , const WString& s2) { return s2.Compare (s1) != 0; } DSTRING_API inline bool __stdcall operator < (const WString& s1, const WString& s2) { return s1.Compare (s2) < 0; } DSTRING_API inline bool __stdcall operator < (const WString& s1, const wchar_t * s2) { return s1.Compare (s2) < 0; } DSTRING_API inline bool __stdcall operator < (const wchar_t * s1 , const WString& s2) { return s2.Compare (s1) > 0; } DSTRING_API inline bool __stdcall operator > (const WString& s1, const WString& s2) { return s1.Compare (s2) > 0; } DSTRING_API inline bool __stdcall operator > (const WString& s1, const wchar_t * s2) { return s1.Compare (s2) > 0; } DSTRING_API inline bool __stdcall operator > (const wchar_t * s1 , const WString& s2) { return s2.Compare (s1) < 0; } DSTRING_API inline bool __stdcall operator <= (const WString& s1, const WString& s2) { return s1.Compare (s2) <= 0; } DSTRING_API inline bool __stdcall operator <= (const WString& s1, const wchar_t * s2) { return s1.Compare (s2) <= 0; } DSTRING_API inline bool __stdcall operator <= (const wchar_t * s1 , const WString& s2) { return s2.Compare (s1) >= 0; } DSTRING_API inline bool __stdcall operator >= (const WString& s1, const WString& s2) { return s1.Compare (s2) >= 0; } DSTRING_API inline bool __stdcall operator >= (const WString& s1, const wchar_t * s2) { return s1.Compare (s2) >= 0; } DSTRING_API inline bool __stdcall operator >= (const wchar_t * s1 , const WString& s2) { return s2.Compare (s1) <= 0; }