Coverage Report

Created: 2025-10-10 06:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cpython/Objects/unicode_formatter.c
Line
Count
Source
1
/* implements the unicode (as opposed to string) version of the
2
   built-in formatters for string, int, float.  that is, the versions
3
   of int.__float__, etc., that take and return unicode objects */
4
5
#include "Python.h"
6
#include "pycore_fileutils.h"     // _Py_GetLocaleconvNumeric()
7
#include "pycore_long.h"          // _PyLong_FormatWriter()
8
#include "pycore_unicodeobject.h" // PyUnicode_MAX_CHAR_VALUE()
9
#include <locale.h>
10
11
12
/* _PyUnicode_InsertThousandsGrouping() helper functions */
13
14
typedef struct {
15
    const char *grouping;
16
    char previous;
17
    Py_ssize_t i; /* Where we're currently pointing in grouping. */
18
} GroupGenerator;
19
20
21
static void
22
GroupGenerator_init(GroupGenerator *self, const char *grouping)
23
128
{
24
128
    self->grouping = grouping;
25
128
    self->i = 0;
26
128
    self->previous = 0;
27
128
}
28
29
30
/* Returns the next grouping, or 0 to signify end. */
31
static Py_ssize_t
32
GroupGenerator_next(GroupGenerator *self)
33
128
{
34
    /* Note that we don't really do much error checking here. If a
35
       grouping string contains just CHAR_MAX, for example, then just
36
       terminate the generator. That shouldn't happen, but at least we
37
       fail gracefully. */
38
128
    switch (self->grouping[self->i]) {
39
0
    case 0:
40
0
        return self->previous;
41
128
    case CHAR_MAX:
42
        /* Stop the generator. */
43
128
        return 0;
44
0
    default: {
45
0
        char ch = self->grouping[self->i];
46
0
        self->previous = ch;
47
0
        self->i++;
48
0
        return (Py_ssize_t)ch;
49
0
    }
50
128
    }
51
128
}
52
53
54
/* Fill in some digits, leading zeros, and thousands separator. All
55
   are optional, depending on when we're called. */
56
static void
57
InsertThousandsGrouping_fill(_PyUnicodeWriter *writer, Py_ssize_t *buffer_pos,
58
                             PyObject *digits, Py_ssize_t *digits_pos,
59
                             Py_ssize_t n_chars, Py_ssize_t n_zeros,
60
                             PyObject *thousands_sep, Py_ssize_t thousands_sep_len,
61
                             Py_UCS4 *maxchar, int forward)
62
128
{
63
128
    if (!writer) {
64
        /* if maxchar > 127, maxchar is already set */
65
64
        if (*maxchar == 127 && thousands_sep) {
66
0
            Py_UCS4 maxchar2 = PyUnicode_MAX_CHAR_VALUE(thousands_sep);
67
0
            *maxchar = Py_MAX(*maxchar, maxchar2);
68
0
        }
69
64
        return;
70
64
    }
71
72
64
    if (thousands_sep) {
73
0
        if (!forward) {
74
0
            *buffer_pos -= thousands_sep_len;
75
0
        }
76
        /* Copy the thousands_sep chars into the buffer. */
77
0
        _PyUnicode_FastCopyCharacters(writer->buffer, *buffer_pos,
78
0
                                      thousands_sep, 0,
79
0
                                      thousands_sep_len);
80
0
        if (forward) {
81
0
            *buffer_pos += thousands_sep_len;
82
0
        }
83
0
    }
84
85
64
    if (!forward) {
86
64
        *buffer_pos -= n_chars;
87
64
        *digits_pos -= n_chars;
88
64
    }
89
64
    _PyUnicode_FastCopyCharacters(writer->buffer, *buffer_pos,
90
64
                                  digits, *digits_pos,
91
64
                                  n_chars);
92
64
    if (forward) {
93
0
        *buffer_pos += n_chars;
94
0
        *digits_pos += n_chars;
95
0
    }
96
97
64
    if (n_zeros) {
98
64
        if (!forward) {
99
64
            *buffer_pos -= n_zeros;
100
64
        }
101
64
        int kind = PyUnicode_KIND(writer->buffer);
102
64
        void *data = PyUnicode_DATA(writer->buffer);
103
64
        _PyUnicode_Fill(kind, data, '0', *buffer_pos, n_zeros);
104
64
        if (forward) {
105
0
            *buffer_pos += n_zeros;
106
0
        }
107
64
    }
108
64
}
109
110
111
/**
112
 * InsertThousandsGrouping:
113
 * @writer: Unicode writer.
114
 * @n_buffer: Number of characters in @buffer.
115
 * @digits: Digits we're reading from. If count is non-NULL, this is unused.
116
 * @d_pos: Start of digits string.
117
 * @n_digits: The number of digits in the string, in which we want
118
 *            to put the grouping chars.
119
 * @min_width: The minimum width of the digits in the output string.
120
 *             Output will be zero-padded on the left to fill.
121
 * @grouping: see definition in localeconv().
122
 * @thousands_sep: see definition in localeconv().
123
 *
124
 * There are 2 modes: counting and filling. If @writer is NULL,
125
 *  we are in counting mode, else filling mode.
126
 * If counting, the required buffer size is returned.
127
 * If filling, we know the buffer will be large enough, so we don't
128
 *  need to pass in the buffer size.
129
 * Inserts thousand grouping characters (as defined by grouping and
130
 *  thousands_sep) into @writer.
131
 *
132
 * Return value: -1 on error, number of characters otherwise.
133
 **/
134
static Py_ssize_t
135
_PyUnicode_InsertThousandsGrouping(
136
    _PyUnicodeWriter *writer,
137
    Py_ssize_t n_buffer,
138
    PyObject *digits,
139
    Py_ssize_t d_pos,
140
    Py_ssize_t n_digits,
141
    Py_ssize_t min_width,
142
    const char *grouping,
143
    PyObject *thousands_sep,
144
    Py_UCS4 *maxchar,
145
    int forward)
146
128
{
147
128
    min_width = Py_MAX(0, min_width);
148
128
    if (writer) {
149
64
        assert(digits != NULL);
150
64
        assert(maxchar == NULL);
151
64
    }
152
64
    else {
153
64
        assert(digits == NULL);
154
64
        assert(maxchar != NULL);
155
64
    }
156
128
    assert(0 <= d_pos);
157
128
    assert(0 <= n_digits);
158
128
    assert(grouping != NULL);
159
160
128
    Py_ssize_t count = 0;
161
128
    Py_ssize_t n_zeros;
162
128
    int loop_broken = 0;
163
128
    int use_separator = 0; /* First time through, don't append the
164
                              separator. They only go between
165
                              groups. */
166
128
    Py_ssize_t buffer_pos;
167
128
    Py_ssize_t digits_pos;
168
128
    Py_ssize_t len;
169
128
    Py_ssize_t n_chars;
170
128
    Py_ssize_t remaining = n_digits; /* Number of chars remaining to
171
                                        be looked at */
172
    /* A generator that returns all of the grouping widths, until it
173
       returns 0. */
174
128
    GroupGenerator groupgen;
175
128
    GroupGenerator_init(&groupgen, grouping);
176
128
    const Py_ssize_t thousands_sep_len = PyUnicode_GET_LENGTH(thousands_sep);
177
178
    /* if digits are not grouped, thousands separator
179
       should be an empty string */
180
128
    assert(!(grouping[0] == CHAR_MAX && thousands_sep_len != 0));
181
182
128
    digits_pos = d_pos + (forward ? 0 : n_digits);
183
128
    if (writer) {
184
64
        buffer_pos = writer->pos + (forward ? 0 : n_buffer);
185
64
        assert(buffer_pos <= PyUnicode_GET_LENGTH(writer->buffer));
186
64
        assert(digits_pos <= PyUnicode_GET_LENGTH(digits));
187
64
    }
188
64
    else {
189
64
        buffer_pos = forward ? 0 : n_buffer;
190
64
    }
191
192
128
    if (!writer) {
193
64
        *maxchar = 127;
194
64
    }
195
196
128
    while ((len = GroupGenerator_next(&groupgen)) > 0) {
197
0
        len = Py_MIN(len, Py_MAX(Py_MAX(remaining, min_width), 1));
198
0
        n_zeros = Py_MAX(0, len - remaining);
199
0
        n_chars = Py_MAX(0, Py_MIN(remaining, len));
200
201
        /* Use n_zero zero's and n_chars chars */
202
203
        /* Count only, don't do anything. */
204
0
        count += (use_separator ? thousands_sep_len : 0) + n_zeros + n_chars;
205
206
        /* Copy into the writer. */
207
0
        InsertThousandsGrouping_fill(writer, &buffer_pos,
208
0
                                     digits, &digits_pos,
209
0
                                     n_chars, n_zeros,
210
0
                                     use_separator ? thousands_sep : NULL,
211
0
                                     thousands_sep_len, maxchar, forward);
212
213
        /* Use a separator next time. */
214
0
        use_separator = 1;
215
216
0
        remaining -= n_chars;
217
0
        min_width -= len;
218
219
0
        if (remaining <= 0 && min_width <= 0) {
220
0
            loop_broken = 1;
221
0
            break;
222
0
        }
223
0
        min_width -= thousands_sep_len;
224
0
    }
225
128
    if (!loop_broken) {
226
        /* We left the loop without using a break statement. */
227
228
128
        len = Py_MAX(Py_MAX(remaining, min_width), 1);
229
128
        n_zeros = Py_MAX(0, len - remaining);
230
128
        n_chars = Py_MAX(0, Py_MIN(remaining, len));
231
232
        /* Use n_zero zero's and n_chars chars */
233
128
        count += (use_separator ? thousands_sep_len : 0) + n_zeros + n_chars;
234
235
        /* Copy into the writer. */
236
128
        InsertThousandsGrouping_fill(writer, &buffer_pos,
237
128
                                     digits, &digits_pos,
238
128
                                     n_chars, n_zeros,
239
128
                                     use_separator ? thousands_sep : NULL,
240
128
                                     thousands_sep_len, maxchar, forward);
241
128
    }
242
128
    return count;
243
128
}
244
245
246
/* Raises an exception about an unknown presentation type for this
247
 * type. */
