Coverage Report

Created: 2026-07-16 07:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cpython3/Objects/unicode_writer.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
#include "Python.h"
42
#include "pycore_freelist.h"      // _Py_FREELIST_FREE()
43
#include "pycore_long.h"          // _PyLong_FormatWriter()
44
#include "pycore_unicodeobject.h" // _PyUnicode_Result()
45
46
47
#ifdef MS_WINDOWS
48
   /* On Windows, overallocate by 50% is the best factor */
49
#  define OVERALLOCATE_FACTOR 2
50
#else
51
   /* On Linux, overallocate by 25% is the best factor */
52
2.99M
#  define OVERALLOCATE_FACTOR 4
53
#endif
54
55
56
/* Compilation of templated routines */
57
58
#define STRINGLIB_GET_EMPTY() _PyUnicode_GetEmpty()
59
60
#include "stringlib/ucs1lib.h"
61
#include "stringlib/find_max_char.h"
62
#include "stringlib/undef.h"
63
64
65
/* Copy an ASCII or latin1 char* string into a Python Unicode string.
66
67
   WARNING: The function doesn't copy the terminating null character and
68
   doesn't check the maximum character (may write a latin1 character in an
69
   ASCII string). */
70
static void
71
unicode_write_cstr(PyObject *unicode, Py_ssize_t index,
72
                   const char *str, Py_ssize_t len)
