Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset aa5acd47 in mainline


Ignore:
Timestamp:
2011-07-20T23:02:33Z (10 years ago)
Author:
Jiří Zárevúcky <zarevucky.jiri@…>
Branches:
lfn, master
Children:
91aded7
Parents:
4cf8ca6
Message:

Modify strtol implementation to use intmax_t. Add strtoimax() and strtoumax().

Location:
uspace/lib/posix
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/posix/inttypes.h

    r4cf8ca6 raa5acd47  
    3939#include "libc/inttypes.h"
    4040
     41extern posix_intmax_t posix_strtoimax(const char *restrict nptr,
     42    char **restrict endptr, int base);
     43extern posix_uintmax_t posix_strtoumax(const char *restrict nptr,
     44    char **restrict endptr, int base);
     45
    4146#endif /* POSIX_INTTYPES_H_ */
    4247
  • uspace/lib/posix/stdint.h

    r4cf8ca6 raa5acd47  
    8888#define AOFF64_MIN  UINT64_MIN
    8989
     90#undef INTMAX_MIN
     91#undef INTMAX_MAX
     92#define INTMAX_MIN INT64_MIN
     93#define INTMAX_MAX INT64_MAX
     94
     95#undef UINTMAX_MIN
     96#undef UINTMAX_MAX
     97#define UINTMAX_MIN UINT64_MIN
     98#define UINTMAX_MAX UINT64_MAX
     99
    90100#include "libc/sys/types.h"
    91101
  • uspace/lib/posix/stdlib/strtol.c

    r4cf8ca6 raa5acd47  
    3838#include "../stdlib.h"
    3939
    40 #include "../limits.h"
    4140#include "../ctype.h"
    4241#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
    4347
    4448/**
     
    6367 *
    6468 * @param c Character representation of the digit.
    65  * @param base Base into which the digit belongs to.
    6669 * @return Digit value represented by an integer.
    6770 */
    68 static inline int get_digit_in_base(int c, int base)
     71static inline int digit_value(int c)
    6972{
    7073        if (c <= '9') {
     
    7679
    7780/**
    78  * Backend for all integer conversion functions. Can be configured by arguments
    79  * to convert both signed and unsigned integers of various sizes.
     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.
    8085 *
    8186 * @param nptr Input string.
    8287 * @param endptr If non-NULL, *endptr is set to the position of the first
    83  *     unrecognized character.
    84  * @param base Expected base of the string representation.
     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.
    8594 * @param min_value Lower bound for the resulting conversion.
    8695 * @param max_value Upper bound for the resulting conversion.
     
    8897 *     bool variable into which shall be placed the negativity of the resulting
    8998 *     converted value.
    90  * @return Result of the conversion.
    91  */
    92 static inline unsigned long long internal_strtol(
     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(
    93104    const char *restrict nptr, char **restrict endptr, int base,
    94     const long long min_value, const unsigned long long max_value,
     105    const intmax_t min_value, const uintmax_t max_value,
    95106    bool *restrict out_negative)
    96107{
     
    105116        }
    106117       
    107         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;
    108122       
    109123        /* Current index in the input string. */
    110         int i = 0;
     124        size_t i = 0;
    111125        bool negative = false;
    112126       
     
    120134        case '-':
    121135                negative = true;
    122                 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               
    123146                /* fallthrough */
    124147        case '+':
     
    131154                if (nptr[i] == '0') {
    132155                        if (tolower(nptr[i + 1]) == 'x') {
     156                                /* 0x... is hex. */
    133157                                base = 16;
    134158                                i += 2;
    135159                        } else {
     160                                /* 0... is octal. */
    136161                                base = 8;
    137162                        }
    138163                } else {
     164                        /* Anything else is decimal by default. */
    139165                        base = 10;
    140166                }
    141167                break;
    142168        case 16:
     169                /* Allow hex number to be prefixed with "0x". */
    143170                if (nptr[i] == '0' && tolower(nptr[i + 1]) == 'x') {
    144171                        i += 2;
     
    160187         * of overflow.
    161188         */
    162         unsigned long long max_safe_value = (real_max_value - base + 1) / base;
    163        
    164         unsigned long long result = 0;
     189        uintmax_t max_safe_value = (real_max_value - base + 1) / base;
     190       
     191        uintmax_t result = 0;
    165192       
    166193        if (real_max_value == 0) {
     
    172199                        if (nptr[i] != '0') {
    173200                                errno = ERANGE;
    174                                 result = max_value;
     201                                result = 0;
    175202                        }
    176203                        i++;
     
    179206       
    180207        while (is_digit_in_base(nptr[i], base)) {
    181                 int digit = get_digit_in_base(nptr[i], base);
     208                int digit = digit_value(nptr[i]);
    182209               
    183210                if (result > max_safe_value) {
    184211                        /* corner case, check for overflow */
    185212                       
    186                         unsigned long long
    187                             boundary = (real_max_value - digit) / base;
     213                        uintmax_t boundary = (real_max_value - digit) / base;
    188214                       
    189215                        if (result > boundary) {
     
    224250{
    225251        bool neg = false;
    226         unsigned long long result =
     252        uintmax_t result =
    227253            internal_strtol(nptr, NULL, 10, INT_MIN, INT_MAX, &neg);
    228254
    229         return (int) (neg ? -result : result);
     255        return (neg ? ((int) -result) : (int) result);
    230256}
    231257
     
    239265{
    240266        bool neg = false;
    241         unsigned long long result =
     267        uintmax_t result =
    242268            internal_strtol(nptr, NULL, 10, LONG_MIN, LONG_MAX, &neg);
    243269
    244         return (long) (neg ? -result : result);
     270        return (neg ? ((long) -result) : (long) result);
    245271}
    246272
     
    254280{
    255281        bool neg = false;
    256         unsigned long long result =
     282        uintmax_t result =
    257283            internal_strtol(nptr, NULL, 10, LLONG_MIN, LLONG_MAX, &neg);
    258284
    259         return (long long) (neg ? -result : result);
     285        return (neg ? ((long long) -result) : (long long) result);
    260286}
    261287
     
    272298{
    273299        bool neg = false;
    274         unsigned long long result =
     300        uintmax_t result =
    275301            internal_strtol(nptr, endptr, base, LONG_MIN, LONG_MAX, &neg);
    276302
    277         return (long) (neg ? -result : result);
     303        return (neg ? ((long) -result) : ((long) result));
    278304}
    279305
     
    291317{
    292318        bool neg = false;
    293         unsigned long long result =
     319        uintmax_t result =
    294320            internal_strtol(nptr, endptr, base, LLONG_MIN, LLONG_MAX, &neg);
    295321
    296         return (long long) (neg ? -result : result);
     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);
    297342}
    298343
     
    309354    const char *restrict nptr, char **restrict endptr, int base)
    310355{
    311         unsigned long long result =
     356        uintmax_t result =
    312357            internal_strtol(nptr, endptr, base, 0, ULONG_MAX, NULL);
    313358
     
    316361
    317362/**
    318  * Convert a string to a an unsigned long long integer.
     363 * Convert a string to an unsigned long long integer.
    319364 *
    320365 * @param nptr Input string.
     
    327372    const char *restrict nptr, char **restrict endptr, int base)
    328373{
    329         return internal_strtol(nptr, endptr, base, 0, ULLONG_MAX, NULL);
     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;
    330396}
    331397
Note: See TracChangeset for help on using the changeset viewer.