Skip to content

Commit 4a58707

Browse files
committed
Add _PyUnicodeWriter_WriteASCIIString() function
1 parent 4d3f109 commit 4a58707

4 files changed

Lines changed: 96 additions & 38 deletions

File tree

Include/unicodeobject.h

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -962,12 +962,20 @@ _PyUnicodeWriter_WriteSubstring(_PyUnicodeWriter *writer,
962962
Py_ssize_t end
963963
);
964964

965+
/* Append a ASCII-encoded byte string.
966+
Return 0 on success, raise an exception and return -1 on error. */
967+
PyAPI_FUNC(int)
968+
_PyUnicodeWriter_WriteASCIIString(_PyUnicodeWriter *writer,
969+
const char *str, /* ASCII-encoded byte string */
970+
Py_ssize_t len /* number of bytes, or -1 if unknown */
971+
);
972+
965973
/* Append a latin1-encoded byte string.
966974
Return 0 on success, raise an exception and return -1 on error. */
967975
PyAPI_FUNC(int)
968-
_PyUnicodeWriter_WriteCstr(_PyUnicodeWriter *writer,
969-
const char *str, /* latin1-encoded byte string */
970-
Py_ssize_t len /* length in bytes */
976+
_PyUnicodeWriter_WriteLatin1String(_PyUnicodeWriter *writer,
977+
const char *str, /* latin1-encoded byte string */
978+
Py_ssize_t len /* length in bytes */
971979
);
972980

973981
/* Get the value of the writer as an Unicode string. Clear the
@@ -979,6 +987,9 @@ _PyUnicodeWriter_Finish(_PyUnicodeWriter *writer);
979987
/* Deallocate memory of a writer (clear its internal buffer). */
980988
PyAPI_FUNC(void)
981989
_PyUnicodeWriter_Dealloc(_PyUnicodeWriter *writer);
990+
991+
PyAPI_FUNC(int) _PyObject_ReprWriter(_PyUnicodeWriter *writer,
992+
PyObject *v);
982993
#endif
983994

984995
#ifndef Py_LIMITED_API

Objects/listobject.c

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -339,19 +339,12 @@ list_repr(PyListObject *v)
339339
{
340340
Py_ssize_t i;
341341
PyObject *s;
342-
static PyObject *sep = NULL;
343342
_PyUnicodeWriter writer;
344343

345344
if (Py_SIZE(v) == 0) {
346345
return PyUnicode_FromString("[]");
347346
}
348347

349-
if (sep == NULL) {
350-
sep = PyUnicode_FromString(", ");
351-
if (sep == NULL)
352-
return NULL;
353-
}
354-
355348
i = Py_ReprEnter((PyObject*)v);
356349
if (i != 0) {
357350
return i > 0 ? PyUnicode_FromString("[...]") : NULL;
@@ -369,7 +362,7 @@ list_repr(PyListObject *v)
369362
so must refetch the list size on each iteration. */
370363
for (i = 0; i < Py_SIZE(v); ++i) {
371364
if (i > 0) {
372-
if (_PyUnicodeWriter_WriteStr(&writer, sep) < 0)
365+
if (_PyUnicodeWriter_WriteASCIIString(&writer, ", ", 2) < 0)
373366
goto error;
374367
}
375368

Objects/unicodeobject.c

Lines changed: 72 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -140,9 +140,9 @@ extern "C" {
140140
buffer where the result characters are written to. */
141141
#define _PyUnicode_CONVERT_BYTES(from_type, to_type, begin, end, to) \
142142
do { \
143-
to_type *_to = (to_type *) to; \
144-
const from_type *_iter = (begin); \
145-
const from_type *_end = (end); \
143+
to_type *_to = (to_type *)(to); \
144+
const from_type *_iter = (from_type *)(begin); \
145+
const from_type *_end = (from_type *)(end); \
146146
Py_ssize_t n = (_end) - (_iter); \
147147
const from_type *_unrolled_end = \
148148
_iter + _Py_SIZE_ROUND_DOWN(n, 4); \
@@ -2562,7 +2562,6 @@ unicode_fromformat_arg(_PyUnicodeWriter *writer,
25622562
precision = len;
25632563

25642564
arglen = Py_MAX(precision, width);
2565-
assert(ucs1lib_find_max_char((Py_UCS1*)buffer, (Py_UCS1*)buffer + len) <= 127);
25662565
if (_PyUnicodeWriter_Prepare(writer, arglen, 127) == -1)
25672566
return NULL;
25682567

@@ -2581,8 +2580,8 @@ unicode_fromformat_arg(_PyUnicodeWriter *writer,
25812580
writer->pos += fill;
25822581
}
25832582

2584-
unicode_write_cstr(writer->buffer, writer->pos, buffer, len);
2585-
writer->pos += len;
2583+
if (_PyUnicodeWriter_WriteASCIIString(writer, buffer, len) < 0)
2584+
return NULL;
25862585
break;
25872586
}
25882587

@@ -2604,11 +2603,8 @@ unicode_fromformat_arg(_PyUnicodeWriter *writer,
26042603
len += 2;
26052604
}
26062605

2607-
assert(ucs1lib_find_max_char((Py_UCS1*)number, (Py_UCS1*)number + len) <= 127);
2608-
if (_PyUnicodeWriter_Prepare(writer, len, 127) == -1)
2606+
if (_PyUnicodeWriter_WriteASCIIString(writer, number, len) < 0)
26092607
return NULL;
2610-
unicode_write_cstr(writer->buffer, writer->pos, number, len);
2611-
writer->pos += len;
26122608
break;
26132609
}
26142610

@@ -2707,7 +2703,7 @@ unicode_fromformat_arg(_PyUnicodeWriter *writer,
27072703
skip the code, since there's no way to know what's in the
27082704
argument list) */
27092705
len = strlen(p);
2710-
if (_PyUnicodeWriter_WriteCstr(writer, p, len) == -1)
2706+
if (_PyUnicodeWriter_WriteLatin1String(writer, p, len) == -1)
27112707
return NULL;
27122708
f = p+len;
27132709
return f;
@@ -2759,10 +2755,9 @@ PyUnicode_FromFormatV(const char *format, va_list vargs)
27592755

27602756
if (*p == '\0')
27612757
writer.overallocate = 0;
2762-
if (_PyUnicodeWriter_Prepare(&writer, len, 127) == -1)
2758+
2759+
if (_PyUnicodeWriter_WriteASCIIString(&writer, f, len) < 0)
27632760
goto fail;
2764-
unicode_write_cstr(writer.buffer, writer.pos, f, len);
2765-
writer.pos += len;
27662761

27672762
f = p;
27682763
}
@@ -13461,7 +13456,68 @@ _PyUnicodeWriter_WriteSubstring(_PyUnicodeWriter *writer, PyObject *str,
1346113456
}
1346213457

1346313458
int
13464-
_PyUnicodeWriter_WriteCstr(_PyUnicodeWriter *writer, const char *str, Py_ssize_t len)
13459+
_PyUnicodeWriter_WriteASCIIString(_PyUnicodeWriter *writer,
13460+
const char *ascii, Py_ssize_t len)
13461+
{
13462+
if (len == -1)
13463+
len = strlen(ascii);
13464+
13465+
assert(ucs1lib_find_max_char((Py_UCS1*)ascii, (Py_UCS1*)ascii + len) < 128);
13466+
13467+
if (writer->buffer == NULL && !writer->overallocate) {
13468+
PyObject *str;
13469+
13470+
str = _PyUnicode_FromASCII(ascii, len);
13471+
if (str == NULL)
13472+
return -1;
13473+
13474+
writer->readonly = 1;
13475+
writer->buffer = str;
13476+
_PyUnicodeWriter_Update(writer);
13477+
writer->pos += len;
13478+
return 0;
13479+
}
13480+
13481+
if (_PyUnicodeWriter_Prepare(writer, len, 127) == -1)
13482+
return -1;
13483+
13484+
switch (writer->kind)
13485+
{
13486+
case PyUnicode_1BYTE_KIND:
13487+
{
13488+
const Py_UCS1 *str = (const Py_UCS1 *)ascii;
13489+
Py_UCS1 *data = writer->data;
13490+
13491+
Py_MEMCPY(data + writer->pos, str, len);
13492+
break;
13493+
}
13494+
case PyUnicode_2BYTE_KIND:
13495+
{
13496+
_PyUnicode_CONVERT_BYTES(
13497+
Py_UCS1, Py_UCS2,
13498+
ascii, ascii + len,
13499+
(Py_UCS2 *)writer->data + writer->pos);
13500+
break;
13501+
}
13502+
case PyUnicode_4BYTE_KIND:
13503+
{
13504+
_PyUnicode_CONVERT_BYTES(
13505+
Py_UCS1, Py_UCS4,
13506+
ascii, ascii + len,
13507+
(Py_UCS4 *)writer->data + writer->pos);
13508+
break;
13509+
}
13510+
default:
13511+
assert(0);
13512+
}
13513+
13514+
writer->pos += len;
13515+
return 0;
13516+
}
13517+
13518+
int
13519+
_PyUnicodeWriter_WriteLatin1String(_PyUnicodeWriter *writer,
13520+
const char *str, Py_ssize_t len)
1346513521
{
1346613522
Py_UCS4 maxchar;
1346713523

@@ -13828,12 +13884,10 @@ formatfloat(PyObject *v, struct unicode_format_arg_t *arg,
1382813884
return -1;
1382913885
len = strlen(p);
1383013886
if (writer) {
13831-
if (_PyUnicodeWriter_Prepare(writer, len, 127) == -1) {
13887+
if (_PyUnicodeWriter_WriteASCIIString(writer, p, len) < 0) {
1383213888
PyMem_Free(p);
1383313889
return -1;
1383413890
}
13835-
unicode_write_cstr(writer->buffer, writer->pos, p, len);
13836-
writer->pos += len;
1383713891
}
1383813892
else
1383913893
*p_output = _PyUnicode_FromASCII(p, len);

Python/formatter_unicode.c

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1053,24 +1053,24 @@ format_float_internal(PyObject *value,
10531053
n_digits += 1;
10541054
}
10551055

1056-
/* Since there is no unicode version of PyOS_double_to_string,
1057-
just use the 8 bit version and then convert to unicode. */
1058-
unicode_tmp = _PyUnicode_FromASCII(buf, n_digits);
1059-
PyMem_Free(buf);
1060-
if (unicode_tmp == NULL)
1061-
goto done;
1062-
10631056
if (format->sign != '+' && format->sign != ' '
10641057
&& format->width == -1
10651058
&& format->type != 'n'
10661059
&& !format->thousands_separators)
10671060
{
10681061
/* Fast path */
1069-
result = _PyUnicodeWriter_WriteStr(writer, unicode_tmp);
1070-
Py_DECREF(unicode_tmp);
1062+
result = _PyUnicodeWriter_WriteASCIIString(writer, buf, n_digits);
1063+
PyMem_Free(buf);
10711064
return result;
10721065
}
10731066

1067+
/* Since there is no unicode version of PyOS_double_to_string,
1068+
just use the 8 bit version and then convert to unicode. */
1069+
unicode_tmp = _PyUnicode_FromASCII(buf, n_digits);
1070+
PyMem_Free(buf);
1071+
if (unicode_tmp == NULL)
1072+
goto done;
1073+
10741074
/* Is a sign character present in the output? If so, remember it
10751075
and skip it */
10761076
index = 0;

0 commit comments

Comments
 (0)