Changeset 6c69d19 in mainline for uspace/lib/posix/stdlib/strtol.c
- Timestamp:
- 2011-07-25T20:34:17Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 00c2de63, c936c7f
- Parents:
- 5889fc74 (diff), d542aad (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/posix/stdlib/strtol.c
r5889fc74 r6c69d19 30 30 * @{ 31 31 */ 32 /** @file 32 /** @file Backend for integer conversions. 33 33 */ 34 34 … … 38 38 #include "../stdlib.h" 39 39 40 #include "../limits.h"41 40 #include "../ctype.h" 42 41 #include "../errno.h" 43 44 // TODO: documentation 45 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 */ 46 55 static inline bool is_digit_in_base(int c, int base) 47 56 { … … 54 63 } 55 64 56 static inline int get_digit_in_base(int c, int base) 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) 57 72 { 58 73 if (c <= '9') { … … 63 78 } 64 79 65 static inline unsigned long long internal_strtol( 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( 66 104 const char *restrict nptr, char **restrict endptr, int base, 67 const long long min_value, const unsigned long longmax_value,105 const intmax_t min_value, const uintmax_t max_value, 68 106 bool *restrict out_negative) 69 107 { … … 78 116 } 79 117 80 unsigned long long real_max_value = max_value; 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; 81 122 82 123 /* Current index in the input string. */ 83 int i = 0;124 size_t i = 0; 84 125 bool negative = false; 85 126 … … 93 134 case '-': 94 135 negative = true; 95 real_max_value = -min_value; 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 96 146 /* fallthrough */ 97 147 case '+': … … 104 154 if (nptr[i] == '0') { 105 155 if (tolower(nptr[i + 1]) == 'x') { 156 /* 0x... is hex. */ 106 157 base = 16; 107 158 i += 2; 108 159 } else { 160 /* 0... is octal. */ 109 161 base = 8; 110 162 } 111 163 } else { 164 /* Anything else is decimal by default. */ 112 165 base = 10; 113 166 } 114 167 break; 115 168 case 16: 169 /* Allow hex number to be prefixed with "0x". */ 116 170 if (nptr[i] == '0' && tolower(nptr[i + 1]) == 'x') { 117 171 i += 2; … … 133 187 * of overflow. 134 188 */ 135 u nsigned long longmax_safe_value = (real_max_value - base + 1) / base;136 137 u nsigned long longresult = 0;189 uintmax_t max_safe_value = (real_max_value - base + 1) / base; 190 191 uintmax_t result = 0; 138 192 139 193 if (real_max_value == 0) { … … 145 199 if (nptr[i] != '0') { 146 200 errno = ERANGE; 147 result = max_value;201 result = 0; 148 202 } 149 203 i++; … … 152 206 153 207 while (is_digit_in_base(nptr[i], base)) { 154 int digit = get_digit_in_base(nptr[i], base);208 int digit = digit_value(nptr[i]); 155 209 156 210 if (result > max_safe_value) { 157 211 /* corner case, check for overflow */ 158 212 159 unsigned long long 160 boundary = (real_max_value - digit) / base; 213 uintmax_t boundary = (real_max_value - digit) / base; 161 214 162 215 if (result > boundary) { 163 216 /* overflow */ 164 217 errno = ERANGE; 165 result = max_value;218 result = real_max_value; 166 219 break; 167 220 } … … 188 241 } 189 242 243 /** 244 * Convert a string to an integer. 245 * 246 * @param nptr Input string. 247 * @return Result of the conversion. 248 */ 190 249 int posix_atoi(const char *nptr) 191 250 { 192 251 bool neg = false; 193 u nsigned long longresult =252 uintmax_t result = 194 253 internal_strtol(nptr, NULL, 10, INT_MIN, INT_MAX, &neg); 195 254 196 return (int) (neg ? -result : result); 197 } 198 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 */ 199 264 long posix_atol(const char *nptr) 200 265 { 201 266 bool neg = false; 202 u nsigned long longresult =267 uintmax_t result = 203 268 internal_strtol(nptr, NULL, 10, LONG_MIN, LONG_MAX, &neg); 204 269 205 return (long) (neg ? -result : result); 206 } 207 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 */ 208 279 long long posix_atoll(const char *nptr) 209 280 { 210 281 bool neg = false; 211 u nsigned long longresult =282 uintmax_t result = 212 283 internal_strtol(nptr, NULL, 10, LLONG_MIN, LLONG_MAX, &neg); 213 284 214 return (long long) (neg ? -result : result); 215 } 216 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 */ 217 297 long posix_strtol(const char *restrict nptr, char **restrict endptr, int base) 218 298 { 219 299 bool neg = false; 220 u nsigned long longresult =300 uintmax_t result = 221 301 internal_strtol(nptr, endptr, base, LONG_MIN, LONG_MAX, &neg); 222 302 223 return (long) (neg ? -result : result); 224 } 225 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 */ 226 315 long long posix_strtoll( 227 316 const char *restrict nptr, char **restrict endptr, int base) 228 317 { 229 318 bool neg = false; 230 u nsigned long longresult =319 uintmax_t result = 231 320 internal_strtol(nptr, endptr, base, LLONG_MIN, LLONG_MAX, &neg); 232 321 233 return (long long) (neg ? -result : result); 234 } 235 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 */ 236 353 unsigned long posix_strtoul( 237 354 const char *restrict nptr, char **restrict endptr, int base) 238 355 { 239 u nsigned long longresult =356 uintmax_t result = 240 357 internal_strtol(nptr, endptr, base, 0, ULONG_MAX, NULL); 241 358 … … 243 360 } 244 361 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 which 367 * was not used for conversion. 368 * @param base Expected base of the string representation. 369 * @return Result of the conversion. 370 */ 245 371 unsigned long long posix_strtoull( 246 372 const char *restrict nptr, char **restrict endptr, int base) 247 373 { 248 return internal_strtol(nptr, endptr, base, 0, ULLONG_MAX, NULL); 249 } 250 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 } 251 397 252 398 /** @} 253 399 */ 254
Note:
See TracChangeset
for help on using the changeset viewer.