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.

404 lines
14 KiB

  1. #ifndef __VSTRING_HPP
  2. #define __VSTRING_HPP
  3. #include "vStandard.h"
  4. // <VDOC<CLASS=VString><DESC=Encapsulates a dynamically allocated C style string><FAMILY=String Processing><AUTHOR=Todd Osborne ([email protected])>VDOC>
  5. class VString
  6. {
  7. public:
  8. // Default constructor
  9. VString()
  10. { m_lpszString = NULL; }
  11. // Construct with existing C string
  12. VString(LPCTSTR lpszString, int nCount = -1)
  13. { m_lpszString = NULL; AllocCopy(lpszString, TRUE, nCount); }
  14. // Construct with existing VString reference
  15. VString(VString& strOriginal, int nCount = -1)
  16. { m_lpszString = NULL; AllocCopy(strOriginal.GetBuffer(), TRUE, nCount); }
  17. // Construct with existing VString pointer
  18. VString(VString* pstrOriginal, int nCount = -1)
  19. { m_lpszString = NULL; AllocCopy(*pstrOriginal, TRUE, nCount); }
  20. // Construct by loading string from resouce. If hResource is NULL, VGetResourceHandle() will be used
  21. VString(UINT nStringID, HINSTANCE hResource = NULL)
  22. { m_lpszString = NULL; LoadString(nStringID, hResource); }
  23. // Construct by initializing with text from a window
  24. VString(HWND hWnd)
  25. { m_lpszString = NULL; GetWindowText(hWnd); }
  26. // Destructor
  27. virtual ~VString()
  28. { Empty(); }
  29. // Overloaded Operators
  30. // Return C style strings
  31. TCHAR &operator[](int nIndex)
  32. { assert(m_lpszString); assert(nIndex < lstrlen(m_lpszString)); return m_lpszString[nIndex]; }
  33. operator LPTSTR()
  34. { return m_lpszString; }
  35. operator LPCTSTR()
  36. { return m_lpszString; }
  37. // Assignment
  38. BOOL operator = (LPCTSTR lpszString)
  39. { return AllocCopy(lpszString, TRUE); }
  40. BOOL operator = (VString& string)
  41. { return AllocCopy((LPCTSTR)string, TRUE); }
  42. BOOL operator = (VString* pString)
  43. { return AllocCopy((LPCTSTR)*pString, TRUE); }
  44. // Concatenation
  45. BOOL operator += (TCHAR nChar)
  46. { return AddChar(nChar); }
  47. BOOL operator += (LPCTSTR lpszString)
  48. { return AllocCopy(lpszString, FALSE); }
  49. BOOL operator += (VString& string)
  50. { return AllocCopy((LPCTSTR)string, FALSE); }
  51. BOOL operator += (VString* pString)
  52. { return AllocCopy((LPCTSTR)*pString, FALSE); }
  53. // Comparison without case
  54. BOOL operator == (LPCTSTR lpszString)
  55. { return CompareNoCase(lpszString) == 0; }
  56. BOOL operator == (VString& string)
  57. { return CompareNoCase((LPCTSTR)string) == 0; }
  58. BOOL operator == (VString* pString)
  59. { return CompareNoCase((LPCTSTR)*pString) == 0; }
  60. BOOL operator != (LPCTSTR lpszString)
  61. { return CompareNoCase(lpszString) != 0; }
  62. BOOL operator != (VString& string)
  63. { return CompareNoCase((LPCTSTR)string) != 0; }
  64. BOOL operator != (VString* pString)
  65. { return CompareNoCase((LPCTSTR)*pString) != 0; }
  66. BOOL operator < (LPCTSTR lpszString)
  67. { return CompareNoCase(lpszString) == -1; }
  68. BOOL operator < (VString& string)
  69. { return CompareNoCase((LPCTSTR)string) == -1; }
  70. BOOL operator < (VString* pString)
  71. { return CompareNoCase((LPCTSTR)*pString) == -1; }
  72. BOOL operator <= (LPCTSTR lpszString)
  73. { return CompareNoCase(lpszString) != 1; }
  74. BOOL operator <= (VString& string)
  75. { return CompareNoCase((LPCTSTR)string) != -1; }
  76. BOOL operator <= (VString* pString)
  77. { return CompareNoCase((LPCTSTR)*pString) != -1; }
  78. BOOL operator > (LPCTSTR lpszString)
  79. { return CompareNoCase(lpszString) == 1; }
  80. BOOL operator > (VString& string)
  81. { return CompareNoCase((LPCTSTR)string) == 1; }
  82. BOOL operator > (VString* pString)
  83. { return CompareNoCase((LPCTSTR)*pString) == 1; }
  84. BOOL operator >= (LPCTSTR lpszString)
  85. { return CompareNoCase(lpszString) != -1; }
  86. BOOL operator >= (VString& string)
  87. { return CompareNoCase((LPCTSTR)string) != -1; }
  88. BOOL operator >= (VString* pString)
  89. { return CompareNoCase((LPCTSTR)*pString) != -1; }
  90. // Add a single character to the end of the string
  91. // Protected by critical section in AllocCopy()
  92. BOOL AddChar(TCHAR nChar)
  93. { TCHAR sz[] = {nChar, _T('\0')}; return AllocCopy(sz, FALSE); }
  94. // Case sensitive comparison
  95. // Returns zero if the strings are identical, -1 if this VString object is less than lpszString, or 1 if this VString object is greater than lpszString
  96. int Compare(LPCTSTR lpszString)
  97. { assert(m_lpszString && lpszString); return lstrcmp(m_lpszString, lpszString); }
  98. // Compare without case
  99. // Returns zero if the strings are identical (ignoring case), -1 if this VString object is less than lpszString (ignoring case), or 1 if this VString object is greater than lpszString (ignoring case)
  100. int CompareNoCase(LPCTSTR lpszString)
  101. { assert(m_lpszString && lpszString); return lstrcmpi(m_lpszString, lpszString); }
  102. // Clear contents of string
  103. void Empty()
  104. {
  105. if (NULL != m_lpszString) {
  106. delete [] m_lpszString;
  107. m_lpszString = NULL;
  108. }
  109. }
  110. // Find first occurence of substring or character in string. Returns index into string if found, -1 otherwise
  111. int Find(LPCTSTR lpszSubString)
  112. { assert(m_lpszString && lpszSubString); LPTSTR lpszFound = _tcsstr(m_lpszString, lpszSubString); return (lpszFound) ? (int)(lpszFound - m_lpszString) : -1; }
  113. int Find(TCHAR nChar)
  114. { assert(m_lpszString); LPTSTR lpszFound = _tcschr(m_lpszString, nChar); return (lpszFound) ? (int)(lpszFound - m_lpszString) : -1; }
  115. // Get the internal buffer
  116. LPTSTR GetBuffer()
  117. { return m_lpszString; }
  118. // Get the length of the string
  119. int GetLength()
  120. { return (m_lpszString) ? lstrlen(m_lpszString) : 0; }
  121. // Set the path of the module in hInstance into VString. If bPathOnly is specified,
  122. // only the path, including the last backlash will be saved, otherwise the entire path will be.
  123. // If hInstance is NULL, VGetInstanceHandle() will be used
  124. BOOL GetModulePath(HINSTANCE hInstance = NULL, BOOL bPathOnly = TRUE)
  125. {
  126. TCHAR sz[MAX_PATH] = {_T('\0')};
  127. if ( GetModuleFileName((hInstance) ? hInstance : VGetInstanceHandle(), sz, sizeof(sz)/sizeof(TCHAR)) )
  128. {
  129. // Terminate after last backslash?
  130. TCHAR *pszEnd = (bPathOnly) ? _tcsrchr(sz, _T('\\')) : NULL;
  131. if ( pszEnd )
  132. *(pszEnd + 1) = _T('\0');
  133. return AllocCopy(sz, TRUE);
  134. }
  135. return FALSE;
  136. }
  137. // Copy text from a window to the VString
  138. BOOL GetWindowText(HWND hWnd)
  139. {
  140. assert(hWnd && IsWindow(hWnd));
  141. BOOL bResult = TRUE;
  142. if ( hWnd && IsWindow(hWnd) )
  143. {
  144. int nLen = (int)::SendMessage(hWnd, WM_GETTEXTLENGTH, 0, 0);
  145. if ( nLen )
  146. {
  147. TCHAR sz[1024];
  148. LPTSTR lpszWindowText = sz;
  149. // Dynamic memory alloc only if stack is not sufficient
  150. if ( nLen > sizeof(sz - 1)/sizeof(TCHAR) )
  151. lpszWindowText = new TCHAR[nLen + 1];
  152. if ( lpszWindowText )
  153. {
  154. // Get text and copy to VString
  155. ::GetWindowText(hWnd, lpszWindowText, nLen + 1);
  156. bResult = AllocCopy(lpszWindowText, TRUE);
  157. }
  158. else
  159. return FALSE;
  160. // Free if not stack alloc
  161. if ( lpszWindowText != sz )
  162. delete [] lpszWindowText;
  163. }
  164. else
  165. // Empty window text is still valid. VString is reset
  166. Empty();
  167. }
  168. return bResult;
  169. }
  170. // Is the string empty?
  171. BOOL IsEmpty()
  172. { return (GetLength()) ? FALSE : TRUE; }
  173. // Substring extraction
  174. VString Left(int nCount)
  175. { VString str; str.AllocCopy(m_lpszString, TRUE, nCount); return str; }
  176. // Load a string from resources. Returns TRUE on success, FALSE on failure
  177. // If hResource is NULL, VGetResourceHandle() will be used
  178. BOOL LoadString(UINT nStringID, HINSTANCE hResource = NULL)
  179. {
  180. TCHAR szTemp[1024];
  181. BOOL bResult = FALSE;
  182. if ( !hResource )
  183. hResource = VGetResourceHandle();
  184. assert(hResource);
  185. // Attempt to load string into stack buffer first
  186. int nLen = ::LoadString(hResource, nStringID, szTemp, sizeof(szTemp)/sizeof(TCHAR));
  187. if ( nLen )
  188. {
  189. if ( nLen == sizeof(szTemp)/sizeof(TCHAR) - 1 )
  190. {
  191. // Calculate the largest size possible for string block (whole block, not just nStringID)
  192. HRSRC hRes = FindResource(hResource, MAKEINTRESOURCE((nStringID >> 4) + 1), RT_STRING);
  193. DWORD dwSize = (hRes) ? SizeofResource(hResource, hRes) : 0;
  194. assert(dwSize);
  195. // Allocate temporary block equal to the size of the entire string block
  196. // This is quite wasteful, but WinAPI does not provide a way to extract an
  197. // exact string length from the resources, and LoadString() will copy only
  198. // up to the buffer size, truncating longer strings
  199. LPTSTR lpszNewString = new TCHAR[dwSize + 1];
  200. if ( lpszNewString )
  201. {
  202. // Load string into temp var and AllocCopy() to set permanently
  203. bResult = (::LoadString(hResource, nStringID, lpszNewString, dwSize)) ? AllocCopy(lpszNewString, TRUE) : FALSE;
  204. // Free local string
  205. delete [] lpszNewString;
  206. }
  207. }
  208. else
  209. bResult = AllocCopy(szTemp, TRUE);
  210. }
  211. return bResult;
  212. }
  213. // Make the string a GetOpenFileName() or GetSaveFileName() filter. That is, replace
  214. // all occurances of \n in the string with \0 (zero terminators)
  215. LPCTSTR MakeFilter()
  216. {
  217. int nLen = GetLength();
  218. for ( int i = 0; i < nLen; i++ )
  219. {
  220. if ( *(m_lpszString + i) == _T('\n') )
  221. *(m_lpszString + i) = _T('\0');
  222. }
  223. return m_lpszString;
  224. }
  225. // Make all characters lower case
  226. LPCTSTR MakeLower()
  227. { assert(m_lpszString); return _tcslwr(m_lpszString); }
  228. // Make all characters upper case
  229. LPCTSTR MakeUpper()
  230. { assert(m_lpszString); return _tcsupr(m_lpszString); }
  231. // Substring extraction
  232. VString Mid(int nFirst, int nCount)
  233. {
  234. assert(m_lpszString);
  235. assert(nCount >= 0);
  236. VString str;
  237. if ( nFirst < GetLength() )
  238. str.AllocCopy(m_lpszString + nFirst, TRUE, nCount);
  239. return str;
  240. }
  241. VString Mid(int nFirst)
  242. { return Mid(nFirst, GetLength() - nFirst); }
  243. VString Right(int nCount)
  244. {
  245. assert(m_lpszString);
  246. VString str;
  247. if ( nCount <= GetLength() )
  248. str.AllocCopy(m_lpszString + (GetLength() - nCount), TRUE, nCount);
  249. return str;
  250. }
  251. // Remote all spaces from left and right side of string
  252. void Trim()
  253. { TrimLeft(); TrimRight(); }
  254. // Remove all space characters from left side of string
  255. void TrimLeft()
  256. {
  257. if ( m_lpszString )
  258. {
  259. int nIndex = 0;
  260. while ( m_lpszString[nIndex] && m_lpszString[nIndex] == _T(' '))
  261. nIndex++;
  262. if ( nIndex )
  263. AllocCopy(m_lpszString + nIndex, TRUE);
  264. }
  265. }
  266. // Remove all space characters from right side of string
  267. void TrimRight()
  268. {
  269. if ( m_lpszString )
  270. {
  271. int nLength = GetLength();
  272. int nIndex = nLength - 1;
  273. while ( m_lpszString[nIndex] && m_lpszString[nIndex] == _T(' '))
  274. nIndex--;
  275. if ( nIndex < nLength - 1 )
  276. AllocCopy(m_lpszString, TRUE, nIndex + 1);
  277. }
  278. }
  279. protected:
  280. // Allocate and copy. If nCount is -1, entire string will be copied, otherwise only nCount characters
  281. BOOL AllocCopy(LPCTSTR lpszString, BOOL bReplace, int nCount = -1)
  282. {
  283. // Fix count of characters to copy if needed
  284. if ( nCount == -1 )
  285. nCount = lstrlen(lpszString);
  286. // Determine length of lpszString
  287. int nLen = (lpszString) ? lstrlen(lpszString) : 0;
  288. if ( nLen )
  289. {
  290. // nCount should not be less that or equal to 0
  291. assert(nCount > 0);
  292. // Use the min of nLen and nCount as the new length
  293. if ( nCount < nLen )
  294. nLen = nCount;
  295. // Allocate memory to new buffer
  296. LPTSTR lpszNewString = new TCHAR[nLen + 1 + ((bReplace || !GetLength()) ? 0 : GetLength())];
  297. if ( lpszNewString )
  298. {
  299. if ( bReplace || !m_lpszString )
  300. lstrcpyn(lpszNewString, lpszString, nLen + 1);
  301. else
  302. {
  303. // Append
  304. lstrcpy(lpszNewString, m_lpszString);
  305. lstrcpyn(lpszNewString + GetLength(), lpszString, nLen + 1);
  306. }
  307. // Free old memory and save new pointer
  308. Empty();
  309. m_lpszString = lpszNewString;
  310. }
  311. else
  312. return FALSE;
  313. }
  314. else
  315. Empty();
  316. return TRUE;
  317. }
  318. private:
  319. // Embedded Member(s)
  320. LPTSTR m_lpszString;
  321. };
  322. #endif // __VSTRING_HPP