Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

680 lines
28 KiB

  1. // FILE: tstring.h
  2. // AUTHOR: Davepl
  3. // REMARKS:
  4. //
  5. //
  6. // This header file declares the tstring class. This string class is
  7. // derived from the Standard C++ Libarary string classes (one of them)
  8. // and adds to them the MFC CString conveniences of
  9. //
  10. // - UNICODE support and
  11. // - implicit casts to PCTSTR
  12. // - loading from resource files
  13. // - formatting (via Format()) function.
  14. // - writing to/reading from COM IStream interfaces
  15. // - Functional objects for use in STL algorithms
  16. //
  17. // This header also declares our own version of the MFC/ATL UNICODE-MBCS
  18. // conversion macros. Our version looks exactly like the originals in order
  19. // facilitate portability.
  20. //
  21. // (c) 1999 Dave Plummer. Portions of this code derived from source
  22. // produced by Joe O'Leary with the following license:
  23. // > This code is free. Use it anywhere you want. Rewrite
  24. // > it, restructure it, whatever you want.
  25. #ifndef _STDSTRING_H_
  26. #define _STDSTRING_H_
  27. // Turn off browser references
  28. #ifdef _MSC_VER
  29. #pragma component(browser, off, references, "tstring")
  30. #endif
  31. // Avoid legacy code mess up -- if _UNICODE is defined, then UNICODE must be as well
  32. #if defined (_UNICODE) && !defined (UNICODE)
  33. #define UNICODE
  34. #endif
  35. #include <locale>
  36. #include <TCHAR.H>
  37. #ifndef STRICT
  38. #define STRICT
  39. #endif
  40. #include <windows.h>
  41. // In non-MFC builds, ASSERT and VERIFY probably won't be defined, so
  42. // check to see if they are defined and, if not, define them ourself.
  43. #ifndef ASSERT
  44. #include <crtdbg.h> // probably already included but do it just in case
  45. #define ASSERT(f) _ASSERTE((f))
  46. #endif
  47. #ifndef VERIFY
  48. #ifdef _DEBUG
  49. #define VERIFY(x) ASSERT((x))
  50. #else
  51. #define VERIFY(x) x
  52. #endif
  53. #endif
  54. #ifndef TRACE
  55. #define TRACE
  56. #endif
  57. #include <functional> // needed for tstring_lessnocase, et al
  58. // If this is a recent enough version of VC include comdef.h, we can write many tstring
  59. // functions to deal with COM types and compiler support classes like _bstr_t
  60. #if defined (_MSC_VER) && (_MSC_VER >= 1100)
  61. #include <comdef.h>
  62. #define STDSTRING_INC_COMDEF // signal that we #included MS comdef.h file
  63. #endif
  64. #ifndef PCTSTR_DEFINED
  65. typedef const TCHAR* PCTSTR;
  66. #define PCTSTR_DEFINED
  67. #endif
  68. #ifndef PCOLESTR
  69. #define PCOLESTR LPCOLESTR
  70. #endif
  71. #ifndef POLESTR
  72. #define POLESTR LPOLESTR
  73. #endif
  74. // UNICODE/MBCS conversion macros. These are made to work just like the MFC/ATL ones. We
  75. // will not define them if
  76. // _NO_STDCONVERSION - the developer explicitly turned them off
  77. // USES_CONVERSION - this is an ATL/MFC build and they are already defined
  78. #ifndef _NO_STDCONVERSION
  79. #if defined (USES_CONVERSION)
  80. #define _NO_STDCONVERSION // Let StdString.cpp know it should not compile functions
  81. #else
  82. // In MFC builds we can just use the MFC UNICODE conversion macros.
  83. // In NON-MFC builds will have to define them ourselves
  84. #include <malloc.h>
  85. #ifdef _MFC_VER
  86. #include <afxconv.h>
  87. #define _NO_STDCONVERSION // Let StdString.cpp know it should not compile functions
  88. #else
  89. // Define our conversion macros to look exactly like the originals
  90. // using this stuff both with and without MFC/ATL. Avert your eyes,
  91. // its not pretty
  92. #ifndef _DEBUG
  93. #define USES_CONVERSION int _convert; _convert
  94. #else
  95. #define USES_CONVERSION int _convert = 0
  96. #endif
  97. PWSTR StdA2WHelper(PWSTR pw, PCSTR pa, int nChars);
  98. PSTR StdW2AHelper(PSTR pa, PCWSTR pw, int nChars);
  99. #define A2W(pa) (\
  100. ((PCSTR)(pa) == NULL) ? NULL : (\
  101. _convert = (strlen((pa))+1),\
  102. StdA2WHelper((LPWSTR) alloca(_convert*2), (pa), _convert)))
  103. #define W2A(pw) (\
  104. ((PCWSTR)(pw) == NULL) ? NULL : (\
  105. _convert = (wcslen((pw))+1)*2,\
  106. StdW2AHelper((PSTR) alloca(_convert), (pw), _convert)))
  107. #define A2CW(pa) ((PCWSTR)A2W((pa)))
  108. #define W2CA(pw) ((PCSTR)W2A((pw)))
  109. #ifdef _UNICODE
  110. #define T2A W2A
  111. #define A2T A2W
  112. inline PWSTR T2W(PTSTR p) { return p; }
  113. inline PTSTR W2T(PWSTR p) { return p; }
  114. #define T2CA W2CA
  115. #define A2CT A2CW
  116. inline PCWSTR T2CW(PCTSTR p) { return p; }
  117. inline PCTSTR W2CT(PCWSTR p) { return p; }
  118. #else
  119. #define T2W A2W
  120. #define W2T W2A
  121. inline PSTR T2A(PTSTR p) { return p; }
  122. inline PTSTR A2T(PSTR p) { return p; }
  123. #define T2CW A2CW
  124. #define W2CT W2CA
  125. inline PCSTR T2CA(PCTSTR p) { return p; }
  126. inline PCTSTR A2CT(PCSTR p) { return p; }
  127. #endif // #ifdef _UNICODE
  128. #if defined(_UNICODE)
  129. // in these cases the default (TCHAR) is the same as OLECHAR
  130. inline size_t ocslen(PCOLESTR x) { return wcslen(x); }
  131. inline OLECHAR* ocscpy(POLESTR dest, PCOLESTR src) { return wcscpy(dest, src); }
  132. inline PCOLESTR T2COLE(PCTSTR p) { return p; }
  133. inline PCTSTR OLE2CT(PCOLESTR p) { return p; }
  134. inline POLESTR T2OLE(PTSTR p) { return p; }
  135. inline PTSTR OLE2T(POLESTR p) { return p; }
  136. #elif defined(OLE2ANSI)
  137. // in these cases the default (TCHAR) is the same as OLECHAR
  138. inline size_t ocslen(PCOLESTR x) { return strlen(x); }
  139. inline OLECHAR* ocscpy(POLESTR dest, LPCOLESTR src) { return strcpy(dest, src); }
  140. inline PCOLESTR T2COLE(PCTSTR p) { return p; }
  141. inline PCTSTR OLE2CT(PCOLESTR p) { return p; }
  142. inline POLESTR T2OLE(PTSTR p) { return p; }
  143. inline PTSTR OLE2T(POLESTR p) { return p; }
  144. #else
  145. inline size_t ocslen(PCOLESTR x) { return wcslen(x); }
  146. inline OLECHAR* ocscpy(POLESTR dest, PCOLESTR src)
  147. {return (POLESTR) memcpy(dest, src, (wcslen(src)+1)*sizeof(WCHAR));}
  148. //CharNextW doesn't work on Win95 so we use this
  149. #define T2COLE(pa) A2CW((pa))
  150. #define T2OLE(pa) A2W((pa))
  151. #define OLE2CT(po) W2CA((po))
  152. #define OLE2T(po) W2A((po))
  153. #endif
  154. #ifdef OLE2ANSI
  155. inline POLESTR A2OLE(PSTR p) { return p;}
  156. inline PSTR OLE2A(POLESTR p) { return p;}
  157. #define W2OLE W2A
  158. #define OLE2W A2W
  159. inline PCOLESTR A2COLE(PCSTR p) { return p;}
  160. inline PCSTR OLE2CA(PCOLESTR p) { return p;}
  161. #define W2COLE W2CA
  162. #define OLE2CW A2CW
  163. #else
  164. inline POLESTR W2OLE(PWSTR p) { return p; }
  165. inline PWSTR OLE2W(POLESTR p) { return p; }
  166. #define A2OLE A2W
  167. #define OLE2A W2A
  168. inline PCOLESTR W2COLE(PCWSTR p) { return p; }
  169. inline PCWSTR OLE2CW(PCOLESTR p) { return p; }
  170. #define A2COLE A2CW
  171. #define OLE2CA W2CA
  172. #endif
  173. inline BSTR OLE2BSTR(PCOLESTR p) {return ::SysAllocString(p);}
  174. #if defined(_UNICODE)
  175. // in these cases the default (TCHAR) is the same as OLECHAR
  176. inline BSTR T2BSTR(PCTSTR p) {return ::SysAllocString(p);}
  177. inline BSTR A2BSTR(PCSTR p) {USES_CONVERSION; return ::SysAllocString(A2COLE(p));}
  178. inline BSTR W2BSTR(PCWSTR p) {return ::SysAllocString(p);}
  179. #elif defined(OLE2ANSI)
  180. // in these cases the default (TCHAR) is the same as OLECHAR
  181. inline BSTR T2BSTR(PCTSTR p) {return ::SysAllocString(p);}
  182. inline BSTR A2BSTR(PCSTR p) {return ::SysAllocString(p);}
  183. inline BSTR W2BSTR(PCWSTR p) {USES_CONVERSION; return ::SysAllocString(W2COLE(p));}
  184. #else
  185. inline BSTR T2BSTR(PCTSTR p) {USES_CONVERSION; return ::SysAllocString(T2COLE(p));}
  186. inline BSTR A2BSTR(PCSTR p) {USES_CONVERSION; return ::SysAllocString(A2COLE(p));}
  187. inline BSTR W2BSTR(PCWSTR p) {return ::SysAllocString(p);}
  188. #endif
  189. #endif // #ifdef _MFC_VER
  190. #endif // #ifndef USES_CONVERSION
  191. #endif // #ifndef _NO_STDCONVERSION
  192. // Define our own macros for "other" type to TCHAR type conversion
  193. // i.e. in a UNICODE build "other" would be char. In a non-UNICODE
  194. // build, "other" would be wchar_t These macros make the declaration
  195. // of the tstring class a lot cleaner
  196. #ifdef _UNICODE
  197. #define O2T A2T // "other" type string to generic text type string
  198. #define O2CT A2CT // constant "other" type string to generic text type string
  199. #define T2O T2A // generic text type string to "other" type string.
  200. #define T2CO T2CA // generic text type string to constant "other type string.
  201. #else
  202. #define O2T W2T
  203. #define O2CT W2CT
  204. #define T2O T2W
  205. #define T2CO T2CW
  206. #endif
  207. // Define some short names for types that we will refer to in our definition of
  208. // the tstring class.
  209. #ifdef _UNICODE
  210. #define TOTHER char // the "other" char type (opposite of TCHAR)
  211. #define POSTR PSTR // the "other" string type (opposite of PTSTR)
  212. #define PCOSTR PCSTR // the "other" const string type (oppsite of PCTSTR)
  213. const PCOSTR szONull = ""; // an empty string of the "other" type.
  214. #else
  215. #define TOTHER wchar_t
  216. #define POSTR PWSTR
  217. #define PCOSTR PCWSTR
  218. const PCOSTR szONull = L"";
  219. #endif
  220. const PCTSTR szTNull = _T(""); // an empty string of the TCHAR type
  221. typedef std::basic_string<TCHAR> STRBASE; // our base class
  222. typedef std::basic_string<TOTHER> STROTHER; // opposite of our base
  223. // Define TSTRING -- this is a basic_string built around the TCHAR type, kind of like MFC CString
  224. // It is also our base class.
  225. #ifndef _TSTRING_DEFINED_
  226. #define _TSTRING_DEFINED_
  227. typedef std::basic_string<TCHAR> TSTRING;
  228. #endif
  229. // tstring class
  230. //
  231. // This class is a simplified version of the Standard C++ Library string or basic string class. It
  232. // is derived from basic_string<TCHAR> and adds some MFC CString-like functionality
  233. class tstring : public STRBASE
  234. {
  235. public:
  236. typedef std::allocator<TCHAR> MYALLOC;
  237. // constructors
  238. tstring();
  239. tstring(const tstring& str);
  240. tstring(const STRBASE& str);
  241. tstring(const STROTHER& str);
  242. tstring(PCTSTR pT);
  243. tstring(PCOSTR pO);
  244. tstring(const_iterator first, const_iterator last);
  245. tstring(size_type nSize, value_type ch, const allocator_type& al=std::allocator<TCHAR>());
  246. tstring(UINT nId);
  247. #ifdef STDSTRING_INC_COMDEF
  248. tstring(const _bstr_t& bstr); // takes the _bstr_t MS compiler COM support class
  249. #endif
  250. // assignment operators
  251. tstring& operator=(const tstring& str); // copy constructor
  252. tstring& operator=(const STRBASE& str); // takes a base std string type (string or wstring)
  253. tstring& operator=(const STROTHER& str); // takes the other std string type (string or wstring)
  254. tstring& operator=(PCTSTR pT); // takes const TCHAR pointer
  255. tstring& operator=(PCOSTR pO); // takes const pointer to "other" type (opposite of PCTSTR)
  256. tstring& operator=(TCHAR); // takes single character of TCHAR type
  257. tstring& operator=(TOTHER); // takes single character of the "other" type
  258. #ifdef STDSTRING_INC_COMDEF
  259. tstring& operator=(const _bstr_t& bstr); // takes the _bstr_t MS compiler COM support class
  260. #endif
  261. // These overloads are also needed to fix the MSVC assignment bug (only for our STL - See KB: Q172398)
  262. tstring& assign(const tstring& str, tstring::size_type nStart, tstring::size_type nChars);
  263. tstring& assign(PCTSTR pT, tstring::size_type nChars);
  264. tstring& assign(tstring::size_type nChars, tstring::value_type val);
  265. tstring& assign(const tstring& str);
  266. tstring& assign(PCTSTR pT);
  267. tstring& assign(tstring::const_iterator iterFirst, tstring::const_iterator iterLast);
  268. // comparison (equality)
  269. bool operator==(const tstring& str) const;
  270. bool operator==(const STRBASE& str) const;
  271. bool operator==(const STROTHER& str) const;
  272. bool operator==(PCTSTR pT) const;
  273. bool operator==(PCOSTR pO) const;
  274. bool operator==(TCHAR t) const;
  275. bool operator==(TOTHER t) const;
  276. // Note the default here is case INsensitive
  277. bool Equals(PCTSTR pT, bool bUseCase=false) const;
  278. // comparison operators (inequality)
  279. bool operator!=(const tstring& str) const;
  280. bool operator!=(const STRBASE& str) const;
  281. bool operator!=(const STROTHER& str) const;
  282. bool operator!=(PCTSTR pT) const;
  283. bool operator!=(PCOSTR pO) const;
  284. bool operator!=(TCHAR t) const;
  285. bool operator!=(TOTHER t) const;
  286. // comparison operator (less than)
  287. bool operator<(const tstring& str) const;
  288. bool operator<(PCTSTR str) const;
  289. // concatenation.
  290. const tstring& operator+=(const tstring& str);
  291. const tstring& operator+=(const STRBASE& str);
  292. const tstring& operator+=(const STROTHER& str);
  293. const tstring& operator+=(PCTSTR pT);
  294. const tstring& operator+=(PCOSTR pO);
  295. const tstring& operator+=(TCHAR t);
  296. const tstring& operator+=(TOTHER t);
  297. #ifdef STDSTRING_INC_COMDEF
  298. const tstring& operator+=(const _bstr_t& bstr);
  299. #endif
  300. // addition operators -- global friend functions.
  301. friend tstring operator+(const tstring& str1, const tstring& str2);
  302. friend tstring operator+(const tstring& str, TCHAR ch);
  303. friend tstring operator+(TCHAR ch, const tstring& str);
  304. friend tstring operator+(const tstring& str, TOTHER ch);
  305. friend tstring operator+(TOTHER ch, const tstring& str);
  306. friend tstring operator+(const tstring& str, PCTSTR sz);
  307. friend tstring operator+(PCTSTR sz, const tstring& str);
  308. friend tstring operator+(const tstring& str, PCOSTR sz);
  309. friend tstring operator+(PCOSTR sz, const tstring& str);
  310. #ifdef STDSTRING_INC_COMDEF
  311. friend tstring operator+(const _bstr_t& bstr, const tstring& str);
  312. friend tstring operator+(const tstring& str, const _bstr_t& bstr);
  313. #endif
  314. // Conversion to "other" type of string (i.e. to string if we're a wstring, to wstring if we're a string)
  315. STROTHER Other() const
  316. {
  317. USES_CONVERSION;
  318. return T2CO(c_str());
  319. };
  320. // General utility stuff
  321. LPTSTR GetBuffer(int n = -1)
  322. {
  323. if ( (-1 != n) && (n > (int)length()) )
  324. resize(n);
  325. return (LPTSTR) data();
  326. }
  327. void ReleaseBuffer( int n = -1 )
  328. {
  329. if (-1 == n)
  330. n = _tcslen( data() );
  331. resize(n);
  332. }
  333. operator CComBSTR() const
  334. {
  335. PCTSTR pFoo = *this;
  336. return CComBSTR( pFoo );
  337. }
  338. operator PCTSTR() const; // implicit cast to const TCHAR*
  339. bool Load(UINT nId); // load using resource id
  340. tstring& Format(PCTSTR szFormat, ...); // format using literal string
  341. tstring& Format(UINT nId, ...); // format using resource string identifier
  342. tstring& FormatV(PCTSTR szFormat, va_list argList); // format using a va_list instead of ...
  343. tstring& TrimRight(); // chop off all whitespace characters on right
  344. tstring& TrimLeft(); // chop off all whitespace characters on left
  345. tstring& ToUpper(); // make uppercase
  346. tstring& ToLower(); // make lowercase
  347. bool IsEmpty() const { return empty(); };
  348. TCHAR& operator[](int nIdx);
  349. const TCHAR& operator[](int nIdx) const;
  350. #ifdef STDSTRING_INC_COMDEF
  351. HRESULT StreamSave(IStream* pStream) const; // write to an IStream
  352. HRESULT StreamLoad(IStream* pStream); // read from an IStream;
  353. ULONG StreamSize() const; // how many bytes needed to write to an IStream?
  354. #endif
  355. // These static functions simplify copying one C-style string to another, either one or two byte.
  356. static void CopyString(PCTSTR p_szSource, PTSTR p_szDest, int p_nMaxChars=0);
  357. static void CopyString(PCOSTR p_szSource, POSTR p_szDest, int p_nMaxChars=0);
  358. static void CopyString(PCSTR p_szSource, PWSTR p_szDest, int p_nMaxChars=0);
  359. static void CopyString(PCWSTR p_szSource, PSTR, int p_nMaxChars=0);
  360. // If this is NOT an MFC build, provide a SetResourceHandle function so that those who call
  361. // the versions of Load(), Format(), or the constructor that take resource IDs can provide
  362. // an alternate HINST of a DLL to search. This is not exactly the list of link libraries
  363. // that MFC provides but it's better than nothing.
  364. static void SetResourceHandle(HINSTANCE hNew);
  365. static HINSTANCE GetResourceHandle();
  366. protected:
  367. #if !defined(_MFC_VER)
  368. static HINSTANCE hInstResource; // implementation of Get/SetResourceHandle in non-MFC builds
  369. #endif
  370. };
  371. #define _TRES(pctstr) (LOWORD((pctstr))) // shorthand conversion from PCTSTR to string resource ID
  372. // tstring inline constructors
  373. inline tstring::tstring() {}
  374. inline tstring::tstring(const STRBASE& str) { *this = str; };
  375. //inline tstring::tstring(PCTSTR pT) { *this = (pT == NULL ? szTNull : pT); };
  376. inline tstring::tstring(PCOSTR pO) { *this = (pO == NULL ? szONull : pO); };
  377. inline tstring::tstring(const tstring& str) { *this = str; };
  378. inline tstring::tstring(const STROTHER& str) { *this = str; };
  379. inline tstring::tstring(const_iterator first, const_iterator last) : STRBASE(first, last) {};
  380. inline tstring::tstring(size_type nSize, value_type ch, const allocator_type& al) : STRBASE(nSize, ch, al) { }
  381. #ifdef STDSTRING_INC_COMDEF
  382. inline tstring::tstring(const _bstr_t& bstr) { *this = static_cast<PCTSTR>(bstr); }
  383. #endif
  384. // tstring inline assignment operators -- the erase() function
  385. // call fixes the MSVC assignment bug (see knowledge base article Q172398).
  386. inline tstring& tstring::operator=(const tstring& str)
  387. { if ( str.data() != data() ) { erase(); STRBASE::assign(str.data());} return *this; };
  388. inline tstring& tstring::operator=(const STRBASE& str)
  389. { if ( str.data() != data() ) { erase(); STRBASE::assign(str.data());} return *this; };
  390. inline tstring& tstring::operator=(const STROTHER& str)
  391. { erase(); USES_CONVERSION; STRBASE::assign(O2CT(str.data())); return *this; };
  392. inline tstring& tstring::operator=(PCTSTR pT)
  393. { if ( pT != data() ) { erase(); if ( pT != NULL ) STRBASE::assign(pT); } return *this; };
  394. inline tstring& tstring::operator=(PCOSTR pO)
  395. { erase(); if ( pO != NULL ) { USES_CONVERSION; STRBASE::assign(O2CT(pO)); } return *this; };
  396. inline tstring& tstring::operator=(TOTHER t)
  397. { erase(); USES_CONVERSION; STRBASE::assign(O2CT(&t)); return *this; };
  398. inline tstring& tstring::operator=(TCHAR t)
  399. { erase(); STRBASE::assign(1,t); return *this; };
  400. #ifdef STDSTRING_INC_COMDEF
  401. inline tstring& tstring::operator=(const _bstr_t& bstr)
  402. { return operator=(static_cast<PCTSTR>(bstr)); }
  403. #endif
  404. // These overloads are also needed to fix the MSVC assignment bug (KB: Q172398)
  405. // *** Thanks to Pete The Plumber for catching this one ***
  406. inline tstring& tstring::assign(const tstring& str, tstring::size_type nStart, tstring::size_type nChars)
  407. { if( str.data() != data() ) erase(); STRBASE::assign(str, nStart, nChars); return *this; }
  408. inline tstring& tstring::assign(PCTSTR pT, tstring::size_type nChars)
  409. { if( pT != data() ) erase(); STRBASE::assign(pT, nChars); return *this; }
  410. inline tstring& tstring::assign(tstring::size_type nChars, tstring::value_type val)
  411. { erase(); STRBASE::assign(nChars, val); return *this; }
  412. inline tstring& tstring::assign(const tstring& str)
  413. { return assign(str, 0, npos); }
  414. inline tstring& tstring::assign(PCTSTR pT)
  415. { return assign(pT, tstring::traits_type::length(pT)); }
  416. inline tstring& tstring::assign(tstring::const_iterator iterFirst, tstring::const_iterator iterLast)
  417. { replace(begin(), end(), iterFirst, iterLast); return *this; }
  418. // tstring inline comparison (equality)
  419. inline bool tstring::operator==(const tstring& str) const
  420. { return compare(str.c_str()) == 0; };
  421. inline bool tstring::operator==(const STRBASE& str) const
  422. { return compare(str.data()) == 0; };
  423. inline bool tstring::operator==(const STROTHER& str) const
  424. { USES_CONVERSION; return compare(O2CT(str.data())) == 0; };
  425. inline bool tstring::operator==(PCTSTR pT) const
  426. { return compare(pT) == 0; };
  427. inline bool tstring::operator==(PCOSTR pO) const
  428. { USES_CONVERSION; return compare(O2CT(pO)) == 0; };
  429. inline bool tstring::operator==(TCHAR t) const
  430. { return operator==(STRBASE(1,t)); };
  431. inline bool tstring::operator==(TOTHER t) const
  432. { USES_CONVERSION; return operator==(tstring(O2CT(&t))); };
  433. inline bool tstring::Equals(PCTSTR pT, bool bUseCase/*=false*/) const // defaults to case insensitive
  434. { return bUseCase ? compare(pT) == 0 : _tcsicmp(tstring(*this), pT) == 0; } // get copy, THEN compare (thread safe)
  435. //inline bool tstring::WildcardEquals(PCTSTR pT, bool bUseCase/*=false*/) const // defaults to case insensitive
  436. //{ tstring me(*this), mask(pT); if( !bUseCase ) { me.ToUpper(); mask.ToUpper(); } return Wildstrcmp(me, mask); } // get copy, THEN compare (thread safe)
  437. // tstring inline comparison operators (inequality)
  438. inline bool tstring::operator!=(const tstring& str) const
  439. { return compare(str.c_str()) != 0; };
  440. inline bool tstring::operator!=(const STRBASE& str) const
  441. { return compare(str.data()) != 0; };
  442. inline bool tstring::operator!=(const STROTHER& str) const
  443. { USES_CONVERSION; return compare(O2CT(str.data())) != 0; };
  444. inline bool tstring::operator!=(PCTSTR pT) const
  445. { return compare(pT) != 0; };
  446. inline bool tstring::operator!=(PCOSTR pO) const
  447. { USES_CONVERSION; return compare(O2CT(pO)) != 0; };
  448. inline bool tstring::operator!=(TCHAR t) const
  449. { return operator!=(STRBASE(1,t)); };
  450. inline bool tstring::operator!=(TOTHER t) const
  451. { USES_CONVERSION; return operator!=(tstring(O2CT(&t))); };
  452. // tstring comparison operator (less than)
  453. inline bool tstring::operator<(const tstring& str) const
  454. { return compare(str) < 0; };
  455. inline bool tstring::operator<(PCTSTR str) const
  456. { return compare(str) < 0; };
  457. // tstring inline concatenation.
  458. inline const tstring& tstring::operator+=(const tstring& str)
  459. { append(str); return *this; };
  460. inline const tstring& tstring::operator+=(const STRBASE& str)
  461. { append(str); return *this; };
  462. inline const tstring& tstring::operator+=(const STROTHER& str)
  463. { USES_CONVERSION; *this += O2CT(str.c_str()); return *this; };
  464. inline const tstring& tstring::operator+=(PCTSTR pT)
  465. { if ( pT != NULL ) append(pT); return *this; };
  466. inline const tstring& tstring::operator+=(PCOSTR pO)
  467. { USES_CONVERSION; if ( pO != NULL ) append(O2CT(pO)); return *this; };
  468. inline const tstring& tstring::operator+=(TCHAR t)
  469. { append(1, t); return *this; };
  470. inline const tstring& tstring::operator+=(TOTHER t)
  471. { USES_CONVERSION; append(O2CT(&t)); return *this; };
  472. #ifdef STDSTRING_INC_COMDEF
  473. inline const tstring& tstring::operator+=(const _bstr_t& bstr)
  474. { return operator+=(static_cast<PCTSTR>(bstr)); }
  475. #endif
  476. // tstring friend addition functions defined as inline
  477. inline tstring operator+(const tstring& str1, const tstring& str2)
  478. { tstring strRet(str1); return strRet.append(str2); }
  479. inline tstring operator+(const tstring& str, TCHAR ch)
  480. { tstring strRet(str); return strRet.append(1, ch); }
  481. inline tstring operator+(TCHAR ch, const tstring& str)
  482. { tstring strRet(1, ch); return strRet.append(str); }
  483. inline tstring operator+(const tstring& str, TOTHER ch)
  484. { return str + STROTHER(1, ch).data(); }
  485. inline tstring operator+(TOTHER ch, const tstring& str)
  486. { tstring strRet; strRet = ch; return strRet.append(str); }
  487. inline tstring operator+(const tstring& str, PCTSTR sz)
  488. { tstring strRet(str); return sz == NULL ? strRet : strRet.append(sz); }
  489. inline tstring operator+(PCTSTR sz, const tstring& str)
  490. { tstring strRet(sz); return strRet.append(str); }
  491. inline tstring operator+(const tstring& str, PCOSTR sz)
  492. { tstring strRet(str); return strRet.append(tstring(sz)); }
  493. inline tstring operator+(PCOSTR sz, const tstring& str)
  494. { tstring strRet(sz); return strRet.append(str); }
  495. #ifdef STDSTRING_INC_COMDEF
  496. inline tstring operator+(const _bstr_t& bstr, const tstring& str)
  497. { return tstring(static_cast<PCTSTR>(bstr)) + str; }
  498. inline tstring operator+(const tstring& str, const _bstr_t& bstr)
  499. { return str + static_cast<PCTSTR>(bstr); }
  500. #endif
  501. inline TCHAR& tstring::operator[](int nIdx) { return STRBASE::operator[](nIdx); }
  502. inline const TCHAR& tstring::operator[](int nIdx) const { return STRBASE::operator[](nIdx); }
  503. inline tstring::operator PCTSTR() const { return c_str(); }; // implicit cast to const TCHAR*
  504. // In MFC builds, define some global serialization operators
  505. #ifdef _MFC_VER
  506. CArchive& AFXAPI operator>>(CArchive& ar, tstring& string);
  507. CArchive& AFXAPI operator<<(CArchive& ar, const tstring& string);
  508. inline void tstring::SetResourceHandle(HINSTANCE hNew) { AfxSetResourceHandle(hNew); }
  509. inline HINSTANCE tstring::GetResourceHandle() { return AfxGetResourceHandle(); };
  510. #else
  511. // Because we're a template with no C file, we can't simply have a glocal static
  512. // HINSTANCE. Instead, we have a class-static function which in turn has a static
  513. // HINSTANCE. Since only that class-static function has access to the HINSTANCE,
  514. // it has the ability to set or retrieve its static HINSTANCE.
  515. //
  516. // In short, the HInstanceSingleton is static to the class, and its _hInstance
  517. // variable is static to the HInstanceSingleton function, so the _hInstance variable
  518. // is static to the class.
  519. inline const HINSTANCE & HInstanceSingleton(HINSTANCE hNew = NULL, bool bSet = false)
  520. {
  521. static HINSTANCE _hInstance = ::GetModuleHandle(NULL);
  522. if (bSet)
  523. _hInstance = hNew;
  524. return _hInstance;
  525. }
  526. inline void tstring::SetResourceHandle(HINSTANCE hNew)
  527. {
  528. HInstanceSingleton(hNew, true);
  529. }
  530. inline HINSTANCE tstring::GetResourceHandle()
  531. {
  532. return HInstanceSingleton();
  533. };
  534. #endif
  535. // Some code still refers to old names of this class -- Account for this.
  536. #define CSTLString tstring
  537. #define CW32String tstring
  538. // WUSysMessage -- return the system string corresponding to a system error or HRESULT value.
  539. tstring WUSysMessage(DWORD dwError, DWORD p_dwLangId=MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT));
  540. // WUFormat -- creates and formats a tstring with one line of code instead of the two it normally takes
  541. tstring WUFormat(PCTSTR szFormat, ...);
  542. tstring WUFormat(UINT nId, ...);
  543. // Functional Comparators
  544. //
  545. // These structs are derived from the std::binary_function template. They give us functional
  546. // classes (which may be used in Standard C++ Library collections and algorithms) that perform
  547. // case-insensitive comparisons of tstring objects. This is useful for maps in which the key
  548. // may be the proper string but in the wrong case.
  549. #define tstring_lessnocase _SSLNC // define shorter name to avoid compiler warning 4786
  550. #define tstring_comparenocase _SSENC // define shorter name to avoid compiler warning 4786
  551. struct tstring_lessnocase : std::binary_function<tstring, tstring, bool>
  552. {
  553. bool operator()(const tstring& strFirst, const tstring& strSecond) const
  554. {
  555. return _tcsicmp(strFirst, strSecond) < 0;
  556. }
  557. };
  558. struct tstring_comparenocase : std::binary_function<tstring, tstring, bool>
  559. {
  560. bool operator()(const tstring& strFirst, const tstring& strSecond) const
  561. {
  562. return _tcsicmp(strFirst, strSecond) == 0;
  563. }
  564. };
  565. #endif // #ifndef _STDSTRING_H_