Back to index

python3.2  3.2.2
Classes | Functions
formatter.h File Reference
#include <locale.h>
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  InternalFormatSpec

Functions

static void unknown_presentation_type (STRINGLIB_CHAR presentation_type, const char *type_name)
static void invalid_comma_type (STRINGLIB_CHAR presentation_type)
static int get_integer (STRINGLIB_CHAR **ptr, STRINGLIB_CHAR *end, Py_ssize_t *result)
 Py_LOCAL_INLINE (int) is_alignment_token(STRINGLIB_CHAR c)
static int parse_internal_render_format_spec (STRINGLIB_CHAR *format_spec, Py_ssize_t format_spec_len, InternalFormatSpec *format, char default_type, char default_align)
static void calc_padding (Py_ssize_t nchars, Py_ssize_t width, STRINGLIB_CHAR align, Py_ssize_t *n_lpadding, Py_ssize_t *n_rpadding, Py_ssize_t *n_total)
static STRINGLIB_CHARfill_padding (STRINGLIB_CHAR *p, Py_ssize_t nchars, STRINGLIB_CHAR fill_char, Py_ssize_t n_lpadding, Py_ssize_t n_rpadding)
static PyObjectformat_string_internal (PyObject *value, const InternalFormatSpec *format)
PyObjectFORMAT_STRING (PyObject *obj, STRINGLIB_CHAR *format_spec, Py_ssize_t format_spec_len)

Class Documentation

struct InternalFormatSpec

Definition at line 133 of file formatter.h.

Class Members
STRINGLIB_CHAR align
int alternate
STRINGLIB_CHAR fill_char
Py_ssize_t precision
STRINGLIB_CHAR sign
int thousands_separators
STRINGLIB_CHAR type
Py_ssize_t width

Function Documentation

static void calc_padding ( Py_ssize_t  nchars,
Py_ssize_t  width,
STRINGLIB_CHAR  align,
Py_ssize_t n_lpadding,
Py_ssize_t n_rpadding,
Py_ssize_t n_total 
) [static]

Definition at line 308 of file formatter.h.

{
    if (width >= 0) {
        if (nchars > width)
            *n_total = nchars;
        else
            *n_total = width;
    }
    else {
        /* not specified, use all of the chars and no more */
        *n_total = nchars;
    }

    /* Figure out how much leading space we need, based on the
       aligning */
    if (align == '>')
        *n_lpadding = *n_total - nchars;
    else if (align == '^')
        *n_lpadding = (*n_total - nchars) / 2;
    else if (align == '<' || align == '=')
        *n_lpadding = 0;
    else {
        /* We should never have an unspecified alignment. */
        *n_lpadding = 0;
        assert(0);
    }

    *n_rpadding = *n_total - nchars - *n_lpadding;
}

Here is the caller graph for this function:

static STRINGLIB_CHAR* fill_padding ( STRINGLIB_CHAR p,
Py_ssize_t  nchars,
STRINGLIB_CHAR  fill_char,
Py_ssize_t  n_lpadding,
Py_ssize_t  n_rpadding 
) [static]

Definition at line 343 of file formatter.h.

{
    /* Pad on left. */
    if (n_lpadding)
        STRINGLIB_FILL(p, fill_char, n_lpadding);

    /* Pad on right. */
    if (n_rpadding)
        STRINGLIB_FILL(p + nchars + n_lpadding, fill_char, n_rpadding);

    /* Pointer to the user content. */
    return p + n_lpadding;
}

Here is the caller graph for this function:

PyObject* FORMAT_STRING ( PyObject obj,
STRINGLIB_CHAR format_spec,
Py_ssize_t  format_spec_len 
)

Definition at line 1277 of file formatter.h.

{
    InternalFormatSpec format;
    PyObject *result = NULL;

    /* check for the special case of zero length format spec, make
       it equivalent to str(obj) */
    if (format_spec_len == 0) {
        result = STRINGLIB_TOSTR(obj);
        goto done;
    }

    /* parse the format_spec */
    if (!parse_internal_render_format_spec(format_spec, format_spec_len,
                                           &format, 's', '<'))
        goto done;

    /* type conversion? */
    switch (format.type) {
    case 's':
        /* no type conversion needed, already a string.  do the formatting */
        result = format_string_internal(obj, &format);
        break;
    default:
        /* unknown */
        unknown_presentation_type(format.type, obj->ob_type->tp_name);
        goto done;
    }

done:
    return result;
}

