1*c2c66affSColin Finck /*
2*c2c66affSColin Finck * COPYRIGHT: See COPYING in the top level directory
3*c2c66affSColin Finck * PROJECT: ReactOS system libraries
4*c2c66affSColin Finck * FILE: lib/sdk/crt/string/wcstol.c
5*c2c66affSColin Finck * PURPOSE: Unknown
6*c2c66affSColin Finck * PROGRAMER: Unknown
7*c2c66affSColin Finck * UPDATE HISTORY:
8*c2c66affSColin Finck * 25/11/05: Added license header
9*c2c66affSColin Finck */
10*c2c66affSColin Finck
11*c2c66affSColin Finck #include <precomp.h>
12*c2c66affSColin Finck /*
13*c2c66affSColin Finck * @implemented
14*c2c66affSColin Finck */
15*c2c66affSColin Finck long
16*c2c66affSColin Finck CDECL
wcstol(const wchar_t * nptr,wchar_t ** endptr,int base)17*c2c66affSColin Finck wcstol(const wchar_t *nptr, wchar_t **endptr, int base)
18*c2c66affSColin Finck {
19*c2c66affSColin Finck const wchar_t *s = nptr;
20*c2c66affSColin Finck long acc;
21*c2c66affSColin Finck int c;
22*c2c66affSColin Finck unsigned long cutoff;
23*c2c66affSColin Finck int neg = 0, any, cutlim;
24*c2c66affSColin Finck
25*c2c66affSColin Finck /*
26*c2c66affSColin Finck * Skip white space and pick up leading +/- sign if any.
27*c2c66affSColin Finck * If base is 0, allow 0x for hex and 0 for octal, else
28*c2c66affSColin Finck * assume decimal; if base is already 16, allow 0x.
29*c2c66affSColin Finck */
30*c2c66affSColin Finck do {
31*c2c66affSColin Finck c = *s++;
32*c2c66affSColin Finck } while (iswctype(c, _SPACE));
33*c2c66affSColin Finck if (c == '-')
34*c2c66affSColin Finck {
35*c2c66affSColin Finck neg = 1;
36*c2c66affSColin Finck c = *s++;
37*c2c66affSColin Finck }
38*c2c66affSColin Finck else if (c == L'+')
39*c2c66affSColin Finck c = *s++;
40*c2c66affSColin Finck if ((base == 0 || base == 16) &&
41*c2c66affSColin Finck c == L'0' && (*s == L'x' || *s == L'X'))
42*c2c66affSColin Finck {
43*c2c66affSColin Finck c = s[1];
44*c2c66affSColin Finck s += 2;
45*c2c66affSColin Finck base = 16;
46*c2c66affSColin Finck }
47*c2c66affSColin Finck if (base == 0)
48*c2c66affSColin Finck base = c == L'0' ? 8 : 10;
49*c2c66affSColin Finck
50*c2c66affSColin Finck /*
51*c2c66affSColin Finck * Compute the cutoff value between legal numbers and illegal
52*c2c66affSColin Finck * numbers. That is the largest legal value, divided by the
53*c2c66affSColin Finck * base. An input number that is greater than this value, if
54*c2c66affSColin Finck * followed by a legal input character, is too big. One that
55*c2c66affSColin Finck * is equal to this value may be valid or not; the limit
56*c2c66affSColin Finck * between valid and invalid numbers is then based on the last
57*c2c66affSColin Finck * digit. For instance, if the range for longs is
58*c2c66affSColin Finck * [-2147483648..2147483647] and the input base is 10,
59*c2c66affSColin Finck * cutoff will be set to 214748364 and cutlim to either
60*c2c66affSColin Finck * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
61*c2c66affSColin Finck * a value > 214748364, or equal but the next digit is > 7 (or 8),
62*c2c66affSColin Finck * the number is too big, and we will return a range error.
63*c2c66affSColin Finck *
64*c2c66affSColin Finck * Set any if any `digits' consumed; make it negative to indicate
65*c2c66affSColin Finck * overflow.
66*c2c66affSColin Finck */
67*c2c66affSColin Finck cutoff = neg ? ((unsigned long)LONG_MAX+1) : LONG_MAX;
68*c2c66affSColin Finck cutlim = cutoff % (unsigned long)base;
69*c2c66affSColin Finck cutoff /= (unsigned long)base;
70*c2c66affSColin Finck for (acc = 0, any = 0;; c = *s++)
71*c2c66affSColin Finck {
72*c2c66affSColin Finck if (iswctype(c, _DIGIT))
73*c2c66affSColin Finck c -= L'0';
74*c2c66affSColin Finck else if (iswctype(c, _ALPHA))
75*c2c66affSColin Finck c -= iswctype(c, _UPPER) ? L'A' - 10 : L'a' - 10;
76*c2c66affSColin Finck else
77*c2c66affSColin Finck break;
78*c2c66affSColin Finck if (c >= base)
79*c2c66affSColin Finck break;
80*c2c66affSColin Finck if (any < 0 || (unsigned long)acc > cutoff || (acc == cutoff && c > cutlim))
81*c2c66affSColin Finck any = -1;
82*c2c66affSColin Finck else
83*c2c66affSColin Finck {
84*c2c66affSColin Finck any = 1;
85*c2c66affSColin Finck acc *= base;
86*c2c66affSColin Finck acc += c;
87*c2c66affSColin Finck }
88*c2c66affSColin Finck }
89*c2c66affSColin Finck if (any < 0)
90*c2c66affSColin Finck {
91*c2c66affSColin Finck acc = neg ? LONG_MIN : LONG_MAX;
92*c2c66affSColin Finck }
93*c2c66affSColin Finck else if (neg)
94*c2c66affSColin Finck acc = 0-acc;
95*c2c66affSColin Finck if (endptr != 0)
96*c2c66affSColin Finck *endptr = any ? (wchar_t *)((size_t)(s - 1)) : (wchar_t *)((size_t)nptr);
97*c2c66affSColin Finck return acc;
98*c2c66affSColin Finck }
99