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.

395 lines
9.0 KiB

  1. //=======================================================================
  2. //
  3. // Copyright (c) 1998-2000 Microsoft Corporation. All Rights Reserved.
  4. //
  5. // File: StringUtil.CPP
  6. //
  7. // Description:
  8. //
  9. // IU string utility library
  10. //
  11. //=======================================================================
  12. #include <windows.h>
  13. #include <tchar.h>
  14. #include <stringutil.h>
  15. #include <memutil.h>
  16. #include <shlwapi.h>
  17. #include<iucommon.h>
  18. #include<MISTSAFE.h>
  19. #define IfNullReturnNull(ptr) if (NULL == ptr) return NULL;
  20. // ----------------------------------------------------------------------
  21. //
  22. // Public function StrChr() - same as shlwapi StrChr()
  23. // Searches a string for the first occurrence of a character that
  24. // matches the specified character. The comparison is case sensitive.
  25. //
  26. // Input:
  27. // lpStart - Address of the string to be searched
  28. // wMatch - Character to be used for comparison
  29. //
  30. // Return:
  31. // Returns the address of the first occurrence of the character in
  32. // the string if successful, or NULL otherwise.
  33. //
  34. // ----------------------------------------------------------------------
  35. LPCTSTR MyStrChr(LPCTSTR lpStart, const TCHAR wMatch)
  36. {
  37. LPCTSTR lpPtr = lpStart;
  38. IfNullReturnNull(lpStart);
  39. while (_T('\0') != *lpPtr && wMatch != *lpPtr)
  40. {
  41. lpPtr = CharNext(lpPtr);
  42. }
  43. return (_T('\0') != *lpPtr) ? lpPtr : NULL;
  44. }
  45. // ----------------------------------------------------------------------
  46. //
  47. // Public function StrRChr() - same as shlwapi StrRChr()
  48. // Searches a string for the last occurrence of a character that
  49. // matches the specified character. The comparison is case sensitive.
  50. //
  51. // Input:
  52. // lpStart - Address of the string to be searched
  53. // lpEnd - Address of the end of the string (NOT included in the search)
  54. // wMatch - Character to be used for comparison
  55. //
  56. // Return:
  57. // Returns the address of the last occurrence of the character in
  58. // the string if successful, or NULL otherwise.
  59. //
  60. // ----------------------------------------------------------------------
  61. LPCTSTR MyStrRChr(LPCTSTR lpStart, LPCTSTR lpEnd, const TCHAR wMatch)
  62. {
  63. LPCTSTR lpFound = NULL;
  64. IfNullReturnNull(lpStart);
  65. if (NULL == lpEnd)
  66. lpEnd = lpStart + lstrlen(lpStart);
  67. LPCTSTR lpPtr = lpEnd;
  68. while (lpPtr > lpStart)
  69. {
  70. if (*lpPtr == wMatch)
  71. break;
  72. lpPtr = CharPrev(lpStart, lpPtr);
  73. }
  74. if (lpStart == lpPtr)
  75. {
  76. return (*lpStart == wMatch) ? lpStart : NULL;
  77. }
  78. else
  79. {
  80. return (lpPtr > lpStart) ? lpPtr : NULL;
  81. }
  82. }
  83. // ----------------------------------------------------------------------
  84. //
  85. // Public function StrChrI() - same as shlwapi StrChrI()
  86. // Searches a string for the first occurrence of a character that
  87. // matches the specified character. The comparison is case INsensitive.
  88. //
  89. // Input:
  90. // lpStart - Address of the string to be searched
  91. // wMatch - Character to be used for comparison
  92. //
  93. // Return:
  94. // Returns the address of the first occurrence of the character in
  95. // the string if successful, or NULL otherwise.
  96. //
  97. // ----------------------------------------------------------------------
  98. LPCTSTR MyStrChrI(LPCTSTR lpStart, const TCHAR wMatch)
  99. {
  100. LPCTSTR lpPtr;
  101. LPTSTR lpBuffer;
  102. DWORD dwLength;
  103. HANDLE hHeap;
  104. IfNullReturnNull(lpStart);
  105. //
  106. // get buffer to store search string
  107. //
  108. hHeap = GetProcessHeap();
  109. dwLength = lstrlen(lpStart);
  110. lpBuffer = (LPTSTR) HeapAlloc(
  111. GetProcessHeap(),
  112. 0,
  113. (dwLength + 1) * sizeof(TCHAR)
  114. );
  115. IfNullReturnNull(lpBuffer);
  116. //
  117. // copy the search string to buffer
  118. //
  119. //The buffer allocated is sufficient to hold the lpStart string.
  120. StringCchCopyEx(lpBuffer,dwLength + 1,lpStart,NULL,NULL,MISTSAFE_STRING_FLAGS);
  121. //
  122. // based on the case of wMatch, determine how to convert
  123. // the search string
  124. //
  125. if (IsCharUpper(wMatch))
  126. {
  127. CharUpperBuff(lpBuffer, dwLength);
  128. }
  129. else
  130. {
  131. CharLowerBuff(lpBuffer, dwLength);
  132. }
  133. //
  134. // search the char in in new string
  135. //
  136. lpPtr = lpBuffer;
  137. while (_T('\0') != *lpPtr && wMatch != *lpPtr)
  138. {
  139. lpPtr = CharNext(lpPtr);
  140. }
  141. //
  142. // map the position to original string, if found.
  143. //
  144. lpPtr = (_T('\0') != *lpPtr) ? lpStart + (lpPtr - lpBuffer) : NULL;
  145. HeapFree(hHeap, 0, lpBuffer);
  146. return lpPtr;
  147. }
  148. // ----------------------------------------------------------------------
  149. //
  150. // Convert a long number content in bstr into long
  151. // if error, 0 returned.
  152. //
  153. // ----------------------------------------------------------------------
  154. LONG MyBSTR2L(BSTR bstrLongNumber)
  155. {
  156. USES_IU_CONVERSION;
  157. LPTSTR lpszNumber = OLE2T(bstrLongNumber);
  158. return StrToInt(lpszNumber);
  159. }
  160. // ----------------------------------------------------------------------
  161. //
  162. // Convert a a long number into bstr
  163. //
  164. // ----------------------------------------------------------------------
  165. BSTR MyL2BSTR(LONG lNumber)
  166. {
  167. USES_IU_CONVERSION;
  168. WCHAR sNumber[32];
  169. StringCchPrintfExW(sNumber,ARRAYSIZE(sNumber),NULL,NULL,MISTSAFE_STRING_FLAGS,L"%ld", lNumber);
  170. return SysAllocString(sNumber);
  171. }
  172. BSTR MyUL2BSTR(ULONG ulNumber)
  173. {
  174. USES_IU_CONVERSION;
  175. WCHAR sNumber[32];
  176. StringCchPrintfExW(sNumber,ARRAYSIZE(sNumber),NULL,NULL,MISTSAFE_STRING_FLAGS,L"%lu", ulNumber);
  177. return SysAllocString(sNumber);
  178. }
  179. // ----------------------------------------------------------------------
  180. //
  181. // Compare a binary buffer with a string, where data in the string
  182. // has format:
  183. //
  184. // <String> ::= <Number> [<Space><String>]
  185. // <Space> ::= TCHAR(' ')
  186. // <Number> ::= 0x<HexValue>|x<HexValue>|<Decimal>
  187. // <Decimal> ::= +<DecimalValue>|-<DecimalValue>
  188. // <DecimalValue> ::= <DecimalDigit>|<DecimalDigit><DecimalValue>
  189. // <DecimalDegit> ::= 0|1|2|3|4|5|6|7|8|9
  190. // <HexValue> ::= <HexDigit>|<HexDigit><HexDigit>
  191. // <HexDigit> ::= <DecimalDigit>|A|B|C|D|E|F
  192. //
  193. // example of strings that this function recognize:
  194. // "12 0 45 0x1F"
  195. //
  196. // Return: similar to lstrcmp() API, each byte is compared
  197. // as unsigned short
  198. // if binary > string, +1
  199. // if binary = string, 0
  200. // if binary < string, -1
  201. //
  202. // Note:
  203. // If the string is shorter than binary buffer, i.e., string contains
  204. // less byte data than the binary buffer contain, we only compare till
  205. // the number of bytes provided by the string offered.
  206. // This request is based on the fact that many v3 data has reg value
  207. // as DWORD but the update created the value with type binary. so for
  208. // string data, e.g., it's "1", for binary data, it's "01 00 00 00" for
  209. // 4 bytes, this function will return 0 meaning equality, per request
  210. // from aavon for bug 364085 in Whistler RAID.
  211. //
  212. // ----------------------------------------------------------------------
  213. int CmpBinaryToString(
  214. LPBYTE pBinaryBuffer, // buffer to contain binary data
  215. UINT nBinarySize, // number of bytes this binary has data
  216. LPCTSTR pstrValue // string contains data to compare
  217. )
  218. {
  219. int rc = 0;
  220. int iNumber;
  221. UINT nCharCount = nBinarySize;
  222. LPCTSTR lpNumber = pstrValue;
  223. if (NULL == pBinaryBuffer)
  224. {
  225. if (NULL == pstrValue)
  226. {
  227. return 0; // both NULL
  228. }
  229. nBinarySize = 0; // make sure
  230. }
  231. if (NULL == pstrValue || _T('\0') == *pstrValue)
  232. {
  233. //
  234. // this is the case that binary not null,
  235. // but string null.
  236. // as of lstrcmp(), string 1 > string 2
  237. //
  238. return +1;
  239. }
  240. while (nBinarySize > 0)
  241. {
  242. if (NULL == lpNumber || _T('\0') == *lpNumber)
  243. {
  244. //
  245. // when binary not done, string done, we don't care the left binary
  246. //
  247. return 0;
  248. }
  249. if (!StrToIntEx(lpNumber, STIF_SUPPORT_HEX, &iNumber) ||
  250. iNumber < 0 ||
  251. iNumber > 255)
  252. {
  253. //
  254. // found un-convertable number in the
  255. // string. or the number if out of range
  256. // of a byte, treat it invalid, so the
  257. // binary win
  258. //
  259. iNumber = 0x0;
  260. }
  261. if ((unsigned short)pBinaryBuffer[nCharCount - nBinarySize] > (unsigned short) iNumber)
  262. {
  263. return +1;
  264. }
  265. else if ((unsigned short)pBinaryBuffer[nCharCount - nBinarySize] < (unsigned short) iNumber)
  266. {
  267. //
  268. // binary is smaller
  269. //
  270. return -1;
  271. }
  272. //
  273. // if equal, continue to compare next byte
  274. //
  275. nBinarySize--;
  276. //
  277. // skip the white spaces before this number
  278. //
  279. while (_T('\0') != *lpNumber &&
  280. (_T(' ') == *lpNumber ||
  281. _T('\t') == *lpNumber ||
  282. _T('\r') == *lpNumber ||
  283. _T('\n') == *lpNumber)) lpNumber++;
  284. //
  285. // try to find the beginning of the next number
  286. //
  287. lpNumber = StrChr(lpNumber, _T(' '));
  288. }
  289. //
  290. // these two parameters point to data having same meaning
  291. //
  292. return 0;
  293. }
  294. /*
  295. * FUNCTION: int atoh(char *ptr)
  296. *
  297. * PURPOSE: This function converts an hexadecimal string into it's decimal value.
  298. *
  299. * PARAMETERS:
  300. *
  301. * char *ptr: pointer to string to be converted
  302. *
  303. * RETURNS: The converted value.
  304. *
  305. * COMMENTS: Like atoi this function ends the conversion on the first innvalid
  306. * hex digit.
  307. *
  308. */
  309. int atoh(LPCSTR ptr)
  310. {
  311. int i = 0;
  312. char ch;
  313. //skip 0x if present
  314. if (NULL == ptr) return 0;
  315. if ( ptr[0] == '0') ptr++;
  316. if ( ptr[0] == 'x' || ptr[0] == 'X') ptr++;
  317. while( 1 )
  318. {
  319. ch = (char)toupper(*ptr);
  320. if ( (ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'F') )
  321. {
  322. ch -= '0';
  323. if ( ch > 10 )
  324. ch -= 7;
  325. i *= 16;
  326. i += (int)ch;
  327. ptr++;
  328. continue;
  329. }
  330. break;
  331. }
  332. return i;
  333. }