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.

523 lines
11 KiB

  1. /*** strlib.c - string functions
  2. *
  3. * Copyright (c) 1996,1997 Microsoft Corporation
  4. * Author: Michael Tsang (MikeTs)
  5. * Created 09/09/96
  6. *
  7. * MODIFICATION HISTORY
  8. */
  9. #include "pch.h"
  10. #ifdef LOCKABLE_PRAGMA
  11. #pragma ACPI_LOCKABLE_DATA
  12. #pragma ACPI_LOCKABLE_CODE
  13. #endif
  14. /***EP StrLen - determine string length
  15. *
  16. * ENTRY
  17. * psz -> string
  18. * n - limiting length
  19. *
  20. * EXIT
  21. * returns string length
  22. */
  23. ULONG EXPORT StrLen(PSZ psz, ULONG n)
  24. {
  25. TRACENAME("STRLEN")
  26. ULONG dwLen;
  27. ENTER(5, ("StrLen(str=%s,n=%d)\n", psz, n));
  28. ASSERT(psz != NULL);
  29. if (n != (ULONG)-1)
  30. n++;
  31. for (dwLen = 0; (dwLen <= n) && (*psz != '\0'); psz++)
  32. dwLen++;
  33. EXIT(5, ("StrLen=%u\n", dwLen));
  34. return dwLen;
  35. } //StrLen
  36. /***EP StrCpy - copy string
  37. *
  38. * ENTRY
  39. * pszDst -> destination string
  40. * pszSrc -> source string
  41. * n - number of bytes to copy
  42. *
  43. * EXIT
  44. * returns pszDst
  45. */
  46. PSZ EXPORT StrCpy(PSZ pszDst, PSZ pszSrc, ULONG n)
  47. {
  48. TRACENAME("STRCPY")
  49. ULONG dwSrcLen;
  50. ENTER(5, ("StrCpy(Dst=%s,Src=%s,n=%d)\n", pszDst, pszSrc, n));
  51. ASSERT(pszDst != NULL);
  52. ASSERT(pszSrc != NULL);
  53. dwSrcLen = StrLen(pszSrc, n);
  54. if ((n == (ULONG)(-1)) || (n > dwSrcLen))
  55. n = dwSrcLen;
  56. MEMCPY(pszDst, pszSrc, n);
  57. pszDst[n] = '\0';
  58. EXIT(5, ("StrCpy=%s\n", pszDst));
  59. return pszDst;
  60. } //StrCpy
  61. /***EP StrCat - concatenate strings
  62. *
  63. * ENTRY
  64. * pszDst -> destination string
  65. * pszSrc -> source string
  66. * n - number of bytes to concatenate
  67. *
  68. * EXIT
  69. * returns pszDst
  70. */
  71. PSZ EXPORT StrCat(PSZ pszDst, PSZ pszSrc, ULONG n)
  72. {
  73. TRACENAME("STRCAT")
  74. ULONG dwSrcLen, dwDstLen;
  75. ENTER(5, ("StrCat(Dst=%s,Src=%s,n=%d)\n", pszDst, pszSrc, n));
  76. ASSERT(pszDst != NULL);
  77. ASSERT(pszSrc != NULL);
  78. dwSrcLen = StrLen(pszSrc, n);
  79. if ((n == (ULONG)(-1)) || (n > dwSrcLen))
  80. n = dwSrcLen;
  81. dwDstLen = StrLen(pszDst, (ULONG)(-1));
  82. MEMCPY(&pszDst[dwDstLen], pszSrc, n);
  83. pszDst[dwDstLen + n] = '\0';
  84. EXIT(5, ("StrCat=%s\n", pszDst));
  85. return pszDst;
  86. } //StrCat
  87. /***EP StrCmp - compare strings
  88. *
  89. * ENTRY
  90. * psz1 -> string 1
  91. * psz2 -> string 2
  92. * n - number of bytes to compare
  93. * fMatchCase - TRUE if case sensitive
  94. *
  95. * EXIT
  96. * returns 0 if string 1 == string 2
  97. * <0 if string 1 < string 2
  98. * >0 if string 1 > string 2
  99. */
  100. LONG EXPORT StrCmp(PSZ psz1, PSZ psz2, ULONG n, BOOLEAN fMatchCase)
  101. {
  102. TRACENAME("STRCMP")
  103. LONG rc;
  104. ULONG dwLen1, dwLen2;
  105. ULONG i;
  106. ENTER(5, ("StrCmp(s1=%s,s2=%s,n=%d,fMatchCase=%d)\n",
  107. psz1, psz2, n, fMatchCase));
  108. ASSERT(psz1 != NULL);
  109. ASSERT(psz2 != NULL);
  110. dwLen1 = StrLen(psz1, n);
  111. dwLen2 = StrLen(psz2, n);
  112. if (n == (ULONG)(-1))
  113. n = (dwLen1 > dwLen2)? dwLen1: dwLen2;
  114. if (fMatchCase)
  115. {
  116. for (i = 0, rc = 0;
  117. (rc == 0) && (i < n) && (i < dwLen1) && (i < dwLen2);
  118. ++i)
  119. {
  120. rc = (LONG)(psz1[i] - psz2[i]);
  121. }
  122. }
  123. else
  124. {
  125. for (i = 0, rc = 0;
  126. (rc == 0) && (i < n) && (i < dwLen1) && (i < dwLen2);
  127. ++i)
  128. {
  129. rc = (LONG)(TOUPPER(psz1[i]) - TOUPPER(psz2[i]));
  130. }
  131. }
  132. if ((rc == 0) && (i < n))
  133. {
  134. if (i < dwLen1)
  135. rc = (LONG)psz1[i];
  136. else if (i < dwLen2)
  137. rc = (LONG)(-psz2[i]);
  138. }
  139. EXIT(5, ("StrCmp=%d\n", rc));
  140. return rc;
  141. } //StrCmp
  142. /***EP StrChr - look for a character in a string
  143. *
  144. * ENTRY
  145. * psz -> string
  146. * c - character to look for
  147. *
  148. * EXIT-SUCCESS
  149. * returns a pointer to the character found
  150. * EXIT-FAILURE
  151. * returns NULL
  152. */
  153. PSZ EXPORT StrChr(PSZ pszStr, CHAR c)
  154. {
  155. TRACENAME("STRCHR")
  156. PSZ psz;
  157. ENTER(5, ("StrChr(s=%s,c=%c)\n", pszStr, c));
  158. ASSERT(pszStr != NULL);
  159. for (psz = pszStr; (*psz != c) && (*psz != '\0'); psz++)
  160. ;
  161. if (*psz != c)
  162. psz = NULL;
  163. EXIT(5, ("StrChr=%x\n", psz));
  164. return psz;
  165. } //StrChr
  166. /***EP StrRChr - look for a character in a string in reverse direction
  167. *
  168. * ENTRY
  169. * psz -> string
  170. * c - character to look for
  171. *
  172. * EXIT-SUCCESS
  173. * returns a pointer to the character found
  174. * EXIT-FAILURE
  175. * returns NULL
  176. */
  177. PSZ EXPORT StrRChr(PSZ pszStr, CHAR c)
  178. {
  179. TRACENAME("STRRCHR")
  180. PSZ psz;
  181. ENTER(5, ("StrChr(s=%s,c=%c)\n", pszStr, c));
  182. ASSERT(pszStr != NULL);
  183. for (psz = &pszStr[StrLen(pszStr, (ULONG)-1)];
  184. (*psz != c) && (psz > pszStr);
  185. psz--)
  186. {
  187. }
  188. if (*psz != c)
  189. psz = NULL;
  190. EXIT(5, ("StrRChr=%x\n", psz));
  191. return psz;
  192. } //StrRChr
  193. /***EP StrTok - find the next token in string
  194. *
  195. * ENTRY
  196. * pszStr -> string containing tokens
  197. * pszSep -> string containing delimiters
  198. *
  199. * EXIT-SUCCESS
  200. * returns the pointer to the beginning of the token
  201. * EXIT-FAILURE
  202. * returns NULL
  203. */
  204. PSZ EXPORT StrTok(PSZ pszStr, PSZ pszSep)
  205. {
  206. TRACENAME("STRTOK")
  207. static PSZ pszNext = NULL;
  208. ENTER(5, ("StrTok(Str=%s,Sep=%s)\n", pszStr, pszSep));
  209. ASSERT(pszSep != NULL);
  210. if (pszStr == NULL)
  211. pszStr = pszNext;
  212. if (pszStr != NULL)
  213. {
  214. //
  215. // Skip leading delimiter characters
  216. //
  217. while ((*pszStr != '\0') && (StrChr(pszSep, *pszStr) != NULL))
  218. pszStr++;
  219. for (pszNext = pszStr;
  220. (*pszNext != '\0') && (StrChr(pszSep, *pszNext) == NULL);
  221. pszNext++)
  222. ;
  223. if (*pszStr == '\0')
  224. pszStr = NULL;
  225. else if (*pszNext != '\0')
  226. {
  227. *pszNext = '\0';
  228. pszNext++;
  229. }
  230. }
  231. EXIT(5, ("StrTok=%s (Next=%s)\n",
  232. pszStr? pszStr: "(null)", pszNext? pszNext: "(null)"));
  233. return pszStr;
  234. } //StrTok
  235. /***EP StrToUL - convert the number in a string to a unsigned long integer
  236. *
  237. * ENTRY
  238. * psz -> string
  239. * ppszEnd -> string pointer to the end of the number (can be NULL)
  240. * dwBase - the base of the number (if 0, auto-detect base)
  241. *
  242. * EXIT
  243. * returns the converted number
  244. */
  245. ULONG EXPORT StrToUL(PSZ psz, PSZ *ppszEnd, ULONG dwBase)
  246. {
  247. TRACENAME("STRTOUL")
  248. ULONG n = 0;
  249. ULONG m;
  250. ENTER(5, ("StrToUL(Str=%s,ppszEnd=%x,Base=%x)\n", psz, ppszEnd, dwBase));
  251. if (dwBase == 0)
  252. {
  253. if (psz[0] == '0')
  254. {
  255. if ((psz[1] == 'x') || (psz[1] == 'X'))
  256. {
  257. dwBase = 16;
  258. psz += 2;
  259. }
  260. else
  261. {
  262. dwBase = 8;
  263. psz++;
  264. }
  265. }
  266. else
  267. dwBase = 10;
  268. }
  269. while (*psz != '\0')
  270. {
  271. if ((*psz >= '0') && (*psz <= '9'))
  272. m = *psz - '0';
  273. else if ((*psz >= 'A') && (*psz <= 'Z'))
  274. m = *psz - 'A' + 10;
  275. else if ((*psz >= 'a') && (*psz <= 'z'))
  276. m = *psz - 'a' + 10;
  277. else
  278. break;
  279. if (m < dwBase)
  280. {
  281. n = (n*dwBase) + m;
  282. psz++;
  283. }
  284. else
  285. break;
  286. }
  287. if (ppszEnd != NULL)
  288. *ppszEnd = psz;
  289. EXIT(5, ("StrToUL=%x (pszEnd=%x)\n", n, ppszEnd? *ppszEnd: 0));
  290. return n;
  291. } //StrToUL
  292. /***EP StrToL - convert the number in a string to a long integer
  293. *
  294. * ENTRY
  295. * psz -> string
  296. * ppszEnd -> string pointer to the end of the number (can be NULL)
  297. * dwBase - the base of the number (if 0, auto-detect base)
  298. *
  299. * EXIT
  300. * returns the converted number
  301. */
  302. LONG EXPORT StrToL(PSZ psz, PSZ *ppszEnd, ULONG dwBase)
  303. {
  304. TRACENAME("STRTOL")
  305. LONG n = 0;
  306. BOOLEAN fMinus;
  307. ENTER(5, ("StrToL(Str=%s,ppszEnd=%x,Base=%x)\n", psz, ppszEnd, dwBase));
  308. if (*psz == '-')
  309. {
  310. fMinus = TRUE;
  311. psz++;
  312. }
  313. else
  314. fMinus = FALSE;
  315. n = (LONG)StrToUL(psz, ppszEnd, dwBase);
  316. if (fMinus)
  317. n = -n;
  318. EXIT(5, ("StrToL=%x (pszEnd=%x)\n", n, ppszEnd? *ppszEnd: 0));
  319. return n;
  320. } //StrToL
  321. /***EP StrStr - find a substring in a given string
  322. *
  323. * ENTRY
  324. * psz1 -> string to be searched
  325. * psz2 -> substring to find
  326. *
  327. * EXIT-SUCCESS
  328. * returns pointer to psz1 where the substring is found
  329. * EXIT-FAILURE
  330. * returns NULL
  331. */
  332. PSZ EXPORT StrStr(PSZ psz1, PSZ psz2)
  333. {
  334. TRACENAME("STRSTR")
  335. PSZ psz = psz1;
  336. ULONG dwLen;
  337. ENTER(5, ("StrStr(psz1=%s,psz2=%s)\n", psz1, psz2));
  338. dwLen = StrLen(psz2, (ULONG)-1);
  339. while ((psz = StrChr(psz, *psz2)) != NULL)
  340. {
  341. if (StrCmp(psz, psz2, dwLen, TRUE) == 0)
  342. break;
  343. else
  344. psz++;
  345. }
  346. EXIT(5, ("StrStr=%s\n", psz));
  347. return psz;
  348. } //StrStr
  349. /***EP StrUpr - convert string to upper case
  350. *
  351. * ENTRY
  352. * pszStr -> string
  353. *
  354. * EXIT
  355. * returns pszStr
  356. */
  357. PSZ EXPORT StrUpr(PSZ pszStr)
  358. {
  359. TRACENAME("STRUPR")
  360. PSZ psz;
  361. ENTER(5, ("StrUpr(Str=%s)\n", pszStr));
  362. for (psz = pszStr; *psz != '\0'; psz++)
  363. {
  364. *psz = TOUPPER(*psz);
  365. }
  366. EXIT(5, ("StrUpr=%s\n", pszStr));
  367. return pszStr;
  368. } //StrUpr
  369. /***EP StrLwr - convert string to lower case
  370. *
  371. * ENTRY
  372. * pszStr -> string
  373. *
  374. * EXIT
  375. * returns pszStr
  376. */
  377. PSZ EXPORT StrLwr(PSZ pszStr)
  378. {
  379. TRACENAME("STRLWR")
  380. PSZ psz;
  381. ENTER(5, ("StrLwr(Str=%s)\n", pszStr));
  382. for (psz = pszStr; *psz != '\0'; psz++)
  383. {
  384. *psz = TOLOWER(*psz);
  385. }
  386. EXIT(5, ("StrLwr=%s\n", pszStr));
  387. return pszStr;
  388. } //StrLwr
  389. /***EP UlToA - convert an unsigned long value to a string
  390. *
  391. * ENTRY
  392. * dwValue - data
  393. * pszStr -> string
  394. * dwRadix - radix
  395. *
  396. * EXIT
  397. * returns pszStr
  398. */
  399. PSZ EXPORT UlToA(ULONG dwValue, PSZ pszStr, ULONG dwRadix)
  400. {
  401. TRACENAME("ULTOA")
  402. PSZ psz;
  403. char ch;
  404. ENTER(5, ("UlToA(Value=%x,pszStr=%x,Radix=%d\n", dwValue, pszStr, dwRadix));
  405. for (psz = pszStr; dwValue != 0; dwValue/=dwRadix, psz++)
  406. {
  407. ch = (char)(dwValue%dwRadix);
  408. if (ch <= 9)
  409. {
  410. *psz = (char)(ch + '0');
  411. }
  412. else
  413. {
  414. *psz = (char)(ch - 10 + 'A');
  415. }
  416. }
  417. if (psz == pszStr)
  418. {
  419. pszStr[0] = '0';
  420. pszStr[1] = '\0';
  421. }
  422. else
  423. {
  424. PSZ psz2;
  425. *psz = '\0';
  426. for (psz2 = pszStr, psz--; psz2 < psz; psz2++, psz--)
  427. {
  428. ch = *psz2;
  429. *psz2 = *psz;
  430. *psz = ch;
  431. }
  432. }
  433. EXIT(5, ("UlToA=%s\n", pszStr));
  434. return pszStr;
  435. } //UlToA