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.

654 lines
24 KiB

  1. /*++
  2. Copyright (c) 2000-2001 Microsoft Corporation
  3. Module Name:
  4. CString.h
  5. Abstract:
  6. A CString class, pure UNICODE internally.
  7. History:
  8. 02/22/2001 robkenny Ported from MFC
  9. 08/14/2001 robkenny Inserted inside the ShimLib namespace.
  10. --*/
  11. #pragma once
  12. #include <limits.h>
  13. namespace ShimLib
  14. {
  15. // Use the standard exception handler, if this is not defined
  16. // the C++ exception handler will be used instead.
  17. //#define USE_SEH
  18. #define AFXAPI __stdcall
  19. #define AFXISAPI __stdcall
  20. #define AFXISAPI_CDECL __cdecl
  21. #define AFX_CDECL __cdecl
  22. #define AFX_INLINE __inline
  23. #define AFX_CORE_DATA
  24. #define AFX_DATA
  25. #define AFX_DATADEF
  26. #define AFX_API
  27. #define AFX_COMDAT
  28. #define AFX_STATIC static
  29. BOOL AFXAPI AfxIsValidString(LPCWSTR lpsz, int nLength = -1);
  30. BOOL AFXAPI AfxIsValidAddress(const void* lp, UINT nBytes, BOOL bReadWrite = TRUE);
  31. inline size_t strlenChars(const char* s1)
  32. {
  33. const char * send = s1;
  34. while (*send)
  35. {
  36. // Can't use CharNextA, since User32 might not be initialized
  37. if (IsDBCSLeadByte(*send))
  38. {
  39. ++send;
  40. }
  41. ++send;
  42. }
  43. return send - s1;
  44. }
  45. // Prototype for a string comparison routine.
  46. typedef WCHAR * (__cdecl *_pfn_wcsstr)(const WCHAR * s1, const WCHAR * s2);
  47. template <class CharType> class CStringData
  48. {
  49. public:
  50. long nRefs; // reference count
  51. int nDataLength; // length of data (including terminator)
  52. int nAllocLength; // length of allocation
  53. // CharType data[nAllocLength]
  54. CharType* data() // CharType* to managed data
  55. { return (CharType*)(this+1); }
  56. };
  57. class CString
  58. {
  59. public:
  60. #ifdef USE_SEH
  61. // SEH Exception information
  62. enum
  63. {
  64. eCStringNoMemoryException = STATUS_NO_MEMORY,
  65. eCStringExceptionValue = 0x12345678,
  66. };
  67. static int ExceptionFilter(PEXCEPTION_POINTERS pexi);
  68. static const ULONG_PTR m_CStringExceptionValue;
  69. #else
  70. // A class used only for throwing C++ exceptions
  71. class CStringError
  72. {
  73. public:
  74. CStringError() {};
  75. ~CStringError() {};
  76. };
  77. #endif
  78. public:
  79. static WCHAR ChNil;
  80. public:
  81. // Constructors
  82. // constructs empty CString
  83. CString();
  84. // copy constructor
  85. CString(const CString & stringSrc);
  86. // from a single character
  87. CString(WCHAR ch, int nRepeat = 1);
  88. // allocate nLen WCHARs space.
  89. CString(int nLength);
  90. CString(const WCHAR * lpsz);
  91. // subset of characters from an ANSI string (converts to WCHAR)
  92. CString(const WCHAR * lpch, int nLength);
  93. // Create from an ANSI string
  94. CString(LPCSTR lpsz);
  95. CString(LPCSTR lpsz, int nCharacters);
  96. // Attributes & Operations
  97. // get data length, number of characters
  98. int GetLength() const;
  99. // TRUE if zero length
  100. BOOL IsEmpty() const;
  101. // clear contents to empty
  102. void Empty();
  103. // return pointer to const string
  104. operator const WCHAR * () const;
  105. const WCHAR * Get() const;
  106. // Get, return NULL if string is empty
  107. const WCHAR * GetNIE() const;
  108. char * GetAnsi() const;
  109. // Get ANSI string: caller is responsible for freeing the string
  110. char * ReleaseAnsi() const;
  111. // Get, return NULL if string is empty
  112. char * GetAnsiNIE() const;
  113. // return single character at zero-based index
  114. WCHAR GetAt(int nIndex) const;
  115. // return single character at zero-based index
  116. WCHAR operator[](int nIndex) const;
  117. // set a single character at zero-based index
  118. void SetAt(int nIndex, WCHAR ch);
  119. // overloaded assignment
  120. // copy string content from UNICODE string
  121. const CString & operator=(const WCHAR * lpsz);
  122. // ref-counted copy from another CString
  123. const CString & operator=(const CString & stringSrc);
  124. // set string content to single character
  125. const CString & operator=(WCHAR ch);
  126. // copy string content from unsigned chars
  127. //const CString & operator=(const unsigned WCHAR* psz);
  128. const CString& CString::operator=(LPCSTR lpsz);
  129. // string concatenation
  130. // concatenate from another CString
  131. const CString & operator+=(const CString & string);
  132. // concatenate a single character
  133. const CString & operator+=(WCHAR ch);
  134. // concatenate a string
  135. const CString & operator+=(const WCHAR * lpsz);
  136. friend CString AFXAPI operator+(const CString & string1, const CString & string2);
  137. friend CString AFXAPI operator+(const CString & string, WCHAR ch);
  138. friend CString AFXAPI operator+(WCHAR ch, const CString & string);
  139. friend CString AFXAPI operator+(const CString & string, const WCHAR * lpsz);
  140. friend CString AFXAPI operator+(const WCHAR * lpsz, const CString & string);
  141. // string comparison
  142. // straight character comparison
  143. int Compare(const WCHAR * lpsz) const;
  144. // compare ignoring case
  145. int CompareNoCase(const WCHAR * lpsz) const;
  146. // NLS aware comparison, case sensitive
  147. int Collate(const WCHAR * lpsz) const;
  148. // NLS aware comparison, case insensitive
  149. int CollateNoCase(const WCHAR * lpsz) const;
  150. int ComparePart(const WCHAR * lpsz, int start, int nChars) const;
  151. int ComparePartNoCase(const WCHAR * lpsz, int start, int nChars) const;
  152. // simple sub-string extraction
  153. // return nCount characters starting at zero-based nFirst
  154. CString Mid(int nFirst, int nCount) const;
  155. // return all characters starting at zero-based nFirst
  156. CString Mid(int nFirst) const;
  157. // return first nCount characters in string
  158. CString Left(int nCount) const;
  159. // return nCount characters from end of string
  160. CString Right(int nCount) const;
  161. // characters from beginning that are also in passed string
  162. CString SpanIncluding(const WCHAR * lpszCharSet) const;
  163. // characters from beginning that are not also in passed string
  164. CString SpanExcluding(const WCHAR * lpszCharSet) const;
  165. // upper/lower/reverse conversion
  166. // NLS aware conversion to uppercase
  167. void MakeUpper();
  168. // NLS aware conversion to lowercase
  169. void MakeLower();
  170. // reverse string right-to-left
  171. void MakeReverse();
  172. // trimming whitespace (either side)
  173. // remove whitespace starting from right edge
  174. void TrimRight();
  175. // remove whitespace starting from left side
  176. void TrimLeft();
  177. // trimming anything (either side)
  178. // remove continuous occurrences of chTarget starting from right
  179. void TrimRight(WCHAR chTarget);
  180. // remove continuous occcurrences of characters in passed string,
  181. // starting from right
  182. void TrimRight(const WCHAR * lpszTargets);
  183. // remove continuous occurrences of chTarget starting from left
  184. void TrimLeft(WCHAR chTarget);
  185. // remove continuous occcurrences of characters in
  186. // passed string, starting from left
  187. void TrimLeft(const WCHAR * lpszTargets);
  188. // advanced manipulation
  189. // replace occurrences of chOld with chNew
  190. int Replace(WCHAR chOld, WCHAR chNew);
  191. // replace occurrences of substring lpszOld with lpszNew;
  192. // empty lpszNew removes instances of lpszOld
  193. int Replace(const WCHAR * lpszOld, const WCHAR * lpszNew);
  194. // Case insensitive version of Replace
  195. int ReplaceI(const WCHAR * lpszOld, const WCHAR * lpszNew);
  196. // remove occurrences of chRemove
  197. int Remove(WCHAR chRemove);
  198. // insert character at zero-based index; concatenates
  199. // if index is past end of string
  200. int Insert(int nIndex, WCHAR ch);
  201. // insert substring at zero-based index; concatenates
  202. // if index is past end of string
  203. int Insert(int nIndex, const WCHAR * pstr);
  204. // delete nCount characters starting at zero-based index
  205. int Delete(int nIndex, int nCount = 1);
  206. // delete all characters to the right of nIndex
  207. void Truncate(int nIndex);
  208. // searching
  209. // find character starting at left, -1 if not found
  210. int Find(WCHAR ch) const;
  211. // find character starting at right
  212. int ReverseFind(WCHAR ch) const;
  213. // find character starting at zero-based index and going right
  214. int Find(WCHAR ch, int nStart) const;
  215. // find first instance of any character in passed string
  216. int FindOneOf(const WCHAR * lpszCharSet) const;
  217. // find first instance of any character in passed string starting at zero-based index
  218. int FindOneOf(const WCHAR * lpszCharSet, int nCount) const;
  219. // find first instance of substring
  220. int Find(const WCHAR * lpszSub) const;
  221. // find first instance of substring starting at zero-based index
  222. int Find(const WCHAR * lpszSub, int nStart) const;
  223. // find first instance of any character *not* in passed string starting at zero-based index
  224. int FindOneNotOf(const WCHAR * lpszCharSet, int nCount) const;
  225. // simple formatting
  226. // printf-like formatting using passed string
  227. void AFX_CDECL Format(const WCHAR * lpszFormat, ...);
  228. // printf-like formatting using referenced string resource
  229. //void AFX_CDECL Format(UINT nFormatID, ...);
  230. // printf-like formatting using variable arguments parameter
  231. void FormatV(const WCHAR * lpszFormat, va_list argList);
  232. // formatting for localization (uses FormatMessage API)
  233. // format using FormatMessage API on passed string
  234. void AFX_CDECL FormatMessage(const WCHAR * lpszFormat, ...);
  235. // input and output
  236. #ifdef _DEBUG
  237. friend CDumpContext& AFXAPI operator<<(CDumpContext& dc,
  238. const CString & string);
  239. #endif
  240. // friend CArchive& AFXAPI operator<<(CArchive& ar, const CString & string);
  241. // friend CArchive& AFXAPI operator>>(CArchive& ar, CString & string);
  242. // friend const CString & AFXAPI AfxGetEmptyString();
  243. // Access to string implementation buffer as "C" character array
  244. // get pointer to modifiable buffer at least as long as nMinBufLength
  245. WCHAR * GetBuffer(int nMinBufLength);
  246. // release buffer, setting length to nNewLength (or to first nul if -1)
  247. void ReleaseBuffer(int nNewLength = -1);
  248. // get pointer to modifiable buffer exactly as long as nNewLength
  249. WCHAR * GetBufferSetLength(int nNewLength);
  250. // release memory allocated to but unused by string
  251. void FreeExtra();
  252. // Use LockBuffer/UnlockBuffer to turn refcounting off
  253. // turn refcounting back on
  254. WCHAR * LockBuffer();
  255. // turn refcounting off
  256. void UnlockBuffer();
  257. // Copy the ansi version of this string into the specified buffer,
  258. DWORD CopyAnsiBytes(char * lpszBuffer, DWORD nBytes);
  259. // Copy the ansi version of this string into the specified buffer,
  260. DWORD CopyAnsiChars(char * lpszBuffer, DWORD nChars);
  261. // ======================================================================
  262. // CString extensions: making life easier.
  263. //
  264. // Win32 API
  265. DWORD GetModuleFileNameW(HMODULE hModule);
  266. DWORD GetShortPathNameW(void);
  267. DWORD GetLongPathNameW(void);
  268. DWORD GetFullPathNameW(void);
  269. DWORD GetSystemDirectoryW(void);
  270. UINT GetSystemWindowsDirectoryW(void);
  271. DWORD GetWindowsDirectoryW(void);
  272. DWORD GetTempPathW(void);
  273. UINT GetTempFileNameW(LPCWSTR lpPathName, LPCWSTR lpPrefixString, UINT uUnique );
  274. DWORD ExpandEnvironmentStringsW(void);
  275. DWORD GetCurrentDirectoryW(void);
  276. // Split this into the seperate path components
  277. void SplitPath(CString * csDrive, CString * csDir, CString * csName, CString * csExt) const;
  278. void MakePath(const CString * csDrive, const CString * csDir, const CString * csName, const CString * csExt);
  279. // Properly append csPath onto the end of this path
  280. void AppendPath(const WCHAR * lpszPath);
  281. // Find the trailing path component
  282. // Return index of the last path seperator or -1 if none found
  283. int FindLastPathComponent() const;
  284. // Get the "file" portion of this path
  285. void GetLastPathComponent(CString & pathComponent) const;
  286. // Get what's not the "file" portion of this path
  287. void GetNotLastPathComponent(CString & pathComponent) const;
  288. // Remove the trailing path component
  289. void StripPath();
  290. // Get the drive portion either c:\ or \\machine\
  291. // Note this is different from SplitPath
  292. void GetDrivePortion(CString & csDrivePortion) const;
  293. // Does this string match the pattern
  294. BOOL PatternMatch(const WCHAR * lpszPattern) const;
  295. BOOL IsPathSep(int index) const;
  296. // More efficient versions of above
  297. void Mid(int nFirst, int nCount, CString & csMid) const;
  298. void Mid(int nFirst, CString & csMid) const;
  299. void Left(int nCount, CString & csLeft) const;
  300. void Right(int nCount, CString & csRight) const;
  301. void SpanIncluding(const WCHAR * lpszCharSet, CString & csSpanInc) const;
  302. void SpanExcluding(const WCHAR * lpszCharSet, CString & csSpanExc) const;
  303. //
  304. // ======================================================================
  305. // Implementation
  306. public:
  307. ~CString();
  308. int GetAllocLength() const;
  309. protected:
  310. WCHAR * m_pchData; // pointer to ref counted string data
  311. mutable char * m_pchDataAnsi; // pointer to non-UNICODE version of string
  312. // implementation helpers
  313. CStringData<WCHAR> * GetData() const;
  314. void Init();
  315. void AllocCopy(CString & dest, int nCopyLen, int nCopyIndex, int nExtraLen) const;
  316. void AllocBuffer(int nLen);
  317. void AssignCopy(int nSrcLen, const WCHAR * lpszSrcData);
  318. void ConcatCopy(int nSrc1Len, const WCHAR * lpszSrc1Data, int nSrc2Len, const WCHAR * lpszSrc2Data);
  319. void ConcatInPlace(int nSrcLen, const WCHAR * lpszSrcData);
  320. void CopyBeforeWrite();
  321. void AllocBeforeWrite(int nLen);
  322. void Release();
  323. //============================================================
  324. // Used by Replace and ReplaceI
  325. int ReplaceRoutine(LPCWSTR lpszOld, LPCWSTR lpszNew, _pfn_wcsstr tcsstr);
  326. static void Release(CStringData<WCHAR>* pData);
  327. static int SafeStrlen(const WCHAR * lpsz);
  328. static void FreeData(CStringData<WCHAR>* pData);
  329. static int _afxInitData[];
  330. static CStringData<WCHAR>* _afxDataNil;
  331. static const WCHAR * _afxPchNil;
  332. };
  333. /*
  334. End of class definitions.
  335. Below are routines that are candidates for inlining.
  336. */
  337. #define afxEmptyString ((CString &)*(CString*)&CString::_afxPchNil)
  338. inline BOOL IsPathSep(WCHAR ch)
  339. {
  340. return ch == L'\\' || ch == L'/';
  341. }
  342. // Compare helpers
  343. AFX_INLINE bool AFXAPI operator==(const CString & s1, const CString & s2) { return s1.Compare(s2) == 0; }
  344. AFX_INLINE bool AFXAPI operator==(const CString & s1, const WCHAR * s2) { return s1.Compare(s2) == 0; }
  345. AFX_INLINE bool AFXAPI operator==(const WCHAR * s1, const CString & s2) { return s2.Compare(s1) == 0; }
  346. AFX_INLINE bool AFXAPI operator!=(const CString & s1, const CString & s2) { return s1.Compare(s2) != 0; }
  347. AFX_INLINE bool AFXAPI operator!=(const CString & s1, const WCHAR * s2) { return s1.Compare(s2) != 0; }
  348. AFX_INLINE bool AFXAPI operator!=(const WCHAR * s1, const CString & s2) { return s2.Compare(s1) != 0; }
  349. AFX_INLINE bool AFXAPI operator<(const CString & s1, const CString & s2) { return s1.Compare(s2) < 0; }
  350. AFX_INLINE bool AFXAPI operator<(const CString & s1, const WCHAR * s2) { return s1.Compare(s2) < 0; }
  351. AFX_INLINE bool AFXAPI operator<(const WCHAR * s1, const CString & s2) { return s2.Compare(s1) > 0; }
  352. AFX_INLINE bool AFXAPI operator>(const CString & s1, const CString & s2) { return s1.Compare(s2) > 0; }
  353. AFX_INLINE bool AFXAPI operator>(const CString & s1, const WCHAR * s2) { return s1.Compare(s2) > 0; }
  354. AFX_INLINE bool AFXAPI operator>(const WCHAR * s1, const CString & s2) { return s2.Compare(s1) < 0; }
  355. AFX_INLINE bool AFXAPI operator<=(const CString & s1, const CString & s2) { return s1.Compare(s2) <= 0; }
  356. AFX_INLINE bool AFXAPI operator<=(const CString & s1, const WCHAR * s2) { return s1.Compare(s2) <= 0; }
  357. AFX_INLINE bool AFXAPI operator<=(const WCHAR * s1, const CString & s2) { return s2.Compare(s1) >= 0; }
  358. AFX_INLINE bool AFXAPI operator>=(const CString & s1, const CString & s2) { return s1.Compare(s2) >= 0; }
  359. AFX_INLINE bool AFXAPI operator>=(const CString & s1, const WCHAR * s2) { return s1.Compare(s2) >= 0; }
  360. AFX_INLINE bool AFXAPI operator>=(const WCHAR * s1, const CString & s2) { return s2.Compare(s1) <= 0; }
  361. // CString
  362. AFX_INLINE CStringData<WCHAR>* CString::GetData() const { ASSERT(m_pchData != NULL, "CString::GetData: NULL m_pchData"); return ((CStringData<WCHAR>*)m_pchData)-1; }
  363. AFX_INLINE void CString::Init() { m_pchData = afxEmptyString.m_pchData; m_pchDataAnsi = NULL; }
  364. AFX_INLINE CString::CString() { Init(); }
  365. //AFX_INLINE CString::CString(const unsigned WCHAR* lpsz) { Init(); *this = (LPCSTR)lpsz; }
  366. //AFX_INLINE const CString & CString::operator=(const unsigned WCHAR* lpsz) { *this = (LPCSTR)lpsz; return *this; }
  367. AFX_INLINE int CString::GetLength() const { return GetData()->nDataLength; }
  368. AFX_INLINE int CString::GetAllocLength() const { return GetData()->nAllocLength; }
  369. AFX_INLINE BOOL CString::IsEmpty() const { return GetData()->nDataLength == 0; }
  370. AFX_INLINE CString::operator const WCHAR *() const { return m_pchData; }
  371. AFX_INLINE const WCHAR * CString::Get() const { return m_pchData; }
  372. AFX_INLINE const WCHAR * CString::GetNIE() const { return IsEmpty() ? NULL : m_pchData; }
  373. AFX_INLINE char * CString::GetAnsiNIE() const { return IsEmpty() ? NULL : GetAnsi(); }
  374. AFX_INLINE char * CString::ReleaseAnsi() const { char * lpsz = GetAnsi(); m_pchDataAnsi = NULL; return lpsz; }
  375. AFX_INLINE int CString::SafeStrlen(const WCHAR * lpsz) { if ( lpsz == NULL ) return 0; else { SIZE_T ilen = wcslen(lpsz); if ( ilen <= INT_MAX ) return (int) ilen; return 0; } }
  376. AFX_INLINE void CString::FreeData(CStringData<WCHAR>* pData) { delete pData; }
  377. AFX_INLINE int CString::Compare(const WCHAR * lpsz) const { ASSERT(AfxIsValidString(lpsz), "CString::Compare: Invalid string"); return wcscmp(m_pchData, lpsz); } // MBCS/Unicode aware
  378. AFX_INLINE int CString::CompareNoCase(const WCHAR * lpsz) const { ASSERT(AfxIsValidString(lpsz), "CString::CompareNoCase: Invalid string"); return _wcsicmp(m_pchData, lpsz); } // MBCS/Unicode aware
  379. AFX_INLINE int CString::Collate(const WCHAR * lpsz) const { ASSERT(AfxIsValidString(lpsz), "CString::Collate: Invalid string"); return wcscoll(m_pchData, lpsz); } // locale sensitive
  380. AFX_INLINE int CString::CollateNoCase(const WCHAR * lpsz) const { ASSERT(AfxIsValidString(lpsz), "CString::CollateNoCase: Invalid string"); return _wcsicoll(m_pchData, lpsz); } // locale sensitive
  381. AFX_INLINE int CString::ComparePart(const WCHAR * lpsz, int start, int nChars) const { ASSERT(AfxIsValidString(lpsz), "CString::CompareNoCase: Invalid string"); return wcsncmp(m_pchData+start, lpsz, nChars); } // MBCS/Unicode aware
  382. AFX_INLINE int CString::ComparePartNoCase(const WCHAR * lpsz, int start, int nChars) const { ASSERT(AfxIsValidString(lpsz), "CString::CompareNoCase: Invalid string"); return _wcsnicmp(m_pchData+start, lpsz, nChars); } // MBCS/Unicode aware
  383. AFX_INLINE WCHAR CString::GetAt(int nIndex) const
  384. {
  385. ASSERT(nIndex >= 0, "CString::GetAt: negative index");
  386. ASSERT(nIndex < GetData()->nDataLength, "CString::GetData: index larger than string");
  387. return m_pchData[nIndex];
  388. }
  389. AFX_INLINE WCHAR CString::operator[](int nIndex) const
  390. {
  391. // same as GetAt
  392. ASSERT(nIndex >= 0, "CString::operator[]: negative index");
  393. ASSERT(nIndex < GetData()->nDataLength, "CString::GetData: index larger than string");
  394. return m_pchData[nIndex];
  395. }
  396. AFX_INLINE BOOL CString::IsPathSep(int index) const
  397. {
  398. return ShimLib::IsPathSep(GetAt(index));
  399. }
  400. #undef afxEmptyString
  401. // ************************************************************************************
  402. // Exception filter for CString __try/__except blocks
  403. // Return EXCEPTION_EXECUTE_HANDLER if this is a CString exception
  404. // otherwise return EXCEPTION_CONTINUE_SEARCH
  405. extern int CStringExceptionFilter(PEXCEPTION_POINTERS pexi);
  406. #if defined(USE_SEH)
  407. #define CSTRING_THROW_EXCEPTION RaiseException((DWORD)CString::eCStringNoMemoryException, 0, 1, &CString::m_CStringExceptionValue); // Continuable, CString specific memory exception
  408. #define CSTRING_TRY __try
  409. #define CSTRING_CATCH __except( CString::ExceptionFilter(GetExceptionInformation()) )
  410. #else
  411. // If we use the C++ exception handler, we need to make sure we have the /GX compile flag
  412. #define CSTRING_THROW_EXCEPTION throw CString::CStringError();
  413. #define CSTRING_TRY try
  414. #define CSTRING_CATCH catch( CString::CStringError & cse )
  415. #endif
  416. }; // end of namespace ShimLib
  417. // ************************************************************************************
  418. namespace ShimLib
  419. {
  420. /*++
  421. Read a registry value into this CString.
  422. REG_EXPAND_SZ is automatically expanded and the type is changed to REG_SZ
  423. If the type is not REG_SZ or REG_EXPAND_SZ, then csRegValue.GetLength()
  424. is the number of *bytes* in the string.
  425. This is typically used to only read REG_SZ/REG_EXPAND_SZ registry values.
  426. Note: This API may only be called after SHIM_STATIC_DLLS_INITIALIZED
  427. --*/
  428. LONG RegQueryValueExW(
  429. CString & csValue,
  430. HKEY hKeyRoot,
  431. const WCHAR * lpszKey,
  432. const WCHAR * lpszValue,
  433. LPDWORD lpType);
  434. /*++
  435. Get the ShSpecial folder name.
  436. Note: This API may only be called after SHIM_STATIC_DLLS_INITIALIZED
  437. --*/
  438. BOOL SHGetSpecialFolderPathW(
  439. CString & csFolder,
  440. int nFolder,
  441. HWND hwndOwner = NULL
  442. );
  443. // ************************************************************************************
  444. /*++
  445. A tokenizer--a replacement for strtok.
  446. Init the class with the string and token delimiter.
  447. Call GetToken to peel off the next token.
  448. ++*/
  449. class CStringToken
  450. {
  451. public:
  452. CStringToken(const CString & csToken, const CString & csDelimit);
  453. // Get the next token
  454. BOOL GetToken(CString & csNextToken);
  455. // Count the number of remaining tokens.
  456. int GetCount() const;
  457. protected:
  458. int m_nPos;
  459. CString m_csToken;
  460. CString m_csDelimit;
  461. BOOL GetToken(CString & csNextToken, int & nPos) const;
  462. };
  463. // ************************************************************************************
  464. /*++
  465. A simple class to assist in command line parsing
  466. --*/
  467. class CStringParser
  468. {
  469. public:
  470. CStringParser(const WCHAR * lpszCl, const WCHAR * lpszSeperators);
  471. ~CStringParser();
  472. int GetCount() const; // Return the current number of args
  473. CString & Get(int nIndex);
  474. CString & operator[](int nIndex);
  475. // Give ownership of the CString array to the caller
  476. // Caller must call delete [] cstring
  477. CString * ReleaseArgv();
  478. protected:
  479. int m_ncsArgList;
  480. CString * m_csArgList;
  481. void SplitSeperator(const CString & csCl, const CString & csSeperator);
  482. void SplitWhite(const CString & csCl);
  483. };
  484. inline int CStringParser::GetCount() const
  485. {
  486. return m_ncsArgList;
  487. }
  488. inline CString & CStringParser::Get(int nIndex)
  489. {
  490. return m_csArgList[nIndex];
  491. }
  492. inline CString & CStringParser::operator[](int nIndex)
  493. {
  494. return m_csArgList[nIndex];
  495. }
  496. inline CString * CStringParser::ReleaseArgv()
  497. {
  498. CString * argv = m_csArgList;
  499. m_csArgList = NULL;
  500. m_ncsArgList = 0;
  501. return argv;
  502. }
  503. }; // end of namespace ShimLib
  504. // ************************************************************************************