Changeset 8666 for trunk/src/kernel32/unicode/string.c
- Timestamp:
- Jun 15, 2002, 12:41:44 PM (23 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kernel32/unicode/string.c
r5450 r8666 5 5 */ 6 6 7 #include <windows.h> 8 #include <limits.h> 9 7 10 #include "wine/unicode.h" 8 11 … … 37 40 return NULL; 38 41 } 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 46 long 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 147 noconv: 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 165 unsigned 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 258 noconv: 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.