Changeset 1c9bf292 in mainline for uspace/lib/c/generic/strtol.c


Ignore:
Timestamp:
2019-05-27T20:27:49Z (5 years ago)
Author:
Jiří Zárevúcky <zarevucky.jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
42e91ae
Parents:
dd0502ae
Message:

Reunite uspace string-to-int conversion functions

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/generic/strtol.c

    rdd0502ae r1c9bf292  
    4444#include <stdbool.h>
    4545#include <stdlib.h>
    46 
    47 // TODO: unit tests
     46#include <str.h>
     47
     48// FIXME: The original HelenOS functions return EOVERFLOW instead
     49//        of ERANGE. It's a pointless distinction from standard functions,
     50//        so we should change that. Beware the callers though.
     51
     52// TODO: more unit tests
    4853
    4954static inline int _digit_value(int c)
     
    6974}
    7075
    71 static inline int _prefixbase(const char *restrict *nptrptr, bool nonstandard_prefixes)
     76static inline int _prefixbase(const char *restrict *nptrptr, bool nonstd)
    7277{
    7378        const char *nptr = *nptrptr;
     
    8388        }
    8489
    85         if (nonstandard_prefixes) {
     90        if (nonstd) {
    8691                switch (nptr[1]) {
    8792                case 'b':
     
    116121static inline uintmax_t _strtoumax(
    117122    const char *restrict nptr, char **restrict endptr, int base,
    118     bool *restrict sgn, errno_t *err, bool nonstandard_prefixes)
     123    bool *restrict sgn, errno_t *err, bool nonstd)
    119124{
    120125        assert(nptr != NULL);
     
    144149
    145150        if (base == 0)
    146                 base = _prefixbase(&nptr, nonstandard_prefixes);
    147 
    148         if (base == 16 && !nonstandard_prefixes) {
     151                base = _prefixbase(&nptr, nonstd);
     152
     153        if (base == 16 && !nonstd) {
    149154                /*
    150155                 * Standard strto* functions allow hexadecimal prefix to be
     
    184189                    __builtin_add_overflow(result * base, digit, &result)) {
    185190
    186                         *err = ERANGE;
     191                        *err = nonstd ? EOVERFLOW : ERANGE;
    187192                        result = UINTMAX_MAX;
    188193                        break;
     
    212217
    213218static inline intmax_t _strtosigned(const char *nptr, char **endptr, int base,
    214     intmax_t min, intmax_t max, errno_t *err, bool nonstandard_prefixes)
     219    intmax_t min, intmax_t max, errno_t *err, bool nonstd)
    215220{
    216221        bool sgn = false;
    217         uintmax_t number = _strtoumax(nptr, endptr, base, &sgn, err,
    218             nonstandard_prefixes);
     222        uintmax_t number = _strtoumax(nptr, endptr, base, &sgn, err, nonstd);
    219223
    220224        if (number > (uintmax_t) max) {
     
    223227                }
    224228
    225                 *err = ERANGE;
     229                *err = nonstd ? EOVERFLOW : ERANGE;
    226230                return (sgn ? min : max);
    227231        }
     
    231235
    232236static inline uintmax_t _strtounsigned(const char *nptr, char **endptr, int base,
    233     uintmax_t max, errno_t *err, bool nonstandard_prefixes)
     237    uintmax_t max, errno_t *err, bool nonstd)
    234238{
    235239        bool sgn = false;
    236         uintmax_t number = _strtoumax(nptr, endptr, base, &sgn, err,
    237             nonstandard_prefixes);
     240        uintmax_t number = _strtoumax(nptr, endptr, base, &sgn, err, nonstd);
     241
     242        if (nonstd && sgn) {
     243                /* Do not allow negative values */
     244                *err = EINVAL;
     245                return 0;
     246        }
    238247
    239248        if (number > max) {
    240                 *err = ERANGE;
     249                *err = nonstd ? EOVERFLOW : ERANGE;
    241250                return max;
    242251        }
     
    316325}
    317326
     327/** Convert string to uint8_t.
     328 *
     329 * @param nptr   Pointer to string.
     330 * @param endptr If not NULL, pointer to the first invalid character
     331 *               is stored here.
     332 * @param base   Zero or number between 2 and 36 inclusive.
     333 * @param strict Do not allow any trailing characters.
     334 * @param result Result of the conversion.
     335 *
     336 * @return EOK if conversion was successful.
     337 *
     338 */
     339errno_t str_uint8_t(const char *nptr, const char **endptr, unsigned int base,
     340    bool strict, uint8_t *result)
     341{
     342        assert(result != NULL);
     343
     344        errno_t rc = EOK;
     345        char *lendptr = (char *) nptr;
     346
     347        uintmax_t r = _strtounsigned(nptr, &lendptr, base, UINT8_MAX, &rc, true);
     348
     349        if (endptr)
     350                *endptr = lendptr;
     351
     352        if (rc != EOK)
     353                return rc;
     354
     355        if (strict && *lendptr != '\0')
     356                return EINVAL;
     357
     358        *result = r;
     359        return EOK;
     360}
     361
     362/** Convert string to uint16_t.
     363 *
     364 * @param nptr   Pointer to string.
     365 * @param endptr If not NULL, pointer to the first invalid character
     366 *               is stored here.
     367 * @param base   Zero or number between 2 and 36 inclusive.
     368 * @param strict Do not allow any trailing characters.
     369 * @param result Result of the conversion.
     370 *
     371 * @return EOK if conversion was successful.
     372 *
     373 */
     374errno_t str_uint16_t(const char *nptr, const char **endptr, unsigned int base,
     375    bool strict, uint16_t *result)
     376{
     377        assert(result != NULL);
     378
     379        errno_t rc = EOK;
     380        char *lendptr = (char *) nptr;
     381
     382        uintmax_t r = _strtounsigned(nptr, &lendptr, base, UINT16_MAX, &rc, true);
     383
     384        if (endptr)
     385                *endptr = lendptr;
     386
     387        if (rc != EOK)
     388                return rc;
     389
     390        if (strict && *lendptr != '\0')
     391                return EINVAL;
     392
     393        *result = r;
     394        return EOK;
     395}
     396
     397/** Convert string to uint32_t.
     398 *
     399 * @param nptr   Pointer to string.
     400 * @param endptr If not NULL, pointer to the first invalid character
     401 *               is stored here.
     402 * @param base   Zero or number between 2 and 36 inclusive.
     403 * @param strict Do not allow any trailing characters.
     404 * @param result Result of the conversion.
     405 *
     406 * @return EOK if conversion was successful.
     407 *
     408 */
     409errno_t str_uint32_t(const char *nptr, const char **endptr, unsigned int base,
     410    bool strict, uint32_t *result)
     411{
     412        assert(result != NULL);
     413
     414        errno_t rc = EOK;
     415        char *lendptr = (char *) nptr;
     416
     417        uintmax_t r = _strtounsigned(nptr, &lendptr, base, UINT32_MAX, &rc, true);
     418
     419        if (endptr)
     420                *endptr = lendptr;
     421
     422        if (rc != EOK)
     423                return rc;
     424
     425        if (strict && *lendptr != '\0')
     426                return EINVAL;
     427
     428        *result = r;
     429        return EOK;
     430}
     431
     432/** Convert string to uint64_t.
     433 *
     434 * @param nptr   Pointer to string.
     435 * @param endptr If not NULL, pointer to the first invalid character
     436 *               is stored here.
     437 * @param base   Zero or number between 2 and 36 inclusive.
     438 * @param strict Do not allow any trailing characters.
     439 * @param result Result of the conversion.
     440 *
     441 * @return EOK if conversion was successful.
     442 *
     443 */
     444errno_t str_uint64_t(const char *nptr, const char **endptr, unsigned int base,
     445    bool strict, uint64_t *result)
     446{
     447        assert(result != NULL);
     448
     449        errno_t rc = EOK;
     450        char *lendptr = (char *) nptr;
     451
     452        uintmax_t r = _strtounsigned(nptr, &lendptr, base, UINT64_MAX, &rc, true);
     453
     454        if (endptr)
     455                *endptr = lendptr;
     456
     457        if (rc != EOK)
     458                return rc;
     459
     460        if (strict && *lendptr != '\0')
     461                return EINVAL;
     462
     463        *result = r;
     464        return EOK;
     465}
     466
     467/** Convert string to int64_t.
     468 *
     469 * @param nptr   Pointer to string.
     470 * @param endptr If not NULL, pointer to the first invalid character
     471 *               is stored here.
     472 * @param base   Zero or number between 2 and 36 inclusive.
     473 * @param strict Do not allow any trailing characters.
     474 * @param result Result of the conversion.
     475 *
     476 * @return EOK if conversion was successful.
     477 *
     478 */
     479errno_t str_int64_t(const char *nptr, const char **endptr, unsigned int base,
     480    bool strict, int64_t *result)
     481{
     482        assert(result != NULL);
     483
     484        errno_t rc = EOK;
     485        char *lendptr = (char *) nptr;
     486
     487        intmax_t r = _strtosigned(nptr, &lendptr, base, INT64_MIN, INT64_MAX, &rc, true);
     488
     489        if (endptr)
     490                *endptr = lendptr;
     491
     492        if (rc != EOK)
     493                return rc;
     494
     495        if (strict && *lendptr != '\0')
     496                return EINVAL;
     497
     498        *result = r;
     499        return EOK;
     500}
     501
     502/** Convert string to size_t.
     503 *
     504 * @param nptr   Pointer to string.
     505 * @param endptr If not NULL, pointer to the first invalid character
     506 *               is stored here.
     507 * @param base   Zero or number between 2 and 36 inclusive.
     508 * @param strict Do not allow any trailing characters.
     509 * @param result Result of the conversion.
     510 *
     511 * @return EOK if conversion was successful.
     512 *
     513 */
     514errno_t str_size_t(const char *nptr, const char **endptr, unsigned int base,
     515    bool strict, size_t *result)
     516{
     517        assert(result != NULL);
     518
     519        errno_t rc = EOK;
     520        char *lendptr = (char *) nptr;
     521
     522        uintmax_t r = _strtounsigned(nptr, &lendptr, base, SIZE_MAX, &rc, true);
     523
     524        if (endptr)
     525                *endptr = lendptr;
     526
     527        if (rc != EOK)
     528                return rc;
     529
     530        if (strict && *lendptr != '\0')
     531                return EINVAL;
     532
     533        *result = r;
     534        return EOK;
     535}
     536
    318537/** @}
    319538 */
Note: See TracChangeset for help on using the changeset viewer.