123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291 |
- #include "Python.h"
- #include "pycore_long.h" // _PyLong_DigitValue
- #if defined(__sgi) && !defined(_SGI_MP_SOURCE)
- #define _SGI_MP_SOURCE
- #endif
- /* strtol and strtoul, renamed to avoid conflicts */
- #include <ctype.h>
- #ifdef HAVE_ERRNO_H
- #include <errno.h>
- #endif
- /* Static overflow check values for bases 2 through 36.
- * smallmax[base] is the largest unsigned long i such that
- * i * base doesn't overflow unsigned long.
- */
- static const unsigned long smallmax[] = {
- 0, /* bases 0 and 1 are invalid */
- 0,
- ULONG_MAX / 2,
- ULONG_MAX / 3,
- ULONG_MAX / 4,
- ULONG_MAX / 5,
- ULONG_MAX / 6,
- ULONG_MAX / 7,
- ULONG_MAX / 8,
- ULONG_MAX / 9,
- ULONG_MAX / 10,
- ULONG_MAX / 11,
- ULONG_MAX / 12,
- ULONG_MAX / 13,
- ULONG_MAX / 14,
- ULONG_MAX / 15,
- ULONG_MAX / 16,
- ULONG_MAX / 17,
- ULONG_MAX / 18,
- ULONG_MAX / 19,
- ULONG_MAX / 20,
- ULONG_MAX / 21,
- ULONG_MAX / 22,
- ULONG_MAX / 23,
- ULONG_MAX / 24,
- ULONG_MAX / 25,
- ULONG_MAX / 26,
- ULONG_MAX / 27,
- ULONG_MAX / 28,
- ULONG_MAX / 29,
- ULONG_MAX / 30,
- ULONG_MAX / 31,
- ULONG_MAX / 32,
- ULONG_MAX / 33,
- ULONG_MAX / 34,
- ULONG_MAX / 35,
- ULONG_MAX / 36,
- };
- /* maximum digits that can't ever overflow for bases 2 through 36,
- * calculated by [int(math.floor(math.log(2**32, i))) for i in range(2, 37)].
- * Note that this is pessimistic if sizeof(long) > 4.
- */
- #if SIZEOF_LONG == 4
- static const int digitlimit[] = {
- 0, 0, 32, 20, 16, 13, 12, 11, 10, 10, /* 0 - 9 */
- 9, 9, 8, 8, 8, 8, 8, 7, 7, 7, /* 10 - 19 */
- 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, /* 20 - 29 */
- 6, 6, 6, 6, 6, 6, 6}; /* 30 - 36 */
- #elif SIZEOF_LONG == 8
- /* [int(math.floor(math.log(2**64, i))) for i in range(2, 37)] */
- static const int digitlimit[] = {
- 0, 0, 64, 40, 32, 27, 24, 22, 21, 20, /* 0 - 9 */
- 19, 18, 17, 17, 16, 16, 16, 15, 15, 15, /* 10 - 19 */
- 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, /* 20 - 29 */
- 13, 12, 12, 12, 12, 12, 12}; /* 30 - 36 */
- #else
- #error "Need table for SIZEOF_LONG"
- #endif
- /*
- ** strtoul
- ** This is a general purpose routine for converting
- ** an ascii string to an integer in an arbitrary base.
- ** Leading white space is ignored. If 'base' is zero
- ** it looks for a leading 0b, 0o or 0x to tell which
- ** base. If these are absent it defaults to 10.
- ** Base must be 0 or between 2 and 36 (inclusive).
- ** If 'ptr' is non-NULL it will contain a pointer to
- ** the end of the scan.
- ** Errors due to bad pointers will probably result in
- ** exceptions - we don't check for them.
- */
- unsigned long
- PyOS_strtoul(const char *str, char **ptr, int base)
- {
- unsigned long result = 0; /* return value of the function */
- int c; /* current input character */
- int ovlimit; /* required digits to overflow */
- /* skip leading white space */
- while (*str && Py_ISSPACE(*str))
- ++str;
- /* check for leading 0b, 0o or 0x for auto-base or base 16 */
- switch (base) {
- case 0: /* look for leading 0b, 0o or 0x */
- if (*str == '0') {
- ++str;
- if (*str == 'x' || *str == 'X') {
- /* there must be at least one digit after 0x */
- if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 16) {
- if (ptr)
- *ptr = (char *)str;
- return 0;
- }
- ++str;
- base = 16;
- } else if (*str == 'o' || *str == 'O') {
- /* there must be at least one digit after 0o */
- if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 8) {
- if (ptr)
- *ptr = (char *)str;
- return 0;
- }
- ++str;
- base = 8;
- } else if (*str == 'b' || *str == 'B') {
- /* there must be at least one digit after 0b */
- if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 2) {
- if (ptr)
- *ptr = (char *)str;
- return 0;
- }
- ++str;
- base = 2;
- } else {
- /* skip all zeroes... */
- while (*str == '0')
- ++str;
- while (Py_ISSPACE(*str))
- ++str;
- if (ptr)
- *ptr = (char *)str;
- return 0;
- }
- }
- else
- base = 10;
- break;
- /* even with explicit base, skip leading 0? prefix */
- case 16:
- if (*str == '0') {
- ++str;
- if (*str == 'x' || *str == 'X') {
- /* there must be at least one digit after 0x */
- if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 16) {
- if (ptr)
- *ptr = (char *)str;
- return 0;
- }
- ++str;
- }
- }
- break;
- case 8:
- if (*str == '0') {
- ++str;
- if (*str == 'o' || *str == 'O') {
- /* there must be at least one digit after 0o */
- if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 8) {
- if (ptr)
- *ptr = (char *)str;
- return 0;
- }
- ++str;
- }
- }
- break;
- case 2:
- if(*str == '0') {
- ++str;
- if (*str == 'b' || *str == 'B') {
- /* there must be at least one digit after 0b */
- if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 2) {
- if (ptr)
- *ptr = (char *)str;
- return 0;
- }
- ++str;
- }
- }
- break;
- }
- /* catch silly bases */
- if (base < 2 || base > 36) {
- if (ptr)
- *ptr = (char *)str;
- return 0;
- }
- /* skip leading zeroes */
- while (*str == '0')
- ++str;
- /* base is guaranteed to be in [2, 36] at this point */
- ovlimit = digitlimit[base];
- /* do the conversion until non-digit character encountered */
- while ((c = _PyLong_DigitValue[Py_CHARMASK(*str)]) < base) {
- if (ovlimit > 0) /* no overflow check required */
- result = result * base + c;
- else { /* requires overflow check */
- unsigned long temp_result;
- if (ovlimit < 0) /* guaranteed overflow */
- goto overflowed;
- /* there could be an overflow */
- /* check overflow just from shifting */
- if (result > smallmax[base])
- goto overflowed;
- result *= base;
- /* check overflow from the digit's value */
- temp_result = result + c;
- if (temp_result < result)
- goto overflowed;
- result = temp_result;
- }
- ++str;
- --ovlimit;
- }
- /* set pointer to point to the last character scanned */
- if (ptr)
- *ptr = (char *)str;
- return result;
- overflowed:
- if (ptr) {
- /* spool through remaining digit characters */
- while (_PyLong_DigitValue[Py_CHARMASK(*str)] < base)
- ++str;
- *ptr = (char *)str;
- }
- errno = ERANGE;
- return (unsigned long)-1;
- }
- /* Checking for overflow in PyOS_strtol is a PITA; see comments
- * about PY_ABS_LONG_MIN in longobject.c.
- */
- #define PY_ABS_LONG_MIN (0-(unsigned long)LONG_MIN)
- long
- PyOS_strtol(const char *str, char **ptr, int base)
- {
- long result;
- unsigned long uresult;
- char sign;
- while (*str && Py_ISSPACE(*str))
- str++;
- sign = *str;
- if (sign == '+' || sign == '-')
- str++;
- uresult = PyOS_strtoul(str, ptr, base);
- if (uresult <= (unsigned long)LONG_MAX) {
- result = (long)uresult;
- if (sign == '-')
- result = -result;
- }
- else if (sign == '-' && uresult == PY_ABS_LONG_MIN) {
- result = LONG_MIN;
- }
- else {
- errno = ERANGE;
- result = LONG_MAX;
- }
- return result;
- }
|