248
249
static void
250
unknown_presentation_type(Py_UCS4 presentation_type,
251
                          const char* type_name)
252
0
{
253
    /* %c might be out-of-range, hence the two cases. */
254
0
    if (presentation_type > 32 && presentation_type < 128)
255
0
        PyErr_Format(PyExc_ValueError,
256
0
                     "Unknown format code '%c' "
257
0
                     "for object of type '%.200s'",
258
0
                     (char)presentation_type,
259
0
                     type_name);
260
0
    else
261
0
        PyErr_Format(PyExc_ValueError,
262
0
                     "Unknown format code '\\x%x' "
263
0
                     "for object of type '%.200s'",
264
0
                     (unsigned int)presentation_type,
265
0
                     type_name);
266
0
}
267
268
static void
269
invalid_thousands_separator_type(char specifier, Py_UCS4 presentation_type)
270
0
{
271
0
    assert(specifier == ',' || specifier == '_');
272
0
    if (presentation_type > 32 && presentation_type < 128)
273
0
        PyErr_Format(PyExc_ValueError,
274
0
                     "Cannot specify '%c' with '%c'.",
275
0
                     specifier, (char)presentation_type);
276
0
    else
277
0
        PyErr_Format(PyExc_ValueError,
278
0
                     "Cannot specify '%c' with '\\x%x'.",
279
0
                     specifier, (unsigned int)presentation_type);
280
0
}
281
282
static void
283
invalid_comma_and_underscore(void)
284
0
{
285
0
    PyErr_Format(PyExc_ValueError, "Cannot specify both ',' and '_'.");
286
0
}
287
288
/*
289
    get_integer consumes 0 or more decimal digit characters from an
290
    input string, updates *result with the corresponding positive
291
    integer, and returns the number of digits consumed.
292
293
    returns -1 on error.
294
*/
295
static int
296
get_integer(PyObject *str, Py_ssize_t *ppos, Py_ssize_t end,
297
                  Py_ssize_t *result)
298
412
{
299
412
    Py_ssize_t accumulator, digitval, pos = *ppos;
300
412
    int numdigits;
301
412
    int kind = PyUnicode_KIND(str);
302
412
    const void *data = PyUnicode_DATA(str);
303
304
412
    accumulator = numdigits = 0;
305
476
    for (; pos < end; pos++, numdigits++) {
306
476
        digitval = Py_UNICODE_TODECIMAL(PyUnicode_READ(kind, data, pos));
307
476
        if (digitval < 0)
308
412
            break;
309
        /*
310
           Detect possible overflow before it happens:
311
312
              accumulator * 10 + digitval > PY_SSIZE_T_MAX if and only if
313
              accumulator > (PY_SSIZE_T_MAX - digitval) / 10.
314
        */
315
64
        if (accumulator > (PY_SSIZE_T_MAX - digitval) / 10) {
316
0
            PyErr_Format(PyExc_ValueError,
317
0
                         "Too many decimal digits in format string");
318
0
            *ppos = pos;
319
0
            return -1;
320
0
        }
321
64
        accumulator = accumulator * 10 + digitval;
322
64
    }
323
412
    *ppos = pos;
324
412
    *result = accumulator;
325
412
    return numdigits;
326
412
}
327
328
/************************************************************************/
329
/*********** standard format specifier parsing **************************/
330
/************************************************************************/
331
332
/* returns true if this character is a specifier alignment token */
333
Py_LOCAL_INLINE(int)
334
is_alignment_token(Py_UCS4 c)
335
476
{
336
476
    switch (c) {
337
0
    case '<': case '>': case '=': case '^':
338
0
        return 1;
339
476
    default:
340
476
        return 0;
341
476
    }
342
476
}
343
344
/* returns true if this character is a sign element */
345
Py_LOCAL_INLINE(int)
346
is_sign_element(Py_UCS4 c)
347
412
{
348
412
    switch (c) {
349
0
    case ' ': case '+': case '-':
350
0
        return 1;
351
412
    default:
352
412
        return 0;
353
412
    }
354
412
}
355
356
/* Locale type codes. LT_NO_LOCALE must be zero. */
357
enum LocaleType {
358
    LT_NO_LOCALE = 0,
359
    LT_DEFAULT_LOCALE = ',',
360
    LT_UNDERSCORE_LOCALE = '_',
361
    LT_UNDER_FOUR_LOCALE,
362
    LT_CURRENT_LOCALE
363
};
364
365
typedef struct {
366
    Py_UCS4 fill_char;
367
    Py_UCS4 align;
368
    int alternate;
369
    int no_neg_0;
370
    Py_UCS4 sign;
371
    Py_ssize_t width;
372
    enum LocaleType thousands_separators;
373
    Py_ssize_t precision;
374
    enum LocaleType frac_thousands_separator;
375
    Py_UCS4 type;
376
} InternalFormatSpec;
377
378
379
/*
380
  ptr points to the start of the format_spec, end points just past its end.
381
  fills in format with the parsed information.
382
  returns 1 on success, 0 on failure.
383
  if failure, sets the exception
384
*/
385
static int
386
parse_internal_render_format_spec(PyObject *obj,
387
                                  PyObject *format_spec,
388
                                  Py_ssize_t start, Py_ssize_t end,
389
                                  InternalFormatSpec *format,
390
                                  char default_type,
391
                                  char default_align)
392
412
{
393
412
    Py_ssize_t pos = start;
394
412
    int kind = PyUnicode_KIND(format_spec);
395
412
    const void *data = PyUnicode_DATA(format_spec);
396
    /* end-pos is used throughout this code to specify the length of
397
       the input string */
398
4.18k
#define READ_spec(index) PyUnicode_READ(kind, data, index)
399
400
412
    Py_ssize_t consumed;
401
412
    int align_specified = 0;
402
412
    int fill_char_specified = 0;
403
404
412
    format->fill_char = ' ';
405
412
    format->align = default_align;
406
412
    format->alternate = 0;
407
412
    format->no_neg_0 = 0;
408
412
    format->sign = '\0';
409
412
    format->width = -1;
410
412
    format->thousands_separators = LT_NO_LOCALE;
411
412
    format->frac_thousands_separator = LT_NO_LOCALE;
412
412
    format->precision = -1;
413
412
    format->type = default_type;
414
415
    /* If the second char is an alignment token,
416
       then parse the fill char */
417
412
    if (end-pos >= 2 && is_alignment_token(READ_spec(pos+1))) {
418
0
        format->align = READ_spec(pos+1);
419
0
        format->fill_char = READ_spec(pos);
420
0
        fill_char_specified = 1;
421
0
        align_specified = 1;
422
0
        pos += 2;
423
0
    }
424
412
    else if (end-pos >= 1 && is_alignment_token(READ_spec(pos))) {
425
0
        format->align = READ_spec(pos);
426
0
        align_specified = 1;
427
0
        ++pos;
428
0
    }
429
430
    /* Parse the various sign options */
431
412
    if (end-pos >= 1 && is_sign_element(READ_spec(pos))) {
432
0
        format->sign = READ_spec(pos);
433
0
        ++pos;
434
0
    }
435
436
    /* If the next character is z, request coercion of negative 0.
437
       Applies only to floats. */
438
412
    if (end-pos >= 1 && READ_spec(pos) == 'z') {
439
0
        format->no_neg_0 = 1;
440
0
        ++pos;
441
0
    }
442
443
    /* If the next character is #, we're in alternate mode.  This only
444
       applies to integers. */
445
412
    if (end-pos >= 1 && READ_spec(pos) == '#') {
446
0
        format->alternate = 1;
447
0
        ++pos;
448
0
    }
449
450
    /* The special case for 0-padding (backwards compat) */
451
412
    if (!fill_char_specified && end-pos >= 1 && READ_spec(pos) == '0') {
452
64
        format->fill_char = '0';
453
64
        if (!align_specified && default_align == '>') {
454
64
            format->align = '=';
455
64
        }
456
64
        ++pos;
457
64
    }
458
459
412
    consumed = get_integer(format_spec, &pos, end, &format->width);
460
412
    if (consumed == -1)
461
        /* Overflow error. Exception already set. */
462
0
        return 0;
463
464
    /* If consumed is 0, we didn't consume any characters for the
465
       width. In that case, reset the width to -1, because
466
       get_integer() will have set it to zero. -1 is how we record
467
       that the width wasn't specified. */
468
412
    if (consumed == 0)
469
348
        format->width = -1;
470
471
    /* Comma signifies add thousands separators */
472
412
    if (end-pos && READ_spec(pos) == ',') {
473
0
        format->thousands_separators = LT_DEFAULT_LOCALE;
474
0
        ++pos;
475
0
    }
476
    /* Underscore signifies add thousands separators */
477
412
    if (end-pos && READ_spec(pos) == '_') {
478
0
        if (format->thousands_separators != LT_NO_LOCALE) {
479
0
            invalid_comma_and_underscore();
480
0
            return 0;
481
0
        }
482
0
        format->thousands_separators = LT_UNDERSCORE_LOCALE;
483
0
        ++pos;
484
0
    }
485
412
    if (end-pos && READ_spec(pos) == ',') {
486
0
        if (format->thousands_separators == LT_UNDERSCORE_LOCALE) {
487
0
            invalid_comma_and_underscore();
488
0
            return 0;
489
0
        }
490
0
    }
491
492
    /* Parse field precision */
493
412
    if (end-pos && READ_spec(pos) == '.') {
494
0
        ++pos;
495
496
0
        consumed = get_integer(format_spec, &pos, end, &format->precision);
497
0
        if (consumed == -1)
498
            /* Overflow error. Exception already set. */
499
0
            return 0;
500
501
0
        if (end-pos && READ_spec(pos) == ',') {
502
0
            if (consumed == 0) {
503
0
                format->precision = -1;
504
0
            }
505
0
            format->frac_thousands_separator = LT_DEFAULT_LOCALE;
506
0
            ++pos;
507
0
            ++consumed;
508
0
        }
509
0
        if (end-pos && READ_spec(pos) == '_') {
510
0
            if (format->frac_thousands_separator != LT_NO_LOCALE) {
511
0
                invalid_comma_and_underscore();
512
0
                return 0;
513
0
            }
514
0
            if (consumed == 0) {
515
0
                format->precision = -1;
516
0
            }
517
0
            format->frac_thousands_separator = LT_UNDERSCORE_LOCALE;
518
0
            ++pos;
519
0
            ++consumed;
520
0
        }
521
0
        if (end-pos && READ_spec(pos) == ',') {
522
0
            if (format->frac_thousands_separator == LT_UNDERSCORE_LOCALE) {
523
0
                invalid_comma_and_underscore();
524
0
                return 0;
525
0
            }
526
0
        }
527
528
        /* Not having a precision or underscore/comma after a dot
529
           is an error. */
530
0
        if (consumed == 0) {
531
0
            PyErr_Format(PyExc_ValueError,
532
0
                         "Format specifier missing precision");
533
0
            return 0;
534
0
        }
535
536
0
    }
537
538
    /* Finally, parse the type field. */
539
540
412
    if (end-pos > 1) {
541
        /* More than one char remains, so this is an invalid format
542
           specifier. */
543
        /* Create a temporary object that contains the format spec we're
544
           operating on.  It's format_spec[start:end] (in Python syntax). */
545
0
        PyObject* actual_format_spec = PyUnicode_FromKindAndData(kind,
546
0
                                         (char*)data + kind*start,
547
0
                                         end-start);
548
0
        if (actual_format_spec != NULL) {
549
0
            PyErr_Format(PyExc_ValueError,
550
0
                "Invalid format specifier '%U' for object of type '%.200s'",
551
0
                actual_format_spec, Py_TYPE(obj)->tp_name);
552
0
            Py_DECREF(actual_format_spec);
553
0
        }
554
0
        return 0;
555
0
    }
556
557
412
    if (end-pos == 1) {
558
412
        format->type = READ_spec(pos);
559
412
        ++pos;
560
412
    }
561
562
    /* Do as much validating as we can, just by looking at the format
563
       specifier.  Do not take into account what type of formatting
564
       we're doing (int, float, string). */
565
566
412
    if (format->thousands_separators) {
567
0
        switch (format->type) {
568
0
        case 'd':
569
0
        case 'e':
570
0
        case 'f':
571
0
        case 'g':
572
0
        case 'E':
573
0
        case 'G':
574
0
        case '%':
575
0
        case 'F':
576
0
        case '\0':
577
            /* These are allowed. See PEP 378.*/
578
0
            break;
579
0
        case 'b':
580
0
        case 'o':
581
0
        case 'x':
582
0
        case 'X':
583
            /* Underscores are allowed in bin/oct/hex. See PEP 515. */
584
0
            if (format->thousands_separators == LT_UNDERSCORE_LOCALE) {
585
                /* Every four digits, not every three, in bin/oct/hex. */
586
0
                format->thousands_separators = LT_UNDER_FOUR_LOCALE;
587
0
                break;
588
0
            }
589
0
            _Py_FALLTHROUGH;
590
0
        default:
591
0
            invalid_thousands_separator_type(format->thousands_separators, format->type);
592
0
            return 0;
593
0
        }
594
0
    }
595
596
412
    if (format->type == 'n'
597
0
        && format->frac_thousands_separator != LT_NO_LOCALE)
598
0
    {
599
0
        invalid_thousands_separator_type(format->frac_thousands_separator,
600
0
                                         format->type);
601
0
        return 0;
602
0
    }
603
604
412
    assert (format->align <= 127);
605
412
    assert (format->sign <= 127);
606
412
    return 1;
607
412
}
608
609
/* Calculate the padding needed. */
610
static void
611
calc_padding(Py_ssize_t nchars, Py_ssize_t width, Py_UCS4 align,
612
             Py_ssize_t *n_lpadding, Py_ssize_t *n_rpadding,
613
             Py_ssize_t *n_total)
