/src/cpython/Objects/unicode_format.c
Line | Count | Source |
1 | | /* |
2 | | |
3 | | Unicode implementation based on original code by Fredrik Lundh, |
4 | | modified by Marc-Andre Lemburg <mal@lemburg.com>. |
5 | | |
6 | | Major speed upgrades to the method implementations at the Reykjavik |
7 | | NeedForSpeed sprint, by Fredrik Lundh and Andrew Dalke. |
8 | | |
9 | | Copyright (c) Corporation for National Research Initiatives. |
10 | | |
11 | | -------------------------------------------------------------------- |
12 | | The original string type implementation is: |
13 | | |
14 | | Copyright (c) 1999 by Secret Labs AB |
15 | | Copyright (c) 1999 by Fredrik Lundh |
16 | | |
17 | | By obtaining, using, and/or copying this software and/or its |
18 | | associated documentation, you agree that you have read, understood, |
19 | | and will comply with the following terms and conditions: |
20 | | |
21 | | Permission to use, copy, modify, and distribute this software and its |
22 | | associated documentation for any purpose and without fee is hereby |
23 | | granted, provided that the above copyright notice appears in all |
24 | | copies, and that both that copyright notice and this permission notice |
25 | | appear in supporting documentation, and that the name of Secret Labs |
26 | | AB or the author not be used in advertising or publicity pertaining to |
27 | | distribution of the software without specific, written prior |
28 | | permission. |
29 | | |
30 | | SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO |
31 | | THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND |
32 | | FITNESS. IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR BE LIABLE FOR |
33 | | ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
34 | | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
35 | | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT |
36 | | OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
37 | | -------------------------------------------------------------------- |
38 | | |
39 | | */ |
40 | | |
41 | | // PyUnicode_Format() implementation |
42 | | |
43 | | #include "Python.h" |
44 | | #include "pycore_abstract.h" // _PyIndex_Check() |
45 | | #include "pycore_format.h" // F_ALT |
46 | | #include "pycore_long.h" // _PyLong_FormatWriter() |
47 | | #include "pycore_object.h" // _PyObject_IsUniquelyReferenced() |
48 | | #include "pycore_unicodeobject.h" // _Py_MAX_UNICODE |
49 | | |
50 | | |
51 | 0 | #define MAX_UNICODE _Py_MAX_UNICODE |
52 | 12.1M | #define ensure_unicode _PyUnicode_EnsureUnicode |
53 | | |
54 | | struct unicode_formatter_t { |
55 | | PyObject *args; |
56 | | int args_owned; |
57 | | Py_ssize_t arglen, argidx; |
58 | | PyObject *dict; |
59 | | |
60 | | int fmtkind; |
61 | | Py_ssize_t fmtcnt, fmtpos; |
62 | | const void *fmtdata; |
63 | | PyObject *fmtstr; |
64 | | |
65 | | _PyUnicodeWriter writer; |
66 | | }; |
67 | | |
68 | | |
69 | | struct unicode_format_arg_t { |
70 | | Py_UCS4 ch; |
71 | | int flags; |
72 | | Py_ssize_t width; |
73 | | int prec; |
74 | | int sign; |
75 | | Py_ssize_t fmtstart; |
76 | | PyObject *key; |
77 | | }; |
78 | | |
79 | | |
80 | | // Use FORMAT_ERROR("...%s", "") when there is no arguments. |
81 | 950k | #define FORMAT_ERROR(EXC, FMT, ...) do { \ |
82 | 950k | if (arg->key != NULL) { \ |
83 | 0 | PyErr_Format((EXC), "format argument %R: " FMT, \ |
84 | 0 | arg->key, __VA_ARGS__); \ |
85 | 0 | } \ |
86 | 950k | else if (ctx->argidx >= 0) { \ |
87 | 0 | PyErr_Format((EXC), "format argument %zd: " FMT, \ |
88 | 0 | ctx->argidx, __VA_ARGS__); \ |
89 | 0 | } \ |
90 | 950k | else { \ |
91 | 950k | PyErr_Format((EXC), "format argument: " FMT, __VA_ARGS__); \ |
92 | 950k | } \ |
93 | 950k | } while (0) |
94 | | |
95 | | |
96 | | static PyObject * |
97 | | unicode_format_getnextarg(struct unicode_formatter_t *ctx, int allowone) |
98 | 21.8M | { |
99 | 21.8M | Py_ssize_t argidx = ctx->argidx; |
100 | | |
101 | 21.8M | if (argidx < ctx->arglen && (allowone || ctx->arglen >= 0)) { |
102 | 21.8M | ctx->argidx++; |
103 | 21.8M | if (ctx->arglen >= 0) { |
104 | 16.0M | return PyTuple_GetItem(ctx->args, argidx); |
105 | 16.0M | } |
106 | 5.84M | else if (allowone) { |
107 | 5.84M | return ctx->args; |
108 | 5.84M | } |
109 | 21.8M | } |
110 | 0 | PyErr_Format(PyExc_TypeError, |
111 | 0 | "not enough arguments for format string (got %zd)", |
112 | 0 | ctx->arglen < 0 ? 1 : ctx->arglen); |
113 | 0 | return NULL; |
114 | 21.8M | } |
115 | | |
116 | | |
117 | | /* Returns a new reference to a PyUnicode object, or NULL on failure. */ |
118 | | |
119 | | /* Format a float into the writer if the writer is not NULL, or into *p_output |
120 | | otherwise. |
121 | | |
122 | | Return 0 on success, raise an exception and return -1 on error. */ |
123 | | static int |
124 | | formatfloat(PyObject *v, |
125 | | struct unicode_formatter_t *ctx, |
126 | | struct unicode_format_arg_t *arg, |
127 | | PyObject **p_output, |
128 | | _PyUnicodeWriter *writer) |
129 | 95 | { |
130 | 95 | char *p; |
131 | 95 | double x; |
132 | 95 | Py_ssize_t len; |
133 | 95 | int prec; |
134 | 95 | int dtoa_flags = 0; |
135 | | |
136 | 95 | x = PyFloat_AsDouble(v); |
137 | 95 | if (x == -1.0 && PyErr_Occurred()) { |
138 | 0 | if (PyErr_ExceptionMatches(PyExc_TypeError)) { |
139 | 0 | FORMAT_ERROR(PyExc_TypeError, |
140 | 0 | "%%%c requires a real number, not %T", |
141 | 0 | arg->ch, v); |
142 | 0 | } |
143 | 0 | return -1; |
144 | 0 | } |
145 | | |
146 | 95 | prec = arg->prec; |
147 | 95 | if (prec < 0) |
148 | 0 | prec = 6; |
149 | | |
150 | 95 | if (arg->flags & F_ALT) |
151 | 0 | dtoa_flags |= Py_DTSF_ALT; |
152 | 95 | p = PyOS_double_to_string(x, arg->ch, prec, dtoa_flags, NULL); |
153 | 95 | if (p == NULL) |
154 | 0 | return -1; |
155 | 95 | len = strlen(p); |
156 | 95 | if (writer) { |
157 | 0 | if (_PyUnicodeWriter_WriteASCIIString(writer, p, len) < 0) { |
158 | 0 | PyMem_Free(p); |
159 | 0 | return -1; |
160 | 0 | } |
161 | 0 | } |
162 | 95 | else { |
163 | 95 | *p_output = _PyUnicode_FromASCII(p, len); |
164 | 95 | if (*p_output == NULL) { |
165 | 0 | PyMem_Free(p); |
166 | 0 | return -1; |
167 | 0 | } |
168 | 95 | } |
169 | 95 | PyMem_Free(p); |
170 | 95 | return 0; |
171 | 95 | } |
172 | | |
173 | | |
174 | | /* formatlong() emulates the format codes d, u, o, x and X, and |
175 | | * the F_ALT flag, for Python's long (unbounded) ints. It's not used for |
176 | | * Python's regular ints. |
177 | | * Return value: a new PyUnicodeObject*, or NULL if error. |
178 | | * The output string is of the form |
179 | | * "-"? ("0x" | "0X")? digit+ |
180 | | * "0x"/"0X" are present only for x and X conversions, with F_ALT |
181 | | * set in flags. The case of hex digits will be correct, |
182 | | * There will be at least prec digits, zero-filled on the left if |
183 | | * necessary to get that many. |
184 | | * val object to be converted |
185 | | * flags bitmask of format flags; only F_ALT is looked at |
186 | | * prec minimum number of digits; 0-fill on left if needed |
187 | | * type a character in [duoxX]; u acts the same as d |
188 | | * |
189 | | * CAUTION: o, x and X conversions on regular ints can never |
190 | | * produce a '-' sign, but can for Python's unbounded ints. |
191 | | */ |
192 | | PyObject * |
193 | | _PyUnicode_FormatLong(PyObject *val, int alt, int prec, int type) |
194 | 5.22M | { |
195 | 5.22M | PyObject *result = NULL; |
196 | 5.22M | char *buf; |
197 | 5.22M | Py_ssize_t i; |
198 | 5.22M | int sign; /* 1 if '-', else 0 */ |
199 | 5.22M | int len; /* number of characters */ |
200 | 5.22M | Py_ssize_t llen; |
201 | 5.22M | int numdigits; /* len == numnondigits + numdigits */ |
202 | 5.22M | int numnondigits = 0; |
203 | | |
204 | | /* Avoid exceeding SSIZE_T_MAX */ |
205 | 5.22M | if (prec > INT_MAX-3) { |
206 | 0 | PyErr_SetString(PyExc_OverflowError, |
207 | 0 | "precision too large"); |
208 | 0 | return NULL; |
209 | 0 | } |
210 | | |
211 | 5.22M | assert(PyLong_Check(val)); |
212 | | |
213 | 5.22M | switch (type) { |
214 | 0 | default: |
215 | 0 | Py_UNREACHABLE(); |
216 | 36 | case 'd': |
217 | 36 | case 'i': |
218 | 36 | case 'u': |
219 | | /* int and int subclasses should print numerically when a numeric */ |
220 | | /* format code is used (see issue18780) */ |
221 | 36 | result = PyNumber_ToBase(val, 10); |
222 | 36 | break; |
223 | 77.5k | case 'o': |
224 | 77.5k | numnondigits = 2; |
225 | 77.5k | result = PyNumber_ToBase(val, 8); |
226 | 77.5k | break; |
227 | 65 | case 'x': |
228 | 5.14M | case 'X': |
229 | 5.14M | numnondigits = 2; |
230 | 5.14M | result = PyNumber_ToBase(val, 16); |
231 | 5.14M | break; |
232 | 5.22M | } |
233 | 5.22M | if (!result) |
234 | 0 | return NULL; |
235 | | |
236 | 5.22M | assert(_PyUnicode_IsModifiable(result)); |
237 | 5.22M | assert(PyUnicode_IS_ASCII(result)); |
238 | | |
239 | | /* To modify the string in-place, there can only be one reference. */ |
240 | 5.22M | if (!_PyObject_IsUniquelyReferenced(result)) { |
241 | 0 | Py_DECREF(result); |
242 | 0 | PyErr_BadInternalCall(); |
243 | 0 | return NULL; |
244 | 0 | } |
245 | 5.22M | buf = PyUnicode_DATA(result); |
246 | 5.22M | llen = PyUnicode_GET_LENGTH(result); |
247 | 5.22M | if (llen > INT_MAX) { |
248 | 0 | Py_DECREF(result); |
249 | 0 | PyErr_SetString(PyExc_ValueError, |
250 | 0 | "string too large in _PyUnicode_FormatLong"); |
251 | 0 | return NULL; |
252 | 0 | } |
253 | 5.22M | len = (int)llen; |
254 | 5.22M | sign = buf[0] == '-'; |
255 | 5.22M | numnondigits += sign; |
256 | 5.22M | numdigits = len - numnondigits; |
257 | 5.22M | assert(numdigits > 0); |
258 | | |
259 | | /* Get rid of base marker unless F_ALT */ |
260 | 5.22M | if (((alt) == 0 && |
261 | 5.22M | (type == 'o' || type == 'x' || type == 'X'))) { |
262 | 5.22M | assert(buf[sign] == '0'); |
263 | 5.22M | assert(buf[sign+1] == 'x' || buf[sign+1] == 'X' || |
264 | 5.22M | buf[sign+1] == 'o'); |
265 | 5.22M | numnondigits -= 2; |
266 | 5.22M | buf += 2; |
267 | 5.22M | len -= 2; |
268 | 5.22M | if (sign) |
269 | 0 | buf[0] = '-'; |
270 | 5.22M | assert(len == numnondigits + numdigits); |
271 | 5.22M | assert(numdigits > 0); |
272 | 5.22M | } |
273 | | |
274 | | /* Fill with leading zeroes to meet minimum width. */ |
275 | 5.22M | if (prec > numdigits) { |
276 | 0 | PyObject *r1 = PyBytes_FromStringAndSize(NULL, |
277 | 0 | numnondigits + prec); |
278 | 0 | char *b1; |
279 | 0 | if (!r1) { |
280 | 0 | Py_DECREF(result); |
281 | 0 | return NULL; |
282 | 0 | } |
283 | 0 | b1 = PyBytes_AS_STRING(r1); |
284 | 0 | for (i = 0; i < numnondigits; ++i) |
285 | 0 | *b1++ = *buf++; |
286 | 0 | for (i = 0; i < prec - numdigits; i++) |
287 | 0 | *b1++ = '0'; |
288 | 0 | for (i = 0; i < numdigits; i++) |
289 | 0 | *b1++ = *buf++; |
290 | 0 | *b1 = '\0'; |
291 | 0 | Py_SETREF(result, r1); |
292 | 0 | buf = PyBytes_AS_STRING(result); |
293 | 0 | len = numnondigits + prec; |
294 | 0 | } |
295 | | |
296 | | /* Fix up case for hex conversions. */ |
297 | 5.22M | if (type == 'X') { |
298 | | /* Need to convert all lower case letters to upper case. |
299 | | and need to convert 0x to 0X (and -0x to -0X). */ |
300 | 35.8M | for (i = 0; i < len; i++) |
301 | 30.7M | if (buf[i] >= 'a' && buf[i] <= 'x') |
302 | 6.56M | buf[i] -= 'a'-'A'; |
303 | 5.14M | } |
304 | 5.22M | if (!PyUnicode_Check(result) |
305 | 5.22M | || buf != PyUnicode_DATA(result)) { |
306 | 5.22M | PyObject *unicode; |
307 | 5.22M | unicode = _PyUnicode_FromASCII(buf, len); |
308 | 5.22M | Py_SETREF(result, unicode); |
309 | 5.22M | } |
310 | 36 | else if (len != PyUnicode_GET_LENGTH(result)) { |
311 | 0 | if (PyUnicode_Resize(&result, len) < 0) |
312 | 0 | Py_CLEAR(result); |
313 | 0 | } |
314 | 5.22M | return result; |
315 | 5.22M | } |
316 | | |
317 | | |
318 | | /* Format an integer or a float as an integer. |
319 | | * Return 1 if the number has been formatted into the writer, |
320 | | * 0 if the number has been formatted into *p_output |
321 | | * -1 and raise an exception on error */ |
322 | | static int |
323 | | mainformatlong(PyObject *v, |
324 | | struct unicode_formatter_t *ctx, |
325 | | struct unicode_format_arg_t *arg, |
326 | | PyObject **p_output, |
327 | | _PyUnicodeWriter *writer) |
328 | 7.68M | { |
329 | 7.68M | PyObject *iobj, *res; |
330 | 7.68M | char type = (char)arg->ch; |
331 | | |
332 | 7.68M | if (!PyNumber_Check(v)) |
333 | 950k | goto wrongtype; |
334 | | |
335 | | /* make sure number is a type of integer for o, x, and X */ |
336 | 6.72M | if (!PyLong_Check(v)) { |
337 | 0 | if (type == 'o' || type == 'x' || type == 'X') { |
338 | 0 | iobj = _PyNumber_Index(v); |
339 | 0 | } |
340 | 0 | else { |
341 | 0 | iobj = PyNumber_Long(v); |
342 | 0 | } |
343 | 0 | if (iobj == NULL ) { |
344 | 0 | if (PyErr_ExceptionMatches(PyExc_TypeError)) |
345 | 0 | goto wrongtype; |
346 | 0 | return -1; |
347 | 0 | } |
348 | 0 | assert(PyLong_Check(iobj)); |
349 | 0 | } |
350 | 6.72M | else { |
351 | 6.72M | iobj = Py_NewRef(v); |
352 | 6.72M | } |
353 | | |
354 | 6.72M | if (PyLong_CheckExact(v) |
355 | 6.72M | && arg->width == -1 && arg->prec == -1 |
356 | 6.64M | && !(arg->flags & (F_SIGN | F_BLANK)) |
357 | 6.64M | && type != 'X') |
358 | 1.50M | { |
359 | | /* Fast path */ |
360 | 1.50M | int alternate = arg->flags & F_ALT; |
361 | 1.50M | int base; |
362 | | |
363 | 1.50M | switch(type) |
364 | 1.50M | { |
365 | 0 | default: |
366 | 0 | Py_UNREACHABLE(); |
367 | 1.50M | case 'd': |
368 | 1.50M | case 'i': |
369 | 1.50M | case 'u': |
370 | 1.50M | base = 10; |
371 | 1.50M | break; |
372 | 0 | case 'o': |
373 | 0 | base = 8; |
374 | 0 | break; |
375 | 44 | case 'x': |
376 | 44 | case 'X': |
377 | 44 | base = 16; |
378 | 44 | break; |
379 | 1.50M | } |
380 | | |
381 | 1.50M | if (_PyLong_FormatWriter(writer, v, base, alternate) == -1) { |
382 | 0 | Py_DECREF(iobj); |
383 | 0 | return -1; |
384 | 0 | } |
385 | 1.50M | Py_DECREF(iobj); |
386 | 1.50M | return 1; |
387 | 1.50M | } |
388 | | |
389 | 5.22M | res = _PyUnicode_FormatLong(iobj, arg->flags & F_ALT, arg->prec, type); |
390 | 5.22M | Py_DECREF(iobj); |
391 | 5.22M | if (res == NULL) |
392 | 0 | return -1; |
393 | 5.22M | *p_output = res; |
394 | 5.22M | return 0; |
395 | | |
396 | 950k | wrongtype: |
397 | 950k | switch(type) |
398 | 950k | { |
399 | 0 | case 'o': |
400 | 0 | case 'x': |
401 | 0 | case 'X': |
402 | 0 | FORMAT_ERROR(PyExc_TypeError, |
403 | 0 | "%%%c requires an integer, not %T", |
404 | 0 | arg->ch, v); |
405 | 0 | break; |
406 | 950k | default: |
407 | 950k | FORMAT_ERROR(PyExc_TypeError, |
408 | 950k | "%%%c requires a real number, not %T", |
409 | 950k | arg->ch, v); |
410 | 950k | break; |
411 | 950k | } |
412 | 950k | return -1; |
413 | 950k | } |
414 | | |
415 | | |
416 | | static Py_UCS4 |
417 | | formatchar(PyObject *v, |
418 | | struct unicode_formatter_t *ctx, |
419 | | struct unicode_format_arg_t *arg) |
420 | 0 | { |
421 | | /* presume that the buffer is at least 3 characters long */ |
422 | 0 | if (PyUnicode_Check(v)) { |
423 | 0 | if (PyUnicode_GET_LENGTH(v) == 1) { |
424 | 0 | return PyUnicode_READ_CHAR(v, 0); |
425 | 0 | } |
426 | 0 | FORMAT_ERROR(PyExc_TypeError, |
427 | 0 | "%%c requires an integer or a unicode character, " |
428 | 0 | "not a string of length %zd", |
429 | 0 | PyUnicode_GET_LENGTH(v)); |
430 | 0 | return (Py_UCS4) -1; |
431 | 0 | } |
432 | 0 | else { |
433 | 0 | int overflow; |
434 | 0 | long x = PyLong_AsLongAndOverflow(v, &overflow); |
435 | 0 | if (x == -1 && PyErr_Occurred()) { |
436 | 0 | if (PyErr_ExceptionMatches(PyExc_TypeError)) { |
437 | 0 | FORMAT_ERROR(PyExc_TypeError, |
438 | 0 | "%%c requires an integer or a unicode character, " |
439 | 0 | "not %T", |
440 | 0 | v); |
441 | 0 | } |
442 | 0 | return (Py_UCS4) -1; |
443 | 0 | } |
444 | | |
445 | 0 | if (x < 0 || x > MAX_UNICODE) { |
446 | | /* this includes an overflow in converting to C long */ |
447 | 0 | FORMAT_ERROR(PyExc_OverflowError, |
448 | 0 | "%%c argument not in range(0x110000)%s", ""); |
449 | 0 | return (Py_UCS4) -1; |
450 | 0 | } |
451 | | |
452 | 0 | return (Py_UCS4) x; |
453 | 0 | } |
454 | 0 | } |
455 | | |
456 | | |
457 | | /* Parse options of an argument: flags, width, precision. |
458 | | Handle also "%(name)" syntax. |
459 | | |
460 | | Return 0 if the argument has been formatted into arg->str. |
461 | | Return 1 if the argument has been written into ctx->writer, |
462 | | Raise an exception and return -1 on error. */ |
463 | | static int |
464 | | unicode_format_arg_parse(struct unicode_formatter_t *ctx, |
465 | | struct unicode_format_arg_t *arg) |
466 | 21.8M | { |
467 | 21.8M | #define FORMAT_READ(ctx) \ |
468 | 22.3M | PyUnicode_READ((ctx)->fmtkind, (ctx)->fmtdata, (ctx)->fmtpos) |
469 | | |
470 | 21.8M | PyObject *v; |
471 | | |
472 | 21.8M | if (arg->ch == '(') { |
473 | | /* Get argument value from a dictionary. Example: "%(name)s". */ |
474 | 51.5k | Py_ssize_t keystart; |
475 | 51.5k | Py_ssize_t keylen; |
476 | 51.5k | int pcount = 1; |
477 | | |
478 | 51.5k | if (ctx->dict == NULL) { |
479 | 0 | PyErr_Format(PyExc_TypeError, |
480 | 0 | "format requires a mapping, not %T", |
481 | 0 | ctx->args); |
482 | 0 | return -1; |
483 | 0 | } |
484 | 51.5k | ++ctx->fmtpos; |
485 | 51.5k | --ctx->fmtcnt; |
486 | 51.5k | keystart = ctx->fmtpos; |
487 | | /* Skip over balanced parentheses */ |
488 | 463k | while (pcount > 0 && --ctx->fmtcnt >= 0) { |
489 | 412k | arg->ch = FORMAT_READ(ctx); |
490 | 412k | if (arg->ch == ')') |
491 | 51.5k | --pcount; |
492 | 360k | else if (arg->ch == '(') |
493 | 0 | ++pcount; |
494 | 412k | ctx->fmtpos++; |
495 | 412k | } |
496 | 51.5k | keylen = ctx->fmtpos - keystart - 1; |
497 | 51.5k | if (ctx->fmtcnt < 0 || pcount > 0) { |
498 | 0 | PyErr_Format(PyExc_ValueError, |
499 | 0 | "stray %% or incomplete format key at position %zd", |
500 | 0 | arg->fmtstart); |
501 | 0 | return -1; |
502 | 0 | } |
503 | 51.5k | arg->key = PyUnicode_Substring(ctx->fmtstr, |
504 | 51.5k | keystart, keystart + keylen); |
505 | 51.5k | if (arg->key == NULL) |
506 | 0 | return -1; |
507 | 51.5k | if (ctx->args_owned) { |
508 | 36.8k | ctx->args_owned = 0; |
509 | 36.8k | Py_DECREF(ctx->args); |
510 | 36.8k | } |
511 | 51.5k | ctx->args = PyObject_GetItem(ctx->dict, arg->key); |
512 | 51.5k | if (ctx->args == NULL) |
513 | 0 | return -1; |
514 | 51.5k | ctx->args_owned = 1; |
515 | 51.5k | ctx->arglen = -3; |
516 | 51.5k | ctx->argidx = -4; |
517 | 51.5k | } |
518 | 21.7M | else { |
519 | 21.7M | if (ctx->arglen < -1) { |
520 | 0 | PyErr_Format(PyExc_ValueError, |
521 | 0 | "format requires a parenthesised mapping key " |
522 | 0 | "at position %zd", |
523 | 0 | arg->fmtstart); |
524 | 0 | return -1; |
525 | 0 | } |
526 | 21.7M | } |
527 | | |
528 | | /* Parse flags. Example: "%+i" => flags=F_SIGN. */ |
529 | 21.8M | while (--ctx->fmtcnt >= 0) { |
530 | 21.8M | arg->ch = FORMAT_READ(ctx); |
531 | 21.8M | ctx->fmtpos++; |
532 | 21.8M | switch (arg->ch) { |
533 | 0 | case '-': arg->flags |= F_LJUST; continue; |
534 | 0 | case '+': arg->flags |= F_SIGN; continue; |
535 | 0 | case ' ': arg->flags |= F_BLANK; continue; |
536 | 44 | case '#': arg->flags |= F_ALT; continue; |
537 | 79.7k | case '0': arg->flags |= F_ZERO; continue; |
538 | 21.8M | } |
539 | 21.8M | break; |
540 | 21.8M | } |
541 | | |
542 | | /* Parse width. Example: "%10s" => width=10 */ |
543 | 21.8M | if (arg->ch == '*') { |
544 | 64.2k | if (ctx->arglen < -1) { |
545 | 0 | PyErr_Format(PyExc_ValueError, |
546 | 0 | "* cannot be used with a parenthesised mapping key " |
547 | 0 | "at position %zd", |
548 | 0 | arg->fmtstart); |
549 | 0 | return -1; |
550 | 0 | } |
551 | 64.2k | v = unicode_format_getnextarg(ctx, 0); |
552 | 64.2k | if (v == NULL) |
553 | 0 | return -1; |
554 | 64.2k | if (!PyLong_Check(v)) { |
555 | 0 | FORMAT_ERROR(PyExc_TypeError, "* requires int, not %T", v); |
556 | 0 | return -1; |
557 | 0 | } |
558 | 64.2k | arg->width = PyLong_AsSsize_t(v); |
559 | 64.2k | if (arg->width == -1 && PyErr_Occurred()) { |
560 | 0 | if (PyErr_ExceptionMatches(PyExc_OverflowError)) { |
561 | 0 | FORMAT_ERROR(PyExc_OverflowError, |
562 | 0 | "too big for width%s", ""); |
563 | 0 | } |
564 | 0 | return -1; |
565 | 0 | } |
566 | 64.2k | if (arg->width < 0) { |
567 | 0 | arg->flags |= F_LJUST; |
568 | 0 | arg->width = -arg->width; |
569 | 0 | } |
570 | 64.2k | if (--ctx->fmtcnt >= 0) { |
571 | 64.2k | arg->ch = FORMAT_READ(ctx); |
572 | 64.2k | ctx->fmtpos++; |
573 | 64.2k | } |
574 | 64.2k | } |
575 | 21.7M | else if (arg->ch >= '0' && arg->ch <= '9') { |
576 | 15.4k | arg->width = arg->ch - '0'; |
577 | 15.4k | while (--ctx->fmtcnt >= 0) { |
578 | 15.4k | arg->ch = FORMAT_READ(ctx); |
579 | 15.4k | ctx->fmtpos++; |
580 | 15.4k | if (arg->ch < '0' || arg->ch > '9') |
581 | 15.4k | break; |
582 | | /* Since arg->ch is unsigned, the RHS would end up as unsigned, |
583 | | mixing signed and unsigned comparison. Since arg->ch is between |
584 | | '0' and '9', casting to int is safe. */ |
585 | 0 | if (arg->width > (PY_SSIZE_T_MAX - ((int)arg->ch - '0')) / 10) { |
586 | 0 | PyErr_Format(PyExc_ValueError, |
587 | 0 | "width too big at position %zd", |
588 | 0 | arg->fmtstart); |
589 | 0 | return -1; |
590 | 0 | } |
591 | 0 | arg->width = arg->width*10 + (arg->ch - '0'); |
592 | 0 | } |
593 | 15.4k | } |
594 | | |
595 | | /* Parse precision. Example: "%.3f" => prec=3 */ |
596 | 21.8M | if (arg->ch == '.') { |
597 | 95 | arg->prec = 0; |
598 | 95 | if (--ctx->fmtcnt >= 0) { |
599 | 95 | arg->ch = FORMAT_READ(ctx); |
600 | 95 | ctx->fmtpos++; |
601 | 95 | } |
602 | 95 | if (arg->ch == '*') { |
603 | 0 | if (ctx->arglen < -1) { |
604 | 0 | PyErr_Format(PyExc_ValueError, |
605 | 0 | "* cannot be used with a parenthesised mapping key " |
606 | 0 | "at position %zd", |
607 | 0 | arg->fmtstart); |
608 | 0 | return -1; |
609 | 0 | } |
610 | 0 | v = unicode_format_getnextarg(ctx, 0); |
611 | 0 | if (v == NULL) |
612 | 0 | return -1; |
613 | 0 | if (!PyLong_Check(v)) { |
614 | 0 | FORMAT_ERROR(PyExc_TypeError, "* requires int, not %T", v); |
615 | 0 | return -1; |
616 | 0 | } |
617 | 0 | arg->prec = PyLong_AsInt(v); |
618 | 0 | if (arg->prec == -1 && PyErr_Occurred()) { |
619 | 0 | if (PyErr_ExceptionMatches(PyExc_OverflowError)) { |
620 | 0 | FORMAT_ERROR(PyExc_OverflowError, |
621 | 0 | "too big for precision%s", ""); |
622 | 0 | } |
623 | 0 | return -1; |
624 | 0 | } |
625 | 0 | if (arg->prec < 0) |
626 | 0 | arg->prec = 0; |
627 | 0 | if (--ctx->fmtcnt >= 0) { |
628 | 0 | arg->ch = FORMAT_READ(ctx); |
629 | 0 | ctx->fmtpos++; |
630 | 0 | } |
631 | 0 | } |
632 | 95 | else if (arg->ch >= '0' && arg->ch <= '9') { |
633 | 95 | arg->prec = arg->ch - '0'; |
634 | 95 | while (--ctx->fmtcnt >= 0) { |
635 | 95 | arg->ch = FORMAT_READ(ctx); |
636 | 95 | ctx->fmtpos++; |
637 | 95 | if (arg->ch < '0' || arg->ch > '9') |
638 | 95 | break; |
639 | 0 | if (arg->prec > (INT_MAX - ((int)arg->ch - '0')) / 10) { |
640 | 0 | PyErr_Format(PyExc_ValueError, |
641 | 0 | "precision too big at position %zd", |
642 | 0 | arg->fmtstart); |
643 | 0 | return -1; |
644 | 0 | } |
645 | 0 | arg->prec = arg->prec*10 + (arg->ch - '0'); |
646 | 0 | } |
647 | 95 | } |
648 | 95 | } |
649 | | |
650 | | /* Ignore "h", "l" and "L" format prefix (ex: "%hi" or "%ls") */ |
651 | 21.8M | if (ctx->fmtcnt >= 0) { |
652 | 21.8M | if (arg->ch == 'h' || arg->ch == 'l' || arg->ch == 'L') { |
653 | 0 | if (--ctx->fmtcnt >= 0) { |
654 | 0 | arg->ch = FORMAT_READ(ctx); |
655 | 0 | ctx->fmtpos++; |
656 | 0 | } |
657 | 0 | } |
658 | 21.8M | } |
659 | 21.8M | if (ctx->fmtcnt < 0) { |
660 | 0 | PyErr_Format(PyExc_ValueError, |
661 | 0 | "stray %% at position %zd", arg->fmtstart); |
662 | 0 | return -1; |
663 | 0 | } |
664 | 21.8M | return 0; |
665 | | |
666 | 21.8M | #undef FORMAT_READ |
667 | 21.8M | } |
668 | | |
669 | | |
670 | | /* Format one argument. Supported conversion specifiers: |
671 | | |
672 | | - "s", "r", "a": any type |
673 | | - "i", "d", "u": int or float |
674 | | - "o", "x", "X": int |
675 | | - "e", "E", "f", "F", "g", "G": float |
676 | | - "c": int or str (1 character) |
677 | | |
678 | | When possible, the output is written directly into the Unicode writer |
679 | | (ctx->writer). A string is created when padding is required. |
680 | | |
681 | | Return 0 if the argument has been formatted into *p_str, |
682 | | 1 if the argument has been written into ctx->writer, |
683 | | -1 on error. */ |
684 | | static int |
685 | | unicode_format_arg_format(struct unicode_formatter_t *ctx, |
686 | | struct unicode_format_arg_t *arg, |
687 | | PyObject **p_str) |
688 | 21.8M | { |
689 | 21.8M | PyObject *v; |
690 | 21.8M | _PyUnicodeWriter *writer = &ctx->writer; |
691 | | |
692 | 21.8M | if (ctx->fmtcnt == 0) |
693 | 7.57M | ctx->writer.overallocate = 0; |
694 | | |
695 | 21.8M | v = unicode_format_getnextarg(ctx, 1); |
696 | 21.8M | if (v == NULL) |
697 | 0 | return -1; |
698 | | |
699 | | |
700 | 21.8M | switch (arg->ch) { |
701 | 14.1M | case 's': |
702 | 14.1M | case 'r': |
703 | 14.1M | case 'a': |
704 | 14.1M | if (PyLong_CheckExact(v) && arg->width == -1 && arg->prec == -1) { |
705 | | /* Fast path */ |
706 | 169 | if (_PyLong_FormatWriter(writer, v, 10, arg->flags & F_ALT) == -1) |
707 | 0 | return -1; |
708 | 169 | return 1; |
709 | 169 | } |
710 | | |
711 | 14.1M | if (PyUnicode_CheckExact(v) && arg->ch == 's') { |
712 | 8.97M | *p_str = Py_NewRef(v); |
713 | 8.97M | } |
714 | 5.14M | else { |
715 | 5.14M | if (arg->ch == 's') |
716 | 5.14M | *p_str = PyObject_Str(v); |
717 | 6.63k | else if (arg->ch == 'r') |
718 | 6.63k | *p_str = PyObject_Repr(v); |
719 | 0 | else |
720 | 0 | *p_str = PyObject_ASCII(v); |
721 | 5.14M | } |
722 | 14.1M | break; |
723 | | |
724 | 0 | case 'i': |
725 | 2.45M | case 'd': |
726 | 2.45M | case 'u': |
727 | 2.53M | case 'o': |
728 | 2.53M | case 'x': |
729 | 7.68M | case 'X': |
730 | 7.68M | { |
731 | 7.68M | int ret = mainformatlong(v, ctx, arg, p_str, writer); |
732 | 7.68M | if (ret != 0) |
733 | 2.45M | return ret; |
734 | 5.22M | arg->sign = 1; |
735 | 5.22M | break; |
736 | 7.68M | } |
737 | | |
738 | 0 | case 'e': |
739 | 0 | case 'E': |
740 | 95 | case 'f': |
741 | 95 | case 'F': |
742 | 95 | case 'g': |
743 | 95 | case 'G': |
744 | 95 | if (arg->width == -1 && arg->prec == -1 |
745 | 0 | && !(arg->flags & (F_SIGN | F_BLANK))) |
746 | 0 | { |
747 | | /* Fast path */ |
748 | 0 | if (formatfloat(v, ctx, arg, NULL, writer) == -1) |
749 | 0 | return -1; |
750 | 0 | return 1; |
751 | 0 | } |
752 | | |
753 | 95 | arg->sign = 1; |
754 | 95 | if (formatfloat(v, ctx, arg, p_str, NULL) == -1) |
755 | 0 | return -1; |
756 | 95 | break; |
757 | | |
758 | 95 | case 'c': |
759 | 0 | { |
760 | 0 | Py_UCS4 ch = formatchar(v, ctx, arg); |
761 | 0 | if (ch == (Py_UCS4) -1) |
762 | 0 | return -1; |
763 | 0 | if (arg->width == -1 && arg->prec == -1) { |
764 | | /* Fast path */ |
765 | 0 | if (_PyUnicodeWriter_WriteCharInline(writer, ch) < 0) |
766 | 0 | return -1; |
767 | 0 | return 1; |
768 | 0 | } |
769 | 0 | *p_str = PyUnicode_FromOrdinal(ch); |
770 | 0 | break; |
771 | 0 | } |
772 | | |
773 | 0 | default: |
774 | 0 | if (arg->ch < 128 && Py_ISALPHA(arg->ch)) { |
775 | 0 | PyErr_Format(PyExc_ValueError, |
776 | 0 | "unsupported format %%%c at position %zd", |
777 | 0 | (int)arg->ch, arg->fmtstart); |
778 | 0 | } |
779 | 0 | else if (arg->ch == '\'') { |
780 | 0 | PyErr_Format(PyExc_ValueError, |
781 | 0 | "stray %% at position %zd or unexpected " |
782 | 0 | "format character \"'\" at position %zd", |
783 | 0 | arg->fmtstart, |
784 | 0 | ctx->fmtpos - 1); |
785 | 0 | } |
786 | 0 | else if (arg->ch >= 32 && arg->ch < 127) { |
787 | 0 | PyErr_Format(PyExc_ValueError, |
788 | 0 | "stray %% at position %zd or unexpected " |
789 | 0 | "format character '%c' at position %zd", |
790 | 0 | arg->fmtstart, |
791 | 0 | (int)arg->ch, ctx->fmtpos - 1); |
792 | 0 | } |
793 | 0 | else if (Py_UNICODE_ISPRINTABLE(arg->ch)) { |
794 | 0 | PyErr_Format(PyExc_ValueError, |
795 | 0 | "stray %% at position %zd or unexpected " |
796 | 0 | "format character '%c' (U+%04X) at position %zd", |
797 | 0 | arg->fmtstart, |
798 | 0 | (int)arg->ch, (int)arg->ch, ctx->fmtpos - 1); |
799 | 0 | } |
800 | 0 | else { |
801 | 0 | PyErr_Format(PyExc_ValueError, |
802 | 0 | "stray %% at position %zd or unexpected " |
803 | 0 | "format character U+%04X at position %zd", |
804 | 0 | arg->fmtstart, (int)arg->ch, ctx->fmtpos - 1); |
805 | 0 | } |
806 | 0 | return -1; |
807 | 21.8M | } |
808 | 19.3M | if (*p_str == NULL) |
809 | 0 | return -1; |
810 | 19.3M | assert (PyUnicode_Check(*p_str)); |
811 | 19.3M | return 0; |
812 | 19.3M | } |
813 | | |
814 | | |
815 | | static int |
816 | | unicode_format_arg_output(struct unicode_formatter_t *ctx, |
817 | | struct unicode_format_arg_t *arg, |
818 | | PyObject *str) |
819 | 19.3M | { |
820 | 19.3M | Py_ssize_t len; |
821 | 19.3M | int kind; |
822 | 19.3M | const void *pbuf; |
823 | 19.3M | Py_ssize_t pindex; |
824 | 19.3M | Py_UCS4 signchar; |
825 | 19.3M | Py_ssize_t buflen; |
826 | 19.3M | Py_UCS4 maxchar; |
827 | 19.3M | Py_ssize_t sublen; |
828 | 19.3M | _PyUnicodeWriter *writer = &ctx->writer; |
829 | 19.3M | Py_UCS4 fill; |
830 | | |
831 | 19.3M | fill = ' '; |
832 | 19.3M | if (arg->sign && arg->flags & F_ZERO) |
833 | 79.7k | fill = '0'; |
834 | | |
835 | 19.3M | len = PyUnicode_GET_LENGTH(str); |
836 | 19.3M | if ((arg->width == -1 || arg->width <= len) |
837 | 19.2M | && (arg->prec == -1 || arg->prec >= len) |
838 | 19.2M | && !(arg->flags & (F_SIGN | F_BLANK))) |
839 | 19.2M | { |
840 | | /* Fast path */ |
841 | 19.2M | if (_PyUnicodeWriter_WriteStr(writer, str) == -1) |
842 | 0 | return -1; |
843 | 19.2M | return 0; |
844 | 19.2M | } |
845 | | |
846 | | /* Truncate the string for "s", "r" and "a" formats |
847 | | if the precision is set */ |
848 | 77.8k | if (arg->ch == 's' || arg->ch == 'r' || arg->ch == 'a') { |
849 | 0 | if (arg->prec >= 0 && len > arg->prec) |
850 | 0 | len = arg->prec; |
851 | 0 | } |
852 | | |
853 | | /* Adjust sign and width */ |
854 | 77.8k | kind = PyUnicode_KIND(str); |
855 | 77.8k | pbuf = PyUnicode_DATA(str); |
856 | 77.8k | pindex = 0; |
857 | 77.8k | signchar = '\0'; |
858 | 77.8k | if (arg->sign) { |
859 | 77.8k | Py_UCS4 ch = PyUnicode_READ(kind, pbuf, pindex); |
860 | 77.8k | if (ch == '-' || ch == '+') { |
861 | 0 | signchar = ch; |
862 | 0 | len--; |
863 | 0 | pindex++; |
864 | 0 | } |
865 | 77.8k | else if (arg->flags & F_SIGN) |
866 | 0 | signchar = '+'; |
867 | 77.8k | else if (arg->flags & F_BLANK) |
868 | 0 | signchar = ' '; |
869 | 77.8k | else |
870 | 77.8k | arg->sign = 0; |
871 | 77.8k | } |
872 | 77.8k | if (arg->width < len) |
873 | 95 | arg->width = len; |
874 | | |
875 | | /* Prepare the writer */ |
876 | 77.8k | maxchar = writer->maxchar; |
877 | 77.8k | if (!(arg->flags & F_LJUST)) { |
878 | 77.8k | if (arg->sign) { |
879 | 0 | if ((arg->width-1) > len) |
880 | 0 | maxchar = Py_MAX(maxchar, fill); |
881 | 0 | } |
882 | 77.8k | else { |
883 | 77.8k | if (arg->width > len) |
884 | 77.7k | maxchar = Py_MAX(maxchar, fill); |
885 | 77.8k | } |
886 | 77.8k | } |
887 | 77.8k | if (PyUnicode_MAX_CHAR_VALUE(str) > maxchar) { |
888 | 77.5k | Py_UCS4 strmaxchar = _PyUnicode_FindMaxChar(str, 0, pindex+len); |
889 | 77.5k | maxchar = Py_MAX(maxchar, strmaxchar); |
890 | 77.5k | } |
891 | | |
892 | 77.8k | buflen = arg->width; |
893 | 77.8k | if (arg->sign && len == arg->width) |
894 | 0 | buflen++; |
895 | 77.8k | if (_PyUnicodeWriter_Prepare(writer, buflen, maxchar) == -1) |
896 | 0 | return -1; |
897 | | |
898 | | /* Write the sign if needed */ |
899 | 77.8k | if (arg->sign) { |
900 | 0 | if (fill != ' ') { |
901 | 0 | PyUnicode_WRITE(writer->kind, writer->data, writer->pos, signchar); |
902 | 0 | writer->pos += 1; |
903 | 0 | } |
904 | 0 | if (arg->width > len) |
905 | 0 | arg->width--; |
906 | 0 | } |
907 | | |
908 | | /* Write the numeric prefix for "x", "X" and "o" formats |
909 | | if the alternate form is used. |
910 | | For example, write "0x" for the "%#x" format. */ |
911 | 77.8k | if ((arg->flags & F_ALT) && (arg->ch == 'x' || arg->ch == 'X' || arg->ch == 'o')) { |
912 | 0 | assert(PyUnicode_READ(kind, pbuf, pindex) == '0'); |
913 | 0 | assert(PyUnicode_READ(kind, pbuf, pindex + 1) == arg->ch); |
914 | 0 | if (fill != ' ') { |
915 | 0 | PyUnicode_WRITE(writer->kind, writer->data, writer->pos, '0'); |
916 | 0 | PyUnicode_WRITE(writer->kind, writer->data, writer->pos+1, arg->ch); |
917 | 0 | writer->pos += 2; |
918 | 0 | pindex += 2; |
919 | 0 | } |
920 | 0 | arg->width -= 2; |
921 | 0 | if (arg->width < 0) |
922 | 0 | arg->width = 0; |
923 | 0 | len -= 2; |
924 | 0 | } |
925 | | |
926 | | /* Pad left with the fill character if needed */ |
927 | 77.8k | if (arg->width > len && !(arg->flags & F_LJUST)) { |
928 | 77.7k | sublen = arg->width - len; |
929 | 77.7k | _PyUnicode_Fill(writer->kind, writer->data, fill, writer->pos, sublen); |
930 | 77.7k | writer->pos += sublen; |
931 | 77.7k | arg->width = len; |
932 | 77.7k | } |
933 | | |
934 | | /* If padding with spaces: write sign if needed and/or numeric prefix if |
935 | | the alternate form is used */ |
936 | 77.8k | if (fill == ' ') { |
937 | 95 | if (arg->sign) { |
938 | 0 | PyUnicode_WRITE(writer->kind, writer->data, writer->pos, signchar); |
939 | 0 | writer->pos += 1; |
940 | 0 | } |
941 | 95 | if ((arg->flags & F_ALT) && (arg->ch == 'x' || arg->ch == 'X' || arg->ch == 'o')) { |
942 | 0 | assert(PyUnicode_READ(kind, pbuf, pindex) == '0'); |
943 | 0 | assert(PyUnicode_READ(kind, pbuf, pindex+1) == arg->ch); |
944 | 0 | PyUnicode_WRITE(writer->kind, writer->data, writer->pos, '0'); |
945 | 0 | PyUnicode_WRITE(writer->kind, writer->data, writer->pos+1, arg->ch); |
946 | 0 | writer->pos += 2; |
947 | 0 | pindex += 2; |
948 | 0 | } |
949 | 95 | } |
950 | | |
951 | | /* Write characters */ |
952 | 77.8k | if (len) { |
953 | 77.8k | _PyUnicode_FastCopyCharacters(writer->buffer, writer->pos, |
954 | 77.8k | str, pindex, len); |
955 | 77.8k | writer->pos += len; |
956 | 77.8k | } |
957 | | |
958 | | /* Pad right with the fill character if needed */ |
959 | 77.8k | if (arg->width > len) { |
960 | 0 | sublen = arg->width - len; |
961 | 0 | _PyUnicode_Fill(writer->kind, writer->data, ' ', writer->pos, sublen); |
962 | 0 | writer->pos += sublen; |
963 | 0 | } |
964 | 77.8k | return 0; |
965 | 77.8k | } |
966 | | |
967 | | |
968 | | /* Helper of PyUnicode_Format(): format one arg. |
969 | | Return 0 on success, raise an exception and return -1 on error. */ |
970 | | static int |
971 | | unicode_format_arg(struct unicode_formatter_t *ctx) |
972 | 21.8M | { |
973 | 21.8M | struct unicode_format_arg_t arg; |
974 | 21.8M | PyObject *str; |
975 | 21.8M | int ret; |
976 | | |
977 | 21.8M | arg.ch = PyUnicode_READ(ctx->fmtkind, ctx->fmtdata, ctx->fmtpos); |
978 | 21.8M | if (arg.ch == '%') { |
979 | 0 | ctx->fmtpos++; |
980 | 0 | ctx->fmtcnt--; |
981 | 0 | if (_PyUnicodeWriter_WriteCharInline(&ctx->writer, '%') < 0) |
982 | 0 | return -1; |
983 | 0 | return 0; |
984 | 0 | } |
985 | 21.8M | arg.flags = 0; |
986 | 21.8M | arg.width = -1; |
987 | 21.8M | arg.prec = -1; |
988 | 21.8M | arg.sign = 0; |
989 | 21.8M | arg.fmtstart = ctx->fmtpos - 1; |
990 | 21.8M | arg.key = NULL; |
991 | 21.8M | str = NULL; |
992 | | |
993 | 21.8M | ret = unicode_format_arg_parse(ctx, &arg); |
994 | 21.8M | if (ret == -1) { |
995 | 0 | goto onError; |
996 | 0 | } |
997 | | |
998 | 21.8M | ret = unicode_format_arg_format(ctx, &arg, &str); |
999 | 21.8M | if (ret == -1) { |
1000 | 950k | goto onError; |
1001 | 950k | } |
1002 | | |
1003 | 20.8M | if (ret != 1) { |
1004 | 19.3M | ret = unicode_format_arg_output(ctx, &arg, str); |
1005 | 19.3M | Py_DECREF(str); |
1006 | 19.3M | if (ret == -1) { |
1007 | 0 | goto onError; |
1008 | 0 | } |
1009 | 19.3M | } |
1010 | | |
1011 | 20.8M | if (ctx->dict && (ctx->argidx < ctx->arglen)) { |
1012 | | // XXX: Never happens? |
1013 | 0 | PyErr_SetString(PyExc_TypeError, |
1014 | 0 | "not all arguments converted during string formatting"); |
1015 | 0 | goto onError; |
1016 | 0 | } |
1017 | 20.8M | Py_XDECREF(arg.key); |
1018 | 20.8M | return 0; |
1019 | | |
1020 | 950k | onError: |
1021 | 950k | Py_XDECREF(arg.key); |
1022 | 950k | return -1; |
1023 | 20.8M | } |
1024 | | |
1025 | | |
1026 | | PyObject * |
1027 | | PyUnicode_Format(PyObject *format, PyObject *args) |
1028 | 12.1M | { |
1029 | 12.1M | struct unicode_formatter_t ctx; |
1030 | | |
1031 | 12.1M | if (format == NULL || args == NULL) { |
1032 | 0 | PyErr_BadInternalCall(); |
1033 | 0 | return NULL; |
1034 | 0 | } |
1035 | | |
1036 | 12.1M | if (ensure_unicode(format) < 0) |
1037 | 0 | return NULL; |
1038 | | |
1039 | 12.1M | ctx.fmtstr = format; |
1040 | 12.1M | ctx.fmtdata = PyUnicode_DATA(ctx.fmtstr); |
1041 | 12.1M | ctx.fmtkind = PyUnicode_KIND(ctx.fmtstr); |
1042 | 12.1M | ctx.fmtcnt = PyUnicode_GET_LENGTH(ctx.fmtstr); |
1043 | 12.1M | ctx.fmtpos = 0; |
1044 | | |
1045 | 12.1M | _PyUnicodeWriter_Init(&ctx.writer); |
1046 | 12.1M | ctx.writer.min_length = ctx.fmtcnt + 100; |
1047 | 12.1M | ctx.writer.overallocate = 1; |
1048 | | |
1049 | 12.1M | if (PyTuple_Check(args)) { |
1050 | 6.36M | ctx.arglen = PyTuple_Size(args); |
1051 | 6.36M | ctx.argidx = 0; |
1052 | 6.36M | } |
1053 | 5.80M | else { |
1054 | 5.80M | ctx.arglen = -1; |
1055 | 5.80M | ctx.argidx = -2; |
1056 | 5.80M | } |
1057 | 12.1M | ctx.args_owned = 0; |
1058 | 12.1M | if (PyMapping_Check(args) && !PyTuple_Check(args) && !PyUnicode_Check(args)) |
1059 | 15.4k | ctx.dict = args; |
1060 | 12.1M | else |
1061 | 12.1M | ctx.dict = NULL; |
1062 | 12.1M | ctx.args = args; |
1063 | | |
1064 | 57.1M | while (--ctx.fmtcnt >= 0) { |
1065 | 45.8M | if (PyUnicode_READ(ctx.fmtkind, ctx.fmtdata, ctx.fmtpos) != '%') { |
1066 | 24.0M | Py_ssize_t nonfmtpos; |
1067 | | |
1068 | 24.0M | nonfmtpos = ctx.fmtpos++; |
1069 | 142M | while (ctx.fmtcnt >= 0 && |
1070 | 137M | PyUnicode_READ(ctx.fmtkind, ctx.fmtdata, ctx.fmtpos) != '%') { |
1071 | 118M | ctx.fmtpos++; |
1072 | 118M | ctx.fmtcnt--; |
1073 | 118M | } |
1074 | 24.0M | if (ctx.fmtcnt < 0) { |
1075 | 4.58M | ctx.fmtpos--; |
1076 | 4.58M | ctx.writer.overallocate = 0; |
1077 | 4.58M | } |
1078 | | |
1079 | 24.0M | if (_PyUnicodeWriter_WriteSubstring(&ctx.writer, ctx.fmtstr, |
1080 | 24.0M | nonfmtpos, ctx.fmtpos) < 0) |
1081 | 0 | goto onError; |
1082 | 24.0M | } |
1083 | 21.8M | else { |
1084 | 21.8M | ctx.fmtpos++; |
1085 | 21.8M | if (unicode_format_arg(&ctx) == -1) |
1086 | 950k | goto onError; |
1087 | 21.8M | } |
1088 | 45.8M | } |
1089 | | |
1090 | 11.2M | if (ctx.argidx < ctx.arglen && !ctx.dict) { |
1091 | 0 | PyErr_Format(PyExc_TypeError, |
1092 | 0 | "not all arguments converted during string formatting " |
1093 | 0 | "(required %zd, got %zd)", |
1094 | 0 | ctx.arglen < 0 ? 0 : ctx.argidx, |
1095 | 0 | ctx.arglen < 0 ? 1 : ctx.arglen); |
1096 | 0 | goto onError; |
1097 | 0 | } |
1098 | | |
1099 | 11.2M | if (ctx.args_owned) { |
1100 | 14.7k | Py_DECREF(ctx.args); |
1101 | 14.7k | } |
1102 | 11.2M | return _PyUnicodeWriter_Finish(&ctx.writer); |
1103 | | |
1104 | 950k | onError: |
1105 | 950k | _PyUnicodeWriter_Dealloc(&ctx.writer); |
1106 | 950k | if (ctx.args_owned) { |
1107 | 0 | Py_DECREF(ctx.args); |
1108 | 0 | } |
1109 | | return NULL; |
1110 | 11.2M | } |