Ignore:
Timestamp:
Jun 15, 2002, 12:41:44 PM (23 years ago)
Author:
sandervl
Message:

added strtolW & strtoulW

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/kernel32/unicode/string.c

    r5450 r8666  
    55 */
    66
     7#include <windows.h>
     8#include <limits.h>
     9
    710#include "wine/unicode.h"
    811
     
    3740    return NULL;
    3841}
     42
     43/* strtolW and strtoulW implementation based on the GNU C library code */
     44/* Copyright (C) 1991,92,94,95,96,97,98,99,2000,2001 Free Software Foundation, Inc. */
     45
     46long int strtolW( const WCHAR *nptr, WCHAR **endptr, int base )
     47{
     48  int negative;
     49  register unsigned long int cutoff;
     50  register unsigned int cutlim;
     51  register unsigned long int i;
     52  register const WCHAR *s;
     53  register WCHAR c;
     54  const WCHAR *save, *end;
     55  int overflow;
     56
     57  if (base < 0 || base == 1 || base > 36) return 0;
     58
     59  save = s = nptr;
     60
     61  /* Skip white space.  */
     62  while (isspaceW (*s))
     63    ++s;
     64  if (!*s) goto noconv;
     65
     66  /* Check for a sign.  */
     67  negative = 0;
     68  if (*s == '-')
     69    {
     70      negative = 1;
     71      ++s;
     72    }
     73  else if (*s == '+')
     74    ++s;
     75
     76  /* Recognize number prefix and if BASE is zero, figure it out ourselves.  */
     77  if (*s == '0')
     78    {
     79      if ((base == 0 || base == 16) && toupperW(s[1]) == 'X')
     80        {
     81          s += 2;
     82          base = 16;
     83        }
     84      else if (base == 0)
     85        base = 8;
     86    }
     87  else if (base == 0)
     88    base = 10;
     89
     90  /* Save the pointer so we can check later if anything happened.  */
     91  save = s;
     92  end = NULL;
     93
     94  cutoff = ULONG_MAX / (unsigned long int) base;
     95  cutlim = ULONG_MAX % (unsigned long int) base;
     96
     97  overflow = 0;
     98  i = 0;
     99  c = *s;
     100  for (;c != '\0'; c = *++s)
     101  {
     102      if (s == end)
     103          break;
     104      if (c >= '0' && c <= '9')
     105          c -= '0';
     106      else if (isalphaW (c))
     107          c = toupperW (c) - 'A' + 10;
     108      else
     109          break;
     110      if ((int) c >= base)
     111          break;
     112      /* Check for overflow.  */
     113      if (i > cutoff || (i == cutoff && c > cutlim))
     114          overflow = 1;
     115      else
     116      {
     117          i *= (unsigned long int) base;
     118          i += c;
     119      }
     120  }
     121
     122  /* Check if anything actually happened.  */
     123  if (s == save)
     124    goto noconv;
     125
     126  /* Store in ENDPTR the address of one character
     127     past the last character we converted.  */
     128  if (endptr != NULL)
     129    *endptr = (WCHAR *)s;
     130
     131  /* Check for a value that is within the range of
     132     `unsigned LONG int', but outside the range of `LONG int'.  */
     133  if (overflow == 0
     134      && i > (negative
     135              ? -((unsigned long int) (LONG_MIN + 1)) + 1
     136              : (unsigned long int) LONG_MAX))
     137    overflow = 1;
     138
     139  if (overflow)
     140    {
     141      return negative ? LONG_MIN : LONG_MAX;
     142    }
     143
     144  /* Return the result of the appropriate sign.  */
     145  return negative ? -i : i;
     146
     147noconv:
     148  /* We must handle a special case here: the base is 0 or 16 and the
     149     first two characters are '0' and 'x', but the rest are no
     150     hexadecimal digits.  This is no error case.  We return 0 and
     151     ENDPTR points to the `x`.  */
     152  if (endptr != NULL)
     153    {
     154      if (save - nptr >= 2 && toupperW (save[-1]) == 'X'
     155          && save[-2] == '0')
     156        *endptr = (WCHAR *)&save[-1];
     157      else
     158        /*  There was no number to convert.  */
     159        *endptr = (WCHAR *)nptr;
     160    }
     161
     162  return 0L;
     163}
     164
     165unsigned long int strtoulW( const WCHAR *nptr, WCHAR **endptr, int base )
     166{
     167  int negative;
     168  register unsigned long int cutoff;
     169  register unsigned int cutlim;
     170  register unsigned long int i;
     171  register const WCHAR *s;
     172  register WCHAR c;
     173  const WCHAR *save, *end;
     174  int overflow;
     175
     176  if (base < 0 || base == 1 || base > 36) return 0;
     177
     178  save = s = nptr;
     179
     180  /* Skip white space.  */
     181  while (isspaceW (*s))
     182    ++s;
     183  if (!*s) goto noconv;
     184
     185  /* Check for a sign.  */
     186  negative = 0;
     187  if (*s == '-')
     188    {
     189      negative = 1;
     190      ++s;
     191    }
     192  else if (*s == '+')
     193    ++s;
     194
     195  /* Recognize number prefix and if BASE is zero, figure it out ourselves.  */
     196  if (*s == '0')
     197    {
     198      if ((base == 0 || base == 16) && toupperW(s[1]) == 'X')
     199        {
     200          s += 2;
     201          base = 16;
     202        }
     203      else if (base == 0)
     204        base = 8;
     205    }
     206  else if (base == 0)
     207    base = 10;
     208
     209  /* Save the pointer so we can check later if anything happened.  */
     210  save = s;
     211  end = NULL;
     212
     213  cutoff = ULONG_MAX / (unsigned long int) base;
     214  cutlim = ULONG_MAX % (unsigned long int) base;
     215
     216  overflow = 0;
     217  i = 0;
     218  c = *s;
     219  for (;c != '\0'; c = *++s)
     220  {
     221      if (s == end)
     222          break;
     223      if (c >= '0' && c <= '9')
     224          c -= '0';
     225      else if (isalphaW (c))
     226          c = toupperW (c) - 'A' + 10;
     227      else
     228          break;
     229      if ((int) c >= base)
     230          break;
     231      /* Check for overflow.  */
     232      if (i > cutoff || (i == cutoff && c > cutlim))
     233          overflow = 1;
     234      else
     235      {
     236          i *= (unsigned long int) base;
     237          i += c;
     238      }
     239  }
     240
     241  /* Check if anything actually happened.  */
     242  if (s == save)
     243    goto noconv;
     244
     245  /* Store in ENDPTR the address of one character
     246     past the last character we converted.  */
     247  if (endptr != NULL)
     248    *endptr = (WCHAR *)s;
     249
     250  if (overflow)
     251    {
     252      return ULONG_MAX;
     253    }
     254
     255  /* Return the result of the appropriate sign.  */
     256  return negative ? -i : i;
     257
     258noconv:
     259  /* We must handle a special case here: the base is 0 or 16 and the
     260     first two characters are '0' and 'x', but the rest are no
     261     hexadecimal digits.  This is no error case.  We return 0 and
     262     ENDPTR points to the `x`.  */
     263  if (endptr != NULL)
     264    {
     265      if (save - nptr >= 2 && toupperW (save[-1]) == 'X'
     266          && save[-2] == '0')
     267        *endptr = (WCHAR *)&save[-1];
     268      else
     269        /*  There was no number to convert.  */
     270        *endptr = (WCHAR *)nptr;
     271    }
     272
     273  return 0L;
     274}
Note: See TracChangeset for help on using the changeset viewer.