/*====================================================================* * * uint64_t basespec (char const * string, unsigned base, unsigned size); * * number.h * * convert a character string to an equivalent unsigned integer and * return the result; terminate the program on failure; * * the base argument is the number base to be used for conversion; * base 0 permits the number base to be determined by the string * string prefix; 0b, 0d or 0x for binary, decimal or hex; * * this implementation accepts a minus sign in order to negate any * number in any base; * * the size argument is the maximum number of bytes permitted in the * result; * * Motley Tools by Charles Maier <cmaier@cmassoc.net>; * Copyright (c) 2001-2006 by Charles Maier Associates; * Licensed under the Internet Software Consortium License; * *--------------------------------------------------------------------*/ #ifndef BASESPEC_SOURCE #define BASESPEC_SOURCE #include <stdlib.h> #include <ctype.h> #include "../tools/number.h" #include "../tools/error.h" uint64_t basespec (char const * string, unsigned base, unsigned size) { char const * number = string; unsigned radix = RADIX_DEC; signed scale = 1; uint64_t limit = 0; uint64_t value = 0; unsigned digit = 0; limit = ~limit; if (size < sizeof (limit)) { limit <<= size << 3; limit = ~limit; } if (base) { radix = base; } if (* number == '=') { number++; } else if (* number == '+') { number++; } else if (* number == '-') { number++; scale = -1; } if (*number == '0') { number++; if ((*number == 'b') || (*number == 'B')) { radix = RADIX_BIN; number++; } else if ((*number == 'd') || (*number == 'D')) { radix = RADIX_DEC; number++; } else if ((*number == 'x') || (*number == 'X')) { radix = RADIX_HEX; number++; } } if ((base) && (base != radix)) { error (1, EINVAL, "%s is not base %d notation", string, base); } while ((digit = todigit (*number)) < radix) { value *= radix; value += digit; if (value > limit) { error (1, ERANGE, "%s exceeds %d bits", string, (size << 3)); } number++; } #ifdef WIN32 while (isspace (*number)) { number++; } #endif if (*number) { error (1, EINVAL, "%s is not base %d notation", string, radix); } return (scale * value); } #endif