73
0
{
74
0
    int kind = PyUnicode_KIND(unicode);
75
0
    const void *data = PyUnicode_DATA(unicode);
76
0
    const char *end = str + len;
77
78
0
    assert(index + len <= PyUnicode_GET_LENGTH(unicode));
79
0
    switch (kind) {
80
0
    case PyUnicode_1BYTE_KIND: {
81
#ifdef Py_DEBUG
82
        if (PyUnicode_IS_ASCII(unicode)) {
83
            Py_UCS4 maxchar = ucs1lib_find_max_char(
84
                (const Py_UCS1*)str,
85
                (const Py_UCS1*)str + len);
86
            assert(maxchar < 128);
87
        }
88
#endif
89
0
        memcpy((char *) data + index, str, len);
90
0
        break;
91
0
    }
92
0
    case PyUnicode_2BYTE_KIND: {
93
0
        Py_UCS2 *start = (Py_UCS2 *)data + index;
94
0
        Py_UCS2 *ucs2 = start;
95
96
0
        for (; str < end; ++ucs2, ++str)
97
0
            *ucs2 = (Py_UCS2)*str;
98
99
0
        assert((ucs2 - start) <= PyUnicode_GET_LENGTH(unicode));
100
0
        break;
101
0
    }
102
0
    case PyUnicode_4BYTE_KIND: {
103
0
        Py_UCS4 *start = (Py_UCS4 *)data + index;
104
0
        Py_UCS4 *ucs4 = start;
105
106
0
        for (; str < end; ++ucs4, ++str)
107
0
            *ucs4 = (Py_UCS4)*str;
108
109
0
        assert((ucs4 - start) <= PyUnicode_GET_LENGTH(unicode));
110
0
        break;
111
0
    }
112
0
    default:
113
0
        Py_UNREACHABLE();
114
0
    }
115
0
}
116
117
118
static inline void
119
_PyUnicodeWriter_Update(_PyUnicodeWriter *writer)
120
1.92M
{
121
1.92M
    writer->maxchar = PyUnicode_MAX_CHAR_VALUE(writer->buffer);
122
1.92M
    writer->data = PyUnicode_DATA(writer->buffer);
123
124
1.92M
    if (!writer->readonly) {
125
1.91M
        writer->kind = PyUnicode_KIND(writer->buffer);
126
1.91M
        writer->size = PyUnicode_GET_LENGTH(writer->buffer);
127
1.91M
    }
128
14.8k
    else {
129
        /* use a value smaller than PyUnicode_1BYTE_KIND() so
130
           _PyUnicodeWriter_PrepareKind() will copy the buffer. */
131
14.8k
        writer->kind = 0;
132
14.8k
        assert(writer->kind <= PyUnicode_1BYTE_KIND);
133
134
        /* Copy-on-write mode: set buffer size to 0 so
135
         * _PyUnicodeWriter_Prepare() will copy (and enlarge) the buffer on
136
         * next write. */
137
14.8k
        writer->size = 0;
138
14.8k
    }
139
1.92M
}
140
141
142
void
143
_PyUnicodeWriter_Init(_PyUnicodeWriter *writer)
144
1.44M
{
145
1.44M
    memset(writer, 0, sizeof(*writer));
146
147
    /* ASCII is the bare minimum */
148
1.44M
    writer->min_char = 127;
149
150
    /* use a kind value smaller than PyUnicode_1BYTE_KIND so
151
       _PyUnicodeWriter_PrepareKind() will copy the buffer. */
152
1.44M
    assert(writer->kind == 0);
153
1.44M
    assert(writer->kind < PyUnicode_1BYTE_KIND);
154
1.44M
}
155
156
157
PyUnicodeWriter*
158
PyUnicodeWriter_Create(Py_ssize_t length)
159
59.4k
{
160
59.4k
    if (length < 0) {
161
0
        PyErr_SetString(PyExc_ValueError,
162
0
                        "length must be positive");
163
0
        return NULL;
164
0
    }
165
166
59.4k
    const size_t size = sizeof(_PyUnicodeWriter);
167
59.4k
    PyUnicodeWriter *pub_writer;
168
59.4k
    pub_writer = _Py_FREELIST_POP_MEM(unicode_writers);
169
59.4k
    if (pub_writer == NULL) {
170
31
        pub_writer = (PyUnicodeWriter *)PyMem_Malloc(size);
171
31
        if (pub_writer == NULL) {
172
0
            return (PyUnicodeWriter *)PyErr_NoMemory();
173
0
        }
174
31
    }
175
59.4k
    _PyUnicodeWriter *writer = (_PyUnicodeWriter *)pub_writer;
176
177
59.4k
    _PyUnicodeWriter_Init(writer);
178
59.4k
    if (_PyUnicodeWriter_Prepare(writer, length, 127) < 0) {
179
0
        PyUnicodeWriter_Discard(pub_writer);
180
0
        return NULL;
181
0
    }
182
59.4k
    writer->overallocate = 1;
183
184
59.4k
    return pub_writer;
185
59.4k
}
186
187
188
void PyUnicodeWriter_Discard(PyUnicodeWriter *writer)
189
1.07k
{
190
1.07k
    if (writer == NULL) {
191
180
        return;
192
180
    }
193
899
    _PyUnicodeWriter_Dealloc((_PyUnicodeWriter*)writer);
194
899
    _Py_FREELIST_FREE(unicode_writers, writer, PyMem_Free);
195
899
}
196
197
198
// Initialize _PyUnicodeWriter with initial buffer
199
void
200
_PyUnicodeWriter_InitWithBuffer(_PyUnicodeWriter *writer, PyObject *buffer)
201
391k
{
202
391k
    memset(writer, 0, sizeof(*writer));
203
391k
    writer->buffer = buffer;
204
391k
    _PyUnicodeWriter_Update(writer);
205
391k
    writer->min_length = writer->size;
206
391k
}
207
208
209
int
210
_PyUnicodeWriter_PrepareInternal(_PyUnicodeWriter *writer,
211
                                 Py_ssize_t length, Py_UCS4 maxchar)