614
0
{
615
0
    if (width >= 0) {
616
0
        if (nchars > width)
617
0
            *n_total = nchars;
618
0
        else
619
0
            *n_total = width;
620
0
    }
621
0
    else {
622
        /* not specified, use all of the chars and no more */
623
0
        *n_total = nchars;
624
0
    }
625
626
    /* Figure out how much leading space we need, based on the
627
       aligning */
628
0
    if (align == '>')
629
0
        *n_lpadding = *n_total - nchars;
630
0
    else if (align == '^')
631
0
        *n_lpadding = (*n_total - nchars) / 2;
632
0
    else if (align == '<' || align == '=')
633
0
        *n_lpadding = 0;
634
0
    else {
635
        /* We should never have an unspecified alignment. */
636
0
        Py_UNREACHABLE();
637
0
    }
638
639
0
    *n_rpadding = *n_total - nchars - *n_lpadding;
640
0
}
641
642
/* Do the padding, and return a pointer to where the caller-supplied
643
   content goes. */
644
static int
645
fill_padding(_PyUnicodeWriter *writer,
646
             Py_ssize_t nchars,
647
             Py_UCS4 fill_char, Py_ssize_t n_lpadding,
648
             Py_ssize_t n_rpadding)
649
0
{
650
0
    Py_ssize_t pos;
651
652
    /* Pad on left. */
653
0
    if (n_lpadding) {
654
0
        pos = writer->pos;
655
0
        _PyUnicode_FastFill(writer->buffer, pos, n_lpadding, fill_char);
656
0
    }
657
658
    /* Pad on right. */
659
0
    if (n_rpadding) {
660
0
        pos = writer->pos + nchars + n_lpadding;
661
0
        _PyUnicode_FastFill(writer->buffer, pos, n_rpadding, fill_char);
662
0
    }
663
664
    /* Pointer to the user content. */
665
0
    writer->pos += n_lpadding;
666
0
    return 0;
667
0
}
668
669
/************************************************************************/
670
/*********** common routines for numeric formatting *********************/
671
/************************************************************************/
672
673
/* Locale info needed for formatting integers and the part of floats
674
   before and including the decimal. Note that locales only support
675
   8-bit chars, not unicode. */
676
typedef struct {
677
    PyObject *decimal_point;
678
    PyObject *thousands_sep;
679
    PyObject *frac_thousands_sep;
680
    const char *grouping;
681
    char *grouping_buffer;
682
} LocaleInfo;
683
684
412
#define LocaleInfo_STATIC_INIT {0, 0, 0, 0}
685
686
/* describes the layout for an integer, see the comment in
687
   calc_number_widths() for details */
688
typedef struct {
689
    Py_ssize_t n_lpadding;
690
    Py_ssize_t n_prefix;
691
    Py_ssize_t n_spadding;
692
    Py_ssize_t n_rpadding;
693
    char sign;
694
    Py_ssize_t n_sign;      /* number of digits needed for sign (0/1) */
695
    Py_ssize_t n_grouped_digits; /* Space taken up by the digits, including
696
                                    any grouping chars. */
697
    Py_ssize_t n_decimal;   /* 0 if only an integer */
698
    Py_ssize_t n_remainder; /* Digits in decimal and/or exponent part,
699
                               excluding the decimal itself, if
700
                               present. */
701
    Py_ssize_t n_frac;
702
    Py_ssize_t n_grouped_frac_digits;
703
704
    /* These 2 are not the widths of fields, but are needed by
705
       STRINGLIB_GROUPING. */
706
    Py_ssize_t n_digits;    /* The number of digits before a decimal
707
                               or exponent. */
708
    Py_ssize_t n_min_width; /* The min_width we used when we computed
709
                               the n_grouped_digits width. */
710
} NumberFieldWidths;
711
712
713
/* Given a number of the form:
714
   digits[remainder]
715
   where ptr points to the start and end points to the end, find where
716
    the integer part ends. This could be a decimal, an exponent, both,
717
    or neither.
718
   If a decimal point is present, set *has_decimal and increment
719
    remainder beyond it.
720
   Results are undefined (but shouldn't crash) for improperly
721
    formatted strings.
722
*/
723
static void
724
parse_number(PyObject *s, Py_ssize_t pos, Py_ssize_t end,
725
             Py_ssize_t *n_remainder, Py_ssize_t *n_frac, int *has_decimal)
726
0
{
727
0
    Py_ssize_t frac;
728
0
    int kind = PyUnicode_KIND(s);
729
0
    const void *data = PyUnicode_DATA(s);
730
731
0
    while (pos<end && Py_ISDIGIT(PyUnicode_READ(kind, data, pos))) {
732
0
        ++pos;
733
0
    }
734
0
    frac = pos;
735
736
    /* Does remainder start with a decimal point? */
737
0
    *has_decimal = pos<end && PyUnicode_READ(kind, data, frac) == '.';
738
739
    /* Skip the decimal point. */
740
0
    if (*has_decimal) {
741
0
        frac++;
742
0
        pos++;
743
0
    }
744
745
0
    while (pos<end && Py_ISDIGIT(PyUnicode_READ(kind, data, pos))) {
746
0
        ++pos;
747
0
    }
748
749
0
    *n_frac = pos - frac;
750
0
    *n_remainder = end - pos;
751
0
}
752
753
/* not all fields of format are used.  for example, precision is
754
   unused.  should this take discrete params in order to be more clear
755
   about what it does?  or is passing a single format parameter easier
756
   and more efficient enough to justify a little obfuscation?
757
   Return -1 on error. */
758
static Py_ssize_t
759
calc_number_widths(NumberFieldWidths *spec, Py_ssize_t n_prefix,
760
                   Py_UCS4 sign_char, Py_ssize_t n_start,
761
                   Py_ssize_t n_end, Py_ssize_t n_remainder, Py_ssize_t n_frac,
762
                   int has_decimal, const LocaleInfo *locale,
763
                   const InternalFormatSpec *format, Py_UCS4 *maxchar)
