string.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720
  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 "wine/asm.h"
  21. #ifdef __ASM_OBSOLETE
  22. #include <assert.h>
  23. #include <errno.h>
  24. #include <limits.h>
  25. #include <stdio.h>
  26. #include <stdarg.h>
  27. #include <windef.h>
  28. #include <winbase.h>
  29. #include <winnls.h>
  30. WCHAR tolowerW( WCHAR ch )
  31. {
  32. extern const WCHAR wine_casemap_lower[];
  33. return ch + wine_casemap_lower[wine_casemap_lower[ch >> 8] + (ch & 0xff)];
  34. }
  35. WCHAR toupperW( WCHAR ch )
  36. {
  37. extern const WCHAR wine_casemap_upper[];
  38. return ch + wine_casemap_upper[wine_casemap_upper[ch >> 8] + (ch & 0xff)];
  39. }
  40. /* the character type contains the C1_* flags in the low 12 bits */
  41. /* and the C2_* type in the high 4 bits */
  42. unsigned short get_char_typeW( WCHAR ch )
  43. {
  44. extern const unsigned short wine_wctype_table[];
  45. return wine_wctype_table[wine_wctype_table[ch >> 8] + (ch & 0xff)];
  46. }
  47. int iscntrlW( WCHAR wc )
  48. {
  49. return get_char_typeW(wc) & C1_CNTRL;
  50. }
  51. int ispunctW( WCHAR wc )
  52. {
  53. return get_char_typeW(wc) & C1_PUNCT;
  54. }
  55. int isspaceW( WCHAR wc )
  56. {
  57. return get_char_typeW(wc) & C1_SPACE;
  58. }
  59. int isdigitW( WCHAR wc )
  60. {
  61. return get_char_typeW(wc) & C1_DIGIT;
  62. }
  63. int isxdigitW( WCHAR wc )
  64. {
  65. return get_char_typeW(wc) & C1_XDIGIT;
  66. }
  67. int islowerW( WCHAR wc )
  68. {
  69. return get_char_typeW(wc) & C1_LOWER;
  70. }
  71. int isupperW( WCHAR wc )
  72. {
  73. return get_char_typeW(wc) & C1_UPPER;
  74. }
  75. int isalnumW( WCHAR wc )
  76. {
  77. return get_char_typeW(wc) & (C1_ALPHA|C1_DIGIT|C1_LOWER|C1_UPPER);
  78. }
  79. int isalphaW( WCHAR wc )
  80. {
  81. return get_char_typeW(wc) & (C1_ALPHA|C1_LOWER|C1_UPPER);
  82. }
  83. int isgraphW( WCHAR wc )
  84. {
  85. return get_char_typeW(wc) & (C1_ALPHA|C1_PUNCT|C1_DIGIT|C1_LOWER|C1_UPPER);
  86. }
  87. int isprintW( WCHAR wc )
  88. {
  89. return get_char_typeW(wc) & (C1_ALPHA|C1_BLANK|C1_PUNCT|C1_DIGIT|C1_LOWER|C1_UPPER);
  90. }
  91. unsigned int strlenW( const WCHAR *str )
  92. {
  93. const WCHAR *s = str;
  94. while (*s) s++;
  95. return s - str;
  96. }
  97. WCHAR *strcpyW( WCHAR *dst, const WCHAR *src )
  98. {
  99. WCHAR *p = dst;
  100. while ((*p++ = *src++));
  101. return dst;
  102. }
  103. int strcmpW( const WCHAR *str1, const WCHAR *str2 )
  104. {
  105. while (*str1 && (*str1 == *str2)) { str1++; str2++; }
  106. return *str1 - *str2;
  107. }
  108. int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
  109. {
  110. if (n <= 0) return 0;
  111. while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
  112. return *str1 - *str2;
  113. }
  114. WCHAR *strcatW( WCHAR *dst, const WCHAR *src )
  115. {
  116. strcpyW( dst + strlenW(dst), src );
  117. return dst;
  118. }
  119. WCHAR *strchrW( const WCHAR *str, WCHAR ch )
  120. {
  121. do { if (*str == ch) return (WCHAR *)(ULONG_PTR)str; } while (*str++);
  122. return NULL;
  123. }
  124. WCHAR *strrchrW( const WCHAR *str, WCHAR ch )
  125. {
  126. WCHAR *ret = NULL;
  127. do { if (*str == ch) ret = (WCHAR *)(ULONG_PTR)str; } while (*str++);
  128. return ret;
  129. }
  130. WCHAR *strpbrkW( const WCHAR *str, const WCHAR *accept )
  131. {
  132. for ( ; *str; str++) if (strchrW( accept, *str )) return (WCHAR *)(ULONG_PTR)str;
  133. return NULL;
  134. }
  135. size_t strspnW( const WCHAR *str, const WCHAR *accept )
  136. {
  137. const WCHAR *ptr;
  138. for (ptr = str; *ptr; ptr++) if (!strchrW( accept, *ptr )) break;
  139. return ptr - str;
  140. }
  141. size_t strcspnW( const WCHAR *str, const WCHAR *reject )
  142. {
  143. const WCHAR *ptr;
  144. for (ptr = str; *ptr; ptr++) if (strchrW( reject, *ptr )) break;
  145. return ptr - str;
  146. }
  147. WCHAR *strlwrW( WCHAR *str )
  148. {
  149. WCHAR *ret;
  150. for (ret = str; *str; str++) *str = tolowerW(*str);
  151. return ret;
  152. }
  153. WCHAR *struprW( WCHAR *str )
  154. {
  155. WCHAR *ret;
  156. for (ret = str; *str; str++) *str = toupperW(*str);
  157. return ret;
  158. }
  159. WCHAR *memchrW( const WCHAR *ptr, WCHAR ch, size_t n )
  160. {
  161. const WCHAR *end;
  162. for (end = ptr + n; ptr < end; ptr++) if (*ptr == ch) return (WCHAR *)(ULONG_PTR)ptr;
  163. return NULL;
  164. }
  165. WCHAR *memrchrW( const WCHAR *ptr, WCHAR ch, size_t n )
  166. {
  167. const WCHAR *end;
  168. WCHAR *ret = NULL;
  169. for (end = ptr + n; ptr < end; ptr++) if (*ptr == ch) ret = (WCHAR *)(ULONG_PTR)ptr;
  170. return ret;
  171. }
  172. int strcmpiW( const WCHAR *str1, const WCHAR *str2 )
  173. {
  174. for (;;)
  175. {
  176. int ret = tolowerW(*str1) - tolowerW(*str2);
  177. if (ret || !*str1) return ret;
  178. str1++;
  179. str2++;
  180. }
  181. }
  182. int strncmpiW( const WCHAR *str1, const WCHAR *str2, int n )
  183. {
  184. int ret = 0;
  185. for ( ; n > 0; n--, str1++, str2++)
  186. if ((ret = tolowerW(*str1) - tolowerW(*str2)) || !*str1) break;
  187. return ret;
  188. }
  189. int memicmpW( const WCHAR *str1, const WCHAR *str2, int n )
  190. {
  191. int ret = 0;
  192. for ( ; n > 0; n--, str1++, str2++)
  193. if ((ret = tolowerW(*str1) - tolowerW(*str2))) break;
  194. return ret;
  195. }
  196. WCHAR *strstrW( const WCHAR *str, const WCHAR *sub )
  197. {
  198. while (*str)
  199. {
  200. const WCHAR *p1 = str, *p2 = sub;
  201. while (*p1 && *p2 && *p1 == *p2) { p1++; p2++; }
  202. if (!*p2) return (WCHAR *)str;
  203. str++;
  204. }
  205. return NULL;
  206. }
  207. /* strtolW and strtoulW implementation based on the GNU C library code */
  208. /* Copyright (C) 1991,92,94,95,96,97,98,99,2000,2001 Free Software Foundation, Inc. */
  209. long int strtolW( const WCHAR *nptr, WCHAR **endptr, int base )
  210. {
  211. int negative;
  212. register unsigned long int cutoff;
  213. register unsigned int cutlim;
  214. register unsigned long int i;
  215. register const WCHAR *s;
  216. register WCHAR c;
  217. const WCHAR *save, *end;
  218. int overflow;
  219. if (base < 0 || base == 1 || base > 36) return 0;
  220. save = s = nptr;
  221. /* Skip white space. */
  222. while (isspaceW (*s))
  223. ++s;
  224. if (!*s) goto noconv;
  225. /* Check for a sign. */
  226. negative = 0;
  227. if (*s == '-')
  228. {
  229. negative = 1;
  230. ++s;
  231. }
  232. else if (*s == '+')
  233. ++s;
  234. /* Recognize number prefix and if BASE is zero, figure it out ourselves. */
  235. if (*s == '0')
  236. {
  237. if ((base == 0 || base == 16) && toupperW(s[1]) == 'X')
  238. {
  239. s += 2;
  240. base = 16;
  241. }
  242. else if (base == 0)
  243. base = 8;
  244. }
  245. else if (base == 0)
  246. base = 10;
  247. /* Save the pointer so we can check later if anything happened. */
  248. save = s;
  249. end = NULL;
  250. cutoff = ULONG_MAX / (unsigned long int) base;
  251. cutlim = ULONG_MAX % (unsigned long int) base;
  252. overflow = 0;
  253. i = 0;
  254. c = *s;
  255. for (;c != '\0'; c = *++s)
  256. {
  257. if (s == end)
  258. break;
  259. if (c >= '0' && c <= '9')
  260. c -= '0';
  261. else if (isalphaW (c))
  262. c = toupperW (c) - 'A' + 10;
  263. else
  264. break;
  265. if ((int) c >= base)
  266. break;
  267. /* Check for overflow. */
  268. if (i > cutoff || (i == cutoff && c > cutlim))
  269. overflow = 1;
  270. else
  271. {
  272. i *= (unsigned long int) base;
  273. i += c;
  274. }
  275. }
  276. /* Check if anything actually happened. */
  277. if (s == save)
  278. goto noconv;
  279. /* Store in ENDPTR the address of one character
  280. past the last character we converted. */
  281. if (endptr != NULL)
  282. *endptr = (WCHAR *)s;
  283. /* Check for a value that is within the range of
  284. `unsigned LONG int', but outside the range of `LONG int'. */
  285. if (overflow == 0
  286. && i > (negative
  287. ? -((unsigned long int) (LONG_MIN + 1)) + 1
  288. : (unsigned long int) LONG_MAX))
  289. overflow = 1;
  290. if (overflow)
  291. {
  292. errno = ERANGE;
  293. return negative ? LONG_MIN : LONG_MAX;
  294. }
  295. /* Return the result of the appropriate sign. */
  296. return negative ? -i : i;
  297. noconv:
  298. /* We must handle a special case here: the base is 0 or 16 and the
  299. first two characters are '0' and 'x', but the rest are not
  300. hexadecimal digits. This is no error case. We return 0 and
  301. ENDPTR points to the `x`. */
  302. if (endptr != NULL)
  303. {
  304. if (save - nptr >= 2 && toupperW (save[-1]) == 'X'
  305. && save[-2] == '0')
  306. *endptr = (WCHAR *)&save[-1];
  307. else
  308. /* There was no number to convert. */
  309. *endptr = (WCHAR *)nptr;
  310. }
  311. return 0L;
  312. }
  313. unsigned long int strtoulW( const WCHAR *nptr, WCHAR **endptr, int base )
  314. {
  315. int negative;
  316. register unsigned long int cutoff;
  317. register unsigned int cutlim;
  318. register unsigned long int i;
  319. register const WCHAR *s;
  320. register WCHAR c;
  321. const WCHAR *save, *end;
  322. int overflow;
  323. if (base < 0 || base == 1 || base > 36) return 0;
  324. save = s = nptr;
  325. /* Skip white space. */
  326. while (isspaceW (*s))
  327. ++s;
  328. if (!*s) goto noconv;
  329. /* Check for a sign. */
  330. negative = 0;
  331. if (*s == '-')
  332. {
  333. negative = 1;
  334. ++s;
  335. }
  336. else if (*s == '+')
  337. ++s;
  338. /* Recognize number prefix and if BASE is zero, figure it out ourselves. */
  339. if (*s == '0')
  340. {
  341. if ((base == 0 || base == 16) && toupperW(s[1]) == 'X')
  342. {
  343. s += 2;
  344. base = 16;
  345. }
  346. else if (base == 0)
  347. base = 8;
  348. }
  349. else if (base == 0)
  350. base = 10;
  351. /* Save the pointer so we can check later if anything happened. */
  352. save = s;
  353. end = NULL;
  354. cutoff = ULONG_MAX / (unsigned long int) base;
  355. cutlim = ULONG_MAX % (unsigned long int) base;
  356. overflow = 0;
  357. i = 0;
  358. c = *s;
  359. for (;c != '\0'; c = *++s)
  360. {
  361. if (s == end)
  362. break;
  363. if (c >= '0' && c <= '9')
  364. c -= '0';
  365. else if (isalphaW (c))
  366. c = toupperW (c) - 'A' + 10;
  367. else
  368. break;
  369. if ((int) c >= base)
  370. break;
  371. /* Check for overflow. */
  372. if (i > cutoff || (i == cutoff && c > cutlim))
  373. overflow = 1;
  374. else
  375. {
  376. i *= (unsigned long int) base;
  377. i += c;
  378. }
  379. }
  380. /* Check if anything actually happened. */
  381. if (s == save)
  382. goto noconv;
  383. /* Store in ENDPTR the address of one character
  384. past the last character we converted. */
  385. if (endptr != NULL)
  386. *endptr = (WCHAR *)s;
  387. if (overflow)
  388. {
  389. errno = ERANGE;
  390. return ULONG_MAX;
  391. }
  392. /* Return the result of the appropriate sign. */
  393. return negative ? -i : i;
  394. noconv:
  395. /* We must handle a special case here: the base is 0 or 16 and the
  396. first two characters are '0' and 'x', but the rest are not
  397. hexadecimal digits. This is no error case. We return 0 and
  398. ENDPTR points to the `x`. */
  399. if (endptr != NULL)
  400. {
  401. if (save - nptr >= 2 && toupperW (save[-1]) == 'X'
  402. && save[-2] == '0')
  403. *endptr = (WCHAR *)&save[-1];
  404. else
  405. /* There was no number to convert. */
  406. *endptr = (WCHAR *)nptr;
  407. }
  408. return 0L;
  409. }
  410. long int atolW( const WCHAR *str )
  411. {
  412. return strtolW( str, NULL, 10 );
  413. }
  414. int atoiW( const WCHAR *str )
  415. {
  416. return (int)atolW( str );
  417. }
  418. /* format a WCHAR string according to a printf format; helper for vsnprintfW */
  419. static size_t format_string( WCHAR *buffer, size_t len, const char *format, const WCHAR *str, int str_len )
  420. {
  421. size_t count = 0;
  422. int i, left_align = 0, width = 0, max = 0;
  423. assert( *format == '%' );
  424. format++; /* skip '%' */
  425. while (*format == '0' || *format == '+' || *format == '-' || *format == ' ' || *format == '#')
  426. {
  427. if (*format == '-') left_align = 1;
  428. format++;
  429. }
  430. while (isdigit(*format)) width = width * 10 + *format++ - '0';
  431. if (str_len == -1) str_len = strlenW( str );
  432. if (*format == '.')
  433. {
  434. format++;
  435. while (isdigit(*format)) max = max * 10 + *format++ - '0';
  436. if (max > str_len) max = str_len;
  437. }
  438. else max = str_len;
  439. if (*format == 'h' || *format == 'l') format++;
  440. assert( *format == 's' );
  441. if (!left_align && width > max)
  442. {
  443. for (i = 0; i < width - max; i++)
  444. {
  445. if (count++ < len)
  446. *buffer++ = ' ';
  447. }
  448. }
  449. if (count < len)
  450. memcpy( buffer, str, min( max, len - count ) * sizeof(WCHAR) );
  451. count += max;
  452. buffer += max;
  453. if (left_align && width > max)
  454. {
  455. for (i = 0; i < width - max; i++)
  456. {
  457. if (count++ < len)
  458. *buffer++ = ' ';
  459. }
  460. }
  461. return count;
  462. }
  463. int vsnprintfW(WCHAR *str, size_t len, const WCHAR *format, va_list valist)
  464. {
  465. unsigned int written = 0;
  466. const WCHAR *iter = format;
  467. char bufa[512], fmtbufa[64], *fmta;
  468. while (*iter)
  469. {
  470. while (*iter && *iter != '%')
  471. {
  472. if (written++ < len)
  473. *str++ = *iter;
  474. iter++;
  475. }
  476. if (*iter == '%')
  477. {
  478. if (iter[1] == '%')
  479. {
  480. if (written++ < len)
  481. *str++ = '%'; /* "%%"->'%' */
  482. iter += 2;
  483. continue;
  484. }
  485. fmta = fmtbufa;
  486. *fmta++ = *iter++;
  487. while (*iter == '0' ||
  488. *iter == '+' ||
  489. *iter == '-' ||
  490. *iter == ' ' ||
  491. *iter == '*' ||
  492. *iter == '#')
  493. {
  494. if (*iter == '*')
  495. {
  496. char *buffiter = bufa;
  497. int fieldlen = va_arg(valist, int);
  498. sprintf(buffiter, "%d", fieldlen);
  499. while (*buffiter)
  500. *fmta++ = *buffiter++;
  501. }
  502. else
  503. *fmta++ = *iter;
  504. iter++;
  505. }
  506. while (isdigit(*iter))
  507. *fmta++ = *iter++;
  508. if (*iter == '.')
  509. {
  510. *fmta++ = *iter++;
  511. if (*iter == '*')
  512. {
  513. char *buffiter = bufa;
  514. int fieldlen = va_arg(valist, int);
  515. sprintf(buffiter, "%d", fieldlen);
  516. while (*buffiter)
  517. *fmta++ = *buffiter++;
  518. iter++;
  519. }
  520. else
  521. while (isdigit(*iter))
  522. *fmta++ = *iter++;
  523. }
  524. if (*iter == 'h' || *iter == 'l')
  525. *fmta++ = *iter++;
  526. switch (*iter)
  527. {
  528. case 's':
  529. {
  530. static const WCHAR none[] = { '(','n','u','l','l',')',0 };
  531. const WCHAR *wstr = va_arg(valist, const WCHAR *);
  532. size_t remaining = written < len ? len - written : 0;
  533. size_t count;
  534. *fmta++ = 's';
  535. *fmta = 0;
  536. count = format_string( str, remaining, fmtbufa, wstr ? wstr : none, -1 );
  537. str += min( count, remaining );
  538. written += count;
  539. iter++;
  540. break;
  541. }
  542. case 'c':
  543. {
  544. WCHAR wstr;
  545. size_t remaining = written < len ? len - written : 0;
  546. size_t count;
  547. wstr = va_arg(valist, int);
  548. *fmta++ = 's';
  549. *fmta = 0;
  550. count = format_string( str, remaining, fmtbufa, &wstr, 1 );
  551. str += min( count, remaining );
  552. written += count;
  553. iter++;
  554. break;
  555. }
  556. default:
  557. {
  558. /* For non wc types, use system sprintf and append to wide char output */
  559. /* FIXME: for unrecognised types, should ignore % when printing */
  560. char *bufaiter = bufa;
  561. if (*iter == 'p')
  562. sprintf(bufaiter, "%0*lX", 2 * (int)sizeof(void*),
  563. (unsigned long)va_arg(valist, void *));
  564. else
  565. {
  566. *fmta++ = *iter;
  567. *fmta = '\0';
  568. if (*iter == 'a' || *iter == 'A' ||
  569. *iter == 'e' || *iter == 'E' ||
  570. *iter == 'f' || *iter == 'F' ||
  571. *iter == 'g' || *iter == 'G')
  572. sprintf(bufaiter, fmtbufa, va_arg(valist, double));
  573. else
  574. {
  575. /* FIXME: On 32 bit systems this doesn't handle int 64's. */
  576. sprintf(bufaiter, fmtbufa, va_arg(valist, void *));
  577. }
  578. }
  579. while (*bufaiter)
  580. {
  581. if (written++ < len)
  582. *str++ = *bufaiter;
  583. bufaiter++;
  584. }
  585. iter++;
  586. break;
  587. }
  588. }
  589. }
  590. }
  591. if (len)
  592. {
  593. if (written >= len)
  594. str--;
  595. *str++ = 0;
  596. }
  597. /* FIXME: POSIX [v]snprintf() returns the equivalent of written, not -1, on short buffer. */
  598. return written < len ? (int)written : -1;
  599. }
  600. int vsprintfW( WCHAR *str, const WCHAR *format, va_list valist )
  601. {
  602. return vsnprintfW( str, INT_MAX, format, valist );
  603. }
  604. int snprintfW( WCHAR *str, size_t len, const WCHAR *format, ...)
  605. {
  606. int retval;
  607. va_list valist;
  608. va_start(valist, format);
  609. retval = vsnprintfW(str, len, format, valist);
  610. va_end(valist);
  611. return retval;
  612. }
  613. int sprintfW( WCHAR *str, const WCHAR *format, ...)
  614. {
  615. int retval;
  616. va_list valist;
  617. va_start(valist, format);
  618. retval = vsnprintfW(str, INT_MAX, format, valist);
  619. va_end(valist);
  620. return retval;
  621. }
  622. #endif /* __ASM_OBSOLETE */