Back to index

python3.2  3.2.2
Defines | Functions | Variables
mystrtoul.c File Reference
#include "Python.h"
#include <ctype.h>

Go to the source code of this file.

Defines

#define PY_ABS_LONG_MIN   (0-(unsigned long)LONG_MIN)

Functions

unsigned long PyOS_strtoul (register char *str, char **ptr, int base)
long PyOS_strtol (char *str, char **ptr, int base)

Variables

static unsigned long smallmax []

Define Documentation

#define PY_ABS_LONG_MIN   (0-(unsigned long)LONG_MIN)

Definition at line 260 of file mystrtoul.c.


Function Documentation

long PyOS_strtol ( char *  str,
char **  ptr,
int  base 
)

Definition at line 263 of file mystrtoul.c.

{
    long result;
    unsigned long uresult;
    char sign;

    while (*str && isspace(Py_CHARMASK(*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;
}

Here is the call graph for this function:

Here is the caller graph for this function:

unsigned long PyOS_strtoul ( register char *  str,
char **  ptr,
int  base 
)

Definition at line 95 of file mystrtoul.c.

{
    register unsigned long result = 0; /* return value of the function */
    register int c;             /* current input character */
    register int ovlimit;       /* required digits to overflow */

    /* skip leading white space */
    while (*str && isspace(Py_CHARMASK(*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 = 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 = 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 = str;
                    return 0;
                }
                ++str;
                base = 2;
            } else {
                /* skip all zeroes... */
                while (*str == '0')
                    ++str;
                while (isspace(Py_CHARMASK(*str)))
                    ++str;
                if (ptr)
                    *ptr = 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 = 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 = 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 = str;
                    return 0;
                }
                ++str;
            }
        }
        break;
    }

    /* catch silly bases */
    if (base < 2 || base > 36) {
        if (ptr)
            *ptr = 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 */
            register 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 = str;

    return result;

overflowed:
    if (ptr) {
        /* spool through remaining digit characters */
        while (_PyLong_DigitValue[Py_CHARMASK(*str)] < base)
            ++str;
        *ptr = str;
    }
    errno = ERANGE;
    return (unsigned long)-1;
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

unsigned long smallmax[] [static]

Definition at line 20 of file mystrtoul.c.