Changeset eccd20e6 in mainline for uspace/lib/posix/stdlib/strtol.c


Ignore:
Timestamp:
2011-07-21T22:34:14Z (13 years ago)
Author:
Petr Koupy <petr.koupy@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
c6f4681, e478cebf
Parents:
df0956ee (diff), cfbb5d18 (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.
Message:

Merge libposix changes.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/posix/stdlib/strtol.c

    rdf0956ee reccd20e6  
    3030 * @{
    3131 */
    32 /** @file
     32/** @file Backend for integer conversions.
    3333 */
    3434
     
    3838#include "../stdlib.h"
    3939
    40 #include "../limits.h"
    4140#include "../ctype.h"
    4241#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 */
    4655static inline bool is_digit_in_base(int c, int base)
    4756{
     
    5463}
    5564
    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 */
     71static inline int digit_value(int c)
    5772{
    5873        if (c <= '9') {
     
    6378}
    6479
    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 */
     103static inline uintmax_t internal_strtol(
    66104    const char *restrict nptr, char **restrict endptr, int base,
    67     const long long min_value, const unsigned long long max_value,
     105    const intmax_t min_value, const uintmax_t max_value,
    68106    bool *restrict out_negative)
    69107{
     
    78116        }
    79117       
    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;
    81122       
    82123        /* Current index in the input string. */
    83         int i = 0;
     124        size_t i = 0;
    84125        bool negative = false;
    85126       
     
    93134        case '-':
    94135                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               
    96146                /* fallthrough */
    97147        case '+':
     
    104154                if (nptr[i] == '0') {
    105155                        if (tolower(nptr[i + 1]) == 'x') {
     156                                /* 0x... is hex. */
    106157                                base = 16;
    107158                                i += 2;
    108159                        } else {
     160                                /* 0... is octal. */
    109161                                base = 8;
    110162                        }
    111163                } else {
     164                        /* Anything else is decimal by default. */
    112165                        base = 10;
    113166                }
    114167                break;
    115168        case 16:
     169                /* Allow hex number to be prefixed with "0x". */
    116170                if (nptr[i] == '0' && tolower(nptr[i + 1]) == 'x') {
    117171                        i += 2;
     
    133187         * of overflow.
    134188         */
    135         unsigned long long max_safe_value = (real_max_value - base + 1) / base;
    136        
    137         unsigned long long result = 0;
     189        uintmax_t max_safe_value = (real_max_value - base + 1) / base;
     190       
     191        uintmax_t result = 0;
    138192       
    139193        if (real_max_value == 0) {
     
    145199                        if (nptr[i] != '0') {
    146200                                errno = ERANGE;
    147                                 result = max_value;
     201                                result = 0;
    148202                        }
    149203                        i++;
     
    152206       
    153207        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]);
    155209               
    156210                if (result > max_safe_value) {
    157211                        /* corner case, check for overflow */
    158212                       
    159                         unsigned long long
    160                             boundary = (real_max_value - digit) / base;
     213                        uintmax_t boundary = (real_max_value - digit) / base;
    161214                       
    162215                        if (result > boundary) {
    163216                                /* overflow */
    164217                                errno = ERANGE;
    165                                 result = max_value;
     218                                result = real_max_value;
    166219                                break;
    167220                        }
     
    188241}
    189242
     243/**
     244 * Convert a string to an integer.
     245 *
     246 * @param nptr Input string.
     247 * @return Result of the conversion.
     248 */
    190249int posix_atoi(const char *nptr)
    191250{
    192251        bool neg = false;
    193         unsigned long long result =
     252        uintmax_t result =
    194253            internal_strtol(nptr, NULL, 10, INT_MIN, INT_MAX, &neg);
    195254
    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 */
    199264long posix_atol(const char *nptr)
    200265{
    201266        bool neg = false;
    202         unsigned long long result =
     267        uintmax_t result =
    203268            internal_strtol(nptr, NULL, 10, LONG_MIN, LONG_MAX, &neg);
    204269
    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 */
    208279long long posix_atoll(const char *nptr)
    209280{
    210281        bool neg = false;
    211         unsigned long long result =
     282        uintmax_t result =
    212283            internal_strtol(nptr, NULL, 10, LLONG_MIN, LLONG_MAX, &neg);
    213284
    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 */
    217297long posix_strtol(const char *restrict nptr, char **restrict endptr, int base)
    218298{
    219299        bool neg = false;
    220         unsigned long long result =
     300        uintmax_t result =
    221301            internal_strtol(nptr, endptr, base, LONG_MIN, LONG_MAX, &neg);
    222302
    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 */
    226315long long posix_strtoll(
    227316    const char *restrict nptr, char **restrict endptr, int base)
    228317{
    229318        bool neg = false;
    230         unsigned long long result =
     319        uintmax_t result =
    231320            internal_strtol(nptr, endptr, base, LLONG_MIN, LLONG_MAX, &neg);
    232321
    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 */
     334intmax_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 */
    236353unsigned long posix_strtoul(
    237354    const char *restrict nptr, char **restrict endptr, int base)
    238355{
    239         unsigned long long result =
     356        uintmax_t result =
    240357            internal_strtol(nptr, endptr, base, 0, ULONG_MAX, NULL);
    241358
     
    243360}
    244361
     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 */
    245371unsigned long long posix_strtoull(
    246372    const char *restrict nptr, char **restrict endptr, int base)
    247373{
    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 */
     389uintmax_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}
    251397
    252398/** @}
    253399 */
    254 
Note: See TracChangeset for help on using the changeset viewer.