764
64
{
765
64
    Py_ssize_t n_non_digit_non_padding;
766
64
    Py_ssize_t n_padding;
767
768
64
    spec->n_digits = n_end - n_start - n_frac - n_remainder - (has_decimal?1:0);
769
64
    spec->n_lpadding = 0;
770
64
    spec->n_prefix = n_prefix;
771
64
    spec->n_decimal = has_decimal ? PyUnicode_GET_LENGTH(locale->decimal_point) : 0;
772
64
    spec->n_remainder = n_remainder;
773
64
    spec->n_frac = n_frac;
774
64
    spec->n_spadding = 0;
775
64
    spec->n_rpadding = 0;
776
64
    spec->sign = '\0';
777
64
    spec->n_sign = 0;
778
779
    /* the output will look like:
780
       |                                                                                         |
781
       | <lpadding> <sign> <prefix> <spadding> <grouped_digits> <decimal> <remainder> <rpadding> |
782
       |                                                                                         |
783
784
       sign is computed from format->sign and the actual
785
       sign of the number
786
787
       prefix is given (it's for the '0x' prefix)
788
789
       digits is already known
790
791
       the total width is either given, or computed from the
792
       actual digits
793
794
       only one of lpadding, spadding, and rpadding can be non-zero,
795
       and it's calculated from the width and other fields
796
    */
797
798
    /* compute the various parts we're going to write */
799
64
    switch (format->sign) {
800
0
    case '+':
801
        /* always put a + or - */
802
0
        spec->n_sign = 1;
803
0
        spec->sign = (sign_char == '-' ? '-' : '+');
804
0
        break;
805
0
    case ' ':
806
0
        spec->n_sign = 1;
807
0
        spec->sign = (sign_char == '-' ? '-' : ' ');
808
0
        break;
809
64
    default:
810
        /* Not specified, or the default (-) */
811
64
        if (sign_char == '-') {
812
0
            spec->n_sign = 1;
813
0
            spec->sign = '-';
814
0
        }
815
64
    }
816
817
64
    if (spec->n_frac == 0) {
818
64
        spec->n_grouped_frac_digits = 0;
819
64
    }
820
0
    else {
821
0
        Py_UCS4 grouping_maxchar;
822
0
        spec->n_grouped_frac_digits = _PyUnicode_InsertThousandsGrouping(
823
0
            NULL, 0,
824
0
            NULL, 0, spec->n_frac,
825
0
            spec->n_frac,
826
0
            locale->grouping, locale->frac_thousands_sep, &grouping_maxchar, 1);
827
0
        if (spec->n_grouped_frac_digits == -1) {
828
0
            return -1;
829
0
        }
830
0
        *maxchar = Py_MAX(*maxchar, grouping_maxchar);
831
0
    }
832
833
    /* The number of chars used for non-digits and non-padding. */
834
64
    n_non_digit_non_padding = spec->n_sign + spec->n_prefix + spec->n_decimal +
835
64
        + spec->n_frac + spec->n_remainder;
836
837
    /* min_width can go negative, that's okay. format->width == -1 means
838
       we don't care. */
839
64
    if (format->fill_char == '0' && format->align == '=')
840
64
        spec->n_min_width = (format->width - n_non_digit_non_padding
841
64
                             + spec->n_frac - spec->n_grouped_frac_digits);
842
0
    else
843
0
        spec->n_min_width = 0;
844
845
64
    if (spec->n_digits == 0)
846
        /* This case only occurs when using 'c' formatting, we need
847
           to special case it because the grouping code always wants
848
           to have at least one character. */
849
0
        spec->n_grouped_digits = 0;
850
64
    else {
851
64
        Py_UCS4 grouping_maxchar;
852
64
        spec->n_grouped_digits = _PyUnicode_InsertThousandsGrouping(
853
64
            NULL, 0,
854
64
            NULL, 0, spec->n_digits,
855
64
            spec->n_min_width,
856
64
            locale->grouping, locale->thousands_sep, &grouping_maxchar, 0);
857
64
        if (spec->n_grouped_digits == -1) {
858
0
            return -1;
859
0
        }
860
64
        *maxchar = Py_MAX(*maxchar, grouping_maxchar);
861
64
    }
862
863
    /* Given the desired width and the total of digit and non-digit
864
       space we consume, see if we need any padding. format->width can
865
       be negative (meaning no padding), but this code still works in
866
       that case. */
867
64
    n_padding = format->width -
868
64
                        (n_non_digit_non_padding + spec->n_grouped_digits
869
64
                         + spec->n_grouped_frac_digits - spec->n_frac);
870
64
    if (n_padding > 0) {
871
        /* Some padding is needed. Determine if it's left, space, or right. */
872
0
        switch (format->align) {
873
0
        case '<':
874
0
            spec->n_rpadding = n_padding;
875
0
            break;
876
0
        case '^':
877
0
            spec->n_lpadding = n_padding / 2;
878
0
            spec->n_rpadding = n_padding - spec->n_lpadding;
879
0
            break;
880
0
        case '=':
881
0
            spec->n_spadding = n_padding;
882
0
            break;
883
0
        case '>':
884
0
            spec->n_lpadding = n_padding;
885
0
            break;
886
0
        default:
887
            /* Shouldn't get here */
888
0
            Py_UNREACHABLE();
889
0
        }
890
0
    }
891
892
64
    if (spec->n_lpadding || spec->n_spadding || spec->n_rpadding)
893
0
        *maxchar = Py_MAX(*maxchar, format->fill_char);
894
895
64
    if (spec->n_decimal)
896
0
        *maxchar = Py_MAX(*maxchar, PyUnicode_MAX_CHAR_VALUE(locale->decimal_point));
897
898
64
    return spec->n_lpadding + spec->n_sign + spec->n_prefix +
899
64
        spec->n_spadding + spec->n_grouped_digits + spec->n_decimal +
900
64
        spec->n_grouped_frac_digits + spec->n_remainder + spec->n_rpadding;
901
64
}
902
903
/* Fill in the digit parts of a number's string representation,
904
   as determined in calc_number_widths().
905
   Return -1 on error, or 0 on success. */
906
static int
907
fill_number(_PyUnicodeWriter *writer, const NumberFieldWidths *spec,
908
            PyObject *digits, Py_ssize_t d_start,
909
            PyObject *prefix, Py_ssize_t p_start,
910
            Py_UCS4 fill_char,
911
            LocaleInfo *locale, int toupper)
912
64
{
913
    /* Used to keep track of digits, decimal, and remainder. */
914
64
    Py_ssize_t d_pos = d_start;
915
64
    const int kind = writer->kind;
916
64
    const void *data = writer->data;
917
64
    Py_ssize_t r;
918
919
64
    if (spec->n_lpadding) {
920
0
        _PyUnicode_FastFill(writer->buffer,
921
0
                            writer->pos, spec->n_lpadding, fill_char);
922
0
        writer->pos += spec->n_lpadding;
923
0
    }
924
64
    if (spec->n_sign == 1) {
925
0
        PyUnicode_WRITE(kind, data, writer->pos, spec->sign);
926
0
        writer->pos++;
927
0
    }
928
64
    if (spec->n_prefix) {
929
0
        _PyUnicode_FastCopyCharacters(writer->buffer, writer->pos,
930
0
                                      prefix, p_start,
931
0
                                      spec->n_prefix);
932
0
        if (toupper) {
933
0
            Py_ssize_t t;
934
0
            for (t = 0; t < spec->n_prefix; t++) {
935
0
                Py_UCS4 c = PyUnicode_READ(kind, data, writer->pos + t);
936
0
                c = Py_TOUPPER(c);
937
0
                assert (c <= 127);
938
0
                PyUnicode_WRITE(kind, data, writer->pos + t, c);
939
0
            }
940
0
        }
941
0
        writer->pos += spec->n_prefix;
942
0
    }
943
64
    if (spec->n_spadding) {
944
0
        _PyUnicode_FastFill(writer->buffer,
945
0
                            writer->pos, spec->n_spadding, fill_char);
946
0
        writer->pos += spec->n_spadding;
947
0
    }
948
949
    /* Only for type 'c' special case, it has no digits. */
950
64
    if (spec->n_digits != 0) {
951
        /* Fill the digits with InsertThousandsGrouping. */
952
64
        r = _PyUnicode_InsertThousandsGrouping(
953
64
                writer, spec->n_grouped_digits,
954
64
                digits, d_pos, spec->n_digits,
955
64
                spec->n_min_width,
956
64
                locale->grouping, locale->thousands_sep, NULL, 0);
957
64
        if (r == -1)
958
0
            return -1;
959
64
        assert(r == spec->n_grouped_digits);
960
64
        d_pos += spec->n_digits;
961
64
    }
962
64
    if (toupper) {
963
0
        Py_ssize_t t;
964
0
        for (t = 0; t < spec->n_grouped_digits; t++) {
965
0
            Py_UCS4 c = PyUnicode_READ(kind, data, writer->pos + t);
966
0
            c = Py_TOUPPER(c);
967
0
            if (c > 127) {
968
0
                PyErr_SetString(PyExc_SystemError, "non-ascii grouped digit");
969
0
                return -1;
970
0
            }
971
0
            PyUnicode_WRITE(kind, data, writer->pos + t, c);
972
0
        }
973
0
    }
974
64
    writer->pos += spec->n_grouped_digits;
975
976
64
    if (spec->n_decimal) {
977
0
        _PyUnicode_FastCopyCharacters(
978
0
            writer->buffer, writer->pos,
979
0
            locale->decimal_point, 0, spec->n_decimal);
980
0
        writer->pos += spec->n_decimal;
981
0
        d_pos += 1;
982
0
    }
983
984
64
    if (spec->n_frac) {
985
0
        r = _PyUnicode_InsertThousandsGrouping(
986
0
                writer, spec->n_grouped_frac_digits,
987
0
                digits, d_pos, spec->n_frac, spec->n_frac,
988
0
                locale->grouping, locale->frac_thousands_sep, NULL, 1);
989
0
        if (r == -1) {
990
0
            return -1;
991
0
        }
992
0
        assert(r == spec->n_grouped_frac_digits);
993
0
        d_pos += spec->n_frac;
994
0
        writer->pos += spec->n_grouped_frac_digits;
995
0
    }
996
997
64
    if (spec->n_remainder) {
998
0
        _PyUnicode_FastCopyCharacters(
999
0
            writer->buffer, writer->pos,
1000
0
            digits, d_pos, spec->n_remainder);
1001
0
        writer->pos += spec->n_remainder;
1002
        /* d_pos += spec->n_remainder; */
1003
0
    }
1004
1005
64
    if (spec->n_rpadding) {
1006
0
        _PyUnicode_FastFill(writer->buffer,
1007
0
                            writer->pos, spec->n_rpadding,
1008
0
                            fill_char);
1009
0
        writer->pos += spec->n_rpadding;
1010
0
    }
1011
64
    return 0;
1012
64
}
1013
1014
static const char no_grouping[1] = {CHAR_MAX};
1015
1016
/* Find the decimal point character(s?), thousands_separator(s?), and
1017
   grouping description, either for the current locale if type is
1018
   LT_CURRENT_LOCALE, a hard-coded locale if LT_DEFAULT_LOCALE or
1019
   LT_UNDERSCORE_LOCALE/LT_UNDER_FOUR_LOCALE, or none if LT_NO_LOCALE. */
