/* * Copyright (c) 2004 Ted Unangst and Todd Miller * All rights reserved. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* * Copyright 2023 Oxide Computer Company */ #include #include #include #define INVALID 1 #define TOOSMALL 2 #define TOOLARGE 3 #define BADBASE 4 #define MBASE ('z' - 'a' + 1 + 10) long long strtonumx(const char *numstr, long long minval, long long maxval, const char **errstrp, int base) { long long ll = 0; int error = 0; char *ep; struct errval { const char *errstr; int err; } ev[5] = { { NULL, 0 }, { "invalid", EINVAL }, { "too small", ERANGE }, { "too large", ERANGE }, { "unparsable; invalid base specified", EINVAL }, }; ev[0].err = errno; errno = 0; if (minval > maxval) { error = INVALID; } else if (base < 0 || base > MBASE || base == 1) { error = BADBASE; } else { ll = strtoll(numstr, &ep, base); if (numstr == ep || *ep != '\0') error = INVALID; else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval) error = TOOSMALL; else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval) error = TOOLARGE; } if (errstrp != NULL) *errstrp = ev[error].errstr; errno = ev[error].err; if (error != 0) ll = 0; return (ll); } long long strtonum(const char *numstr, long long minval, long long maxval, const char **errstrp) { return (strtonumx(numstr, minval, maxval, errstrp, 10)); }