tech-userlevel archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: strtonum(3) from OpenBSD?



On Tue, 23 Jun 2009 19:28:37 +0200
Adam Hoka <adam.hoka%gmail.com@localhost> wrote:

> And what about implementing something with similar functionality sans the 
> mentioned
> api problems and put it into libutil?

Would OpenBSD and those few other programs also convert their code to
use a new interface though?  Otherwise we don't solve much...

Two possible draft alternatives are attached to fuel even more
debate (yes, seems I had too much time on my hands tonight :)  But
looking at how small these functions really are, maybe they're still
best embedded into the programs needing them?  Which if already
embedding strtonum() might best be left as-is.

So strtoint() uses intmax_t but doesn't allow to know if the supplied
value was too large or too small if out of range, as it uses standard
errno values.

On the other hand, strtoi() also using intmax_t provides an interface
with a custom error system (in this case it's still better than
strtonum() where this information was only human-readable, and its
optional error string could be provided via a localized and thread-safe
function similar to strerror_r(), over-engineering for a simple problem
but allright for "correctness" :)
-- 
Matt
#include <errno.h>
#include <inttypes.h>
#include <limits.h>
#include <stdint.h>
#include <stdlib.h>

/*
 * Converts supplied <str> into <i>, returning 0 on success or -1 on error.
 * Sets errno to ERANGE or EINVAL as appropriate in case of error.
 */
int
strtoint(intmax_t *i, const char *str, intmax_t min, intmax_t max)
{
        char *ep;

        if (min > max) {
                errno = EINVAL;
                return -1;
        }

        *i = strtoimax(str, &ep, 10);
        if (errno == ERANGE)
                return -1;

        if (str == ep || *ep != '\0') {
                errno = EINVAL;
                return -1;
        }

        if (*i < min || *i > max) {
                errno = ERANGE;
                return -1;
        }

        return 0;
}
#include <errno.h>
#include <inttypes.h>
#include <limits.h>
#include <stdint.h>
#include <stdlib.h>

enum strtoi_results {
        STRTOI_OK = 0,
        STRTOI_INVALID,
        STRTOI_TOOSMALL,
        STRTOI_TOOLARGE
};

/*
 * Converts supplied <str> into <i>, returning STRTOI_OK on success or one of
 * the other STRTOI_ error code on error.
 */
int
strtoi(intmax_t *i, const char *str, intmax_t min, intmax_t max)
{
        char *ep;

        *i = 0;

        if (min > max)
                return STRTOI_INVALID;

        *i = strtoimax(str, &ep, 10);
        if (str == ep || *ep != '\0')
                return STRTOI_INVALID;
        else if ((*i == INTMAX_MIN && errno == ERANGE) || *i < min)
                return STRTOI_TOOSMALL;
        else if ((*i == INTMAX_MAX && errno == ERANGE) || *i > max)
                return STRTOI_TOOLARGE;

        return STRTOI_OK;
}

/* Then one may optionally have a localizable strtoi_error() function :) */
int
strtoi_error(int code, char *buf, size_t bufsize);


Home | Main Index | Thread Index | Old Index