ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

string.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.