Here is the call graph for this function:

static PyObject* format_string_internal ( PyObject value,
const InternalFormatSpec format 
) [static]

Definition at line 673 of file formatter.h.

{
    Py_ssize_t lpad;
    Py_ssize_t rpad;
    Py_ssize_t total;
    STRINGLIB_CHAR *p;
    Py_ssize_t len = STRINGLIB_LEN(value);
    PyObject *result = NULL;

    /* sign is not allowed on strings */
    if (format->sign != '\0') {
        PyErr_SetString(PyExc_ValueError,
                        "Sign not allowed in string format specifier");
        goto done;
    }

    /* alternate is not allowed on strings */
    if (format->alternate) {
        PyErr_SetString(PyExc_ValueError,
                        "Alternate form (#) not allowed in string format "
                        "specifier");
        goto done;
    }

    /* '=' alignment not allowed on strings */
    if (format->align == '=') {
        PyErr_SetString(PyExc_ValueError,
                        "'=' alignment not allowed "
                        "in string format specifier");
        goto done;
    }

    /* if precision is specified, output no more that format.precision
       characters */
    if (format->precision >= 0 && len >= format->precision) {
        len = format->precision;
    }

    calc_padding(len, format->width, format->align, &lpad, &rpad, &total);

    /* allocate the resulting string */
    result = STRINGLIB_NEW(NULL, total);
    if (result == NULL)
        goto done;

    /* Write into that space. First the padding. */
    p = fill_padding(STRINGLIB_STR(result), len,
                     format->fill_char=='\0'?' ':format->fill_char,
                     lpad, rpad);

    /* Then the source string. */
    memcpy(p, STRINGLIB_STR(value), len * sizeof(STRINGLIB_CHAR));

done:
    return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int get_integer ( STRINGLIB_CHAR **  ptr,
STRINGLIB_CHAR end,
Py_ssize_t result 
) [static]

Definition at line 73 of file formatter.h.

{
    Py_ssize_t accumulator, digitval, oldaccumulator;
    int numdigits;
    accumulator = numdigits = 0;
    for (;;(*ptr)++, numdigits++) {
        if (*ptr >= end)
            break;
        digitval = STRINGLIB_TODECIMAL(**ptr);
        if (digitval < 0)
            break;
        /*
           This trick was copied from old Unicode format code.  It's cute,
           but would really suck on an old machine with a slow divide
           implementation.  Fortunately, in the normal case we do not
           expect too many digits.
        */
        oldaccumulator = accumulator;
        accumulator *= 10;
        if ((accumulator+10)/10 != oldaccumulator+1) {
            PyErr_Format(PyExc_ValueError,
                         "Too many decimal digits in format string");
            return -1;
        }
        accumulator += digitval;
    }
    *result = accumulator;
    return numdigits;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void invalid_comma_type ( STRINGLIB_CHAR  presentation_type) [static]

Definition at line 48 of file formatter.h.

{
#if STRINGLIB_IS_UNICODE
    /* See comment in unknown_presentation_type */
    if (presentation_type > 32 && presentation_type < 128)
#endif
        PyErr_Format(PyExc_ValueError,
                     "Cannot specify ',' with '%c'.",
                     (char)presentation_type);
#if STRINGLIB_IS_UNICODE
    else
        PyErr_Format(PyExc_ValueError,
                     "Cannot specify ',' with '\\x%x'.",
                     (unsigned int)presentation_type);
#endif
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int parse_internal_render_format_spec ( STRINGLIB_CHAR format_spec,
Py_ssize_t  format_spec_len,
InternalFormatSpec format,
char  default_type,
char  default_align 
) [static]

Definition at line 171 of file formatter.h.

{
    STRINGLIB_CHAR *ptr = format_spec;
    STRINGLIB_CHAR *end = format_spec + format_spec_len;

    /* end-ptr is used throughout this code to specify the length of
       the input string */

    Py_ssize_t consumed;
    int align_specified = 0;

    format->fill_char = '\0';
    format->align = default_align;
    format->alternate = 0;
    format->sign = '\0';
    format->width = -1;
    format->thousands_separators = 0;
    format->precision = -1;
    format->type = default_type;

    /* If the second char is an alignment token,
       then parse the fill char */
    if (end-ptr >= 2 && is_alignment_token(ptr[1])) {
        format->align = ptr[1];
        format->fill_char = ptr[0];
        align_specified = 1;
        ptr += 2;
    }
    else if (end-ptr >= 1 && is_alignment_token(ptr[0])) {
        format->align = ptr[0];
        align_specified = 1;
        ++ptr;
    }

    /* Parse the various sign options */
    if (end-ptr >= 1 && is_sign_element(ptr[0])) {
        format->sign = ptr[0];
        ++ptr;
    }

    /* If the next character is #, we're in alternate mode.  This only
       applies to integers. */
    if (end-ptr >= 1 && ptr[0] == '#') {
        format->alternate = 1;
        ++ptr;
    }

    /* The special case for 0-padding (backwards compat) */
    if (format->fill_char == '\0' && end-ptr >= 1 && ptr[0] == '0') {
        format->fill_char = '0';
        if (!align_specified) {
            format->align = '=';
        }
        ++ptr;
    }

    consumed = get_integer(&ptr, end, &format->width);
    if (consumed == -1)
        /* Overflow error. Exception already set. */
        return 0;

    /* If consumed is 0, we didn't consume any characters for the
       width. In that case, reset the width to -1, because
       get_integer() will have set it to zero. -1 is how we record
       that the width wasn't specified. */
    if (consumed == 0)
        format->width = -1;

    /* Comma signifies add thousands separators */
    if (end-ptr && ptr[0] == ',') {
        format->thousands_separators = 1;
        ++ptr;
    }

    /* Parse field precision */
    if (end-ptr && ptr[0] == '.') {
        ++ptr;

        consumed = get_integer(&ptr, end, &format->precision);
        if (consumed == -1)
            /* Overflow error. Exception already set. */
            return 0;

        /* Not having a precision after a dot is an error. */
        if (consumed == 0) {
            PyErr_Format(PyExc_ValueError,
                         "Format specifier missing precision");
            return 0;
        }

    }

    /* Finally, parse the type field. */

    if (end-ptr > 1) {
        /* More than one char remain, invalid conversion spec. */
        PyErr_Format(PyExc_ValueError, "Invalid conversion specification");
        return 0;
    }

    if (end-ptr == 1) {
        format->type = ptr[0];
        ++ptr;
    }

    /* Do as much validating as we can, just by looking at the format
       specifier.  Do not take into account what type of formatting
       we're doing (int, float, string). */

    if (format->thousands_separators) {
        switch (format->type) {
        case 'd':
        case 'e':
        case 'f':
        case 'g':
        case 'E':
        case 'G':
        case '%':
        case 'F':
        case '\0':
            /* These are allowed. See PEP 378.*/
            break;
        default:
            invalid_comma_type(format->type);
            return 0;
        }
    }

    return 1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 109 of file formatter.h.

{
    switch (c) {
    case '<': case '>': case '=': case '^':
        return 1;
    default:
        return 0;
    }
}
static void unknown_presentation_type ( STRINGLIB_CHAR  presentation_type,
const char *  type_name 
) [static]

Definition at line 23 of file formatter.h.

{
#if STRINGLIB_IS_UNICODE
    /* If STRINGLIB_CHAR is Py_UNICODE, %c might be out-of-range,
       hence the two cases. If it is char, gcc complains that the
       condition below is always true, hence the ifdef. */
    if (presentation_type > 32 && presentation_type < 128)
#endif
        PyErr_Format(PyExc_ValueError,
                     "Unknown format code '%c' "
                     "for object of type '%.200s'",
                     (char)presentation_type,
                     type_name);
#if STRINGLIB_IS_UNICODE
    else
        PyErr_Format(PyExc_ValueError,
                     "Unknown format code '\\x%x' "
                     "for object of type '%.200s'",
                     (unsigned int)presentation_type,
                     type_name);
#endif
}

Here is the call graph for this function:

Here is the caller graph for this function: