Leaked source code of windows server 2003
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.

1227 lines
34 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // File: strings.cpp
  4. //
  5. // Module: CMUTIL.DLL
  6. //
  7. // Synopsis: Basic string manipulation routines
  8. //
  9. // Copyright (c) 1997-1999 Microsoft Corporation
  10. //
  11. // Author: henryt Created 03/01/98
  12. //
  13. //+----------------------------------------------------------------------------
  14. #include "cmmaster.h"
  15. //
  16. // Include the locale-safe replacement for lstrcmpi
  17. //
  18. #define _CMUTIL_STRINGS_CPP_
  19. #include "CompareString.cpp"
  20. //+----------------------------------------------------------------------------
  21. //
  22. // Function: WzToSz
  23. //
  24. // Synopsis: Standard conversion function for converting Wide Characters to
  25. // Ansi Characters
  26. //
  27. // Arguments: IN LPCWSTR pszwStrIn - Input Unicode string
  28. // OUT LPSTR pszStrOut - Ansi Ouput Buffer
  29. // IN int nOutBufferSize - number of Chars in pszStrOut
  30. //
  31. // Returns: int - 0 on failure, if return Value is > nOutBufferSize then the
  32. // buffer is too small. Otherwise the number of chars copied
  33. // to pszStrOut.
  34. //
  35. // History: Created Header 4/22/99
  36. //
  37. //+----------------------------------------------------------------------------
  38. CMUTILAPI int WzToSz(IN LPCWSTR pszwStrIn, OUT LPSTR pszStrOut, IN int nOutBufferSize)
  39. {
  40. int nReturn = 0;
  41. //
  42. // nOutBufferSize could be 0 and pszStrOut could be NULL (passing zero size and a NULL out
  43. // buffer causes WideCharToMultiByte to return the number of chars needed to convert the
  44. // input string. It is used as a sizing technique). Only check pszwStrIn
  45. //
  46. if (pszwStrIn)
  47. {
  48. nReturn = WideCharToMultiByte(CP_ACP, 0, pszwStrIn, -1, pszStrOut, nOutBufferSize, NULL, NULL);
  49. }
  50. else
  51. {
  52. SetLastError(ERROR_INVALID_PARAMETER);
  53. }
  54. return nReturn;
  55. }
  56. //+----------------------------------------------------------------------------
  57. //
  58. // Function: SzToWz
  59. //
  60. // Synopsis: Standard Wrapper for converting from an Ansi string to a Wide String
  61. //
  62. // Arguments: IN LPCSTR pszInput - Ansi String to Convert
  63. // OUT LPWSTR pszwOutput - Wide string output buffer
  64. // IN int nBufferSize - number of chars in Wide String buffer
  65. //
  66. // Returns: int - 0 on failure, otherwise if return is < nBufferSize then insufficient
  67. // buffer space. Otherwise the number of chars copied to the buffer.
  68. //
  69. // History: quintinb Created 4/22/99
  70. //
  71. //+----------------------------------------------------------------------------
  72. CMUTILAPI int SzToWz(IN LPCSTR pszInput, OUT LPWSTR pszwOutput, IN int nBufferSize)
  73. {
  74. int nReturn = 0;
  75. if (pszInput)
  76. {
  77. return MultiByteToWideChar(CP_ACP, 0, pszInput, -1, pszwOutput, nBufferSize);
  78. }
  79. else
  80. {
  81. SetLastError(ERROR_INVALID_PARAMETER);
  82. }
  83. return nReturn;
  84. }
  85. //+----------------------------------------------------------------------------
  86. //
  87. // Function: SzToWzWithAlloc
  88. //
  89. // Synopsis: Simple wrapper to encapsulate converting a string from
  90. // MultiByte To Wide Char that Allocates memory using the sizing
  91. // capabilities of the MultiByteToWideChar Api.
  92. //
  93. // Arguments: LPCSTR pszAnsiString - Source string to be converted.
  94. //
  95. // Returns: LPWSTR - returns NULL on failure, otherwise the converted string.
  96. // The caller is responsible for freeing the Alloc-ed Memory.
  97. //
  98. // History: quintinb Created 4/8/99
  99. //
  100. //+----------------------------------------------------------------------------
  101. CMUTILAPI LPWSTR SzToWzWithAlloc(LPCSTR pszAnsiString)
  102. {
  103. LPWSTR pszwString = NULL;
  104. DWORD dwSize = 0;
  105. //
  106. // Find out how large the string is by calling MultiByteToWideChar with
  107. // Zero for the size field.
  108. //
  109. if (NULL != pszAnsiString)
  110. {
  111. dwSize = SzToWz(pszAnsiString, NULL, 0);
  112. CMASSERTMSG((dwSize != 0), TEXT("SzToWzWithAlloc -- First MultiByteToWideChar Failed."));
  113. if (0 != dwSize)
  114. {
  115. pszwString = (LPWSTR)CmMalloc(dwSize*sizeof(WCHAR));
  116. CMASSERTMSG(pszwString, TEXT("SzToWzWithAlloc -- CmMalloc of pszwString Failed."));
  117. if (pszwString)
  118. {
  119. if (!SzToWz(pszAnsiString, pszwString, dwSize))
  120. {
  121. //
  122. // Make sure to return a NULL string if we fail.
  123. //
  124. CMASSERTMSG(FALSE, TEXT("SzToWzWithAlloc -- Second MultiByteToWideChar Failed."));
  125. CmFree(pszwString);
  126. pszwString = NULL;
  127. }
  128. #ifdef DEBUG
  129. else
  130. {
  131. //
  132. // If this is a debug build then we want to take the Wide string that we are going to
  133. // return, convert it to Ansi and compare it to the original ansi string passed in.
  134. //
  135. LPSTR pszString;
  136. dwSize = WzToSz(pszwString, NULL, 0);
  137. if (0 != dwSize)
  138. {
  139. pszString = (LPSTR)CmMalloc(dwSize*sizeof(CHAR));
  140. CMASSERTMSG(pszString, TEXT("SzToWzWithAlloc -- conversion of return value back to original Ansi string failed. Unable to allocate memory."));
  141. if (pszString)
  142. {
  143. if (WzToSz(pszwString, pszString, dwSize))
  144. {
  145. MYDBGASSERT(0 == lstrcmpA(pszString, pszAnsiString));
  146. }
  147. else
  148. {
  149. CMASSERTMSG(FALSE, TEXT("SzToWzWithAlloc -- conversion of return value back to original Ansi string failed."));
  150. }
  151. CmFree(pszString);
  152. }
  153. }
  154. else
  155. {
  156. CMASSERTMSG(FALSE, TEXT("SzToWzWithAlloc -- conversion of return value back to original Ansi string failed. Unable to properly size the string."));
  157. }
  158. }
  159. #endif
  160. }
  161. }
  162. }
  163. return pszwString;
  164. }
  165. //+----------------------------------------------------------------------------
  166. //
  167. // Function: WzToSzWithAlloc
  168. //
  169. // Synopsis: Simple wrapper to encapsulate converting a string from
  170. // Unicode to MBCS that allocates memory using the sizing
  171. // capabilities of the WideCharToMultiByte Api.
  172. //
  173. // Arguments: LPCWSTR pszwWideString - Source string to be converted.
  174. //
  175. // Returns: LPSTR - returns NULL on failure, otherwise the converted string.
  176. // The caller is responsible for freeing the Alloc-ed Memory.
  177. //
  178. // History: quintinb Created 4/8/99
  179. //
  180. //+----------------------------------------------------------------------------
  181. CMUTILAPI LPSTR WzToSzWithAlloc(LPCWSTR pszwWideString)
  182. {
  183. LPSTR pszString = NULL;
  184. DWORD dwSize = 0;
  185. //
  186. // Find out how large the string is by calling WideCharToMultiByte with
  187. // Zero for the size field.
  188. //
  189. if (NULL != pszwWideString)
  190. {
  191. dwSize = WzToSz(pszwWideString, NULL, 0);
  192. CMASSERTMSG((0 != dwSize), TEXT("WzToSzWithAlloc -- First WzToSz Failed."));
  193. if (0 != dwSize)
  194. {
  195. pszString = (LPSTR)CmMalloc(dwSize*sizeof(CHAR));
  196. CMASSERTMSG(pszString, TEXT("WzToSzWithAlloc -- CmMalloc failed to alloc pszString."));
  197. if (pszString)
  198. {
  199. if (!WzToSz(pszwWideString, pszString, dwSize))
  200. {
  201. //
  202. // Make sure to return a NULL string if we fail.
  203. //
  204. CMASSERTMSG(FALSE, TEXT("WzToSzWithAlloc -- Second WzToSz Failed."));
  205. CmFree(pszString);
  206. pszString = NULL;
  207. }
  208. #ifdef DEBUG
  209. else
  210. {
  211. //
  212. // If this is a debug build then we want to take the Ansi string that we are
  213. // going to return, convert it to Unicode and compare it to the original Unicode
  214. // string passed in.
  215. //
  216. LPWSTR pszwString;
  217. dwSize = SzToWz(pszString, NULL, 0);
  218. if (0 != dwSize)
  219. {
  220. pszwString = (LPWSTR)CmMalloc(dwSize*sizeof(WCHAR));
  221. CMASSERTMSG(pszwString, TEXT("WzToSzWithAlloc -- conversion of return value back to original Ansi string failed. Unable to allocate memory."));
  222. if (pszwString)
  223. {
  224. if (SzToWz(pszString, pszwString, dwSize))
  225. {
  226. MYDBGASSERT(0 == lstrcmpU(pszwString, pszwWideString));
  227. }
  228. else
  229. {
  230. CMASSERTMSG(FALSE, TEXT("WzToSzWithAlloc -- conversion of return value back to original Ansi string failed."));
  231. }
  232. CmFree(pszwString);
  233. }
  234. }
  235. else
  236. {
  237. CMASSERTMSG(FALSE, TEXT("WzToSzWithAlloc -- conversion of return value back to original Ansi string failed. Unable to properly size the string."));
  238. }
  239. }
  240. #endif
  241. }
  242. }
  243. }
  244. return pszString;
  245. }
  246. //+----------------------------------------------------------------------------
  247. //
  248. // Function: CmStrTrimA
  249. //
  250. // Synopsis: Helper function to trim leading and trailing blanks from a
  251. // string
  252. //
  253. // Arguments: LPTSTR pszStr - The string to be trimmed
  254. //
  255. // Returns: void WINAPI - Nothing
  256. //
  257. // History: nickball Created Header 3/11/98
  258. //
  259. //+----------------------------------------------------------------------------
  260. CMUTILAPI void WINAPI CmStrTrimA(LPSTR pszStr)
  261. {
  262. //
  263. // first, skip all the spaces at the begining of the string
  264. //
  265. MYDBGASSERT(pszStr);
  266. if (pszStr)
  267. {
  268. LPSTR pszTmp = pszStr;
  269. while (CmIsSpaceA(pszTmp))
  270. {
  271. pszTmp = CharNextA(pszTmp);
  272. }
  273. if (pszTmp != pszStr)
  274. {
  275. CmMoveMemory(pszStr, pszTmp, lstrlenA(pszTmp)+1);
  276. }
  277. //
  278. // secondly, delete all the spaces at the end of the string
  279. //
  280. pszTmp = CmEndOfStrA(pszStr);
  281. while (pszTmp != pszStr)
  282. {
  283. pszTmp = CharPrevA(pszStr, pszTmp);
  284. if (!CmIsSpaceA(pszTmp))
  285. {
  286. break;
  287. }
  288. *pszTmp = TEXT('\0');
  289. }
  290. }
  291. }
  292. //+----------------------------------------------------------------------------
  293. //
  294. // Function: CmStrTrimW
  295. //
  296. // Synopsis: Helper function to trim leading and trailing blanks from a
  297. // string.
  298. //
  299. // Arguments: LPTSTR pszStr - The string to be trimmed
  300. //
  301. // Returns: void WINAPI - Nothing
  302. //
  303. // History: quintinb Created 2/27/99
  304. //
  305. //+----------------------------------------------------------------------------
  306. CMUTILAPI void WINAPI CmStrTrimW(LPWSTR pszStr)
  307. {
  308. //
  309. // first, skip all the spaces at the begining of the string
  310. //
  311. MYDBGASSERT(pszStr);
  312. if (pszStr)
  313. {
  314. LPWSTR pszTmp = pszStr;
  315. while (CmIsSpaceW(pszTmp))
  316. {
  317. pszTmp = CharNextU(pszTmp);
  318. }
  319. if (pszTmp != pszStr)
  320. {
  321. CmMoveMemory(pszStr, pszTmp, (lstrlenU(pszTmp)+1)*sizeof(WCHAR));
  322. }
  323. //
  324. // secondly, delete all the spaces at the end of the string
  325. //
  326. pszTmp = CmEndOfStrW(pszStr);
  327. while (pszTmp != pszStr)
  328. {
  329. pszTmp = CharPrevU(pszStr, pszTmp);
  330. if (!CmIsSpaceW(pszTmp))
  331. {
  332. break;
  333. }
  334. *pszTmp = TEXT('\0');
  335. }
  336. }
  337. }
  338. //+----------------------------------------------------------------------------
  339. //
  340. // Function: CmIsSpaceA
  341. //
  342. // Synopsis: Checks to see if the char is a space. Note that spaces, new line chars,
  343. // line feed chars, tabs, and most other forms of whitespace are considered
  344. // spaces.
  345. //
  346. // Arguments: psz - an ansi or dbcs char
  347. //
  348. // Returns: TRUE or FALSE
  349. //
  350. //+----------------------------------------------------------------------------
  351. CMUTILAPI BOOL WINAPI CmIsSpaceA(LPSTR psz)
  352. {
  353. WORD wType = 0;
  354. MYDBGASSERT(psz);
  355. if (psz)
  356. {
  357. if (IsDBCSLeadByte(*psz))
  358. {
  359. MYVERIFY(GetStringTypeExA(LOCALE_USER_DEFAULT, CT_CTYPE1, psz, 2, &wType));
  360. }
  361. else
  362. {
  363. MYVERIFY(GetStringTypeExA(LOCALE_USER_DEFAULT, CT_CTYPE1, psz, 1, &wType));
  364. }
  365. }
  366. return (wType & C1_SPACE);
  367. }
  368. //+----------------------------------------------------------------------------
  369. //
  370. // Function: CmIsSpaceW
  371. //
  372. // Synopsis: Checks to see if the char is a space. Note that spaces, new line chars,
  373. // line feed chars, tabs, and most other forms of whitespace are considered
  374. // spaces.
  375. //
  376. // Arguments: psz - pointer to a string
  377. //
  378. // Returns: TRUE or FALSE
  379. //
  380. //+----------------------------------------------------------------------------
  381. CMUTILAPI BOOL WINAPI CmIsSpaceW(LPWSTR pszwStr)
  382. {
  383. WORD wType = 0;
  384. LPWSTR pszwNextChar;
  385. int iCharCount;
  386. MYDBGASSERT(pszwStr);
  387. if (pszwStr)
  388. {
  389. pszwNextChar = CharNextU(pszwStr);
  390. iCharCount = (INT)(pszwNextChar - pszwStr);
  391. if (0 == GetStringTypeExU(LOCALE_USER_DEFAULT, CT_CTYPE1, pszwStr, iCharCount, &wType))
  392. {
  393. CMTRACE3(TEXT("CmIsSpaceW -- GetStringTypeExW failed on %s, iCharCount is %d, GLE=%u"), pszwStr, iCharCount, GetLastError());
  394. return FALSE;
  395. }
  396. }
  397. return (wType & C1_SPACE);
  398. }
  399. //+----------------------------------------------------------------------------
  400. //
  401. // Function: CmIsDigitA
  402. //
  403. // Synopsis: Checks to see if the char is a digit.
  404. //
  405. // Arguments: psz - an ansi or dbcs char
  406. //
  407. // Returns: TRUE or FALSE
  408. //
  409. //+----------------------------------------------------------------------------
  410. CMUTILAPI BOOL WINAPI CmIsDigitA(LPSTR psz)
  411. {
  412. WORD wType = 0;
  413. MYDBGASSERT(psz);
  414. if (psz)
  415. {
  416. if (IsDBCSLeadByte(*psz))
  417. {
  418. MYVERIFY(GetStringTypeExA(LOCALE_USER_DEFAULT, CT_CTYPE1, psz, 2, &wType));
  419. }
  420. else
  421. {
  422. MYVERIFY(GetStringTypeExA(LOCALE_USER_DEFAULT, CT_CTYPE1, psz, 1, &wType));
  423. }
  424. }
  425. return (wType & C1_DIGIT);
  426. }
  427. //+----------------------------------------------------------------------------
  428. //
  429. // Function: CmIsDigitW
  430. //
  431. // Synopsis: Checks to see if the WCHAR is a digit.
  432. //
  433. // Arguments: pszwStr -- WCHAR string
  434. //
  435. // Returns: TRUE or FALSE
  436. //
  437. //+----------------------------------------------------------------------------
  438. CMUTILAPI BOOL WINAPI CmIsDigitW(LPWSTR pszwStr)
  439. {
  440. WORD wType = 0;
  441. LPWSTR pszwNextChar;
  442. int iCharCount;
  443. MYDBGASSERT(pszwStr);
  444. if (pszwStr)
  445. {
  446. pszwNextChar = CharNextU(pszwStr);
  447. iCharCount = (INT)(pszwNextChar - pszwStr);
  448. if (0 == GetStringTypeExU(LOCALE_USER_DEFAULT, CT_CTYPE1, pszwStr, iCharCount, &wType))
  449. {
  450. CMTRACE1(TEXT("CmIsDigitW -- GetStringTypeExU failed, GLE=%u"), GetLastError());
  451. return FALSE;
  452. }
  453. }
  454. return (wType & C1_DIGIT);
  455. }
  456. //+----------------------------------------------------------------------------
  457. //
  458. // Function: CmEndOfStrA
  459. //
  460. // Synopsis: Given a string, returns the ptr to the end of the string(null char).
  461. //
  462. // Arguments: psz - an ansi or dbcs char
  463. //
  464. // Returns: LPSTR ptr to null char
  465. //
  466. //+----------------------------------------------------------------------------
  467. CMUTILAPI LPSTR WINAPI CmEndOfStrA(LPSTR psz)
  468. {
  469. MYDBGASSERT(psz);
  470. if (psz)
  471. {
  472. while (*psz)
  473. {
  474. psz = CharNextA(psz);
  475. }
  476. }
  477. return psz;
  478. }
  479. //+----------------------------------------------------------------------------
  480. //
  481. // Function: CmEndOfStrW
  482. //
  483. // Synopsis: Given a string, returns the ptr to the end of the string(null char).
  484. //
  485. // Arguments: pszwStr - a WCHAR
  486. //
  487. // Returns: LPWSTR ptr to null char
  488. //
  489. //+----------------------------------------------------------------------------
  490. CMUTILAPI LPWSTR WINAPI CmEndOfStrW(LPWSTR pszwStr)
  491. {
  492. MYDBGASSERT(pszwStr);
  493. if (pszwStr)
  494. {
  495. while (*pszwStr)
  496. {
  497. pszwStr = CharNextU(pszwStr);
  498. }
  499. }
  500. return pszwStr;
  501. }
  502. //+----------------------------------------------------------------------------
  503. //
  504. // Function: CmStrCpyAllocA
  505. //
  506. // Synopsis: Copies pszSrc into a newly allocated buffer (using CmMalloc) and
  507. // returns the buffer to its caller who is responsible for freeing
  508. // the buffer.
  509. //
  510. // Arguments: LPCSTR pszSrc - source string
  511. //
  512. // Returns: LPSTR - returns NULL if pszSrc is NULL or the Alloc fails,
  513. // otherwise it returns the newly allocated buffer with
  514. // a copy of pszSrc in it.
  515. //
  516. // History: quintinb Created Header and changed name to include Alloc 4/9/99
  517. //
  518. //+----------------------------------------------------------------------------
  519. CMUTILAPI LPSTR CmStrCpyAllocA(LPCSTR pszSrc)
  520. {
  521. LPSTR pszBuffer = NULL;
  522. if (pszSrc)
  523. {
  524. pszBuffer = (LPSTR) CmMalloc(lstrlenA(pszSrc) + 1);
  525. if (pszBuffer)
  526. {
  527. lstrcpyA(pszBuffer, pszSrc);
  528. }
  529. }
  530. return (pszBuffer);
  531. }
  532. //+----------------------------------------------------------------------------
  533. //
  534. // Function: CmStrCpyAllocW
  535. //
  536. // Synopsis: Copies pszSrc into a newly allocated buffer (using CmMalloc) and
  537. // returns the buffer to its caller who is responsible for freeing
  538. // the buffer.
  539. //
  540. // Arguments: LPCSTR pszSrc - source string
  541. //
  542. // Returns: LPSTR - returns NULL if pszSrc is NULL or the Alloc fails,
  543. // otherwise it returns the newly allocated buffer with
  544. // a copy of pszSrc in it.
  545. //
  546. // History: quintinb Created Header and changed name to include Alloc 4/9/99
  547. //
  548. //+----------------------------------------------------------------------------
  549. CMUTILAPI LPWSTR CmStrCpyAllocW(LPCWSTR pszSrc)
  550. {
  551. LPWSTR pszBuffer = NULL;
  552. if (pszSrc)
  553. {
  554. size_t nLen = lstrlenU(pszSrc) + 1;
  555. pszBuffer = (LPWSTR) CmMalloc(nLen*sizeof(WCHAR));
  556. if (pszBuffer)
  557. {
  558. lstrcpyU(pszBuffer, pszSrc);
  559. }
  560. }
  561. return (pszBuffer);
  562. }
  563. //+----------------------------------------------------------------------------
  564. //
  565. // Function: CmStrCatAllocA
  566. //
  567. // Synopsis: This function reallocs the passed in string to a size large enough
  568. // to hold the original data and the concatenates the new string onto
  569. // the original string.
  570. //
  571. // Arguments: LPSTR *ppszDst - original string
  572. // LPCSTR pszSrc - new piece of string to concatenate
  573. //
  574. // Returns: LPSTR - pointer to the concatenated string
  575. //
  576. // History: quintinb Created Header 4/9/99
  577. //
  578. //+----------------------------------------------------------------------------
  579. CMUTILAPI LPSTR CmStrCatAllocA(LPSTR *ppszDst, LPCSTR pszSrc)
  580. {
  581. if (!ppszDst)
  582. {
  583. return NULL;
  584. }
  585. if (pszSrc && *pszSrc)
  586. {
  587. DWORD dwSize = (lstrlenA(*ppszDst) + lstrlenA(pszSrc) + 1);
  588. LPSTR pszTmp = (LPSTR)CmRealloc((LPVOID)*ppszDst, dwSize);
  589. if (NULL != pszTmp)
  590. {
  591. lstrcatA(pszTmp, pszSrc);
  592. *ppszDst = pszTmp;
  593. }
  594. }
  595. return (*ppszDst);
  596. }
  597. //+----------------------------------------------------------------------------
  598. //
  599. // Function: CmStrCatAllocW
  600. //
  601. // Synopsis: This function reallocs the passed in string to a size large enough
  602. // to hold the original data and the concatenates the new string onto
  603. // the original string.
  604. //
  605. // Arguments: LPWSTR *ppszDst - original string
  606. // LPCWSTR pszSrc - new piece of string to concatenate
  607. //
  608. // Returns: LPWSTR - pointer to the concatenated string
  609. //
  610. // History: quintinb Created Header 4/9/99
  611. //
  612. //+----------------------------------------------------------------------------
  613. CMUTILAPI LPWSTR CmStrCatAllocW(LPWSTR *ppszDst, LPCWSTR pszSrc)
  614. {
  615. if (!ppszDst)
  616. {
  617. return NULL;
  618. }
  619. if (pszSrc && *pszSrc)
  620. {
  621. DWORD dwSize = (lstrlenU(*ppszDst) + lstrlenU(pszSrc) + 1)*sizeof(WCHAR);
  622. LPWSTR pszTmp = (LPWSTR)CmRealloc((LPVOID)*ppszDst, dwSize);
  623. if (NULL != pszTmp)
  624. {
  625. lstrcatU(pszTmp, pszSrc);
  626. *ppszDst = pszTmp;
  627. }
  628. }
  629. return (*ppszDst);
  630. }
  631. //+----------------------------------------------------------------------------
  632. //
  633. // Function: CmStrchrA
  634. //
  635. // Synopsis: This function returns the first occurence of ch in the string pszString.
  636. //
  637. // Arguments: LPCSTR pszString - String to search in
  638. // CHAR ch - character to look for
  639. //
  640. // Returns: LPSTR - pointer to the first occurence of the Character ch in pszString
  641. //
  642. // History: quintinb Created Header 4/9/99
  643. //
  644. //+----------------------------------------------------------------------------
  645. CMUTILAPI LPSTR WINAPI CmStrchrA(LPCSTR pszString, const char ch)
  646. {
  647. LPSTR pszTmp = (LPSTR)pszString;
  648. if (NULL == pszTmp)
  649. {
  650. CMASSERTMSG(FALSE, TEXT("CmStrchr - NULL pointer passed"));
  651. return NULL;
  652. }
  653. while (*pszTmp && (*pszTmp != ch))
  654. {
  655. pszTmp = CharNextA(pszTmp);
  656. }
  657. if (*pszTmp == ch)
  658. {
  659. return pszTmp;
  660. }
  661. return NULL;
  662. }
  663. //+----------------------------------------------------------------------------
  664. //
  665. // Function: CmStrchrW
  666. //
  667. // Synopsis: This function returns the first occurence of ch in the string pszString.
  668. //
  669. // Arguments: LPCWSTR pszString - String to search in
  670. // WCHAR ch - character to look for
  671. //
  672. // Returns: LPWSTR - pointer to the first occurence of the Character ch in pszString
  673. //
  674. // History: quintinb Created Header 4/9/99
  675. //
  676. //+----------------------------------------------------------------------------
  677. CMUTILAPI LPWSTR WINAPI CmStrchrW(LPCWSTR pszString, const WCHAR ch)
  678. {
  679. LPWSTR pszTmp = (LPWSTR)pszString;
  680. if (NULL == pszTmp)
  681. {
  682. CMASSERTMSG(FALSE, TEXT("CmStrchr - NULL pointer passed"));
  683. return NULL;
  684. }
  685. while (*pszTmp && (*pszTmp != ch))
  686. {
  687. pszTmp = CharNextU(pszTmp);
  688. }
  689. if (*pszTmp == ch)
  690. {
  691. return pszTmp;
  692. }
  693. return NULL;
  694. }
  695. //+----------------------------------------------------------------------------
  696. //
  697. // Function: CmStrrchrA
  698. //
  699. // Synopsis: Find the last occurence of a character in a string
  700. //
  701. // Arguments: LPCSTR pszString - string to search in
  702. // CHAR ch - character to look for
  703. //
  704. // Returns: LPSTR - NULL if the char is not found, a pointer to the char in
  705. // the string otherwise
  706. //
  707. // History: quintinb Created Header and cleaned up 4/9/99
  708. //
  709. //+----------------------------------------------------------------------------
  710. CMUTILAPI LPSTR CmStrrchrA (LPCSTR pszString, const char ch)
  711. {
  712. LPSTR pszTmp = NULL;
  713. LPSTR pszCurrent = (LPSTR)pszString;
  714. if (NULL == pszString)
  715. {
  716. CMASSERTMSG(FALSE, TEXT("CmStrrchr - NULL pointer passed"));
  717. }
  718. else
  719. {
  720. while (TEXT('\0') != *pszCurrent)
  721. {
  722. if (ch == (*pszCurrent))
  723. {
  724. pszTmp = pszCurrent;
  725. }
  726. pszCurrent = CharNextA(pszCurrent);
  727. }
  728. }
  729. return pszTmp;
  730. }
  731. //+----------------------------------------------------------------------------
  732. //
  733. // Function: CmStrrchrW
  734. //
  735. // Synopsis: Find the last occurence of a character in a string
  736. //
  737. // Arguments: LPCWSTR pszString - string to search in
  738. // WCHAR ch - character to look for
  739. //
  740. // Returns: LPWSTR - NULL if the char is not found, a pointer to the char in
  741. // the string otherwise
  742. //
  743. // History: quintinb Created Header and cleaned up 4/9/99
  744. //
  745. //+----------------------------------------------------------------------------
  746. CMUTILAPI LPWSTR CmStrrchrW (LPCWSTR pszString, const WCHAR ch)
  747. {
  748. LPWSTR pszTmp = NULL;
  749. LPWSTR pszCurrent = (LPWSTR)pszString;
  750. if (NULL == pszString)
  751. {
  752. CMASSERTMSG(FALSE, TEXT("CmStrrchr - NULL pointer passed"));
  753. }
  754. else
  755. {
  756. while (TEXT('\0') != *pszCurrent)
  757. {
  758. if (ch == (*pszCurrent))
  759. {
  760. pszTmp = pszCurrent;
  761. }
  762. pszCurrent = CharNextU(pszCurrent);
  763. }
  764. }
  765. return pszTmp;
  766. }
  767. //+----------------------------------------------------------------------------
  768. //
  769. // Function: CmStrtokA
  770. //
  771. // Synopsis: CM implementation of strtok
  772. //
  773. // Arguments: LPSTR pszStr - string to tokenize or NULL if getting a second token
  774. // LPCSTR pszControl - set of token chars
  775. //
  776. // Returns: LPSTR - NULL if no token could be found or a pointer to a token string.
  777. //
  778. // History: quintinb Created Header and cleaned up for UNICODE conversion 4/9/99
  779. //
  780. //+----------------------------------------------------------------------------
  781. CMUTILAPI LPSTR CmStrtokA(LPSTR pszStr, LPCSTR pszControl)
  782. {
  783. LPSTR pszToken;
  784. LPSTR pszTmpStr;
  785. LPCSTR pszTmpCtl;
  786. LPSTR pszTmpDelim;
  787. //
  788. // If the pszStr param is NULL, then we need to retrieve the stored string
  789. //
  790. if (NULL != pszStr)
  791. {
  792. pszTmpStr = pszStr;
  793. }
  794. else
  795. {
  796. pszTmpStr = (LPSTR)TlsGetValue(g_dwTlsIndex);
  797. }
  798. //
  799. // Find beginning of token (skip over leading delimiters). Note that
  800. // there is no token if this loop sets string to point to the terminal
  801. // null (*string == '\0')
  802. //
  803. while (*pszTmpStr)
  804. {
  805. for (pszTmpCtl = pszControl; *pszTmpCtl && *pszTmpCtl != *pszTmpStr;
  806. pszTmpCtl = CharNextA(pszTmpCtl))
  807. {
  808. ; // do nothing
  809. }
  810. if (!*pszTmpCtl)
  811. {
  812. break;
  813. }
  814. pszTmpStr = CharNextA(pszTmpStr);
  815. }
  816. pszToken = pszTmpStr;
  817. //
  818. // Find the end of the token. If it is not the end of the string,
  819. // put a null there.
  820. //
  821. for ( ; *pszTmpStr ; pszTmpStr = CharNextA(pszTmpStr))
  822. {
  823. for (pszTmpCtl = pszControl; *pszTmpCtl && *pszTmpCtl != *pszTmpStr;
  824. pszTmpCtl = CharNextA(pszTmpCtl))
  825. {
  826. ; // Do nothing
  827. }
  828. if (*pszTmpCtl)
  829. {
  830. pszTmpDelim = pszTmpStr;
  831. pszTmpStr = CharNextA(pszTmpStr);
  832. *pszTmpDelim = '\0';
  833. break;
  834. }
  835. }
  836. //
  837. // Update nextoken (or the corresponding field in the per-thread data structure
  838. //
  839. TlsSetValue(g_dwTlsIndex, (LPVOID)pszTmpStr);
  840. //
  841. // Determine if a token has been found.
  842. //
  843. if (pszToken == pszTmpStr)
  844. {
  845. return NULL;
  846. }
  847. else
  848. {
  849. return pszToken;
  850. }
  851. }
  852. //+----------------------------------------------------------------------------
  853. //
  854. // Function: CmStrtokW
  855. //
  856. // Synopsis: CM implementation of strtok
  857. //
  858. // Arguments: LPWSTR pszStr - string to tokenize or NULL if getting a second tokey
  859. // LPCWSTR pszControl - set of token chars
  860. //
  861. // Returns: LPWSTR - NULL if no token could be found or a pointer to a token string.
  862. //
  863. // History: quintinb Created Header and cleaned up for UNICODE conversion 4/9/99
  864. //
  865. //+----------------------------------------------------------------------------
  866. CMUTILAPI LPWSTR CmStrtokW(LPWSTR pszStr, LPCWSTR pszControl)
  867. {
  868. LPWSTR pszToken;
  869. LPWSTR pszTmpStr;
  870. LPWSTR pszTmpCtl;
  871. LPWSTR pszTmpDelim;
  872. //
  873. // If the pszStr param is NULL, then we need to retrieve the stored string
  874. //
  875. if (NULL != pszStr)
  876. {
  877. pszTmpStr = pszStr;
  878. }
  879. else
  880. {
  881. pszTmpStr = (LPWSTR)TlsGetValue(g_dwTlsIndex);
  882. }
  883. //
  884. // Find beginning of token (skip over leading delimiters). Note that
  885. // there is no token iff this loop sets string to point to the terminal
  886. // null (*string == '\0')
  887. //
  888. while (*pszTmpStr)
  889. {
  890. for (pszTmpCtl = (LPWSTR)pszControl; *pszTmpCtl && *pszTmpCtl != *pszTmpStr;
  891. pszTmpCtl = CharNextU(pszTmpCtl))
  892. {
  893. ; // do nothing
  894. }
  895. if (!*pszTmpCtl)
  896. {
  897. break;
  898. }
  899. pszTmpStr = CharNextU(pszTmpStr);
  900. }
  901. pszToken = pszTmpStr;
  902. //
  903. // Find the end of the token. If it is not the end of the string,
  904. // put a null there.
  905. //
  906. for ( ; *pszTmpStr ; pszTmpStr = CharNextU(pszTmpStr))
  907. {
  908. for (pszTmpCtl = (LPWSTR)pszControl; *pszTmpCtl && *pszTmpCtl != *pszTmpStr;
  909. pszTmpCtl = CharNextU(pszTmpCtl))
  910. {
  911. ; // Do nothing
  912. }
  913. if (*pszTmpCtl)
  914. {
  915. pszTmpDelim = pszTmpStr;
  916. pszTmpStr = CharNextU(pszTmpStr);
  917. *pszTmpDelim = L'\0';
  918. break;
  919. }
  920. }
  921. //
  922. // Update nextoken (or the corresponding field in the per-thread data structure
  923. //
  924. TlsSetValue(g_dwTlsIndex, (LPVOID)pszTmpStr);
  925. //
  926. // Determine if a token has been found.
  927. //
  928. if (pszToken == pszTmpStr)
  929. {
  930. return NULL;
  931. }
  932. else
  933. {
  934. return pszToken;
  935. }
  936. }
  937. //+----------------------------------------------------------------------------
  938. //
  939. // Function: CmStrStrA
  940. //
  941. // Synopsis: Simple replacement for StrStr from C runtime
  942. //
  943. // Arguments: LPCTSTR pszString - The string to search in
  944. // LPCTSTR pszSubString - The string to search for
  945. //
  946. // Returns: LPTSTR - Ptr to the first occurence of pszSubString in pszString.
  947. // NULL if pszSubString does not occur in pszString
  948. //
  949. //
  950. // History: nickball Created Header 04/01/98
  951. // nickball Added ptr check 02/21/99
  952. // quintinb rewrote for unicode conversion 04/08/99
  953. //
  954. //+----------------------------------------------------------------------------
  955. CMUTILAPI LPSTR CmStrStrA(LPCSTR pszString, LPCSTR pszSubString)
  956. {
  957. //
  958. // Check the inputs
  959. //
  960. MYDBGASSERT(pszString);
  961. MYDBGASSERT(pszSubString);
  962. if (NULL == pszSubString || NULL == pszString)
  963. {
  964. return NULL;
  965. }
  966. //
  967. // Check to make sure we have something to look for
  968. //
  969. if (TEXT('\0') == pszSubString[0])
  970. {
  971. return((LPSTR)pszString);
  972. }
  973. //
  974. // Okay, start looking for the string
  975. //
  976. LPSTR pszCurrent = (LPSTR)pszString;
  977. LPSTR pszTmp1;
  978. LPSTR pszTmp2;
  979. while (*pszCurrent)
  980. {
  981. pszTmp1 = pszCurrent;
  982. pszTmp2 = (LPSTR) pszSubString;
  983. while (*pszTmp1 && *pszTmp2 && ((*pszTmp1) == (*pszTmp2)))
  984. {
  985. pszTmp1 = CharNextA(pszTmp1);
  986. pszTmp2 = CharNextA(pszTmp2);
  987. }
  988. if (TEXT('\0') == *pszTmp2)
  989. {
  990. return pszCurrent;
  991. }
  992. pszCurrent = CharNextA(pszCurrent);
  993. }
  994. return NULL;
  995. }
  996. //+----------------------------------------------------------------------------
  997. //
  998. // Function: CmStrStrW
  999. //
  1000. // Synopsis: Simple replacement for StrStr from C runtime
  1001. //
  1002. // Arguments: LPCTSTR pszString - The string to search in
  1003. // LPCTSTR pszSubString - The string to search for
  1004. //
  1005. // Returns: LPTSTR - Ptr to the first occurence of pszSubString in pszString.
  1006. // NULL if pszSubString does not occur in pszString
  1007. //
  1008. //
  1009. // History: nickball Created Header 04/01/98
  1010. // nickball Added ptr check 02/21/99
  1011. // quintinb rewrote for unicode conversion 04/08/99
  1012. //
  1013. //+----------------------------------------------------------------------------
  1014. CMUTILAPI LPWSTR CmStrStrW(LPCWSTR pszString, LPCWSTR pszSubString)
  1015. {
  1016. //
  1017. // Check the inputs
  1018. //
  1019. MYDBGASSERT(pszString);
  1020. MYDBGASSERT(pszSubString);
  1021. if (NULL == pszSubString || NULL == pszString)
  1022. {
  1023. return NULL;
  1024. }
  1025. //
  1026. // Check to make sure we have something to look for
  1027. //
  1028. if (TEXT('\0') == pszSubString[0])
  1029. {
  1030. return((LPWSTR)pszString);
  1031. }
  1032. //
  1033. // Okay, start looking for the string
  1034. //
  1035. LPWSTR pszCurrent = (LPWSTR)pszString;
  1036. LPWSTR pszTmp1;
  1037. LPWSTR pszTmp2;
  1038. while (*pszCurrent)
  1039. {
  1040. pszTmp1 = pszCurrent;
  1041. pszTmp2 = (LPWSTR) pszSubString;
  1042. while (*pszTmp1 && *pszTmp2 && ((*pszTmp1) == (*pszTmp2)))
  1043. {
  1044. pszTmp1 = CharNextU(pszTmp1);
  1045. pszTmp2 = CharNextU(pszTmp2);
  1046. }
  1047. if (TEXT('\0') == *pszTmp2)
  1048. {
  1049. return pszCurrent;
  1050. }
  1051. pszCurrent = CharNextU(pszCurrent);
  1052. }
  1053. return NULL;
  1054. }
  1055. //+----------------------------------------------------------------------------
  1056. //
  1057. // Function: CmCompareStringA
  1058. //
  1059. // Synopsis: redirected to function in CompareString.cpp
  1060. //
  1061. //+----------------------------------------------------------------------------
  1062. CMUTILAPI int CmCompareStringA(LPCSTR lpString1, LPCSTR lpString2)
  1063. {
  1064. return SafeCompareStringA(lpString1, lpString2);
  1065. }
  1066. //+----------------------------------------------------------------------------
  1067. //
  1068. // Function: CmCompareStringW
  1069. //
  1070. // Synopsis: redirected to function in CompareString.cpp
  1071. //
  1072. //+----------------------------------------------------------------------------
  1073. CMUTILAPI int CmCompareStringW(LPCWSTR lpString1, LPCWSTR lpString2)
  1074. {
  1075. return SafeCompareStringW(lpString1, lpString2);
  1076. }