212
1.51M
{
213
1.51M
    Py_ssize_t newlen;
214
1.51M
    PyObject *newbuffer;
215
216
1.51M
    assert(length >= 0);
217
1.51M
    assert(maxchar <= _Py_MAX_UNICODE);
218
219
    /* ensure that the _PyUnicodeWriter_Prepare macro was used */
220
1.51M
    assert((maxchar > writer->maxchar && length >= 0)
221
1.51M
           || length > 0);
222
223
1.51M
    if (length > PY_SSIZE_T_MAX - writer->pos) {
224
0
        PyErr_NoMemory();
225
0
        return -1;
226
0
    }
227
1.51M
    newlen = writer->pos + length;
228
229
1.51M
    maxchar = Py_MAX(maxchar, writer->min_char);
230
231
1.51M
    if (writer->buffer == NULL) {
232
1.42M
        assert(!writer->readonly);
233
1.42M
        if (writer->overallocate
234
1.42M
            && newlen <= (PY_SSIZE_T_MAX - newlen / OVERALLOCATE_FACTOR)) {
235
            /* overallocate to limit the number of realloc() */
236
1.42M
            newlen += newlen / OVERALLOCATE_FACTOR;
237
1.42M
        }
238
1.42M
        if (newlen < writer->min_length)
239
1.36M
            newlen = writer->min_length;
240
241
1.42M
        writer->buffer = PyUnicode_New(newlen, maxchar);
242
1.42M
        if (writer->buffer == NULL)
243
0
            return -1;
244
1.42M
    }
245
94.7k
    else if (newlen > writer->size) {
246
77.4k
        if (writer->overallocate
247
74.8k
            && newlen <= (PY_SSIZE_T_MAX - newlen / OVERALLOCATE_FACTOR)) {
248
            /* overallocate to limit the number of realloc() */
249
74.8k
            newlen += newlen / OVERALLOCATE_FACTOR;
250
74.8k
        }
251
77.4k
        if (newlen < writer->min_length)
252
0
            newlen = writer->min_length;
253
254
77.4k
        if (maxchar > writer->maxchar || writer->readonly) {
255
            /* resize + widen */
256
25.3k
            maxchar = Py_MAX(maxchar, writer->maxchar);
257
25.3k
            newbuffer = PyUnicode_New(newlen, maxchar);
258
25.3k
            if (newbuffer == NULL)
259
0
                return -1;
260
25.3k
            _PyUnicode_FastCopyCharacters(newbuffer, 0,
261
25.3k
                                          writer->buffer, 0, writer->pos);
262
25.3k
            Py_DECREF(writer->buffer);
263
25.3k
            writer->readonly = 0;
264
25.3k
        }
265
52.0k
        else {
266
52.0k
            newbuffer = _PyUnicode_ResizeCompact(writer->buffer, newlen);
267
52.0k
            if (newbuffer == NULL)
268
0
                return -1;
269
52.0k
        }
270
77.4k
        writer->buffer = newbuffer;
271
77.4k
    }
272
17.3k
    else if (maxchar > writer->maxchar) {
273
17.3k
        assert(!writer->readonly);
274
17.3k
        newbuffer = PyUnicode_New(writer->size, maxchar);
275
17.3k
        if (newbuffer == NULL)
276
0
            return -1;
277
17.3k
        _PyUnicode_FastCopyCharacters(newbuffer, 0,
278
17.3k
                                      writer->buffer, 0, writer->pos);
279
17.3k
        Py_SETREF(writer->buffer, newbuffer);
280
17.3k
    }
281
1.51M
    _PyUnicodeWriter_Update(writer);
282
1.51M
    return 0;
283
284
1.51M
#undef OVERALLOCATE_FACTOR
285
1.51M
}
286
287
int
288
_PyUnicodeWriter_PrepareKindInternal(_PyUnicodeWriter *writer,
289
                                     int kind)
