Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenstring.c
Go to the documentation of this file.
00001 /* 00002 * Unicode string manipulation functions 00003 * 00004 * Copyright 2000 Alexandre Julliard 00005 * 00006 * This library is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2.1 of the License, or (at your option) any later version. 00010 * 00011 * This library is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public 00017 * License along with this library; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00019 */ 00020 00021 #include <assert.h> 00022 #include <limits.h> 00023 #include <stdio.h> 00024 00025 #define WINE_UNICODE_INLINE /* nothing */ 00026 #include "wine/unicode.h" 00027 00028 int strcmpiW( const WCHAR *str1, const WCHAR *str2 ) 00029 { 00030 for (;;) 00031 { 00032 int ret = tolowerW(*str1) - tolowerW(*str2); 00033 if (ret || !*str1) return ret; 00034 str1++; 00035 str2++; 00036 } 00037 } 00038 00039 int strncmpiW( const WCHAR *str1, const WCHAR *str2, int n ) 00040 { 00041 int ret = 0; 00042 for ( ; n > 0; n--, str1++, str2++) 00043 if ((ret = tolowerW(*str1) - tolowerW(*str2)) || !*str1) break; 00044 return ret; 00045 } 00046 00047 int memicmpW( const WCHAR *str1, const WCHAR *str2, int n ) 00048 { 00049 int ret = 0; 00050 for ( ; n > 0; n--, str1++, str2++) 00051 if ((ret = tolowerW(*str1) - tolowerW(*str2))) break; 00052 return ret; 00053 } 00054 00055 WCHAR *strstrW( const WCHAR *str, const WCHAR *sub ) 00056 { 00057 while (*str) 00058 { 00059 const WCHAR *p1 = str, *p2 = sub; 00060 while (*p1 && *p2 && *p1 == *p2) { p1++; p2++; } 00061 if (!*p2) return (WCHAR *)str; 00062 str++; 00063 } 00064 return NULL; 00065 } 00066 00067 /* strtolW and strtoulW implementation based on the GNU C library code */ 00068 /* Copyright (C) 1991,92,94,95,96,97,98,99,2000,2001 Free Software Foundation, Inc. */ 00069 00070 long int strtolW( const WCHAR *nptr, WCHAR **endptr, int base ) 00071 { 00072 int negative; 00073 register unsigned long int cutoff; 00074 register unsigned int cutlim; 00075 register unsigned long int i; 00076 register const WCHAR *s; 00077 register WCHAR c; 00078 const WCHAR *save, *end; 00079 int overflow; 00080 00081 if (base < 0 || base == 1 || base > 36) return 0; 00082 00083 save = s = nptr; 00084 00085 /* Skip white space. */ 00086 while (isspaceW (*s)) 00087 ++s; 00088 if (!*s) goto noconv; 00089 00090 /* Check for a sign. */ 00091 negative = 0; 00092 if (*s == '-') 00093 { 00094 negative = 1; 00095 ++s; 00096 } 00097 else if (*s == '+') 00098 ++s; 00099 00100 /* Recognize number prefix and if BASE is zero, figure it out ourselves. */ 00101 if (*s == '0') 00102 { 00103 if ((base == 0 || base == 16) && toupperW(s[1]) == 'X') 00104 { 00105 s += 2; 00106 base = 16; 00107 } 00108 else if (base == 0) 00109 base = 8; 00110 } 00111 else if (base == 0) 00112 base = 10; 00113 00114 /* Save the pointer so we can check later if anything happened. */ 00115 save = s; 00116 end = NULL; 00117 00118 cutoff = ULONG_MAX / (unsigned long int) base; 00119 cutlim = ULONG_MAX % (unsigned long int) base; 00120 00121 overflow = 0; 00122 i = 0; 00123 c = *s; 00124 for (;c != '\0'; c = *++s) 00125 { 00126 if (s == end) 00127 break; 00128 if (c >= '0' && c <= '9') 00129 c -= '0'; 00130 else if (isalphaW (c)) 00131 c = toupperW (c) - 'A' + 10; 00132 else 00133 break; 00134 if ((int) c >= base) 00135 break; 00136 /* Check for overflow. */ 00137 if (i > cutoff || (i == cutoff && c > cutlim)) 00138 overflow = 1; 00139 else 00140 { 00141 i *= (unsigned long int) base; 00142 i += c; 00143 } 00144 } 00145 00146 /* Check if anything actually happened. */ 00147 if (s == save) 00148 goto noconv; 00149 00150 /* Store in ENDPTR the address of one character 00151 past the last character we converted. */ 00152 if (endptr != NULL) 00153 *endptr = (WCHAR *)s; 00154 00155 /* Check for a value that is within the range of 00156 `unsigned LONG int', but outside the range of `LONG int'. */ 00157 if (overflow == 0 00158 && i > (negative 00159 ? -((unsigned long int) (LONG_MIN + 1)) + 1 00160 : (unsigned long int) LONG_MAX)) 00161 overflow = 1; 00162 00163 if (overflow) 00164 { 00165 return negative ? LONG_MIN : LONG_MAX; 00166 } 00167 00168 /* Return the result of the appropriate sign. */ 00169 return negative ? -i : i; 00170 00171 noconv: 00172 /* We must handle a special case here: the base is 0 or 16 and the 00173 first two characters are '0' and 'x', but the rest are not 00174 hexadecimal digits. This is no error case. We return 0 and 00175 ENDPTR points to the `x`. */ 00176 if (endptr != NULL) 00177 { 00178 if (save - nptr >= 2 && toupperW (save[-1]) == 'X' 00179 && save[-2] == '0') 00180 *endptr = (WCHAR *)&save[-1]; 00181 else 00182 /* There was no number to convert. */ 00183 *endptr = (WCHAR *)nptr; 00184 } 00185 00186 return 0L; 00187 } 00188 00189 00190 unsigned long int strtoulW( const WCHAR *nptr, WCHAR **endptr, int base ) 00191 { 00192 int negative; 00193 register unsigned long int cutoff; 00194 register unsigned int cutlim; 00195 register unsigned long int i; 00196 register const WCHAR *s; 00197 register WCHAR c; 00198 const WCHAR *save, *end; 00199 int overflow; 00200 00201 if (base < 0 || base == 1 || base > 36) return 0; 00202 00203 save = s = nptr; 00204 00205 /* Skip white space. */ 00206 while (isspaceW (*s)) 00207 ++s; 00208 if (!*s) goto noconv; 00209 00210 /* Check for a sign. */ 00211 negative = 0; 00212 if (*s == '-') 00213 { 00214 negative = 1; 00215 ++s; 00216 } 00217 else if (*s == '+') 00218 ++s; 00219 00220 /* Recognize number prefix and if BASE is zero, figure it out ourselves. */ 00221 if (*s == '0') 00222 { 00223 if ((base == 0 || base == 16) && toupperW(s[1]) == 'X') 00224 { 00225 s += 2; 00226 base = 16; 00227 } 00228 else if (base == 0) 00229 base = 8; 00230 } 00231 else if (base == 0) 00232 base = 10; 00233 00234 /* Save the pointer so we can check later if anything happened. */ 00235 save = s; 00236 end = NULL; 00237 00238 cutoff = ULONG_MAX / (unsigned long int) base; 00239 cutlim = ULONG_MAX % (unsigned long int) base; 00240 00241 overflow = 0; 00242 i = 0; 00243 c = *s; 00244 for (;c != '\0'; c = *++s) 00245 { 00246 if (s == end) 00247 break; 00248 if (c >= '0' && c <= '9') 00249 c -= '0'; 00250 else if (isalphaW (c)) 00251 c = toupperW (c) - 'A' + 10; 00252 else 00253 break; 00254 if ((int) c >= base) 00255 break; 00256 /* Check for overflow. */ 00257 if (i > cutoff || (i == cutoff && c > cutlim)) 00258 overflow = 1; 00259 else 00260 { 00261 i *= (unsigned long int) base; 00262 i += c; 00263 } 00264 } 00265 00266 /* Check if anything actually happened. */ 00267 if (s == save) 00268 goto noconv; 00269 00270 /* Store in ENDPTR the address of one character 00271 past the last character we converted. */ 00272 if (endptr != NULL) 00273 *endptr = (WCHAR *)s; 00274 00275 if (overflow) 00276 { 00277 return ULONG_MAX; 00278 } 00279 00280 /* Return the result of the appropriate sign. */ 00281 return negative ? -i : i; 00282 00283 noconv: 00284 /* We must handle a special case here: the base is 0 or 16 and the 00285 first two characters are '0' and 'x', but the rest are not 00286 hexadecimal digits. This is no error case. We return 0 and 00287 ENDPTR points to the `x`. */ 00288 if (endptr != NULL) 00289 { 00290 if (save - nptr >= 2 && toupperW (save[-1]) == 'X' 00291 && save[-2] == '0') 00292 *endptr = (WCHAR *)&save[-1]; 00293 else 00294 /* There was no number to convert. */ 00295 *endptr = (WCHAR *)nptr; 00296 } 00297 00298 return 0L; 00299 } 00300 00301 00302 /* format a WCHAR string according to a printf format; helper for vsnprintfW */ 00303 static int format_string( WCHAR *buffer, size_t len, const char *format, const WCHAR *str, int str_len ) 00304 { 00305 size_t count = 0; 00306 int i, left_align = 0, width = 0, max = 0; 00307 00308 assert( *format == '%' ); 00309 format++; /* skip '%' */ 00310 00311 while (*format == '0' || *format == '+' || *format == '-' || *format == ' ' || *format == '#') 00312 { 00313 if (*format == '-') left_align = 1; 00314 format++; 00315 } 00316 00317 while (isdigit(*format)) width = width * 10 + *format++ - '0'; 00318 00319 if (str_len == -1) str_len = strlenW( str ); 00320 if (*format == '.') 00321 { 00322 format++; 00323 while (isdigit(*format)) max = max * 10 + *format++ - '0'; 00324 if (max > str_len) max = str_len; 00325 } 00326 else max = str_len; 00327 00328 if (*format == 'h' || *format == 'l') format++; 00329 00330 assert( *format == 's' ); 00331 00332 if (!left_align && width > max) 00333 { 00334 if ((count += width - max) >= len) return -1; 00335 for (i = 0; i < width - max; i++) *buffer++ = ' '; 00336 } 00337 00338 if ((count += max) >= len) return -1; 00339 memcpy( buffer, str, max * sizeof(WCHAR) ); 00340 buffer += max; 00341 00342 if (left_align && width > max) 00343 { 00344 if ((count += width - max) >= len) return -1; 00345 for (i = 0; i < width - max; i++) *buffer++ = ' '; 00346 } 00347 return count; 00348 } 00349 00350 int vsnprintfW(WCHAR *str, size_t len, const WCHAR *format, va_list valist) 00351 { 00352 unsigned int written = 0; 00353 const WCHAR *iter = format; 00354 char bufa[512], fmtbufa[64], *fmta; 00355 00356 while (*iter) 00357 { 00358 while (*iter && *iter != '%') 00359 { 00360 if (written++ >= len) 00361 return -1; 00362 *str++ = *iter++; 00363 } 00364 if (*iter == '%') 00365 { 00366 if (iter[1] == '%') 00367 { 00368 if (written++ >= len) 00369 return -1; 00370 *str++ = '%'; /* "%%"->'%' */ 00371 iter += 2; 00372 continue; 00373 } 00374 00375 fmta = fmtbufa; 00376 *fmta++ = *iter++; 00377 while (*iter == '0' || 00378 *iter == '+' || 00379 *iter == '-' || 00380 *iter == ' ' || 00381 *iter == '*' || 00382 *iter == '#') 00383 { 00384 if (*iter == '*') 00385 { 00386 char *buffiter = bufa; 00387 int fieldlen = va_arg(valist, int); 00388 sprintf(buffiter, "%d", fieldlen); 00389 while (*buffiter) 00390 *fmta++ = *buffiter++; 00391 } 00392 else 00393 *fmta++ = *iter; 00394 iter++; 00395 } 00396 00397 while (isdigit(*iter)) 00398 *fmta++ = *iter++; 00399 00400 if (*iter == '.') 00401 { 00402 *fmta++ = *iter++; 00403 if (*iter == '*') 00404 { 00405 char *buffiter = bufa; 00406 int fieldlen = va_arg(valist, int); 00407 sprintf(buffiter, "%d", fieldlen); 00408 while (*buffiter) 00409 *fmta++ = *buffiter++; 00410 iter++; 00411 } 00412 else 00413 while (isdigit(*iter)) 00414 *fmta++ = *iter++; 00415 } 00416 if (*iter == 'h' || *iter == 'l') 00417 *fmta++ = *iter++; 00418 00419 switch (*iter) 00420 { 00421 case 's': 00422 { 00423 static const WCHAR none[] = { '(','n','u','l','l',')',0 }; 00424 const WCHAR *wstr = va_arg(valist, const WCHAR *); 00425 int count; 00426 00427 *fmta++ = 's'; 00428 *fmta = 0; 00429 count = format_string( str, len - written, fmtbufa, wstr ? wstr : none, -1 ); 00430 if (count == -1) return -1; 00431 str += count; 00432 written += count; 00433 iter++; 00434 break; 00435 } 00436 00437 case 'c': 00438 { 00439 WCHAR wstr; 00440 int count; 00441 00442 wstr = va_arg(valist, int); 00443 *fmta++ = 's'; 00444 *fmta = 0; 00445 count = format_string( str, len - written, fmtbufa, &wstr, 1 ); 00446 if (count == -1) return -1; 00447 str += count; 00448 written += count; 00449 iter++; 00450 break; 00451 } 00452 00453 default: 00454 { 00455 /* For non wc types, use system sprintf and append to wide char output */ 00456 /* FIXME: for unrecognised types, should ignore % when printing */ 00457 char *bufaiter = bufa; 00458 if (*iter == 'p') 00459 sprintf(bufaiter, "%0*lX", 2 * (int)sizeof(void*), 00460 (unsigned long)va_arg(valist, void *)); 00461 else 00462 { 00463 *fmta++ = *iter; 00464 *fmta = '\0'; 00465 if (*iter == 'a' || *iter == 'A' || 00466 *iter == 'e' || *iter == 'E' || 00467 *iter == 'f' || *iter == 'F' || 00468 *iter == 'g' || *iter == 'G') 00469 sprintf(bufaiter, fmtbufa, va_arg(valist, double)); 00470 else 00471 { 00472 /* FIXME: On 32 bit systems this doesn't handle int 64's. */ 00473 sprintf(bufaiter, fmtbufa, va_arg(valist, void *)); 00474 } 00475 } 00476 while (*bufaiter) 00477 { 00478 if (written++ >= len) 00479 return -1; 00480 *str++ = *bufaiter++; 00481 } 00482 iter++; 00483 break; 00484 } 00485 } 00486 } 00487 } 00488 if (written >= len) 00489 return -1; 00490 *str++ = 0; 00491 return (int)written; 00492 } 00493 00494 int vsprintfW( WCHAR *str, const WCHAR *format, va_list valist ) 00495 { 00496 return vsnprintfW( str, INT_MAX, format, valist ); 00497 } 00498 00499 int snprintfW( WCHAR *str, size_t len, const WCHAR *format, ...) 00500 { 00501 int retval; 00502 va_list valist; 00503 va_start(valist, format); 00504 retval = vsnprintfW(str, len, format, valist); 00505 va_end(valist); 00506 return retval; 00507 } 00508 00509 int sprintfW( WCHAR *str, const WCHAR *format, ...) 00510 { 00511 int retval; 00512 va_list valist; 00513 va_start(valist, format); 00514 retval = vsnprintfW(str, INT_MAX, format, valist); 00515 va_end(valist); 00516 return retval; 00517 } Generated on Sat May 26 2012 04:16:32 for ReactOS by
1.7.6.1
|