string.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531
  1. /*
  2. * Unicode string manipulation functions
  3. *
  4. * Copyright 2000 Alexandre Julliard
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2.1 of the License, or (at your option) any later version.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  19. */
  20. #include <assert.h>
  21. #include <errno.h>
  22. #include <limits.h>
  23. #include <stdio.h>
  24. #include "wine/unicode.h"
  25. int strcmpiW( const WCHAR *str1, const WCHAR *str2 )
  26. {
  27. for (;;)
  28. {
  29. int ret = tolowerW(*str1) - tolowerW(*str2);
  30. if (ret || !*str1) return ret;
  31. str1++;
  32. str2++;
  33. }
  34. }
  35. int strncmpiW( const WCHAR *str1, const WCHAR *str2, int n )
  36. {
  37. int ret = 0;
  38. for ( ; n > 0; n--, str1++, str2++)
  39. if ((ret = tolowerW(*str1) - tolowerW(*str2)) || !*str1) break;
  40. return ret;
  41. }
  42. int memicmpW( const WCHAR *str1, const WCHAR *str2, int n )
  43. {
  44. int ret = 0;
  45. for ( ; n > 0; n--, str1++, str2++)
  46. if ((ret = tolowerW(*str1) - tolowerW(*str2))) break;
  47. return ret;
  48. }
  49. WCHAR *strstrW( const WCHAR *str, const WCHAR *sub )
  50. {
  51. while (*str)
  52. {
  53. const WCHAR *p1 = str, *p2 = sub;
  54. while (*p1 && *p2 && *p1 == *p2) { p1++; p2++; }
  55. if (!*p2) return (WCHAR *)str;
  56. str++;
  57. }
  58. return NULL;
  59. }
  60. /* strtolW and strtoulW implementation based on the GNU C library code */
  61. /* Copyright (C) 1991,92,94,95,96,97,98,99,2000,2001 Free Software Foundation, Inc. */
  62. long int strtolW( const WCHAR *nptr, WCHAR **endptr, int base )
  63. {
  64. int negative;
  65. register unsigned long int cutoff;
  66. register unsigned int cutlim;
  67. register unsigned long int i;
  68. register const WCHAR *s;
  69. register WCHAR c;
  70. const WCHAR *save, *end;
  71. int overflow;
  72. if (base < 0 || base == 1 || base > 36) return 0;
  73. save = s = nptr;
  74. /* Skip white space. */
  75. while (isspaceW (*s))
  76. ++s;
  77. if (!*s) goto noconv;
  78. /* Check for a sign. */
  79. negative = 0;
  80. if (*s == '-')
  81. {
  82. negative = 1;
  83. ++s;
  84. }
  85. else if (*s == '+')
  86. ++s;
  87. /* Recognize number prefix and if BASE is zero, figure it out ourselves. */
  88. if (*s == '0')
  89. {
  90. if ((base == 0 || base == 16) && toupperW(s[1]) == 'X')
  91. {
  92. s += 2;
  93. base = 16;
  94. }
  95. else if (base == 0)
  96. base = 8;
  97. }
  98. else if (base == 0)
  99. base = 10;
  100. /* Save the pointer so we can check later if anything happened. */
  101. save = s;
  102. end = NULL;
  103. cutoff = ULONG_MAX / (unsigned long int) base;
  104. cutlim = ULONG_MAX % (unsigned long int) base;
  105. overflow = 0;
  106. i = 0;
  107. c = *s;
  108. for (;c != '\0'; c = *++s)
  109. {
  110. if (s == end)
  111. break;
  112. if (c >= '0' && c <= '9')
  113. c -= '0';
  114. else if (isalphaW (c))
  115. c = toupperW (c) - 'A' + 10;
  116. else
  117. break;
  118. if ((int) c >= base)
  119. break;
  120. /* Check for overflow. */
  121. if (i > cutoff || (i == cutoff && c > cutlim))
  122. overflow = 1;
  123. else
  124. {
  125. i *= (unsigned long int) base;
  126. i += c;
  127. }
  128. }
  129. /* Check if anything actually happened. */
  130. if (s == save)
  131. goto noconv;
  132. /* Store in ENDPTR the address of one character
  133. past the last character we converted. */
  134. if (endptr != NULL)
  135. *endptr = (WCHAR *)s;
  136. /* Check for a value that is within the range of
  137. `unsigned LONG int', but outside the range of `LONG int'. */
  138. if (overflow == 0
  139. && i > (negative
  140. ? -((unsigned long int) (LONG_MIN + 1)) + 1
  141. : (unsigned long int) LONG_MAX))
  142. overflow = 1;
  143. if (overflow)
  144. {
  145. errno = ERANGE;
  146. return negative ? LONG_MIN : LONG_MAX;
  147. }
  148. /* Return the result of the appropriate sign. */
  149. return negative ? -i : i;
  150. noconv:
  151. /* We must handle a special case here: the base is 0 or 16 and the
  152. first two characters are '0' and 'x', but the rest are not
  153. hexadecimal digits. This is no error case. We return 0 and
  154. ENDPTR points to the `x`. */
  155. if (endptr != NULL)
  156. {
  157. if (save - nptr >= 2 && toupperW (save[-1]) == 'X'
  158. && save[-2] == '0')
  159. *endptr = (WCHAR *)&save[-1];
  160. else
  161. /* There was no number to convert. */
  162. *endptr = (WCHAR *)nptr;
  163. }
  164. return 0L;
  165. }
  166. unsigned long int strtoulW( const WCHAR *nptr, WCHAR **endptr, int base )
  167. {
  168. int negative;
  169. register unsigned long int cutoff;
  170. register unsigned int cutlim;
  171. register unsigned long int i;
  172. register const WCHAR *s;
  173. register WCHAR c;
  174. const WCHAR *save, *end;
  175. int overflow;
  176. if (base < 0 || base == 1 || base > 36) return 0;
  177. save = s = nptr;
  178. /* Skip white space. */
  179. while (isspaceW (*s))
  180. ++s;
  181. if (!*s) goto noconv;
  182. /* Check for a sign. */
  183. negative = 0;
  184. if (*s == '-')
  185. {
  186. negative = 1;
  187. ++s;
  188. }
  189. else if (*s == '+')
  190. ++s;
  191. /* Recognize number prefix and if BASE is zero, figure it out ourselves. */
  192. if (*s == '0')
  193. {
  194. if ((base == 0 || base == 16) && toupperW(s[1]) == 'X')
  195. {
  196. s += 2;
  197. base = 16;
  198. }
  199. else if (base == 0)
  200. base = 8;
  201. }
  202. else if (base == 0)
  203. base = 10;
  204. /* Save the pointer so we can check later if anything happened. */
  205. save = s;
  206. end = NULL;
  207. cutoff = ULONG_MAX / (unsigned long int) base;
  208. cutlim = ULONG_MAX % (unsigned long int) base;
  209. overflow = 0;
  210. i = 0;
  211. c = *s;
  212. for (;c != '\0'; c = *++s)
  213. {
  214. if (s == end)
  215. break;
  216. if (c >= '0' && c <= '9')
  217. c -= '0';
  218. else if (isalphaW (c))
  219. c = toupperW (c) - 'A' + 10;
  220. else
  221. break;
  222. if ((int) c >= base)
  223. break;
  224. /* Check for overflow. */
  225. if (i > cutoff || (i == cutoff && c > cutlim))
  226. overflow = 1;
  227. else
  228. {
  229. i *= (unsigned long int) base;
  230. i += c;
  231. }
  232. }
  233. /* Check if anything actually happened. */
  234. if (s == save)
  235. goto noconv;
  236. /* Store in ENDPTR the address of one character
  237. past the last character we converted. */
  238. if (endptr != NULL)
  239. *endptr = (WCHAR *)s;
  240. if (overflow)
  241. {
  242. errno = ERANGE;
  243. return ULONG_MAX;
  244. }
  245. /* Return the result of the appropriate sign. */
  246. return negative ? -i : i;
  247. noconv:
  248. /* We must handle a special case here: the base is 0 or 16 and the
  249. first two characters are '0' and 'x', but the rest are not
  250. hexadecimal digits. This is no error case. We return 0 and
  251. ENDPTR points to the `x`. */
  252. if (endptr != NULL)
  253. {
  254. if (save - nptr >= 2 && toupperW (save[-1]) == 'X'
  255. && save[-2] == '0')
  256. *endptr = (WCHAR *)&save[-1];
  257. else
  258. /* There was no number to convert. */
  259. *endptr = (WCHAR *)nptr;
  260. }
  261. return 0L;
  262. }
  263. /* format a WCHAR string according to a printf format; helper for vsnprintfW */
  264. static size_t format_string( WCHAR *buffer, size_t len, const char *format, const WCHAR *str, int str_len )
  265. {
  266. size_t count = 0;
  267. int i, left_align = 0, width = 0, max = 0;
  268. assert( *format == '%' );
  269. format++; /* skip '%' */
  270. while (*format == '0' || *format == '+' || *format == '-' || *format == ' ' || *format == '#')
  271. {
  272. if (*format == '-') left_align = 1;
  273. format++;
  274. }
  275. while (isdigit(*format)) width = width * 10 + *format++ - '0';
  276. if (str_len == -1) str_len = strlenW( str );
  277. if (*format == '.')
  278. {
  279. format++;
  280. while (isdigit(*format)) max = max * 10 + *format++ - '0';
  281. if (max > str_len) max = str_len;
  282. }
  283. else max = str_len;
  284. if (*format == 'h' || *format == 'l') format++;
  285. assert( *format == 's' );
  286. if (!left_align && width > max)
  287. {
  288. for (i = 0; i < width - max; i++)
  289. {
  290. if (count++ < len)
  291. *buffer++ = ' ';
  292. }
  293. }
  294. if (count < len)
  295. memcpy( buffer, str, min( max, len - count ) * sizeof(WCHAR) );
  296. count += max;
  297. buffer += max;
  298. if (left_align && width > max)
  299. {
  300. for (i = 0; i < width - max; i++)
  301. {
  302. if (count++ < len)
  303. *buffer++ = ' ';
  304. }
  305. }
  306. return count;
  307. }
  308. int vsnprintfW(WCHAR *str, size_t len, const WCHAR *format, va_list valist)
  309. {
  310. unsigned int written = 0;
  311. const WCHAR *iter = format;
  312. char bufa[512], fmtbufa[64], *fmta;
  313. while (*iter)
  314. {
  315. while (*iter && *iter != '%')
  316. {
  317. if (written++ < len)
  318. *str++ = *iter;
  319. iter++;
  320. }
  321. if (*iter == '%')
  322. {
  323. if (iter[1] == '%')
  324. {
  325. if (written++ < len)
  326. *str++ = '%'; /* "%%"->'%' */
  327. iter += 2;
  328. continue;
  329. }
  330. fmta = fmtbufa;
  331. *fmta++ = *iter++;
  332. while (*iter == '0' ||
  333. *iter == '+' ||
  334. *iter == '-' ||
  335. *iter == ' ' ||
  336. *iter == '*' ||
  337. *iter == '#')
  338. {
  339. if (*iter == '*')
  340. {
  341. char *buffiter = bufa;
  342. int fieldlen = va_arg(valist, int);
  343. sprintf(buffiter, "%d", fieldlen);
  344. while (*buffiter)
  345. *fmta++ = *buffiter++;
  346. }
  347. else
  348. *fmta++ = *iter;
  349. iter++;
  350. }
  351. while (isdigit(*iter))
  352. *fmta++ = *iter++;
  353. if (*iter == '.')
  354. {
  355. *fmta++ = *iter++;
  356. if (*iter == '*')
  357. {
  358. char *buffiter = bufa;
  359. int fieldlen = va_arg(valist, int);
  360. sprintf(buffiter, "%d", fieldlen);
  361. while (*buffiter)
  362. *fmta++ = *buffiter++;
  363. iter++;
  364. }
  365. else
  366. while (isdigit(*iter))
  367. *fmta++ = *iter++;
  368. }
  369. if (*iter == 'h' || *iter == 'l')
  370. *fmta++ = *iter++;
  371. switch (*iter)
  372. {
  373. case 's':
  374. {
  375. static const WCHAR none[] = { '(','n','u','l','l',')',0 };
  376. const WCHAR *wstr = va_arg(valist, const WCHAR *);
  377. size_t remaining = written < len ? len - written : 0;
  378. size_t count;
  379. *fmta++ = 's';
  380. *fmta = 0;
  381. count = format_string( str, remaining, fmtbufa, wstr ? wstr : none, -1 );
  382. str += min( count, remaining );
  383. written += count;
  384. iter++;
  385. break;
  386. }
  387. case 'c':
  388. {
  389. WCHAR wstr;
  390. size_t remaining = written < len ? len - written : 0;
  391. size_t count;
  392. wstr = va_arg(valist, int);
  393. *fmta++ = 's';
  394. *fmta = 0;
  395. count = format_string( str, remaining, fmtbufa, &wstr, 1 );
  396. str += min( count, remaining );
  397. written += count;
  398. iter++;
  399. break;
  400. }
  401. default:
  402. {
  403. /* For non wc types, use system sprintf and append to wide char output */
  404. /* FIXME: for unrecognised types, should ignore % when printing */
  405. char *bufaiter = bufa;
  406. if (*iter == 'p')
  407. sprintf(bufaiter, "%0*lX", 2 * (int)sizeof(void*),
  408. (unsigned long)va_arg(valist, void *));
  409. else
  410. {
  411. *fmta++ = *iter;
  412. *fmta = '\0';
  413. if (*iter == 'a' || *iter == 'A' ||
  414. *iter == 'e' || *iter == 'E' ||
  415. *iter == 'f' || *iter == 'F' ||
  416. *iter == 'g' || *iter == 'G')
  417. sprintf(bufaiter, fmtbufa, va_arg(valist, double));
  418. else
  419. {
  420. /* FIXME: On 32 bit systems this doesn't handle int 64's. */
  421. sprintf(bufaiter, fmtbufa, va_arg(valist, void *));
  422. }
  423. }
  424. while (*bufaiter)
  425. {
  426. if (written++ < len)
  427. *str++ = *bufaiter;
  428. bufaiter++;
  429. }
  430. iter++;
  431. break;
  432. }
  433. }
  434. }
  435. }
  436. if (len)
  437. {
  438. if (written >= len)
  439. str--;
  440. *str++ = 0;
  441. }
  442. /* FIXME: POSIX [v]snprintf() returns the equivalent of written, not -1, on short buffer. */
  443. return written < len ? (int)written : -1;
  444. }
  445. int vsprintfW( WCHAR *str, const WCHAR *format, va_list valist )
  446. {
  447. return vsnprintfW( str, INT_MAX, format, valist );
  448. }
  449. int snprintfW( WCHAR *str, size_t len, const WCHAR *format, ...)
  450. {
  451. int retval;
  452. va_list valist;
  453. va_start(valist, format);
  454. retval = vsnprintfW(str, len, format, valist);
  455. va_end(valist);
  456. return retval;
  457. }
  458. int sprintfW( WCHAR *str, const WCHAR *format, ...)
  459. {
  460. int retval;
  461. va_list valist;
  462. va_start(valist, format);
  463. retval = vsnprintfW(str, INT_MAX, format, valist);
  464. va_end(valist);
  465. return retval;
  466. }