290
181
{
291
181
    Py_UCS4 maxchar;
292
293
    /* ensure that the _PyUnicodeWriter_PrepareKind macro was used */
294
181
    assert(writer->kind < kind);
295
296
181
    switch (kind)
297
181
    {
298
0
    case PyUnicode_1BYTE_KIND: maxchar = 0xff; break;
299
181
    case PyUnicode_2BYTE_KIND: maxchar = 0xffff; break;
300
0
    case PyUnicode_4BYTE_KIND: maxchar = _Py_MAX_UNICODE; break;
301
0
    default:
302
0
        Py_UNREACHABLE();
303
181
    }
304
305
181
    return _PyUnicodeWriter_PrepareInternal(writer, 0, maxchar);
306
181
}
307
308
309
int
310
_PyUnicodeWriter_WriteChar(_PyUnicodeWriter *writer, Py_UCS4 ch)
311
413k
{
312
413k
    return _PyUnicodeWriter_WriteCharInline(writer, ch);
313
413k
}
314
315
316
int
317
PyUnicodeWriter_WriteChar(PyUnicodeWriter *writer, Py_UCS4 ch)
318
413k
{
319
413k
    if (ch > _Py_MAX_UNICODE) {
320
0
        PyErr_SetString(PyExc_ValueError,
321
0
                        "character must be in range(0x110000)");
322
0
        return -1;
323
0
    }
324
325
413k
    return _PyUnicodeWriter_WriteChar((_PyUnicodeWriter*)writer, ch);
326
413k
}
327
328
329
int
330
_PyUnicodeWriter_WriteStr(_PyUnicodeWriter *writer, PyObject *str)
331
328k
{
332
328k
    assert(PyUnicode_Check(str));
333
334
328k
    Py_UCS4 maxchar;
335
328k
    Py_ssize_t len;
336
337
328k
    len = PyUnicode_GET_LENGTH(str);
338
328k
    if (len == 0)
339
0
        return 0;
340
328k
    maxchar = PyUnicode_MAX_CHAR_VALUE(str);
341
328k
    if (maxchar > writer->maxchar || len > writer->size - writer->pos) {
342
10.8k
        if (writer->buffer == NULL && !writer->overallocate) {
343
0
            assert(_PyUnicode_CheckConsistency(str, 1));
344
0
            writer->readonly = 1;
345
0
            writer->buffer = Py_NewRef(str);
346
0
            _PyUnicodeWriter_Update(writer);
347
0
            writer->pos += len;
348
0
            return 0;
349
0
        }
350
10.8k
        if (_PyUnicodeWriter_PrepareInternal(writer, len, maxchar) == -1)
351
0
            return -1;
352
10.8k
    }
353
328k
    _PyUnicode_FastCopyCharacters(writer->buffer, writer->pos,
354
328k
                                  str, 0, len);
355
328k
    writer->pos += len;
356
328k
    return 0;
357
328k
}
358
359
360
int
361
PyUnicodeWriter_WriteStr(PyUnicodeWriter *writer, PyObject *obj)
362
144
{
363
144
    PyTypeObject *type = Py_TYPE(obj);
364
144
    if (type == &PyUnicode_Type) {
365
144
        return _PyUnicodeWriter_WriteStr((_PyUnicodeWriter*)writer, obj);
366
144
    }
367
368
0
    if (type == &PyLong_Type) {
369
0
        return _PyLong_FormatWriter((_PyUnicodeWriter*)writer, obj, 10, 0);
370
0
    }
371
372
0
    PyObject *str = PyObject_Str(obj);
373
0
    if (str == NULL) {
374
0
        return -1;
375
0
    }
376
377
0
    int res = _PyUnicodeWriter_WriteStr((_PyUnicodeWriter*)writer, str);
378
0
    Py_DECREF(str);
379
0
    return res;
380
0
}
381
382
383
int
384
PyUnicodeWriter_WriteRepr(PyUnicodeWriter *writer, PyObject *obj)
385
0
{
386
0
    if (obj == NULL) {
387
0
        return _PyUnicodeWriter_WriteASCIIString((_PyUnicodeWriter*)writer, "<NULL>", 6);
388
0
    }
389
390
0
    if (Py_TYPE(obj) == &PyLong_Type) {
391
0
        return _PyLong_FormatWriter((_PyUnicodeWriter*)writer, obj, 10, 0);
392
0
    }
393
394
0
    PyObject *repr = PyObject_Repr(obj);
395
0
    if (repr == NULL) {
396
0
        return -1;
397
0
    }
398
399
0
    int res = _PyUnicodeWriter_WriteStr((_PyUnicodeWriter*)writer, repr);
400
0
    Py_DECREF(repr);
401
0
    return res;
402
0
}
403
404
405
int
406
_PyUnicodeWriter_WriteSubstring(_PyUnicodeWriter *writer, PyObject *str,
407
                                Py_ssize_t start, Py_ssize_t end)
408
2.05M
{
409
2.05M
    assert(0 <= start);
410
2.05M
    assert(end <= PyUnicode_GET_LENGTH(str));
411
2.05M
    assert(start <= end);
412
413
2.05M
    if (start == 0 && end == PyUnicode_GET_LENGTH(str))
414
0
        return _PyUnicodeWriter_WriteStr(writer, str);
415
416
2.05M
    Py_ssize_t len = end - start;
417
2.05M
    if (len == 0) {
418
0
        return 0;
419
0
    }
420
421
2.05M
    Py_UCS4 maxchar;
422
2.05M
    if (PyUnicode_MAX_CHAR_VALUE(str) > writer->maxchar) {
423
1.44M
        maxchar = _PyUnicode_FindMaxChar(str, start, end);
424
1.44M
    }
425
610k
    else {
426
610k
        maxchar = writer->maxchar;
427
610k
    }
428
2.05M
    if (_PyUnicodeWriter_Prepare(writer, len, maxchar) < 0) {
429
0
        return -1;
430
0
    }
431
432
2.05M
    _PyUnicode_FastCopyCharacters(writer->buffer, writer->pos,
433
2.05M
                                  str, start, len);
434
2.05M
    writer->pos += len;
435
2.05M
    return 0;
436
2.05M
}
437
438
439
int
440
PyUnicodeWriter_WriteSubstring(PyUnicodeWriter *writer, PyObject *str,
441
                               Py_ssize_t start, Py_ssize_t end)