1020
static int
1021
get_locale_info(enum LocaleType type, enum LocaleType frac_type,
1022
                LocaleInfo *locale_info)
1023
64
{
1024
64
    switch (type) {
1025
0
    case LT_CURRENT_LOCALE: {
1026
0
        struct lconv *lc = localeconv();
1027
0
        if (_Py_GetLocaleconvNumeric(lc,
1028
0
                                     &locale_info->decimal_point,
1029
0
                                     &locale_info->thousands_sep) < 0) {
1030
0
            return -1;
1031
0
        }
1032
1033
        /* localeconv() grouping can become a dangling pointer or point
1034
           to a different string if another thread calls localeconv() during
1035
           the string formatting. Copy the string to avoid this risk. */
1036
0
        locale_info->grouping_buffer = _PyMem_Strdup(lc->grouping);
1037
0
        if (locale_info->grouping_buffer == NULL) {
1038
0
            PyErr_NoMemory();
1039
0
            return -1;
1040
0
        }
1041
0
        locale_info->grouping = locale_info->grouping_buffer;
1042
0
        break;
1043
0
    }
1044
0
    case LT_DEFAULT_LOCALE:
1045
0
    case LT_UNDERSCORE_LOCALE:
1046
0
    case LT_UNDER_FOUR_LOCALE:
1047
0
        locale_info->decimal_point = PyUnicode_FromOrdinal('.');
1048
0
        locale_info->thousands_sep = PyUnicode_FromOrdinal(
1049
0
            type == LT_DEFAULT_LOCALE ? ',' : '_');
1050
0
        if (!locale_info->decimal_point || !locale_info->thousands_sep)
1051
0
            return -1;
1052
0
        if (type != LT_UNDER_FOUR_LOCALE)
1053
0
            locale_info->grouping = "\3"; /* Group every 3 characters.  The
1054
                                         (implicit) trailing 0 means repeat
1055
                                         infinitely. */
1056
0
        else
1057
0
            locale_info->grouping = "\4"; /* Bin/oct/hex group every four. */
1058
0
        break;
1059
64
    case LT_NO_LOCALE:
1060
64
        locale_info->decimal_point = PyUnicode_FromOrdinal('.');
1061
64
        locale_info->thousands_sep = Py_GetConstant(Py_CONSTANT_EMPTY_STR);
1062
64
        if (!locale_info->decimal_point || !locale_info->thousands_sep)
1063
0
            return -1;
1064
64
        locale_info->grouping = no_grouping;
1065
64
        break;
1066
64
    }
1067
64
    if (frac_type != LT_NO_LOCALE) {
1068
0
        locale_info->frac_thousands_sep = PyUnicode_FromOrdinal(
1069
0
            frac_type == LT_DEFAULT_LOCALE ? ',' : '_');
1070
0
        if (!locale_info->frac_thousands_sep) {
1071
0
            return -1;
1072
0
        }
1073
0
        if (locale_info->grouping == no_grouping) {
1074
0
            locale_info->grouping = "\3";
1075
0
        }
1076
0
    }
1077
64
    else {
1078
64
        locale_info->frac_thousands_sep = Py_GetConstant(Py_CONSTANT_EMPTY_STR);
1079
64
    }
1080
64
    return 0;
1081
64
}
1082
1083
static void
1084
free_locale_info(LocaleInfo *locale_info)
1085
64
{
1086
64
    Py_XDECREF(locale_info->decimal_point);
1087
64
    Py_XDECREF(locale_info->thousands_sep);
1088
64
    Py_XDECREF(locale_info->frac_thousands_sep);
1089
64
    PyMem_Free(locale_info->grouping_buffer);
1090
64
}
1091
1092
/************************************************************************/
1093
/*********** string formatting ******************************************/
1094
/************************************************************************/
1095
1096
static int
1097
format_string_internal(PyObject *value, const InternalFormatSpec *format,
1098
                       _PyUnicodeWriter *writer)
1099
0
{
1100
0
    Py_ssize_t lpad;
1101
0
    Py_ssize_t rpad;
1102
0
    Py_ssize_t total;
1103
0
    Py_ssize_t len;
1104
0
    int result = -1;
1105
0
    Py_UCS4 maxchar;
1106
1107
0
    len = PyUnicode_GET_LENGTH(value);
1108
1109
    /* sign is not allowed on strings */
1110
0
    if (format->sign != '\0') {
1111
0
        if (format->sign == ' ') {
1112
0
            PyErr_SetString(PyExc_ValueError,
1113
0
                "Space not allowed in string format specifier");
1114
0
        }
1115
0
        else {
1116
0
            PyErr_SetString(PyExc_ValueError,
1117
0
                "Sign not allowed in string format specifier");
1118
0
        }
1119
0
        goto done;
1120
0
    }
1121
1122
    /* negative 0 coercion is not allowed on strings */
1123
0
    if (format->no_neg_0) {
1124
0
        PyErr_SetString(PyExc_ValueError,
1125
0
                        "Negative zero coercion (z) not allowed in string format "
1126
0
                        "specifier");
1127
0
        goto done;
1128
0
    }
1129
1130
    /* alternate is not allowed on strings */
1131
0
    if (format->alternate) {
1132
0
        PyErr_SetString(PyExc_ValueError,
1133
0
                        "Alternate form (#) not allowed in string format "
1134
0
                        "specifier");
1135
0
        goto done;
1136
0
    }
1137
1138
    /* '=' alignment not allowed on strings */
1139
0
    if (format->align == '=') {
1140
0
        PyErr_SetString(PyExc_ValueError,
1141
0
                        "'=' alignment not allowed "
1142
0
                        "in string format specifier");
1143
0
        goto done;
1144
0
    }
1145
1146
0
    if ((format->width == -1 || format->width <= len)
1147
0
        && (format->precision == -1 || format->precision >= len)) {
1148
        /* Fast path */
1149
0
        return _PyUnicodeWriter_WriteStr(writer, value);
1150
0
    }
1151
1152
    /* if precision is specified, output no more that format.precision
1153
       characters */
1154
0
    if (format->precision >= 0 && len >= format->precision) {
1155
0
        len = format->precision;
1156
0
    }
1157
1158
0
    calc_padding(len, format->width, format->align, &lpad, &rpad, &total);
1159
1160
0
    maxchar = writer->maxchar;
1161
0
    if (lpad != 0 || rpad != 0)
1162
0
        maxchar = Py_MAX(maxchar, format->fill_char);
1163
0
    if (PyUnicode_MAX_CHAR_VALUE(value) > maxchar) {
1164
0
        Py_UCS4 valmaxchar = _PyUnicode_FindMaxChar(value, 0, len);
1165
0
        maxchar = Py_MAX(maxchar, valmaxchar);
1166
0
    }
1167
1168
    /* allocate the resulting string */
1169
0
    if (_PyUnicodeWriter_Prepare(writer, total, maxchar) == -1)
1170
0
        goto done;
1171
1172
    /* Write into that space. First the padding. */
1173
0
    result = fill_padding(writer, len, format->fill_char, lpad, rpad);
1174
0
    if (result == -1)
1175
0
        goto done;
1176
1177
    /* Then the source string. */
1178
0
    if (len) {
1179
0
        _PyUnicode_FastCopyCharacters(writer->buffer, writer->pos,
1180
0
                                      value, 0, len);
1181
0
    }
1182
0
    writer->pos += (len + rpad);
1183
0
    result = 0;
1184
1185
0
done:
1186
0
    return result;
1187
0
}
1188
1189
1190
/************************************************************************/
1191
/*********** long formatting ********************************************/
1192
/************************************************************************/
1193
1194
static int
1195
format_long_internal(PyObject *value, const InternalFormatSpec *format,
1196
                     _PyUnicodeWriter *writer)
