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