442
416k
{
443
416k
    if (!PyUnicode_Check(str)) {
444
0
        PyErr_Format(PyExc_TypeError, "expect str, not %T", str);
445
0
        return -1;
446
0
    }
447
416k
    if (start < 0 || start > end) {
448
0
        PyErr_Format(PyExc_ValueError, "invalid start argument");
449
0
        return -1;
450
0
    }
451
416k
    if (end > PyUnicode_GET_LENGTH(str)) {
452
0
        PyErr_Format(PyExc_ValueError, "invalid end argument");
453
0
        return -1;
454
0
    }
455
456
416k
    return _PyUnicodeWriter_WriteSubstring((_PyUnicodeWriter*)writer, str,
457
416k
                                           start, end);
458
416k
}
459
460
461
int
462
_PyUnicodeWriter_WriteASCIIString(_PyUnicodeWriter *writer,
463
                                  const char *ascii, Py_ssize_t len)
464
42.8k
{
465
42.8k
    if (len == -1)
466
0
        len = strlen(ascii);
467
468
42.8k
    if (len == 0) {
469
0
        return 0;
470
0
    }
471
472
42.8k
    assert(ucs1lib_find_max_char((const Py_UCS1*)ascii, (const Py_UCS1*)ascii + len) < 128);
473
474
42.8k
    if (writer->buffer == NULL && !writer->overallocate) {
475
14.8k
        PyObject *str;
476
477
14.8k
        str = _PyUnicode_FromASCII(ascii, len);
478
14.8k
        if (str == NULL)
479
0
            return -1;
480
481
14.8k
        writer->readonly = 1;
482
14.8k
        writer->buffer = str;
483
14.8k
        _PyUnicodeWriter_Update(writer);
484
14.8k
        writer->pos += len;
485
14.8k
        return 0;
486
14.8k
    }
487
488
27.9k
    if (_PyUnicodeWriter_Prepare(writer, len, 127) == -1)
489
0
        return -1;
490
491
27.9k
    switch (writer->kind)
492
27.9k
    {
493
26.3k
    case PyUnicode_1BYTE_KIND:
494
26.3k
    {
495
26.3k
        const Py_UCS1 *str = (const Py_UCS1 *)ascii;
496
26.3k
        Py_UCS1 *data = writer->data;
497
498
26.3k
        memcpy(data + writer->pos, str, len);
499
26.3k
        break;
500
0
    }
501
934
    case PyUnicode_2BYTE_KIND:
502
934
    {
503
934
        _PyUnicode_CONVERT_BYTES(
504
934
            Py_UCS1, Py_UCS2,
505
934
            ascii, ascii + len,
506
934
            (Py_UCS2 *)writer->data + writer->pos);
507
934
        break;
508
0
    }
509
655
    case PyUnicode_4BYTE_KIND:
510
655
    {
511
655
        _PyUnicode_CONVERT_BYTES(
512
655
            Py_UCS1, Py_UCS4,
513
655
            ascii, ascii + len,
514
655
            (Py_UCS4 *)writer->data + writer->pos);
515
655
        break;
516
0
    }
517
0
    default:
518
0
        Py_UNREACHABLE();
519
27.9k
    }
520
521
27.9k
    writer->pos += len;
522
27.9k
    return 0;
523
27.9k
}
524
525
526
int
527
PyUnicodeWriter_WriteASCII(PyUnicodeWriter *writer,
528
                           const char *str,
529
                           Py_ssize_t size)
530
39
{
531
39
    assert(writer != NULL);
532
39
    _Py_AssertHoldsTstate();
533
534
39
    _PyUnicodeWriter *priv_writer = (_PyUnicodeWriter*)writer;
535
39
    return _PyUnicodeWriter_WriteASCIIString(priv_writer, str, size);
536
39
}
537
538
539
int
540
PyUnicodeWriter_WriteUTF8(PyUnicodeWriter *writer,
541
                          const char *str,
542
                          Py_ssize_t size)
