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