ReactOS 0.4.16-dev-340-g0540c21
string.c
Go to the documentation of this file.
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
21#include <assert.h>
22#include <errno.h>
23#include <limits.h>
24#include <stdio.h>
25
26#include "wine/unicode.h"
27
28#ifdef __REACTOS__
29#define min(a,b) (((a) < (b)) ? (a) : (b))
30#endif
31
32int strcmpiW( const WCHAR *str1, const WCHAR *str2 )
33{
34 for (;;)
35 {
36 int ret = tolowerW(*str1) - tolowerW(*str2);
37 if (ret || !*str1) return ret;
38 str1++;
39 str2++;
40 }
41}
42
43int strncmpiW( const WCHAR *str1, const WCHAR *str2, int n )
44{
45 int ret = 0;
46 for ( ; n > 0; n--, str1++, str2++)
47 if ((ret = tolowerW(*str1) - tolowerW(*str2)) || !*str1) break;
48 return ret;
49}
50
51int memicmpW( const WCHAR *str1, const WCHAR *str2, int n )
52{
53 int ret = 0;
54 for ( ; n > 0; n--, str1++, str2++)
55 if ((ret = tolowerW(*str1) - tolowerW(*str2))) break;
56 return ret;
57}
58
59WCHAR *strstrW( const WCHAR *str, const WCHAR *sub )
60{
61 while (*str)
62 {
63 const WCHAR *p1 = str, *p2 = sub;
64 while (*p1 && *p2 && *p1 == *p2) { p1++; p2++; }
65 if (!*p2) return (WCHAR *)str;
66 str++;
67 }
68 return NULL;
69}
70
71/* strtolW and strtoulW implementation based on the GNU C library code */
72/* Copyright (C) 1991,92,94,95,96,97,98,99,2000,2001 Free Software Foundation, Inc. */
73
74long int strtolW( const WCHAR *nptr, WCHAR **endptr, int base )
75{
76 int negative;
77 register unsigned long int cutoff;
78 register unsigned int cutlim;
79 register unsigned long int i;
80 register const WCHAR *s;
81 register WCHAR c;
82 const WCHAR *save, *end;
83 int overflow;
84
85 if (base < 0 || base == 1 || base > 36) return 0;
86
87 save = s = nptr;
88
89 /* Skip white space. */
90 while (isspaceW (*s))
91 ++s;
92 if (!*s) goto noconv;
93
94 /* Check for a sign. */
95 negative = 0;
96 if (*s == '-')
97 {
98 negative = 1;
99 ++s;
100 }
101 else if (*s == '+')
102 ++s;
103
104 /* Recognize number prefix and if BASE is zero, figure it out ourselves. */
105 if (*s == '0')
106 {
107 if ((base == 0 || base == 16) && toupperW(s[1]) == 'X')
108 {
109 s += 2;
110 base = 16;
111 }
112 else if (base == 0)
113 base = 8;
114 }
115 else if (base == 0)
116 base = 10;
117
118 /* Save the pointer so we can check later if anything happened. */
119 save = s;
120 end = NULL;
121
122 cutoff = ULONG_MAX / (unsigned long int) base;
123 cutlim = ULONG_MAX % (unsigned long int) base;
124
125 overflow = 0;
126 i = 0;
127 c = *s;
128 for (;c != '\0'; c = *++s)
129 {
130 if (s == end)
131 break;
132 if (c >= '0' && c <= '9')
133 c -= '0';
134 else if (isalphaW (c))
135 c = toupperW (c) - 'A' + 10;
136 else
137 break;
138 if ((int) c >= base)
139 break;
140 /* Check for overflow. */
141 if (i > cutoff || (i == cutoff && c > cutlim))
142 overflow = 1;
143 else
144 {
145 i *= (unsigned long int) base;
146 i += c;
147 }
148 }
149
150 /* Check if anything actually happened. */
151 if (s == save)
152 goto noconv;
153
154 /* Store in ENDPTR the address of one character
155 past the last character we converted. */
156 if (endptr != NULL)
157 *endptr = (WCHAR *)s;
158
159 /* Check for a value that is within the range of
160 `unsigned LONG int', but outside the range of `LONG int'. */
161 if (overflow == 0
162 && i > (negative
163 ? -((unsigned long int) (LONG_MIN + 1)) + 1
164 : (unsigned long int) LONG_MAX))
165 overflow = 1;
166
167 if (overflow)
168 {
169 errno = ERANGE;
170 return negative ? LONG_MIN : LONG_MAX;
171 }
172
173 /* Return the result of the appropriate sign. */
174 return negative ? -i : i;
175
176noconv:
177 /* We must handle a special case here: the base is 0 or 16 and the
178 first two characters are '0' and 'x', but the rest are not
179 hexadecimal digits. This is no error case. We return 0 and
180 ENDPTR points to the `x`. */
181 if (endptr != NULL)
182 {
183 if (save - nptr >= 2 && toupperW (save[-1]) == 'X'
184 && save[-2] == '0')
185 *endptr = (WCHAR *)&save[-1];
186 else
187 /* There was no number to convert. */
188 *endptr = (WCHAR *)nptr;
189 }
190
191 return 0L;
192}
193
194
195unsigned long int strtoulW( const WCHAR *nptr, WCHAR **endptr, int base )
196{
197 int negative;
198 register unsigned long int cutoff;
199 register unsigned int cutlim;
200 register unsigned long int i;
201 register const WCHAR *s;
202 register WCHAR c;
203 const WCHAR *save, *end;
204 int overflow;
205
206 if (base < 0 || base == 1 || base > 36) return 0;
207
208 save = s = nptr;
209
210 /* Skip white space. */
211 while (isspaceW (*s))
212 ++s;
213 if (!*s) goto noconv;
214
215 /* Check for a sign. */
216 negative = 0;
217 if (*s == '-')
218 {
219 negative = 1;
220 ++s;
221 }
222 else if (*s == '+')
223 ++s;
224
225 /* Recognize number prefix and if BASE is zero, figure it out ourselves. */
226 if (*s == '0')
227 {
228 if ((base == 0 || base == 16) && toupperW(s[1]) == 'X')
229 {
230 s += 2;
231 base = 16;
232 }
233 else if (base == 0)
234 base = 8;
235 }
236 else if (base == 0)
237 base = 10;
238
239 /* Save the pointer so we can check later if anything happened. */
240 save = s;
241 end = NULL;
242
243 cutoff = ULONG_MAX / (unsigned long int) base;
244 cutlim = ULONG_MAX % (unsigned long int) base;
245
246 overflow = 0;
247 i = 0;
248 c = *s;
249 for (;c != '\0'; c = *++s)
250 {
251 if (s == end)
252 break;
253 if (c >= '0' && c <= '9')
254 c -= '0';
255 else if (isalphaW (c))
256 c = toupperW (c) - 'A' + 10;
257 else
258 break;
259 if ((int) c >= base)
260 break;
261 /* Check for overflow. */
262 if (i > cutoff || (i == cutoff && c > cutlim))
263 overflow = 1;
264 else
265 {
266 i *= (unsigned long int) base;
267 i += c;
268 }
269 }
270
271 /* Check if anything actually happened. */
272 if (s == save)
273 goto noconv;
274
275 /* Store in ENDPTR the address of one character
276 past the last character we converted. */
277 if (endptr != NULL)
278 *endptr = (WCHAR *)s;
279
280 if (overflow)
281 {
282 errno = ERANGE;
283 return ULONG_MAX;
284 }
285
286 /* Return the result of the appropriate sign. */
287 return negative ? -i : i;
288
289noconv:
290 /* We must handle a special case here: the base is 0 or 16 and the
291 first two characters are '0' and 'x', but the rest are not
292 hexadecimal digits. This is no error case. We return 0 and
293 ENDPTR points to the `x`. */
294 if (endptr != NULL)
295 {
296 if (save - nptr >= 2 && toupperW (save[-1]) == 'X'
297 && save[-2] == '0')
298 *endptr = (WCHAR *)&save[-1];
299 else
300 /* There was no number to convert. */
301 *endptr = (WCHAR *)nptr;
302 }
303
304 return 0L;
305}
306
307
308/* format a WCHAR string according to a printf format; helper for vsnprintfW */
309static size_t format_string( WCHAR *buffer, size_t len, const char *format, const WCHAR *str, int str_len )
310{
311 size_t count = 0;
312 int i, left_align = 0, width = 0, max = 0;
313
314 assert( *format == '%' );
315 format++; /* skip '%' */
316
317 while (*format == '0' || *format == '+' || *format == '-' || *format == ' ' || *format == '#')
318 {
319 if (*format == '-') left_align = 1;
320 format++;
321 }
322
323 while (isdigit(*format)) width = width * 10 + *format++ - '0';
324
325 if (str_len == -1) str_len = strlenW( str );
326 if (*format == '.')
327 {
328 format++;
329 while (isdigit(*format)) max = max * 10 + *format++ - '0';
330 if (max > str_len) max = str_len;
331 }
332 else max = str_len;
333
334 if (*format == 'h' || *format == 'l') format++;
335
336 assert( *format == 's' );
337
338 if (!left_align && width > max)
339 {
340 for (i = 0; i < width - max; i++)
341 {
342 if (count++ < len)
343 *buffer++ = ' ';
344 }
345 }
346
347 if (count < len)
348 memcpy( buffer, str, min( max, len - count ) * sizeof(WCHAR) );
349 count += max;
350 buffer += max;
351
352 if (left_align && width > max)
353 {
354 for (i = 0; i < width - max; i++)
355 {
356 if (count++ < len)
357 *buffer++ = ' ';
358 }
359 }
360 return count;
361}
362
364{
365 unsigned int written = 0;
366 const WCHAR *iter = format;
367 char bufa[512], fmtbufa[64], *fmta;
368
369 while (*iter)
370 {
371 while (*iter && *iter != '%')
372 {
373 if (written++ < len)
374 *str++ = *iter;
375 iter++;
376 }
377 if (*iter == '%')
378 {
379 if (iter[1] == '%')
380 {
381 if (written++ < len)
382 *str++ = '%'; /* "%%"->'%' */
383 iter += 2;
384 continue;
385 }
386
387 fmta = fmtbufa;
388 *fmta++ = *iter++;
389 while (*iter == '0' ||
390 *iter == '+' ||
391 *iter == '-' ||
392 *iter == ' ' ||
393 *iter == '*' ||
394 *iter == '#')
395 {
396 if (*iter == '*')
397 {
398 char *buffiter = bufa;
399 int fieldlen = va_arg(valist, int);
400 sprintf(buffiter, "%d", fieldlen);
401 while (*buffiter)
402 *fmta++ = *buffiter++;
403 }
404 else
405 *fmta++ = *iter;
406 iter++;
407 }
408
409 while (isdigit(*iter))
410 *fmta++ = *iter++;
411
412 if (*iter == '.')
413 {
414 *fmta++ = *iter++;
415 if (*iter == '*')
416 {
417 char *buffiter = bufa;
418 int fieldlen = va_arg(valist, int);
419 sprintf(buffiter, "%d", fieldlen);
420 while (*buffiter)
421 *fmta++ = *buffiter++;
422 iter++;
423 }
424 else
425 while (isdigit(*iter))
426 *fmta++ = *iter++;
427 }
428 if (*iter == 'h' || *iter == 'l')
429 *fmta++ = *iter++;
430
431 switch (*iter)
432 {
433 case 's':
434 {
435 static const WCHAR none[] = { '(','n','u','l','l',')',0 };
436 const WCHAR *wstr = va_arg(valist, const WCHAR *);
437 size_t remaining = written < len ? len - written : 0;
438 size_t count;
439
440 *fmta++ = 's';
441 *fmta = 0;
442 count = format_string( str, remaining, fmtbufa, wstr ? wstr : none, -1 );
443 str += min( count, remaining );
444 written += count;
445 iter++;
446 break;
447 }
448
449 case 'c':
450 {
451 WCHAR wstr;
452 size_t remaining = written < len ? len - written : 0;
453 size_t count;
454
455 wstr = va_arg(valist, int);
456 *fmta++ = 's';
457 *fmta = 0;
458 count = format_string( str, remaining, fmtbufa, &wstr, 1 );
459 str += min( count, remaining );
460 written += count;
461 iter++;
462 break;
463 }
464
465 default:
466 {
467 /* For non wc types, use system sprintf and append to wide char output */
468 /* FIXME: for unrecognised types, should ignore % when printing */
469 char *bufaiter = bufa;
470 if (*iter == 'p')
471#ifdef __REACTOS__
472 sprintf(bufaiter, "%p", va_arg(valist, void*));
473#else
474 sprintf(bufaiter, "%0*lX", 2 * (int)sizeof(void*),
475 (unsigned long)va_arg(valist, void *));
476#endif
477 else
478 {
479 *fmta++ = *iter;
480 *fmta = '\0';
481 if (*iter == 'a' || *iter == 'A' ||
482 *iter == 'e' || *iter == 'E' ||
483 *iter == 'f' || *iter == 'F' ||
484 *iter == 'g' || *iter == 'G')
485 sprintf(bufaiter, fmtbufa, va_arg(valist, double));
486 else
487 {
488 /* FIXME: On 32 bit systems this doesn't handle int 64's. */
489 sprintf(bufaiter, fmtbufa, va_arg(valist, void *));
490 }
491 }
492 while (*bufaiter)
493 {
494 if (written++ < len)
495 *str++ = *bufaiter;
496 bufaiter++;
497 }
498 iter++;
499 break;
500 }
501 }
502 }
503 }
504 if (len)
505 {
506 if (written >= len)
507 str--;
508 *str++ = 0;
509 }
510
511 /* FIXME: POSIX [v]snprintf() returns the equivalent of written, not -1, on short buffer. */
512 return written < len ? (int)written : -1;
513}
514
516{
517 return vsnprintfW( str, INT_MAX, format, valist );
518}
519
520int snprintfW( WCHAR *str, size_t len, const WCHAR *format, ...)
521{
522 int retval;
525 retval = vsnprintfW(str, len, format, valist);
526 va_end(valist);
527 return retval;
528}
529
530int sprintfW( WCHAR *str, const WCHAR *format, ...)
531{
532 int retval;
535 retval = vsnprintfW(str, INT_MAX, format, valist);
536 va_end(valist);
537 return retval;
538}
#define isdigit(c)
Definition: acclib.h:68
#define ERANGE
Definition: acclib.h:92
char * va_list
Definition: acmsvcex.h:78
#define va_end(ap)
Definition: acmsvcex.h:90
#define va_start(ap, A)
Definition: acmsvcex.h:91
#define va_arg(ap, T)
Definition: acmsvcex.h:89
#define NULL
Definition: types.h:112
#define assert(x)
Definition: debug.h:53
GLdouble s
Definition: gl.h:2039
GLuint GLuint end
Definition: gl.h:1545
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLint GLint GLsizei width
Definition: gl.h:1546
GLdouble n
Definition: glext.h:7729
GLuint buffer
Definition: glext.h:5915
const GLubyte * c
Definition: glext.h:8905
GLenum GLsizei len
Definition: glext.h:6722
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define ULONG_MAX
Definition: intsafe.h:155
#define LONG_MAX
Definition: intsafe.h:154
#define INT_MAX
Definition: intsafe.h:150
#define LONG_MIN
Definition: intsafe.h:125
#define c
Definition: ke_i.h:80
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define sprintf(buf, format,...)
Definition: sprintf.c:55
static __ms_va_list valist
Definition: printf.c:66
static char int
Definition: string.c:71
#define min(a, b)
Definition: monoChain.cc:55
#define L(x)
Definition: ntvdm.h:50
#define strncmpiW(s1, s2, n)
Definition: unicode.h:46
#define toupperW(n)
Definition: unicode.h:51
#define strstrW(d, s)
Definition: unicode.h:38
#define memicmpW(s1, s2, n)
Definition: unicode.h:33
#define strcmpiW(s1, s2)
Definition: unicode.h:45
#define tolowerW(n)
Definition: unicode.h:50
#define strlenW(s)
Definition: unicode.h:34
#define strtoulW(s1, s2, b)
Definition: unicode.h:47
#define vsprintfW
Definition: unicode.h:65
#define isspaceW(n)
Definition: unicode.h:58
#define vsnprintfW
Definition: unicode.h:67
#define snprintfW
Definition: unicode.h:66
#define sprintfW
Definition: unicode.h:64
#define strtolW(s, e, b)
Definition: unicode.h:39
#define isalphaW(n)
Definition: unicode.h:54
const WCHAR * str
#define errno
Definition: errno.h:18
static size_t format_string(WCHAR *buffer, size_t len, const char *format, const WCHAR *str, int str_len)
Definition: string.c:309
Definition: format.c:58
#define max(a, b)
Definition: svc.c:63
#define str_len
Definition: treelist.c:89
int ret
__wchar_t WCHAR
Definition: xmlstorage.h:180