1197
412
{
1198
412
    int result = -1;
1199
412
    Py_UCS4 maxchar = 127;
1200
412
    PyObject *tmp = NULL;
1201
412
    Py_ssize_t inumeric_chars;
1202
412
    Py_UCS4 sign_char = '\0';
1203
412
    Py_ssize_t n_digits;       /* count of digits need from the computed
1204
                                  string */
1205
412
    Py_ssize_t n_remainder = 0; /* Used only for 'c' formatting, which
1206
                                   produces non-digits */
1207
412
    Py_ssize_t n_prefix = 0;   /* Count of prefix chars, (e.g., '0x') */
1208
412
    Py_ssize_t n_total;
1209
412
    Py_ssize_t prefix = 0;
1210
412
    NumberFieldWidths spec;
1211
412
    long x;
1212
1213
    /* Locale settings, either from the actual locale or
1214
       from a hard-code pseudo-locale */
1215
412
    LocaleInfo locale = LocaleInfo_STATIC_INIT;
1216
1217
    /* no precision allowed on integers */
1218
412
    if (format->precision != -1) {
1219
0
        PyErr_SetString(PyExc_ValueError,
1220
0
                        "Precision not allowed in integer format specifier");
1221
0
        goto done;
1222
0
    }
1223
    /* no negative zero coercion on integers */
1224
412
    if (format->no_neg_0) {
1225
0
        PyErr_SetString(PyExc_ValueError,
1226
0
                        "Negative zero coercion (z) not allowed in integer"
1227
0
                        " format specifier");
1228
0
        goto done;
1229
0
    }
1230
1231
    /* special case for character formatting */
1232
412
    if (format->type == 'c') {
1233
        /* error to specify a sign */
1234
0
        if (format->sign != '\0') {
1235
0
            PyErr_SetString(PyExc_ValueError,
1236
0
                            "Sign not allowed with integer"
1237
0
                            " format specifier 'c'");
1238
0
            goto done;
1239
0
        }
1240
        /* error to request alternate format */
1241
0
        if (format->alternate) {
1242
0
            PyErr_SetString(PyExc_ValueError,
1243
0
                            "Alternate form (#) not allowed with integer"
1244
0
                            " format specifier 'c'");
1245
0
            goto done;
1246
0
        }
1247
1248
        /* taken from unicodeobject.c formatchar() */
1249
        /* Integer input truncated to a character */
1250
0
        x = PyLong_AsLong(value);
1251
0
        if (x == -1 && PyErr_Occurred())
1252
0
            goto done;
1253
0
        if (x < 0 || x > 0x10ffff) {
1254
0
            PyErr_SetString(PyExc_OverflowError,
1255
0
                            "%c arg not in range(0x110000)");
1256
0
            goto done;
1257
0
        }
1258
0
        tmp = PyUnicode_FromOrdinal(x);
1259
0
        inumeric_chars = 0;
1260
0
        n_digits = 1;
1261
0
        maxchar = Py_MAX(maxchar, (Py_UCS4)x);
1262
1263
        /* As a sort-of hack, we tell calc_number_widths that we only
1264
           have "remainder" characters. calc_number_widths thinks
1265
           these are characters that don't get formatted, only copied
1266
           into the output string. We do this for 'c' formatting,
1267
           because the characters are likely to be non-digits. */
1268
0
        n_remainder = 1;
1269
0
    }
1270
412
    else {
1271
412
        int base;
1272
412
        int leading_chars_to_skip = 0;  /* Number of characters added by
1273
                                           PyNumber_ToBase that we want to
1274
                                           skip over. */
1275
1276
        /* Compute the base and how many characters will be added by
1277
           PyNumber_ToBase */
1278
412
        switch (format->type) {
1279
0
        case 'b':
1280
0
            base = 2;
1281
0
            leading_chars_to_skip = 2; /* 0b */
1282
0
            break;
1283
0
        case 'o':
1284
0
            base = 8;
1285
0
            leading_chars_to_skip = 2; /* 0o */
1286
0
            break;
1287
412
        case 'x':
1288
412
        case 'X':
1289
412
            base = 16;
1290
412
            leading_chars_to_skip = 2; /* 0x */
1291
412
            break;
1292
0
        default:  /* shouldn't be needed, but stops a compiler warning */
1293
0
        case 'd':
1294
0
        case 'n':
1295
0
            base = 10;
1296
0
            break;
1297
412
        }
1298
1299
412
        if (format->sign != '+' && format->sign != ' '
1300
412
            && format->width == -1
1301
348
            && format->type != 'X' && format->type != 'n'
1302
348
            && !format->thousands_separators
1303
348
            && PyLong_CheckExact(value))
1304
348
        {
1305
            /* Fast path */
1306
348
            return _PyLong_FormatWriter(writer, value, base, format->alternate);
1307
348
        }
1308
1309
        /* The number of prefix chars is the same as the leading
1310
           chars to skip */
1311
64
        if (format->alternate)
1312
0
            n_prefix = leading_chars_to_skip;
1313
1314
        /* Do the hard part, converting to a string in a given base */
1315
64
        tmp = _PyLong_Format(value, base);
1316
64
        if (tmp == NULL)
1317
0
            goto done;
1318
1319
64
        inumeric_chars = 0;
1320
64
        n_digits = PyUnicode_GET_LENGTH(tmp);
1321
1322
64
        prefix = inumeric_chars;
1323
1324
        /* Is a sign character present in the output?  If so, remember it
1325
           and skip it */
1326
64
        if (PyUnicode_READ_CHAR(tmp, inumeric_chars) == '-') {
1327
0
            sign_char = '-';
1328
0
            ++prefix;
1329
0
            ++leading_chars_to_skip;
1330
0
        }
1331
1332
        /* Skip over the leading chars (0x, 0b, etc.) */
1333
64
        n_digits -= leading_chars_to_skip;
1334
64
        inumeric_chars += leading_chars_to_skip;
1335
64
    }
1336
1337
    /* Determine the grouping, separator, and decimal point, if any. */
1338
64
    if (get_locale_info(format->type == 'n' ? LT_CURRENT_LOCALE :
1339
64
                        format->thousands_separators, 0,
1340
64
                        &locale) == -1)
1341
0
        goto done;
1342
1343
    /* Calculate how much memory we'll need. */
1344
64
    n_total = calc_number_widths(&spec, n_prefix, sign_char, inumeric_chars,
1345
64
                                 inumeric_chars + n_digits, n_remainder, 0, 0,
1346
64
                                 &locale, format, &maxchar);
1347
64
    if (n_total == -1) {
1348
0
        goto done;
1349
0
    }
1350
1351
    /* Allocate the memory. */
1352
64
    if (_PyUnicodeWriter_Prepare(writer, n_total, maxchar) == -1)
1353
0
        goto done;
1354
1355
    /* Populate the memory. */
1356
64
    result = fill_number(writer, &spec,
1357
64
                         tmp, inumeric_chars,
1358
64
                         tmp, prefix, format->fill_char,
1359
64
                         &locale, format->type == 'X');
1360
1361
64
done:
1362
64
    Py_XDECREF(tmp);
1363
64
    free_locale_info(&locale);
1364
64
    return result;
1365
64
}
1366
1367
/************************************************************************/
1368
/*********** float formatting *******************************************/
1369
/************************************************************************/
1370
1371
/* much of this is taken from unicodeobject.c */
1372
static int
1373
format_float_internal(PyObject *value,
1374
                      const InternalFormatSpec *format,
1375
                      _PyUnicodeWriter *writer)
1376
0
{
1377
0
    char *buf = NULL;       /* buffer returned from PyOS_double_to_string */
1378
0
    Py_ssize_t n_digits;
1379
0
    Py_ssize_t n_remainder;
1380
0
    Py_ssize_t n_frac;
1381
0
    Py_ssize_t n_total;
1382
0
    int has_decimal;
1383
0
    double val;
1384
0
    int precision, default_precision = 6;
1385
0
    Py_UCS4 type = format->type;
1386
0
    int add_pct = 0;
1387
0
    Py_ssize_t index;
1388
0
    NumberFieldWidths spec;
1389
0
    int flags = 0;
1390
0
    int result = -1;
1391
0
    Py_UCS4 maxchar = 127;
1392
0
    Py_UCS4 sign_char = '\0';
1393
0
    int float_type; /* Used to see if we have a nan, inf, or regular float. */
1394
0
    PyObject *unicode_tmp = NULL;
1395
1396
    /* Locale settings, either from the actual locale or
1397
       from a hard-code pseudo-locale */
1398
0
    LocaleInfo locale = LocaleInfo_STATIC_INIT;
1399
1400
0
    if (format->precision > INT_MAX) {
1401
0
        PyErr_SetString(PyExc_ValueError, "precision too big");
1402
0
        goto done;
1403
0
    }
1404
0
    precision = (int)format->precision;
1405
1406
0
    if (format->alternate)
1407
0
        flags |= Py_DTSF_ALT;
1408
0
    if (format->no_neg_0)
1409
0
        flags |= Py_DTSF_NO_NEG_0;
1410
1411
0
    if (type == '\0') {
1412
        /* Omitted type specifier.  Behaves in the same way as repr(x)
1413
           and str(x) if no precision is given, else like 'g', but with
1414
           at least one digit after the decimal point. */
1415
0
        flags |= Py_DTSF_ADD_DOT_0;
1416
0
        type = 'r';
1417
0
        default_precision = 0;
1418
0
    }
1419
1420
0
    if (type == 'n')
1421
        /* 'n' is the same as 'g', except for the locale used to
1422
           format the result. We take care of that later. */
1423
0
        type = 'g';
1424
1425
0
    val = PyFloat_AsDouble(value);
1426
0
    if (val == -1.0 && PyErr_Occurred())
1427
0
        goto done;
1428
1429
0
    if (type == '%') {
1430
0
        type = 'f';
1431
0
        val *= 100;
1432
0
        add_pct = 1;
1433
0
    }
1434
1435
0
    if (precision < 0)
1436
0
        precision = default_precision;
1437
0
    else if (type == 'r')
1438
0
        type = 'g';
1439
1440
    /* Cast "type", because if we're in unicode we need to pass an
1441
       8-bit char. This is safe, because we've restricted what "type"
1442
       can be. */
1443
0
    buf = PyOS_double_to_string(val, (char)type, precision, flags,
1444
0
                                &float_type);
1445
0
    if (buf == NULL)
1446
0
        goto done;
1447
0
    n_digits = strlen(buf);
1448
1449
0
    if (add_pct) {
1450
        /* We know that buf has a trailing zero (since we just called
1451
           strlen() on it), and we don't use that fact any more. So we
1452
           can just write over the trailing zero. */
1453
0
        buf[n_digits] = '%';
1454
0
        n_digits += 1;
1455
0
    }
1456
1457
0
    if (format->sign != '+' && format->sign != ' '
1458
0
        && format->width == -1
1459
0
        && format->type != 'n'
1460
0
        && !format->thousands_separators
1461
0
        && !format->frac_thousands_separator)
1462
0
    {
1463
        /* Fast path */
1464
0
        result = _PyUnicodeWriter_WriteASCIIString(writer, buf, n_digits);
1465
0
        PyMem_Free(buf);
1466
0
        return result;
1467
0
    }
1468
1469
    /* Since there is no unicode version of PyOS_double_to_string,
1470
       just use the 8 bit version and then convert to unicode. */
1471
0
    unicode_tmp = _PyUnicode_FromASCII(buf, n_digits);
1472
0
    PyMem_Free(buf);
1473
0
    if (unicode_tmp == NULL)
1474
0
        goto done;
1475
1476
    /* Is a sign character present in the output?  If so, remember it
1477
       and skip it */
1478
0
    index = 0;
1479
0
    if (PyUnicode_READ_CHAR(unicode_tmp, index) == '-') {
1480
0
        sign_char = '-';
1481
0
        ++index;
1482
0
        --n_digits;
1483
0
    }
1484
1485
    /* Determine if we have any "remainder" (after the digits, might include
1486
       decimal or exponent or both (or neither)) */
1487
0
    parse_number(unicode_tmp, index, index + n_digits,
1488
0
                 &n_remainder, &n_frac, &has_decimal);
1489
1490
    /* Determine the grouping, separator, and decimal point, if any. */
1491
0
    if (get_locale_info(format->type == 'n' ? LT_CURRENT_LOCALE :
1492
0
                        format->thousands_separators,
1493
0
                        format->frac_thousands_separator,
1494
0
                        &locale) == -1)
1495
0
        goto done;
1496
1497
    /* Calculate how much memory we'll need. */
1498
0
    n_total = calc_number_widths(&spec, 0, sign_char, index,
1499
0
                                 index + n_digits, n_remainder, n_frac,
1500
0
                                 has_decimal, &locale, format, &maxchar);
1501
0
    if (n_total == -1) {
1502
0
        goto done;
1503
0
    }
1504
1505
    /* Allocate the memory. */
1506
0
    if (_PyUnicodeWriter_Prepare(writer, n_total, maxchar) == -1)
1507
0
        goto done;
1508
1509
    /* Populate the memory. */
1510
0
    result = fill_number(writer, &spec,
1511
0
                         unicode_tmp, index,
1512
0
                         NULL, 0, format->fill_char,
1513
0
                         &locale, 0);
1514
1515
0
done:
1516
0
    Py_XDECREF(unicode_tmp);
1517
0
    free_locale_info(&locale);
1518
0
    return result;
1519
0
}
1520
1521
/************************************************************************/
1522
/*********** complex formatting *****************************************/
1523
/************************************************************************/
1524
1525
static int
1526
format_complex_internal(PyObject *value,
1527
                        const InternalFormatSpec *format,
1528
                        _PyUnicodeWriter *writer)
