Changes in uspace/lib/posix/stdlib/strtol.c [aa5acd47:ec18957a] in mainline
- File:
-
- 1 edited
-
uspace/lib/posix/stdlib/strtol.c (modified) (12 diffs)
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/posix/stdlib/strtol.c
raa5acd47 rec18957a 30 30 * @{ 31 31 */ 32 /** @file Backend for integer conversions.32 /** @file 33 33 */ 34 34 … … 38 38 #include "../stdlib.h" 39 39 40 #include "../limits.h" 40 41 #include "../ctype.h" 41 42 #include "../errno.h" 42 #include "../inttypes.h" 43 #include "../limits.h" 44 45 #define intmax_t posix_intmax_t 46 #define uintmax_t posix_uintmax_t 47 48 /** 49 * Decides whether a digit belongs to a particular base. 50 * 51 * @param c Character representation of the digit. 52 * @param base Base against which the digit shall be tested. 53 * @return True if the digit belongs to the base, false otherwise. 54 */ 43 44 // TODO: documentation 45 55 46 static inline bool is_digit_in_base(int c, int base) 56 47 { … … 63 54 } 64 55 65 /** 66 * Derive a digit from its character representation. 67 * 68 * @param c Character representation of the digit. 69 * @return Digit value represented by an integer. 70 */ 71 static inline int digit_value(int c) 56 static inline int get_digit_in_base(int c, int base) 72 57 { 73 58 if (c <= '9') { … … 78 63 } 79 64 80 /** 81 * Generic function for parsing an integer from it's string representation. 82 * Different variants differ in lower and upper bounds. 83 * The parsed string returned by this function is always positive, sign 84 * information is provided via a dedicated parameter. 85 * 86 * @param nptr Input string. 87 * @param endptr If non-NULL, *endptr is set to the position of the first 88 * unrecognized character. If no digit has been parsed, value of 89 * nptr is stored there (regardless of any skipped characters at the 90 * beginning). 91 * @param base Expected base of the string representation. If 0, base is 92 * determined to be decimal, octal or hexadecimal using the same rules 93 * as C syntax. Otherwise, value must be between 2 and 36, inclusive. 94 * @param min_value Lower bound for the resulting conversion. 95 * @param max_value Upper bound for the resulting conversion. 96 * @param out_negative Either NULL for unsigned conversion or a pointer to the 97 * bool variable into which shall be placed the negativity of the resulting 98 * converted value. 99 * @return The absolute value of the parsed value, or the closest in-range value 100 * if the parsed value is out of range. If the input is invalid, zero is 101 * returned and errno is set to EINVAL. 102 */ 103 static inline uintmax_t internal_strtol( 65 static inline unsigned long long internal_strtol( 104 66 const char *restrict nptr, char **restrict endptr, int base, 105 const intmax_t min_value, const uintmax_tmax_value,67 const long long min_value, const unsigned long long max_value, 106 68 bool *restrict out_negative) 107 69 { … … 116 78 } 117 79 118 /* The maximal absolute value that can be returned in this run. 119 * Depends on sign. 120 */ 121 uintmax_t real_max_value = max_value; 80 unsigned long long real_max_value = max_value; 122 81 123 82 /* Current index in the input string. */ 124 size_t i = 0;83 int i = 0; 125 84 bool negative = false; 126 85 … … 134 93 case '-': 135 94 negative = true; 136 137 /* The strange computation is are there to avoid a corner case 138 * where -min_value can't be represented in intmax_t. 139 * (I'm not exactly sure what the semantics are in such a 140 * case, but this should be safe for any case.) 141 */ 142 real_max_value = (min_value == 0) 143 ? 0 144 :(((uintmax_t) -(min_value + 1)) + 1); 145 95 real_max_value = -min_value; 146 96 /* fallthrough */ 147 97 case '+': … … 154 104 if (nptr[i] == '0') { 155 105 if (tolower(nptr[i + 1]) == 'x') { 156 /* 0x... is hex. */157 106 base = 16; 158 107 i += 2; 159 108 } else { 160 /* 0... is octal. */161 109 base = 8; 162 110 } 163 111 } else { 164 /* Anything else is decimal by default. */165 112 base = 10; 166 113 } 167 114 break; 168 115 case 16: 169 /* Allow hex number to be prefixed with "0x". */170 116 if (nptr[i] == '0' && tolower(nptr[i + 1]) == 'x') { 171 117 i += 2; … … 187 133 * of overflow. 188 134 */ 189 u intmax_tmax_safe_value = (real_max_value - base + 1) / base;190 191 u intmax_tresult = 0;135 unsigned long long max_safe_value = (real_max_value - base + 1) / base; 136 137 unsigned long long result = 0; 192 138 193 139 if (real_max_value == 0) { … … 199 145 if (nptr[i] != '0') { 200 146 errno = ERANGE; 201 result = 0;147 result = max_value; 202 148 } 203 149 i++; … … 206 152 207 153 while (is_digit_in_base(nptr[i], base)) { 208 int digit = digit_value(nptr[i]);154 int digit = get_digit_in_base(nptr[i], base); 209 155 210 156 if (result > max_safe_value) { 211 157 /* corner case, check for overflow */ 212 158 213 uintmax_t boundary = (real_max_value - digit) / base; 159 unsigned long long 160 boundary = (real_max_value - digit) / base; 214 161 215 162 if (result > boundary) { 216 163 /* overflow */ 217 164 errno = ERANGE; 218 result = real_max_value;165 result = max_value; 219 166 break; 220 167 } … … 241 188 } 242 189 243 /**244 * Convert a string to an integer.245 *246 * @param nptr Input string.247 * @return Result of the conversion.248 */249 190 int posix_atoi(const char *nptr) 250 191 { 251 192 bool neg = false; 252 u intmax_tresult =193 unsigned long long result = 253 194 internal_strtol(nptr, NULL, 10, INT_MIN, INT_MAX, &neg); 254 195 255 return (neg ? ((int) -result) : (int) result); 256 } 257 258 /** 259 * Convert a string to a long integer. 260 * 261 * @param nptr Input string. 262 * @return Result of the conversion. 263 */ 196 return (int) (neg ? -result : result); 197 } 198 264 199 long posix_atol(const char *nptr) 265 200 { 266 201 bool neg = false; 267 u intmax_tresult =202 unsigned long long result = 268 203 internal_strtol(nptr, NULL, 10, LONG_MIN, LONG_MAX, &neg); 269 204 270 return (neg ? ((long) -result) : (long) result); 271 } 272 273 /** 274 * Convert a string to a long long integer. 275 * 276 * @param nptr Input string. 277 * @return Result of the conversion. 278 */ 205 return (long) (neg ? -result : result); 206 } 207 279 208 long long posix_atoll(const char *nptr) 280 209 { 281 210 bool neg = false; 282 u intmax_tresult =211 unsigned long long result = 283 212 internal_strtol(nptr, NULL, 10, LLONG_MIN, LLONG_MAX, &neg); 284 213 285 return (neg ? ((long long) -result) : (long long) result); 286 } 287 288 /** 289 * Convert a string to a long integer. 290 * 291 * @param nptr Input string. 292 * @param endptr Pointer to the final part of the string which 293 * was not used for conversion. 294 * @param base Expected base of the string representation. 295 * @return Result of the conversion. 296 */ 214 return (long long) (neg ? -result : result); 215 } 216 297 217 long posix_strtol(const char *restrict nptr, char **restrict endptr, int base) 298 218 { 299 219 bool neg = false; 300 u intmax_tresult =220 unsigned long long result = 301 221 internal_strtol(nptr, endptr, base, LONG_MIN, LONG_MAX, &neg); 302 222 303 return (neg ? ((long) -result) : ((long) result)); 304 } 305 306 /** 307 * Convert a string to a long long integer. 308 * 309 * @param nptr Input string. 310 * @param endptr Pointer to the final part of the string which 311 * was not used for conversion. 312 * @param base Expected base of the string representation. 313 * @return Result of the conversion. 314 */ 223 return (long) (neg ? -result : result); 224 } 225 315 226 long long posix_strtoll( 316 227 const char *restrict nptr, char **restrict endptr, int base) 317 228 { 318 229 bool neg = false; 319 u intmax_tresult =230 unsigned long long result = 320 231 internal_strtol(nptr, endptr, base, LLONG_MIN, LLONG_MAX, &neg); 321 232 322 return (neg ? ((long long) -result) : (long long) result); 323 } 324 325 /** 326 * Convert a string to a largest signed integer type. 327 * 328 * @param nptr Input string. 329 * @param endptr Pointer to the final part of the string which 330 * was not used for conversion. 331 * @param base Expected base of the string representation. 332 * @return Result of the conversion. 333 */ 334 intmax_t posix_strtoimax( 335 const char *restrict nptr, char **restrict endptr, int base) 336 { 337 bool neg = false; 338 uintmax_t result = 339 internal_strtol(nptr, endptr, base, INTMAX_MIN, INTMAX_MAX, &neg); 340 341 return (neg ? ((intmax_t) -result) : (intmax_t) result); 342 } 343 344 /** 345 * Convert a string to an unsigned long integer. 346 * 347 * @param nptr Input string. 348 * @param endptr Pointer to the final part of the string which 349 * was not used for conversion. 350 * @param base Expected base of the string representation. 351 * @return Result of the conversion. 352 */ 233 return (long long) (neg ? -result : result); 234 } 235 353 236 unsigned long posix_strtoul( 354 237 const char *restrict nptr, char **restrict endptr, int base) 355 238 { 356 u intmax_tresult =239 unsigned long long result = 357 240 internal_strtol(nptr, endptr, base, 0, ULONG_MAX, NULL); 358 241 … … 360 243 } 361 244 362 /**363 * Convert a string to an unsigned long long integer.364 *365 * @param nptr Input string.366 * @param endptr Pointer to the final part of the string which367 * was not used for conversion.368 * @param base Expected base of the string representation.369 * @return Result of the conversion.370 */371 245 unsigned long long posix_strtoull( 372 246 const char *restrict nptr, char **restrict endptr, int base) 373 247 { 374 uintmax_t result = 375 internal_strtol(nptr, endptr, base, 0, ULLONG_MAX, NULL); 376 377 return (unsigned long long) result; 378 } 379 380 /** 381 * Convert a string to a largest unsigned integer type. 382 * 383 * @param nptr Input string. 384 * @param endptr Pointer to the final part of the string which 385 * was not used for conversion. 386 * @param base Expected base of the string representation. 387 * @return Result of the conversion. 388 */ 389 uintmax_t posix_strtoumax( 390 const char *restrict nptr, char **restrict endptr, int base) 391 { 392 uintmax_t result = 393 internal_strtol(nptr, endptr, base, 0, UINTMAX_MAX, NULL); 394 395 return result; 396 } 248 return internal_strtol(nptr, endptr, base, 0, ULLONG_MAX, NULL); 249 } 250 397 251 398 252 /** @} 399 253 */ 254
Note:
See TracChangeset
for help on using the changeset viewer.
