WString.hpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. #pragma once
  2. #ifdef DSTRING_EXPORTS
  3. #define DSTRING_API _declspec(dllexport)
  4. #else
  5. #define DSTRING_API _declspec(dllimport)
  6. #endif
  7. #ifndef _OLEAUTO_H_
  8. typedef LPWSTR BSTR;// must (semantically) match typedef in oleauto.h
  9. #endif
  10. struct WStringData
  11. {
  12. long nRefs; // reference count
  13. int nDataLength; // length of data (including terminator)
  14. int nAllocLength; // length of allocation
  15. // wchar_t data[nAllocLength]
  16. wchar_t * data () // wchar_t* to managed data
  17. { return (wchar_t *) (this+1); }
  18. };
  19. class DSTRING_API WString
  20. {
  21. public:
  22. WString ();
  23. WString (const wchar_t * lpsz);
  24. WString (const BSTR bstr);
  25. // WString (const DString & From, UINT CodePage);
  26. explicit WString (const DString & From);
  27. explicit WString (const char * lpsz);
  28. WString (const WString & Src);
  29. WString (WString && Src);
  30. ~WString ();
  31. // 返回的是字符数, 而不是真正的长度 ! 真正的长度要乘以 2
  32. int GetLength () const { return GetData ()->nDataLength; }
  33. int GetByteLength () const { return GetLength () << 1; }
  34. bool IsEmpty () const { return (GetData ()->nDataLength == 0); }
  35. void Empty ();
  36. void Release ();
  37. wchar_t GetAt (int nIndex) const
  38. {
  39. return m_pchData [nIndex];
  40. }
  41. wchar_t operator [] (int nIndex) const { return GetAt (nIndex); }
  42. void SetAt (int nIndex, wchar_t ch);
  43. // Number of ch
  44. int Count (wchar_t ch) const;
  45. // Number of lpszSub
  46. int Count (const wchar_t * lpszSub) const;
  47. // ref-counted copy from another WString
  48. WString & operator = (const WString & stringSrc);
  49. WString & operator = (const DString & stringSrc);
  50. WString & operator = (wchar_t ch);
  51. WString & operator = (const wchar_t * lpsz);
  52. WString & operator = (WString && Src);
  53. // string concatenation
  54. WString & Append (const WString & string)
  55. {
  56. ConcatInPlace (string.GetData ()->nDataLength, string.m_pchData);
  57. return *this;
  58. }
  59. WString & Append (const DString & string)
  60. {
  61. return Append (WString (string));
  62. }
  63. WString & Append (wchar_t ch)
  64. {
  65. ConcatInPlace (1, &ch);
  66. return *this;
  67. }
  68. WString & Append (const wchar_t * lpsz)
  69. {
  70. ConcatInPlace ((int)wcslen (lpsz), lpsz);
  71. return *this;
  72. }
  73. WString & operator += (const WString & string) { return Append (string); }
  74. WString & operator += (wchar_t ch) { return Append (ch); }
  75. WString & operator += (const wchar_t * lpsz) { return Append (lpsz); }
  76. WString & operator += (const DString & string) { return Append (WString (string)); }
  77. WString & operator << (const DString & string) { return Append (WString (string)); }
  78. WString & operator << (const char * string) { return Append (WString (string)); }
  79. WString & operator << (const WString & string) { return Append (string); }
  80. WString & operator << (wchar_t ch) { return Append (ch); }
  81. WString & operator << (const wchar_t * lpsz) { return Append (lpsz); }
  82. WString & operator << (short v) { return Append (From (v)); }
  83. WString & operator << (int v) { return Append (From (v)); }
  84. WString & operator << (long v) { return Append (From (v)); }
  85. WString & operator << (UINT16 v) { return Append (From (v)); }
  86. WString & operator << (UINT32 v) { return Append (From (v)); }
  87. #if 0
  88. template <typename T>
  89. WString & operator << (const T t)
  90. {
  91. return Append (WString::From (t));
  92. }
  93. #endif
  94. DSTRING_API friend WString operator + (const WString & string1, const char * string2);
  95. DSTRING_API friend WString operator + (const WString & string1, const DString & string2);
  96. DSTRING_API friend WString operator + (const WString & string1, const WString & string2);
  97. DSTRING_API friend WString operator + (const WString & string, wchar_t ch);
  98. DSTRING_API friend WString operator + (wchar_t ch, const WString & string);
  99. DSTRING_API friend WString operator + (const WString & string, const wchar_t * lpsz);
  100. DSTRING_API friend WString operator + (const wchar_t * lpsz, const WString & string);
  101. // string comparison
  102. int Compare (const wchar_t * lpsz) const;
  103. int CompareNoCase (const wchar_t * lpsz) const;
  104. // simple sub-string extraction
  105. WString Mid (int nFirst, int nCount) const;
  106. WString Mid (int nFirst) const;
  107. WString Left (int nCount) const;
  108. WString Right (int nCount) const;
  109. // upper/lower/reverse conversion
  110. void MakeUpper ();
  111. void MakeLower ();
  112. void MakeReverse ();
  113. // trimming whitespace (either side)
  114. void TrimRight ();
  115. void TrimLeft ();
  116. void TrimRight (wchar_t chTarget);
  117. void TrimRight (const wchar_t * lpszTargets);
  118. void TrimLeft (wchar_t chTarget);
  119. void TrimLeft (const wchar_t * lpszTargets);
  120. WString Trim () const { WString copy = *this; copy.TrimRight (); copy.TrimLeft (); return copy; }
  121. // advanced manipulation
  122. int Replace (wchar_t chOld, wchar_t chNew);
  123. int Replace (const wchar_t * lpszOld, const wchar_t * lpszNew);
  124. int Remove (const wchar_t * lpszSub);
  125. int Remove (wchar_t chRemove);
  126. int RemoveSpace ();
  127. int RemovePunctuation ();
  128. int RemoveControl ();
  129. int NCRemove (const wchar_t * lpszSub);
  130. int NCRemove (wchar_t chRemove);
  131. // searching
  132. int Find (wchar_t ch) const;
  133. int ReverseFind (wchar_t ch) const;
  134. int Find (wchar_t ch, int nStart) const;
  135. int FindOneOf (const wchar_t * lpszCharSet) const;
  136. int Find (const wchar_t * lpszSub) const;
  137. int Find (const wchar_t * lpszSub, int nStart) const;
  138. int NCFind (wchar_t ch) const;
  139. int NCFind (const wchar_t * lpszSub) const;
  140. public:
  141. WString Elements (int start, int stop, wchar_t sep) const;
  142. WString Element (int i, wchar_t sep) const;
  143. public:
  144. // get pointer to modifiable buffer at least as long as nMinBufLength
  145. wchar_t * GetBuffer (int nMinBufLength);
  146. // release buffer, setting length to nNewLength (or to first nul if -1)
  147. void ReleaseBuffer (int nNewLength = -1);
  148. // get pointer to modifiable buffer exactly as long as nNewLength
  149. wchar_t * GetBufferSetLength (int nNewLength);
  150. // release memory allocated to but unused by string
  151. void FreeExtra ();
  152. public:
  153. int GetAllocLength () const { return GetData ()->nAllocLength; }
  154. public:
  155. double Double () const { return _wtof (m_pchData); }
  156. int Int () const { int i = _wtoi (m_pchData); if (i) return i; return wcstol (m_pchData, NULL, 16); }
  157. long Long () const { long l = _wtol (m_pchData); if (l) return l; return wcstol (m_pchData, NULL, 16); }
  158. wchar_t Char () const { return m_pchData[0]; }
  159. bool Bool () const;
  160. __int64 Int64 () const { __int64 i = _wtoi64 (m_pchData); if (i) return i; return _wcstoi64 (m_pchData, NULL, 16); }
  161. protected:
  162. static int __cdecl GetFormattedLength (const wchar_t * pszFormat, va_list argList);
  163. static int __cdecl VFormat (wchar_t * lpzBuffer, const wchar_t * pszFormat, va_list argList);
  164. public:
  165. static WString From (const int i);
  166. static WString From (const long i);
  167. static WString From (const unsigned int u);
  168. static WString From (const unsigned long u);
  169. static WString From (const __int64 i);
  170. static WString From (const unsigned __int64 u);
  171. static WString From (const double d);
  172. static WString FromCodePage (const DString & from, UINT CodePage);
  173. static WString FromCodePage (const char * from, UINT CodePage);
  174. // repeat a single character
  175. static WString FromRepeat (wchar_t ch, int nRepeat);
  176. protected:
  177. static WString _FromCodePage (const char * from, int len, UINT CodePage);
  178. protected:
  179. void FormatV (const wchar_t * lpszFormat, va_list argList);
  180. void AppendFormatV (const wchar_t * lpszFormat, va_list argList);
  181. protected:
  182. // 对于字符串,代码中很容易忘记 L 前缀, 导致传入的是 char *, 而期望的是 wchar_t *
  183. // 比如, 正确的写法是: Format ("%s", L"abcd"); 但是很容易写成 Format ("%s", "abcd");
  184. // 为了避免出现这种 BUG, 把这几个函数改成 protected
  185. static WString FromFormat (const wchar_t * szFormat, ...);
  186. void Format (const wchar_t * lpszFormat, ...);
  187. void AppendFormat (const wchar_t * lpszFormat, ...);
  188. // Cast
  189. public:
  190. operator const wchar_t * () const { return m_pchData; }
  191. const wchar_t * constBuffer (void) const { return m_pchData; }
  192. DString ToDString () const;
  193. DString ToDString (UINT CodePage) const;
  194. // explicit operator const DString () const { return ToDString (); }
  195. operator const DString () const = delete;
  196. operator bool () const = delete;
  197. protected:
  198. wchar_t * m_pchData; // pointer to ref counted string data
  199. WStringData * WString::GetData() const
  200. {
  201. return ((WStringData *) m_pchData)-1;
  202. }
  203. void Init ();
  204. void AllocCopy (WString& dest, int nCopyLen, int nCopyIndex, int nExtraLen) const;
  205. void AllocBuffer (int nLen);
  206. void AssignCopy (int nSrcLen, const wchar_t * lpszSrcData);
  207. void ConcatCopy (int nSrc1Len, const wchar_t * lpszSrc1Data, int nSrc2Len, const wchar_t * lpszSrc2Data);
  208. void ConcatInPlace (int nSrcLen, const wchar_t * lpszSrcData);
  209. void CopyBeforeWrite ();
  210. void AllocBeforeWrite (int nLen);
  211. void MoveAssign (WString & Src);
  212. static void Release (WStringData * pData);
  213. static void FreeData (WStringData * pData);
  214. };
  215. // Compare helpers
  216. DSTRING_API inline bool __stdcall operator == (const WString& s1, const WString& s2) { return s1.Compare (s2) == 0; }
  217. DSTRING_API inline bool __stdcall operator == (const WString& s1, const wchar_t * s2) { return s1.Compare (s2) == 0; }
  218. DSTRING_API inline bool __stdcall operator == (const wchar_t * s1 , const WString& s2) { return s2.Compare (s1) == 0; }
  219. DSTRING_API inline bool __stdcall operator != (const WString& s1, const WString& s2) { return s1.Compare (s2) != 0; }
  220. DSTRING_API inline bool __stdcall operator != (const WString& s1, const wchar_t * s2) { return s1.Compare (s2) != 0; }
  221. DSTRING_API inline bool __stdcall operator != (const wchar_t * s1 , const WString& s2) { return s2.Compare (s1) != 0; }
  222. DSTRING_API inline bool __stdcall operator < (const WString& s1, const WString& s2) { return s1.Compare (s2) < 0; }
  223. DSTRING_API inline bool __stdcall operator < (const WString& s1, const wchar_t * s2) { return s1.Compare (s2) < 0; }
  224. DSTRING_API inline bool __stdcall operator < (const wchar_t * s1 , const WString& s2) { return s2.Compare (s1) > 0; }
  225. DSTRING_API inline bool __stdcall operator > (const WString& s1, const WString& s2) { return s1.Compare (s2) > 0; }
  226. DSTRING_API inline bool __stdcall operator > (const WString& s1, const wchar_t * s2) { return s1.Compare (s2) > 0; }
  227. DSTRING_API inline bool __stdcall operator > (const wchar_t * s1 , const WString& s2) { return s2.Compare (s1) < 0; }
  228. DSTRING_API inline bool __stdcall operator <= (const WString& s1, const WString& s2) { return s1.Compare (s2) <= 0; }
  229. DSTRING_API inline bool __stdcall operator <= (const WString& s1, const wchar_t * s2) { return s1.Compare (s2) <= 0; }
  230. DSTRING_API inline bool __stdcall operator <= (const wchar_t * s1 , const WString& s2) { return s2.Compare (s1) >= 0; }
  231. DSTRING_API inline bool __stdcall operator >= (const WString& s1, const WString& s2) { return s1.Compare (s2) >= 0; }
  232. DSTRING_API inline bool __stdcall operator >= (const WString& s1, const wchar_t * s2) { return s1.Compare (s2) >= 0; }
  233. DSTRING_API inline bool __stdcall operator >= (const wchar_t * s1 , const WString& s2) { return s2.Compare (s1) <= 0; }