1529
0
{
1530
0
    double re;
1531
0
    double im;
1532
0
    char *re_buf = NULL;       /* buffer returned from PyOS_double_to_string */
1533
0
    char *im_buf = NULL;       /* buffer returned from PyOS_double_to_string */
1534
1535
0
    InternalFormatSpec tmp_format = *format;
1536
0
    Py_ssize_t n_re_digits;
1537
0
    Py_ssize_t n_im_digits;
1538
0
    Py_ssize_t n_re_remainder;
1539
0
    Py_ssize_t n_im_remainder;
1540
0
    Py_ssize_t n_re_frac;
1541
0
    Py_ssize_t n_im_frac;
1542
0
    Py_ssize_t n_re_total;
1543
0
    Py_ssize_t n_im_total;
1544
0
    int re_has_decimal;
1545
0
    int im_has_decimal;
1546
0
    int precision, default_precision = 6;
1547
0
    Py_UCS4 type = format->type;
1548
0
    Py_ssize_t i_re;
1549
0
    Py_ssize_t i_im;
1550
0
    NumberFieldWidths re_spec;
1551
0
    NumberFieldWidths im_spec;
1552
0
    int flags = 0;
1553
0
    int result = -1;
1554
0
    Py_UCS4 maxchar = 127;
1555
0
    int rkind;
1556
0
    void *rdata;
1557
0
    Py_UCS4 re_sign_char = '\0';
1558
0
    Py_UCS4 im_sign_char = '\0';
1559
0
    int re_float_type; /* Used to see if we have a nan, inf, or regular float. */
1560
0
    int im_float_type;
1561
0
    int add_parens = 0;
1562
0
    int skip_re = 0;
1563
0
    Py_ssize_t lpad;
1564
0
    Py_ssize_t rpad;
1565
0
    Py_ssize_t total;
1566
0
    PyObject *re_unicode_tmp = NULL;
1567
0
    PyObject *im_unicode_tmp = NULL;
1568
1569
    /* Locale settings, either from the actual locale or
1570
       from a hard-code pseudo-locale */
1571
0
    LocaleInfo locale = LocaleInfo_STATIC_INIT;
1572
1573
0
    if (format->precision > INT_MAX) {
1574
0
        PyErr_SetString(PyExc_ValueError, "precision too big");
1575
0
        goto done;
1576
0
    }
1577
0
    precision = (int)format->precision;
1578
1579
    /* Zero padding is not allowed. */
1580
0
    if (format->fill_char == '0') {
1581
0
        PyErr_SetString(PyExc_ValueError,
1582
0
                        "Zero padding is not allowed in complex format "
1583
0
                        "specifier");
1584
0
        goto done;
1585
0
    }
1586
1587
    /* Neither is '=' alignment . */
1588
0
    if (format->align == '=') {
1589
0
        PyErr_SetString(PyExc_ValueError,
1590
0
                        "'=' alignment flag is not allowed in complex format "
1591
0
                        "specifier");
1592
0
        goto done;
1593
0
    }
1594
1595
0
    re = PyComplex_RealAsDouble(value);
1596
0
    if (re == -1.0 && PyErr_Occurred())
1597
0
        goto done;
1598
0
    im = PyComplex_ImagAsDouble(value);
1599
0
    if (im == -1.0 && PyErr_Occurred())
1600
0
        goto done;
1601
1602
0
    if (format->alternate)
1603
0
        flags |= Py_DTSF_ALT;
1604
0
    if (format->no_neg_0)
1605
0
        flags |= Py_DTSF_NO_NEG_0;
1606
1607
0
    if (type == '\0') {
1608
        /* Omitted type specifier. Should be like str(self). */
1609
0
        type = 'r';
1610
0
        default_precision = 0;
1611
0
        if (re == 0.0 && copysign(1.0, re) == 1.0)
1612
0
            skip_re = 1;
1613
0
        else
1614
0
            add_parens = 1;
1615
0
    }
1616
1617
0
    if (type == 'n')
1618
        /* 'n' is the same as 'g', except for the locale used to
1619
           format the result. We take care of that later. */
1620
0
        type = 'g';
1621
1622
0
    if (precision < 0)
1623
0
        precision = default_precision;
1624
0
    else if (type == 'r')
1625
0
        type = 'g';
1626
1627
    /* Cast "type", because if we're in unicode we need to pass an
1628
       8-bit char. This is safe, because we've restricted what "type"
1629
       can be. */
1630
0
    re_buf = PyOS_double_to_string(re, (char)type, precision, flags,
1631
0
                                   &re_float_type);
1632
0
    if (re_buf == NULL)
1633
0
        goto done;
1634
0
    im_buf = PyOS_double_to_string(im, (char)type, precision, flags,
1635
0
                                   &im_float_type);
1636
0
    if (im_buf == NULL)
1637
0
        goto done;
1638
1639
0
    n_re_digits = strlen(re_buf);
1640
0
    n_im_digits = strlen(im_buf);
1641
1642
    /* Since there is no unicode version of PyOS_double_to_string,
1643
       just use the 8 bit version and then convert to unicode. */
1644
0
    re_unicode_tmp = _PyUnicode_FromASCII(re_buf, n_re_digits);
1645
0
    if (re_unicode_tmp == NULL)
1646
0
        goto done;
1647
0
    i_re = 0;
1648
1649
0
    im_unicode_tmp = _PyUnicode_FromASCII(im_buf, n_im_digits);
1650
0
    if (im_unicode_tmp == NULL)
1651
0
        goto done;
1652
0
    i_im = 0;
1653
1654
    /* Is a sign character present in the output?  If so, remember it
1655
       and skip it */
1656
0
    if (PyUnicode_READ_CHAR(re_unicode_tmp, i_re) == '-') {
1657
0
        re_sign_char = '-';
1658
0
        ++i_re;
1659
0
        --n_re_digits;
1660
0
    }
1661
0
    if (PyUnicode_READ_CHAR(im_unicode_tmp, i_im) == '-') {
1662
0
        im_sign_char = '-';
1663
0
        ++i_im;
1664
0
        --n_im_digits;
1665
0
    }
1666
1667
    /* Determine if we have any "remainder" (after the digits, might include
1668
       decimal or exponent or both (or neither)) */
1669
0
    parse_number(re_unicode_tmp, i_re, i_re + n_re_digits,
1670
0
                 &n_re_remainder, &n_re_frac, &re_has_decimal);
1671
0
    parse_number(im_unicode_tmp, i_im, i_im + n_im_digits,
1672
0
                 &n_im_remainder, &n_im_frac, &im_has_decimal);
1673
1674
    /* Determine the grouping, separator, and decimal point, if any. */
1675
0
    if (get_locale_info(format->type == 'n' ? LT_CURRENT_LOCALE :
1676
0
                        format->thousands_separators,
1677
0
                        format->frac_thousands_separator,
1678
0
                        &locale) == -1)
1679
0
        goto done;
1680
1681
    /* Turn off any padding. We'll do it later after we've composed
1682
       the numbers without padding. */
1683
0
    tmp_format.fill_char = '\0';
1684
0
    tmp_format.align = '<';
1685
0
    tmp_format.width = -1;
1686
1687
    /* Calculate how much memory we'll need. */
1688
0
    n_re_total = calc_number_widths(&re_spec, 0, re_sign_char,
1689
0
                                    i_re, i_re + n_re_digits, n_re_remainder,
1690
0
                                    n_re_frac, re_has_decimal, &locale,
1691
0
                                    &tmp_format, &maxchar);
1692
0
    if (n_re_total == -1) {
1693
0
        goto done;
1694
0
    }
1695
1696
    /* Same formatting, but always include a sign, unless the real part is
1697
     * going to be omitted, in which case we use whatever sign convention was
1698
     * requested by the original format. */
1699
0
    if (!skip_re)
1700
0
        tmp_format.sign = '+';
1701
0
    n_im_total = calc_number_widths(&im_spec, 0, im_sign_char,
1702
0
                                    i_im, i_im + n_im_digits, n_im_remainder,
1703
0
                                    n_im_frac, im_has_decimal, &locale,
1704
0
                                    &tmp_format, &maxchar);
1705
0
    if (n_im_total == -1) {
1706
0
        goto done;
1707
0
    }
1708
1709
0
    if (skip_re)
1710
0
        n_re_total = 0;
1711
1712
    /* Add 1 for the 'j', and optionally 2 for parens. */
1713
0
    calc_padding(n_re_total + n_im_total + 1 + add_parens * 2,
1714
0
                 format->width, format->align, &lpad, &rpad, &total);
1715
1716
0
    if (lpad || rpad)
1717
0
        maxchar = Py_MAX(maxchar, format->fill_char);
1718
1719
0
    if (_PyUnicodeWriter_Prepare(writer, total, maxchar) == -1)
1720
0
        goto done;
1721
0
    rkind = writer->kind;
1722
0
    rdata = writer->data;
1723
1724
    /* Populate the memory. First, the padding. */
1725
0
    result = fill_padding(writer,
1726
0
                          n_re_total + n_im_total + 1 + add_parens * 2,
1727
0
                          format->fill_char, lpad, rpad);
1728
0
    if (result == -1)
1729
0
        goto done;
1730
1731
0
    if (add_parens) {
1732
0
        PyUnicode_WRITE(rkind, rdata, writer->pos, '(');
1733
0
        writer->pos++;
1734
0
    }
1735
1736
0
    if (!skip_re) {
1737
0
        result = fill_number(writer, &re_spec,
1738
0
                             re_unicode_tmp, i_re,
1739
0
                             NULL, 0,
1740
0
                             0,
1741
0
                             &locale, 0);
1742
0
        if (result == -1)
1743
0
            goto done;
1744
0
    }
1745
0
    result = fill_number(writer, &im_spec,
1746
0
                         im_unicode_tmp, i_im,
1747
0
                         NULL, 0,
1748
0
                         0,
1749
0
                         &locale, 0);
1750
0
    if (result == -1)
1751
0
        goto done;
1752
0
    PyUnicode_WRITE(rkind, rdata, writer->pos, 'j');
1753
0
    writer->pos++;
1754
1755
0
    if (add_parens) {
1756
0
        PyUnicode_WRITE(rkind, rdata, writer->pos, ')');
1757
0
        writer->pos++;
1758
0
    }
1759
1760
0
    writer->pos += rpad;
1761
1762
0
done:
1763
0
    PyMem_Free(re_buf);
1764
0
    PyMem_Free(im_buf);
1765
0
    Py_XDECREF(re_unicode_tmp);
1766
0
    Py_XDECREF(im_unicode_tmp);
1767
0
    free_locale_info(&locale);
1768
0
    return result;
1769
0
}
1770
1771
/************************************************************************/
1772
/*********** built in formatters ****************************************/
1773
/************************************************************************/
1774
static int
1775
format_obj(PyObject *obj, _PyUnicodeWriter *writer)
1776
0
{
1777
0
    PyObject *str;
1778
0
    int err;
1779
1780
0
    str = PyObject_Str(obj);
1781
0
    if (str == NULL)
1782
0
        return -1;
1783
0
    err = _PyUnicodeWriter_WriteStr(writer, str);
1784
0
    Py_DECREF(str);
1785
0
    return err;
1786
0
}
1787
1788
int
1789
_PyUnicode_FormatAdvancedWriter(_PyUnicodeWriter *writer,
1790
                                PyObject *obj,
1791
                                PyObject *format_spec,
1792
                                Py_ssize_t start, Py_ssize_t end)
