mirror of https://github.com/python/cpython
gh-112301: Use literal format strings in unicode_fromformat_arg (GH-124203)
This commit is contained in:
parent
162d152146
commit
da5855e99a
|
@ -2694,11 +2694,6 @@ unicode_fromformat_write_wcstr(_PyUnicodeWriter *writer, const wchar_t *str,
|
||||||
#define F_SIZE 3
|
#define F_SIZE 3
|
||||||
#define F_PTRDIFF 4
|
#define F_PTRDIFF 4
|
||||||
#define F_INTMAX 5
|
#define F_INTMAX 5
|
||||||
static const char * const formats[] = {"%d", "%ld", "%lld", "%zd", "%td", "%jd"};
|
|
||||||
static const char * const formats_o[] = {"%o", "%lo", "%llo", "%zo", "%to", "%jo"};
|
|
||||||
static const char * const formats_u[] = {"%u", "%lu", "%llu", "%zu", "%tu", "%ju"};
|
|
||||||
static const char * const formats_x[] = {"%x", "%lx", "%llx", "%zx", "%tx", "%jx"};
|
|
||||||
static const char * const formats_X[] = {"%X", "%lX", "%llX", "%zX", "%tX", "%jX"};
|
|
||||||
|
|
||||||
static const char*
|
static const char*
|
||||||
unicode_fromformat_arg(_PyUnicodeWriter *writer,
|
unicode_fromformat_arg(_PyUnicodeWriter *writer,
|
||||||
|
@ -2840,47 +2835,44 @@ unicode_fromformat_arg(_PyUnicodeWriter *writer,
|
||||||
case 'd': case 'i':
|
case 'd': case 'i':
|
||||||
case 'o': case 'u': case 'x': case 'X':
|
case 'o': case 'u': case 'x': case 'X':
|
||||||
{
|
{
|
||||||
/* used by sprintf */
|
|
||||||
char buffer[MAX_INTMAX_CHARS];
|
char buffer[MAX_INTMAX_CHARS];
|
||||||
const char *fmt = NULL;
|
|
||||||
switch (*f) {
|
// Fill buffer using sprinf, with one of many possible format
|
||||||
case 'o': fmt = formats_o[sizemod]; break;
|
// strings, like "%llX" for `long long` in hexadecimal.
|
||||||
case 'u': fmt = formats_u[sizemod]; break;
|
// The type/size is in `sizemod`; the format is in `*f`.
|
||||||
case 'x': fmt = formats_x[sizemod]; break;
|
|
||||||
case 'X': fmt = formats_X[sizemod]; break;
|
// Use macros with nested switches to keep the sprintf format strings
|
||||||
default: fmt = formats[sizemod]; break;
|
// as compile-time literals, avoiding warnings and maybe allowing
|
||||||
}
|
// optimizations.
|
||||||
int issigned = (*f == 'd' || *f == 'i');
|
|
||||||
|
// `SPRINT` macro does one sprintf
|
||||||
|
// Example usage: SPRINT("l", "X", unsigned long) expands to
|
||||||
|
// sprintf(buffer, "%" "l" "X", va_arg(*vargs, unsigned long))
|
||||||
|
#define SPRINT(SIZE_SPEC, FMT_CHAR, TYPE) \
|
||||||
|
sprintf(buffer, "%" SIZE_SPEC FMT_CHAR, va_arg(*vargs, TYPE))
|
||||||
|
|
||||||
|
// One inner switch to handle all format variants
|
||||||
|
#define DO_SPRINTS(SIZE_SPEC, SIGNED_TYPE, UNSIGNED_TYPE) \
|
||||||
|
switch (*f) { \
|
||||||
|
case 'o': len = SPRINT(SIZE_SPEC, "o", UNSIGNED_TYPE); break; \
|
||||||
|
case 'u': len = SPRINT(SIZE_SPEC, "u", UNSIGNED_TYPE); break; \
|
||||||
|
case 'x': len = SPRINT(SIZE_SPEC, "x", UNSIGNED_TYPE); break; \
|
||||||
|
case 'X': len = SPRINT(SIZE_SPEC, "X", UNSIGNED_TYPE); break; \
|
||||||
|
default: len = SPRINT(SIZE_SPEC, "d", SIGNED_TYPE); break; \
|
||||||
|
}
|
||||||
|
|
||||||
|
// Outer switch to handle all the sizes/types
|
||||||
switch (sizemod) {
|
switch (sizemod) {
|
||||||
case F_LONG:
|
case F_LONG: DO_SPRINTS("l", long, unsigned long); break;
|
||||||
len = issigned ?
|
case F_LONGLONG: DO_SPRINTS("ll", long long, unsigned long long); break;
|
||||||
sprintf(buffer, fmt, va_arg(*vargs, long)) :
|
case F_SIZE: DO_SPRINTS("z", Py_ssize_t, size_t); break;
|
||||||
sprintf(buffer, fmt, va_arg(*vargs, unsigned long));
|
case F_PTRDIFF: DO_SPRINTS("t", ptrdiff_t, ptrdiff_t); break;
|
||||||
break;
|
case F_INTMAX: DO_SPRINTS("j", intmax_t, uintmax_t); break;
|
||||||
case F_LONGLONG:
|
default: DO_SPRINTS("", int, unsigned int); break;
|
||||||
len = issigned ?
|
|
||||||
sprintf(buffer, fmt, va_arg(*vargs, long long)) :
|
|
||||||
sprintf(buffer, fmt, va_arg(*vargs, unsigned long long));
|
|
||||||
break;
|
|
||||||
case F_SIZE:
|
|
||||||
len = issigned ?
|
|
||||||
sprintf(buffer, fmt, va_arg(*vargs, Py_ssize_t)) :
|
|
||||||
sprintf(buffer, fmt, va_arg(*vargs, size_t));
|
|
||||||
break;
|
|
||||||
case F_PTRDIFF:
|
|
||||||
len = sprintf(buffer, fmt, va_arg(*vargs, ptrdiff_t));
|
|
||||||
break;
|
|
||||||
case F_INTMAX:
|
|
||||||
len = issigned ?
|
|
||||||
sprintf(buffer, fmt, va_arg(*vargs, intmax_t)) :
|
|
||||||
sprintf(buffer, fmt, va_arg(*vargs, uintmax_t));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
len = issigned ?
|
|
||||||
sprintf(buffer, fmt, va_arg(*vargs, int)) :
|
|
||||||
sprintf(buffer, fmt, va_arg(*vargs, unsigned int));
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
#undef SPRINT
|
||||||
|
#undef DO_SPRINTS
|
||||||
|
|
||||||
assert(len >= 0);
|
assert(len >= 0);
|
||||||
|
|
||||||
int sign = (buffer[0] == '-');
|
int sign = (buffer[0] == '-');
|
||||||
|
|
Loading…
Reference in New Issue