543
33
{
544
33
    if (size < 0) {
545
33
        size = strlen(str);
546
33
    }
547
548
33
    _PyUnicodeWriter *_writer = (_PyUnicodeWriter*)writer;
549
33
    Py_ssize_t old_pos = _writer->pos;
550
33
    int res = _PyUnicode_DecodeUTF8Writer(_writer, str, size,
551
33
                                          _Py_ERROR_STRICT, NULL, NULL);
552
33
    if (res < 0) {
553
0
        _writer->pos = old_pos;
554
0
    }
555
33
    return res;
556
33
}
557
558
559
int
560
PyUnicodeWriter_DecodeUTF8Stateful(PyUnicodeWriter *writer,
561
                                   const char *string,
562
                                   Py_ssize_t length,
563
                                   const char *errors,
564
                                   Py_ssize_t *consumed)
565
0
{
566
0
    if (length < 0) {
567
0
        length = strlen(string);
568
0
    }
569
570
0
    _PyUnicodeWriter *_writer = (_PyUnicodeWriter*)writer;
571
0
    Py_ssize_t old_pos = _writer->pos;
572
0
    int res = _PyUnicode_DecodeUTF8Writer(_writer, string, length,
573
0
                                          _Py_ERROR_UNKNOWN, errors,
574
0
                                          consumed);
575
0
    if (res < 0) {
576
0
        _writer->pos = old_pos;
577
0
        if (consumed) {
578
0
            *consumed = 0;
579
0
        }
580
0
    }
581
0
    return res;
582
0
}
583
584
585
int
586
_PyUnicodeWriter_WriteLatin1String(_PyUnicodeWriter *writer,
587
                                   const char *str, Py_ssize_t len)
588
0
{
589
0
    Py_UCS4 maxchar;
590
591
0
    maxchar = ucs1lib_find_max_char((const Py_UCS1*)str, (const Py_UCS1*)str + len);
592
0
    if (_PyUnicodeWriter_Prepare(writer, len, maxchar) == -1)
593
0
        return -1;
594
0
    unicode_write_cstr(writer->buffer, writer->pos, str, len);
595
0
    writer->pos += len;
596
0
    return 0;
597
0
}
598
599
600
PyObject *
601
_PyUnicodeWriter_Finish(_PyUnicodeWriter *writer)
602
1.82M
{
603
1.82M
    PyObject *str;
604
605
1.82M
    if (writer->pos == 0) {
606
0
        Py_CLEAR(writer->buffer);
607
0
        return _PyUnicode_GetEmpty();
608
0
    }
609
610
1.82M
    str = writer->buffer;
611
1.82M
    writer->buffer = NULL;
612
613
1.82M
    if (writer->readonly) {
614
14.8k
        assert(PyUnicode_GET_LENGTH(str) == writer->pos);
615
14.8k
        return str;
616
14.8k
    }
617
618
1.81M
    if (PyUnicode_GET_LENGTH(str) != writer->pos) {
619
1.40M
        PyObject *str2;
620
1.40M
        str2 = _PyUnicode_ResizeCompact(str, writer->pos);
621
1.40M
        if (str2 == NULL) {
622
0
            Py_DECREF(str);
623
0
            return NULL;
624
0
        }
625
1.40M
        str = str2;
626
1.40M
    }
627
628
1.81M
    assert(_PyUnicode_CheckConsistency(str, 1));
629
1.81M
    return _PyUnicode_Result(str);
630
1.81M
}
631
632
633
PyObject*
634
PyUnicodeWriter_Finish(PyUnicodeWriter *writer)
635
58.5k
{
636
58.5k
    PyObject *str = _PyUnicodeWriter_Finish((_PyUnicodeWriter*)writer);
637
58.5k
    assert(((_PyUnicodeWriter*)writer)->buffer == NULL);
638
58.5k
    _Py_FREELIST_FREE(unicode_writers, writer, PyMem_Free);
639
58.5k
    return str;
640
58.5k
}
641
642
643
void
644
_PyUnicodeWriter_Dealloc(_PyUnicodeWriter *writer)
645
3.79k
{
646
    Py_CLEAR(writer->buffer);
647
3.79k
}