xref: /reactos/sdk/lib/crt/string/wcstoul.c (revision c2c66aff)
1*c2c66affSColin Finck #include <precomp.h>
2*c2c66affSColin Finck 
3*c2c66affSColin Finck 
4*c2c66affSColin Finck /*
5*c2c66affSColin Finck  * Convert a unicode string to an unsigned long integer.
6*c2c66affSColin Finck  *
7*c2c66affSColin Finck  * Ignores `locale' stuff.  Assumes that the upper and lower case
8*c2c66affSColin Finck  * alphabets and digits are each contiguous.
9*c2c66affSColin Finck  *
10*c2c66affSColin Finck  * @implemented
11*c2c66affSColin Finck  */
12*c2c66affSColin Finck unsigned long
13*c2c66affSColin Finck CDECL
wcstoul(const wchar_t * nptr,wchar_t ** endptr,int base)14*c2c66affSColin Finck wcstoul(const wchar_t *nptr, wchar_t **endptr, int base)
15*c2c66affSColin Finck {
16*c2c66affSColin Finck   const wchar_t *s = nptr;
17*c2c66affSColin Finck   unsigned long acc;
18*c2c66affSColin Finck   int c;
19*c2c66affSColin Finck   unsigned long cutoff;
20*c2c66affSColin Finck   int neg = 0, any, cutlim;
21*c2c66affSColin Finck 
22*c2c66affSColin Finck   /*
23*c2c66affSColin Finck    * See strtol for comments as to the logic used.
24*c2c66affSColin Finck    */
25*c2c66affSColin Finck   do {
26*c2c66affSColin Finck     c = *s++;
27*c2c66affSColin Finck   } while (iswctype(c, _SPACE));
28*c2c66affSColin Finck   if (c == L'-')
29*c2c66affSColin Finck   {
30*c2c66affSColin Finck     neg = 1;
31*c2c66affSColin Finck     c = *s++;
32*c2c66affSColin Finck   }
33*c2c66affSColin Finck   else if (c == L'+')
34*c2c66affSColin Finck     c = *s++;
35*c2c66affSColin Finck   if ((base == 0 || base == 16) &&
36*c2c66affSColin Finck       c == L'0' && (*s == L'x' || *s == L'X'))
37*c2c66affSColin Finck   {
38*c2c66affSColin Finck     c = s[1];
39*c2c66affSColin Finck     s += 2;
40*c2c66affSColin Finck     base = 16;
41*c2c66affSColin Finck   }
42*c2c66affSColin Finck   if (base == 0)
43*c2c66affSColin Finck     base = c == L'0' ? 8 : 10;
44*c2c66affSColin Finck   cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
45*c2c66affSColin Finck   cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
46*c2c66affSColin Finck   for (acc = 0, any = 0;; c = *s++)
47*c2c66affSColin Finck   {
48*c2c66affSColin Finck     if (iswctype(c, _DIGIT))
49*c2c66affSColin Finck       c -= L'0';
50*c2c66affSColin Finck     else if (iswctype(c, _ALPHA))
51*c2c66affSColin Finck       c -= iswctype(c, _UPPER) ? L'A' - 10 : L'a' - 10;
52*c2c66affSColin Finck     else
53*c2c66affSColin Finck       break;
54*c2c66affSColin Finck     if (c >= base)
55*c2c66affSColin Finck       break;
56*c2c66affSColin Finck     if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
57*c2c66affSColin Finck       any = -1;
58*c2c66affSColin Finck     else {
59*c2c66affSColin Finck       any = 1;
60*c2c66affSColin Finck       acc *= base;
61*c2c66affSColin Finck       acc += c;
62*c2c66affSColin Finck     }
63*c2c66affSColin Finck   }
64*c2c66affSColin Finck   if (any < 0)
65*c2c66affSColin Finck   {
66*c2c66affSColin Finck     acc = ULONG_MAX;
67*c2c66affSColin Finck   }
68*c2c66affSColin Finck   else if (neg)
69*c2c66affSColin Finck     acc = 0-acc;
70*c2c66affSColin Finck   if (endptr != 0)
71*c2c66affSColin Finck     *endptr = any ? (wchar_t *)((size_t)(s - 1)) : (wchar_t *)((size_t)nptr);
72*c2c66affSColin Finck   return acc;
73*c2c66affSColin Finck }
74