1793
17.3M
{
1794
17.3M
    InternalFormatSpec format;
1795
1796
17.3M
    assert(PyUnicode_Check(obj));
1797
1798
    /* check for the special case of zero length format spec, make
1799
       it equivalent to str(obj) */
1800
17.3M
    if (start == end) {
1801
17.3M
        if (PyUnicode_CheckExact(obj))
1802
17.3M
            return _PyUnicodeWriter_WriteStr(writer, obj);
1803
0
        else
1804
0
            return format_obj(obj, writer);
1805
17.3M
    }
1806
1807
    /* parse the format_spec */
1808
0
    if (!parse_internal_render_format_spec(obj, format_spec, start, end,
1809
0
                                           &format, 's', '<'))
1810
0
        return -1;
1811
1812
    /* type conversion? */
1813
0
    switch (format.type) {
1814
0
    case 's':
1815
        /* no type conversion needed, already a string.  do the formatting */
1816
0
        return format_string_internal(obj, &format, writer);
1817
0
    default:
1818
        /* unknown */
1819
0
        unknown_presentation_type(format.type, Py_TYPE(obj)->tp_name);
1820
0
        return -1;
1821
0
    }
1822
0
}
1823
1824
int
1825
_PyLong_FormatAdvancedWriter(_PyUnicodeWriter *writer,
1826
                             PyObject *obj,
1827
                             PyObject *format_spec,
1828
                             Py_ssize_t start, Py_ssize_t end)
1829
76.6k
{
1830
76.6k
    PyObject *tmp = NULL;
1831
76.6k
    InternalFormatSpec format;
1832
76.6k
    int result = -1;
1833
1834
    /* check for the special case of zero length format spec, make
1835
       it equivalent to str(obj) */
1836
76.6k
    if (start == end) {
1837
76.2k
        if (PyLong_CheckExact(obj))
1838
76.2k
            return _PyLong_FormatWriter(writer, obj, 10, 0);
1839
0
        else
1840
0
            return format_obj(obj, writer);
1841
76.2k
    }
1842
1843
    /* parse the format_spec */
1844
412
    if (!parse_internal_render_format_spec(obj, format_spec, start, end,
1845
412
                                           &format, 'd', '>'))
1846
0
        goto done;
1847
1848
    /* type conversion? */
1849
412
    switch (format.type) {
1850
0
    case 'b':
1851
0
    case 'c':
1852
0
    case 'd':
1853
0
    case 'o':
1854
412
    case 'x':
1855
412
    case 'X':
1856
412
    case 'n':
1857
        /* no type conversion needed, already an int.  do the formatting */
1858
412
        result = format_long_internal(obj, &format, writer);
1859
412
        break;
1860
1861
0
    case 'e':
1862
0
    case 'E':
1863
0
    case 'f':
1864
0
    case 'F':
1865
0
    case 'g':
1866
0
    case 'G':
1867
0
    case '%':
1868
        /* convert to float */
1869
0
        tmp = PyNumber_Float(obj);
1870
0
        if (tmp == NULL)
1871
0
            goto done;
1872
0
        result = format_float_internal(tmp, &format, writer);
1873
0
        break;
1874
1875
0
    default:
1876
        /* unknown */
1877
0
        unknown_presentation_type(format.type, Py_TYPE(obj)->tp_name);
1878
0
        goto done;
1879
412
    }
1880
1881
412
done:
1882
412
    Py_XDECREF(tmp);
1883
412
    return result;
1884
412
}
1885
1886
int
1887
_PyFloat_FormatAdvancedWriter(_PyUnicodeWriter *writer,
1888
                              PyObject *obj,
1889
                              PyObject *format_spec,
1890
                              Py_ssize_t start, Py_ssize_t end)
1891
0
{
1892
0
    InternalFormatSpec format;
1893
1894
    /* check for the special case of zero length format spec, make
1895
       it equivalent to str(obj) */
1896
0
    if (start == end)
1897
0
        return format_obj(obj, writer);
1898
1899
    /* parse the format_spec */
1900
0
    if (!parse_internal_render_format_spec(obj, format_spec, start, end,
1901
0
                                           &format, '\0', '>'))
1902
0
        return -1;
1903
1904
    /* type conversion? */
1905
0
    switch (format.type) {
1906
0
    case '\0': /* No format code: like 'g', but with at least one decimal. */
1907
0
    case 'e':
1908
0
    case 'E':
1909
0
    case 'f':
1910
0
    case 'F':
1911
0
    case 'g':
1912
0
    case 'G':
1913
0
    case 'n':
1914
0
    case '%':
1915
        /* no conversion, already a float.  do the formatting */
1916
0
        return format_float_internal(obj, &format, writer);
1917
1918
0
    default:
1919
        /* unknown */
1920
0
        unknown_presentation_type(format.type, Py_TYPE(obj)->tp_name);
1921
0
        return -1;
1922
0
    }
1923
0
}
1924
1925
int
1926
_PyComplex_FormatAdvancedWriter(_PyUnicodeWriter *writer,
1927
                                PyObject *obj,
1928
                                PyObject *format_spec,
1929
                                Py_ssize_t start, Py_ssize_t end)
1930
0
{
1931
0
    InternalFormatSpec format;
1932
1933
    /* check for the special case of zero length format spec, make
1934
       it equivalent to str(obj) */
1935
0
    if (start == end)
1936
0
        return format_obj(obj, writer);
1937
1938
    /* parse the format_spec */
1939
0
    if (!parse_internal_render_format_spec(obj, format_spec, start, end,
1940
0
                                           &format, '\0', '>'))
1941
0
        return -1;
1942
1943
    /* type conversion? */
1944
0
    switch (format.type) {
1945
0
    case '\0': /* No format code: like 'g', but with at least one decimal. */
1946
0
    case 'e':
1947
0
    case 'E':
1948
0
    case 'f':
1949
0
    case 'F':
1950
0
    case 'g':
1951
0
    case 'G':
1952
0
    case 'n':
1953
        /* no conversion, already a complex.  do the formatting */
1954
0
        return format_complex_internal(obj, &format, writer);
1955
1956
0
    default:
1957
        /* unknown */
1958
0
        unknown_presentation_type(format.type, Py_TYPE(obj)->tp_name);
1959
0
        return -1;
1960
0
    }
1961
0
}