Skip to content

Commit ad77158

Browse files
committed
_PyBytesWriter: simplify code to avoid "prealloc" parameters
Substract preallocate bytes from min_size before calling _PyBytesWriter_Prepare().
1 parent 53926a1 commit ad77158

3 files changed

Lines changed: 47 additions & 47 deletions

File tree

Objects/bytesobject.c

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -411,8 +411,7 @@ getnextarg(PyObject *args, Py_ssize_t arglen, Py_ssize_t *p_argidx)
411411

412412
static char*
413413
formatfloat(PyObject *v, int flags, int prec, int type,
414-
PyObject **p_result, _PyBytesWriter *writer, char *str,
415-
Py_ssize_t prealloc)
414+
PyObject **p_result, _PyBytesWriter *writer, char *str)
416415
{
417416
char *p;
418417
PyObject *result;
@@ -437,11 +436,9 @@ formatfloat(PyObject *v, int flags, int prec, int type,
437436

438437
len = strlen(p);
439438
if (writer != NULL) {
440-
if ((Py_ssize_t)len > prealloc) {
441-
str = _PyBytesWriter_Prepare(writer, str, len - prealloc);
442-
if (str == NULL)
443-
return NULL;
444-
}
439+
str = _PyBytesWriter_Prepare(writer, str, len);
440+
if (str == NULL)
441+
return NULL;
445442
Py_MEMCPY(str, p, len);
446443
str += len;
447444
return str;
@@ -865,13 +862,14 @@ _PyBytes_Format(PyObject *format, PyObject *args)
865862
&& !(flags & (F_SIGN | F_BLANK)))
866863
{
867864
/* Fast path */
868-
res = formatfloat(v, flags, prec, c, NULL, &writer, res, 1);
865+
writer.min_size -= 2; /* size preallocated by "%f" */
866+
res = formatfloat(v, flags, prec, c, NULL, &writer, res);
869867
if (res == NULL)
870868
goto error;
871869
continue;
872870
}
873871

874-
if (!formatfloat(v, flags, prec, c, &temp, NULL, res, 1))
872+
if (!formatfloat(v, flags, prec, c, &temp, NULL, res))
875873
goto error;
876874
pbuf = PyBytes_AS_STRING(temp);
877875
len = PyBytes_GET_SIZE(temp);

Objects/stringlib/codecs.h

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -345,15 +345,19 @@ STRINGLIB(utf8_encoder)(PyObject *unicode,
345345
break;
346346

347347
case _Py_ERROR_BACKSLASHREPLACE:
348-
p = backslashreplace(&writer, max_char_size, p,
348+
/* substract preallocated bytes */
349+
writer.min_size -= max_char_size * (endpos - startpos);
350+
p = backslashreplace(&writer, p,
349351
unicode, startpos, endpos);
350352
if (p == NULL)
351353
goto error;
352354
i += (endpos - startpos - 1);
353355
break;
354356

355357
case _Py_ERROR_XMLCHARREFREPLACE:
356-
p = xmlcharrefreplace(&writer, max_char_size, p,
358+
/* substract preallocated bytes */
359+
writer.min_size -= max_char_size * (endpos - startpos);
360+
p = xmlcharrefreplace(&writer, p,
357361
unicode, startpos, endpos);
358362
if (p == NULL)
359363
goto error;
@@ -381,17 +385,17 @@ STRINGLIB(utf8_encoder)(PyObject *unicode,
381385
if (!rep)
382386
goto error;
383387

388+
/* substract preallocated bytes */
389+
writer.min_size -= max_char_size;
390+
384391
if (PyBytes_Check(rep))
385392
repsize = PyBytes_GET_SIZE(rep);
386393
else
387394
repsize = PyUnicode_GET_LENGTH(rep);
388395

389-
if (repsize > max_char_size) {
390-
p = _PyBytesWriter_Prepare(&writer, p,
391-
repsize - max_char_size);
392-
if (p == NULL)
393-
goto error;
394-
}
396+
p = _PyBytesWriter_Prepare(&writer, p, repsize);
397+
if (p == NULL)
398+
goto error;
395399

396400
if (PyBytes_Check(rep)) {
397401
memcpy(p, PyBytes_AS_STRING(rep), repsize);

Objects/unicodeobject.c

Lines changed: 28 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -565,11 +565,10 @@ unicode_result_unchanged(PyObject *unicode)
565565
/* Implementation of the "backslashreplace" error handler for 8-bit encodings:
566566
ASCII, Latin1, UTF-8, etc. */
567567
static char*
568-
backslashreplace(_PyBytesWriter *writer, Py_ssize_t prealloc_per_char,
569-
char *str,
568+
backslashreplace(_PyBytesWriter *writer, char *str,
570569
PyObject *unicode, Py_ssize_t collstart, Py_ssize_t collend)
571570
{
572-
Py_ssize_t size, i, prealloc;
571+
Py_ssize_t size, i;
573572
Py_UCS4 ch;
574573
enum PyUnicode_Kind kind;
575574
void *data;
@@ -600,12 +599,9 @@ backslashreplace(_PyBytesWriter *writer, Py_ssize_t prealloc_per_char,
600599
size += incr;
601600
}
602601

603-
prealloc = prealloc_per_char * (collend - collstart);
604-
if (size > prealloc) {
605-
str = _PyBytesWriter_Prepare(writer, str, size - prealloc);
606-
if (str == NULL)
607-
return NULL;
608-
}
602+
str = _PyBytesWriter_Prepare(writer, str, size);
603+
if (str == NULL)
604+
return NULL;
609605

610606
/* generate replacement */
611607
for (i = collstart; i < collend; ++i) {
@@ -636,11 +632,10 @@ backslashreplace(_PyBytesWriter *writer, Py_ssize_t prealloc_per_char,
636632
/* Implementation of the "xmlcharrefreplace" error handler for 8-bit encodings:
637633
ASCII, Latin1, UTF-8, etc. */
638634
static char*
639-
xmlcharrefreplace(_PyBytesWriter *writer, Py_ssize_t prealloc_per_char,
640-
char *str,
635+
xmlcharrefreplace(_PyBytesWriter *writer, char *str,
641636
PyObject *unicode, Py_ssize_t collstart, Py_ssize_t collend)
642637
{
643-
Py_ssize_t size, i, prealloc;
638+
Py_ssize_t size, i;
644639
Py_UCS4 ch;
645640
enum PyUnicode_Kind kind;
646641
void *data;
@@ -679,12 +674,9 @@ xmlcharrefreplace(_PyBytesWriter *writer, Py_ssize_t prealloc_per_char,
679674
size += incr;
680675
}
681676

682-
prealloc = prealloc_per_char * (collend - collstart);
683-
if (size > prealloc) {
684-
str = _PyBytesWriter_Prepare(writer, str, size - prealloc);
685-
if (str == NULL)
686-
return NULL;
687-
}
677+
str = _PyBytesWriter_Prepare(writer, str, size);
678+
if (str == NULL)
679+
return NULL;
688680

689681
/* generate replacement */
690682
for (i = collstart; i < collend; ++i) {
@@ -6666,15 +6658,19 @@ unicode_encode_ucs1(PyObject *unicode,
66666658
break;
66676659

66686660
case _Py_ERROR_BACKSLASHREPLACE:
6669-
str = backslashreplace(&writer, 1, str,
6661+
/* substract preallocated bytes */
6662+
writer.min_size -= (collend - collstart);
6663+
str = backslashreplace(&writer, str,
66706664
unicode, collstart, collend);
66716665
if (str == NULL)
66726666
goto onError;
66736667
pos = collend;
66746668
break;
66756669

66766670
case _Py_ERROR_XMLCHARREFREPLACE:
6677-
str = xmlcharrefreplace(&writer, 1, str,
6671+
/* substract preallocated bytes */
6672+
writer.min_size -= (collend - collstart);
6673+
str = xmlcharrefreplace(&writer, str,
66786674
unicode, collstart, collend);
66796675
if (str == NULL)
66806676
goto onError;
@@ -6705,14 +6701,17 @@ unicode_encode_ucs1(PyObject *unicode,
67056701
PyUnicode_READY(repunicode) == -1))
67066702
goto onError;
67076703

6704+
/* substract preallocated bytes */
6705+
writer.min_size -= 1;
6706+
67086707
if (PyBytes_Check(repunicode)) {
67096708
/* Directly copy bytes result to output. */
67106709
repsize = PyBytes_Size(repunicode);
6711-
if (repsize > 1) {
6712-
str = _PyBytesWriter_Prepare(&writer, str, repsize-1);
6713-
if (str == NULL)
6714-
goto onError;
6715-
}
6710+
6711+
str = _PyBytesWriter_Prepare(&writer, str, repsize);
6712+
if (str == NULL)
6713+
goto onError;
6714+
67166715
memcpy(str, PyBytes_AsString(repunicode), repsize);
67176716
str += repsize;
67186717
pos = newpos;
@@ -6724,11 +6723,10 @@ unicode_encode_ucs1(PyObject *unicode,
67246723
have+the replacement+the rest of the string, so
67256724
we won't have to check space for encodable characters) */
67266725
repsize = PyUnicode_GET_LENGTH(repunicode);
6727-
if (repsize > 1) {
6728-
str = _PyBytesWriter_Prepare(&writer, str, repsize-1);
6729-
if (str == NULL)
6730-
goto onError;
6731-
}
6726+
6727+
str = _PyBytesWriter_Prepare(&writer, str, repsize);
6728+
if (str == NULL)
6729+
goto onError;
67326730

67336731
/* check if there is anything unencodable in the replacement
67346732
and copy it to the output */

0 commit comments

Comments
 (0)