[CRT][LIBCNTPR] Adopt strtoul() from Wine Staging 1.7.37. Fixes a msvcrt:string test...
[reactos.git] / reactos / lib / sdk / crt / string / strtoul.c
1 #include <precomp.h>
2
3 /* Based on Wine Staging 1.7.37 - dlls/msvcrt/string.c */
4
5 /*********************************************************************
6 * _strtoi64_l (MSVCRT.@)
7 *
8 * FIXME: locale parameter is ignored
9 */
10 __int64 CDECL strtoi64_l(const char *nptr, char **endptr, int base, _locale_t locale)
11 {
12 BOOL negative = FALSE;
13 __int64 ret = 0;
14
15 #ifndef _LIBCNT_
16 TRACE("(%s %p %d %p)\n", debugstr_a(nptr), endptr, base, locale);
17 #endif
18
19 if (!MSVCRT_CHECK_PMT(nptr != NULL)) return 0;
20 if (!MSVCRT_CHECK_PMT(base == 0 || base >= 2)) return 0;
21 if (!MSVCRT_CHECK_PMT(base <= 36)) return 0;
22
23 while(isspace(*nptr)) nptr++;
24
25 if(*nptr == '-') {
26 negative = TRUE;
27 nptr++;
28 } else if(*nptr == '+')
29 nptr++;
30
31 if((base==0 || base==16) && *nptr=='0' && tolower(*(nptr+1))=='x') {
32 base = 16;
33 nptr += 2;
34 }
35
36 if(base == 0) {
37 if(*nptr=='0')
38 base = 8;
39 else
40 base = 10;
41 }
42
43 while(*nptr) {
44 char cur = tolower(*nptr);
45 int v;
46
47 if(isdigit(cur)) {
48 if(cur >= '0'+base)
49 break;
50 v = cur-'0';
51 } else {
52 if(cur<'a' || cur>='a'+base-10)
53 break;
54 v = cur-'a'+10;
55 }
56
57 if(negative)
58 v = -v;
59
60 nptr++;
61
62 if(!negative && (ret>_I64_MAX/base || ret*base>_I64_MAX-v)) {
63 ret = _I64_MAX;
64 #ifndef _LIBCNT_
65 *_errno() = ERANGE;
66 #endif
67 } else if(negative && (ret<_I64_MIN/base || ret*base<_I64_MIN-v)) {
68 ret = _I64_MIN;
69 #ifndef _LIBCNT_
70 *_errno() = ERANGE;
71 #endif
72 } else
73 ret = ret*base + v;
74 }
75
76 if(endptr)
77 *endptr = (char*)nptr;
78
79 return ret;
80 }
81
82 /******************************************************************
83 * _strtoul_l (MSVCRT.@)
84 */
85 unsigned long CDECL strtoul_l(const char* nptr, char** end, int base, _locale_t locale)
86 {
87 __int64 ret = strtoi64_l(nptr, end, base, locale);
88
89 if(ret > ULONG_MAX) {
90 ret = ULONG_MAX;
91 #ifndef _LIBCNT_
92 *_errno() = ERANGE;
93 #endif
94 }else if(ret < -(__int64)ULONG_MAX) {
95 ret = 1;
96 #ifndef _LIBCNT_
97 *_errno() = ERANGE;
98 #endif
99 }
100
101 return ret;
102 }
103
104 /******************************************************************
105 * strtoul (MSVCRT.@)
106 */
107 unsigned long CDECL strtoul(const char* nptr, char** end, int base)
108 {
109 return strtoul_l(nptr, end, base, NULL);
110 }