Coverage Report

Created: 2026-05-16 06:46

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cpython/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
78.8M
#  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
84.9M
{
121
84.9M
    writer->maxchar = PyUnicode_MAX_CHAR_VALUE(writer->buffer);
122
84.9M
    writer->data = PyUnicode_DATA(writer->buffer);
123
124
84.9M
    if (!writer->readonly) {
125
84.8M
        writer->kind = PyUnicode_KIND(writer->buffer);
126
84.8M
        writer->size = PyUnicode_GET_LENGTH(writer->buffer);
127
84.8M
    }
128
95.7k
    else {
129
        /* use a value smaller than PyUnicode_1BYTE_KIND() so
130
           _PyUnicodeWriter_PrepareKind() will copy the buffer. */
131
95.7k
        writer->kind = 0;
132
95.7k
        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
95.7k
        writer->size = 0;
138
95.7k
    }
139
84.9M
}
140
141
142
void
143
_PyUnicodeWriter_Init(_PyUnicodeWriter *writer)
144
41.1M
{
145
41.1M
    memset(writer, 0, sizeof(*writer));
146
147
    /* ASCII is the bare minimum */
148
41.1M
    writer->min_char = 127;
149
150
    /* use a kind value smaller than PyUnicode_1BYTE_KIND so
151
       _PyUnicodeWriter_PrepareKind() will copy the buffer. */
152
41.1M
    assert(writer->kind == 0);
153
41.1M
    assert(writer->kind < PyUnicode_1BYTE_KIND);
154
41.1M
}
155
156
157
PyUnicodeWriter*
158
PyUnicodeWriter_Create(Py_ssize_t length)
159
3.80M
{
160
3.80M
    if (length < 0) {
161
0
        PyErr_SetString(PyExc_ValueError,
162
0
                        "length must be positive");
163
0
        return NULL;
164
0
    }
165
166
3.80M
    const size_t size = sizeof(_PyUnicodeWriter);
167
3.80M
    PyUnicodeWriter *pub_writer;
168
3.80M
    pub_writer = _Py_FREELIST_POP_MEM(unicode_writers);
169
3.80M
    if (pub_writer == NULL) {
170
1.98M
        pub_writer = (PyUnicodeWriter *)PyMem_Malloc(size);
171
1.98M
        if (pub_writer == NULL) {
172
0
            return (PyUnicodeWriter *)PyErr_NoMemory();
173
0
        }
174
1.98M
    }
175
3.80M
    _PyUnicodeWriter *writer = (_PyUnicodeWriter *)pub_writer;
176
177
3.80M
    _PyUnicodeWriter_Init(writer);
178
3.80M
    if (_PyUnicodeWriter_Prepare(writer, length, 127) < 0) {
179
0
        PyUnicodeWriter_Discard(pub_writer);
180
0
        return NULL;
181
0
    }
182
3.80M
    writer->overallocate = 1;
183
184
3.80M
    return pub_writer;
185
3.80M
}
186
187
188
void PyUnicodeWriter_Discard(PyUnicodeWriter *writer)
189
75.5k
{
190
75.5k
    if (writer == NULL) {
191
74.8k
        return;
192
74.8k
    }
193
697
    _PyUnicodeWriter_Dealloc((_PyUnicodeWriter*)writer);
194
697
    _Py_FREELIST_FREE(unicode_writers, writer, PyMem_Free);
195
697
}
196
197
198
// Initialize _PyUnicodeWriter with initial buffer
199
void
200
_PyUnicodeWriter_InitWithBuffer(_PyUnicodeWriter *writer, PyObject *buffer)
201
18.2M
{
202
18.2M
    memset(writer, 0, sizeof(*writer));
203
18.2M
    writer->buffer = buffer;
204
18.2M
    _PyUnicodeWriter_Update(writer);
205
18.2M
    writer->min_length = writer->size;
206
18.2M
}
207
208
209
int
210
_PyUnicodeWriter_PrepareInternal(_PyUnicodeWriter *writer,
211
                                 Py_ssize_t length, Py_UCS4 maxchar)
212
66.6M
{
213
66.6M
    Py_ssize_t newlen;
214
66.6M
    PyObject *newbuffer;
215
216
66.6M
    assert(length >= 0);
217
66.6M
    assert(maxchar <= _Py_MAX_UNICODE);
218
219
    /* ensure that the _PyUnicodeWriter_Prepare macro was used */
220
66.6M
    assert((maxchar > writer->maxchar && length >= 0)
221
66.6M
           || length > 0);
222
223
66.6M
    if (length > PY_SSIZE_T_MAX - writer->pos) {
224
0
        PyErr_NoMemory();
225
0
        return -1;
226
0
    }
227
66.6M
    newlen = writer->pos + length;
228
229
66.6M
    maxchar = Py_MAX(maxchar, writer->min_char);
230
231
66.6M
    if (writer->buffer == NULL) {
232
39.9M
        assert(!writer->readonly);
233
39.9M
        if (writer->overallocate
234
30.7M
            && newlen <= (PY_SSIZE_T_MAX - newlen / OVERALLOCATE_FACTOR)) {
235
            /* overallocate to limit the number of realloc() */
236
30.7M
            newlen += newlen / OVERALLOCATE_FACTOR;
237
30.7M
        }
238
39.9M
        if (newlen < writer->min_length)
239
31.7M
            newlen = writer->min_length;
240
241
39.9M
        writer->buffer = PyUnicode_New(newlen, maxchar);
242
39.9M
        if (writer->buffer == NULL)
243
0
            return -1;
244
39.9M
    }
245
26.6M
    else if (newlen > writer->size) {
246
9.02M
        if (writer->overallocate
247
8.68M
            && newlen <= (PY_SSIZE_T_MAX - newlen / OVERALLOCATE_FACTOR)) {
248
            /* overallocate to limit the number of realloc() */
249
8.68M
            newlen += newlen / OVERALLOCATE_FACTOR;
250
8.68M
        }
251
9.02M
        if (newlen < writer->min_length)
252
1.29k
            newlen = writer->min_length;
253
254
9.02M
        if (maxchar > writer->maxchar || writer->readonly) {
255
            /* resize + widen */
256
2.52M
            maxchar = Py_MAX(maxchar, writer->maxchar);
257
2.52M
            newbuffer = PyUnicode_New(newlen, maxchar);
258
2.52M
            if (newbuffer == NULL)
259
0
                return -1;
260
2.52M
            _PyUnicode_FastCopyCharacters(newbuffer, 0,
261
2.52M
                                          writer->buffer, 0, writer->pos);
262
2.52M
            Py_DECREF(writer->buffer);
263
2.52M
            writer->readonly = 0;
264
2.52M
        }
265
6.49M
        else {
266
6.49M
            newbuffer = _PyUnicode_ResizeCompact(writer->buffer, newlen);
267
6.49M
            if (newbuffer == NULL)
268
0
                return -1;
269
6.49M
        }
270
9.02M
        writer->buffer = newbuffer;
271
9.02M
    }
272
17.6M
    else if (maxchar > writer->maxchar) {
273
17.6M
        assert(!writer->readonly);
274
17.6M
        newbuffer = PyUnicode_New(writer->size, maxchar);
275
17.6M
        if (newbuffer == NULL)
276
0
            return -1;
277
17.6M
        _PyUnicode_FastCopyCharacters(newbuffer, 0,
278
17.6M
                                      writer->buffer, 0, writer->pos);
279
17.6M
        Py_SETREF(writer->buffer, newbuffer);
280
17.6M
    }
281
66.6M
    _PyUnicodeWriter_Update(writer);
282
66.6M
    return 0;
283
284
66.6M
#undef OVERALLOCATE_FACTOR
285
66.6M
}
286
287
int
288
_PyUnicodeWriter_PrepareKindInternal(_PyUnicodeWriter *writer,
289
                                     int kind)
290
188k
{
291
188k
    Py_UCS4 maxchar;
292
293
    /* ensure that the _PyUnicodeWriter_PrepareKind macro was used */
294
188k
    assert(writer->kind < kind);
295
296
188k
    switch (kind)
297
188k
    {
298
0
    case PyUnicode_1BYTE_KIND: maxchar = 0xff; break;
299
188k
    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
188k
    }
304
305
188k
    return _PyUnicodeWriter_PrepareInternal(writer, 0, maxchar);
306
188k
}
307
308
309
int
310
_PyUnicodeWriter_WriteChar(_PyUnicodeWriter *writer, Py_UCS4 ch)
311
122M
{
312
122M
    return _PyUnicodeWriter_WriteCharInline(writer, ch);
313
122M
}
314
315
316
int
317
PyUnicodeWriter_WriteChar(PyUnicodeWriter *writer, Py_UCS4 ch)
318
78.8M
{
319
78.8M
    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
78.8M
    return _PyUnicodeWriter_WriteChar((_PyUnicodeWriter*)writer, ch);
326
78.8M
}
327
328
329
int
330
_PyUnicodeWriter_WriteStr(_PyUnicodeWriter *writer, PyObject *str)
331
54.4M
{
332
54.4M
    assert(PyUnicode_Check(str));
333
334
54.4M
    Py_UCS4 maxchar;
335
54.4M
    Py_ssize_t len;
336
337
54.4M
    len = PyUnicode_GET_LENGTH(str);
338
54.4M
    if (len == 0)
339
5.22M
        return 0;
340
49.1M
    maxchar = PyUnicode_MAX_CHAR_VALUE(str);
341
49.1M
    if (maxchar > writer->maxchar || len > writer->size - writer->pos) {
342
16.3M
        if (writer->buffer == NULL && !writer->overallocate) {
343
6.83k
            assert(_PyUnicode_CheckConsistency(str, 1));
344
6.83k
            writer->readonly = 1;
345
6.83k
            writer->buffer = Py_NewRef(str);
346
6.83k
            _PyUnicodeWriter_Update(writer);
347
6.83k
            writer->pos += len;
348
6.83k
            return 0;
349
6.83k
        }
350
16.3M
        if (_PyUnicodeWriter_PrepareInternal(writer, len, maxchar) == -1)
351
0
            return -1;
352
16.3M
    }
353
49.1M
    _PyUnicode_FastCopyCharacters(writer->buffer, writer->pos,
354
49.1M
                                  str, 0, len);
355
49.1M
    writer->pos += len;
356
49.1M
    return 0;
357
49.1M
}
358
359
360
int
361
PyUnicodeWriter_WriteStr(PyUnicodeWriter *writer, PyObject *obj)
362
3.72M
{
363
3.72M
    PyTypeObject *type = Py_TYPE(obj);
364
3.72M
    if (type == &PyUnicode_Type) {
365
3.72M
        return _PyUnicodeWriter_WriteStr((_PyUnicodeWriter*)writer, obj);
366
3.72M
    }
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
7.39M
{
386
7.39M
    if (obj == NULL) {
387
0
        return _PyUnicodeWriter_WriteASCIIString((_PyUnicodeWriter*)writer, "<NULL>", 6);
388
0
    }
389
390
7.39M
    if (Py_TYPE(obj) == &PyLong_Type) {
391
517k
        return _PyLong_FormatWriter((_PyUnicodeWriter*)writer, obj, 10, 0);
392
517k
    }
393
394
6.87M
    PyObject *repr = PyObject_Repr(obj);
395
6.87M
    if (repr == NULL) {
396
0
        return -1;
397
0
    }
398
399
6.87M
    int res = _PyUnicodeWriter_WriteStr((_PyUnicodeWriter*)writer, repr);
400
6.87M
    Py_DECREF(repr);
401
6.87M
    return res;
402
6.87M
}
403
404
405
int
406
_PyUnicodeWriter_WriteSubstring(_PyUnicodeWriter *writer, PyObject *str,
407
                                Py_ssize_t start, Py_ssize_t end)
408
41.7M
{
409
41.7M
    assert(0 <= start);
410
41.7M
    assert(end <= PyUnicode_GET_LENGTH(str));
411
41.7M
    assert(start <= end);
412
413
41.7M
    if (start == 0 && end == PyUnicode_GET_LENGTH(str))
414
90
        return _PyUnicodeWriter_WriteStr(writer, str);
415
416
41.7M
    Py_ssize_t len = end - start;
417
41.7M
    if (len == 0) {
418
192
        return 0;
419
192
    }
420
421
41.7M
    Py_UCS4 maxchar;
422
41.7M
    if (PyUnicode_MAX_CHAR_VALUE(str) > writer->maxchar) {
423
11.2M
        maxchar = _PyUnicode_FindMaxChar(str, start, end);
424
11.2M
    }
425
30.5M
    else {
426
30.5M
        maxchar = writer->maxchar;
427
30.5M
    }
428
41.7M
    if (_PyUnicodeWriter_Prepare(writer, len, maxchar) < 0) {
429
0
        return -1;
430
0
    }
431
432
41.7M
    _PyUnicode_FastCopyCharacters(writer->buffer, writer->pos,
433
41.7M
                                  str, start, len);
434
41.7M
    writer->pos += len;
435
41.7M
    return 0;
436
41.7M
}
437
438
439
int
440
PyUnicodeWriter_WriteSubstring(PyUnicodeWriter *writer, PyObject *str,
441
                               Py_ssize_t start, Py_ssize_t end)
442
660k
{
443
660k
    if (!PyUnicode_Check(str)) {
444
0
        PyErr_Format(PyExc_TypeError, "expect str, not %T", str);
445
0
        return -1;
446
0
    }
447
660k
    if (start < 0 || start > end) {
448
0
        PyErr_Format(PyExc_ValueError, "invalid start argument");
449
0
        return -1;
450
0
    }
451
660k
    if (end > PyUnicode_GET_LENGTH(str)) {
452
0
        PyErr_Format(PyExc_ValueError, "invalid end argument");
453
0
        return -1;
454
0
    }
455
456
660k
    return _PyUnicodeWriter_WriteSubstring((_PyUnicodeWriter*)writer, str,
457
660k
                                           start, end);
458
660k
}
459
460
461
int
462
_PyUnicodeWriter_WriteASCIIString(_PyUnicodeWriter *writer,
463
                                  const char *ascii, Py_ssize_t len)
464
41.6M
{
465
41.6M
    if (len == -1)
466
0
        len = strlen(ascii);
467
468
41.6M
    if (len == 0) {
469
231k
        return 0;
470
231k
    }
471
472
41.6M
    assert(ucs1lib_find_max_char((const Py_UCS1*)ascii, (const Py_UCS1*)ascii + len) < 128);
473
474
41.4M
    if (writer->buffer == NULL && !writer->overallocate) {
475
88.9k
        PyObject *str;
476
477
88.9k
        str = _PyUnicode_FromASCII(ascii, len);
478
88.9k
        if (str == NULL)
479
0
            return -1;
480
481
88.9k
        writer->readonly = 1;
482
88.9k
        writer->buffer = str;
483
88.9k
        _PyUnicodeWriter_Update(writer);
484
88.9k
        writer->pos += len;
485
88.9k
        return 0;
486
88.9k
    }
487
488
41.3M
    if (_PyUnicodeWriter_Prepare(writer, len, 127) == -1)
489
0
        return -1;
490
491
41.3M
    switch (writer->kind)
492
41.3M
    {
493
41.3M
    case PyUnicode_1BYTE_KIND:
494
41.3M
    {
495
41.3M
        const Py_UCS1 *str = (const Py_UCS1 *)ascii;
496
41.3M
        Py_UCS1 *data = writer->data;
497
498
41.3M
        memcpy(data + writer->pos, str, len);
499
41.3M
        break;
500
0
    }
501
9.96k
    case PyUnicode_2BYTE_KIND:
502
9.96k
    {
503
9.96k
        _PyUnicode_CONVERT_BYTES(
504
9.96k
            Py_UCS1, Py_UCS2,
505
9.96k
            ascii, ascii + len,
506
9.96k
            (Py_UCS2 *)writer->data + writer->pos);
507
9.96k
        break;
508
0
    }
509
4.51k
    case PyUnicode_4BYTE_KIND:
510
4.51k
    {
511
4.51k
        _PyUnicode_CONVERT_BYTES(
512
4.51k
            Py_UCS1, Py_UCS4,
513
4.51k
            ascii, ascii + len,
514
4.51k
            (Py_UCS4 *)writer->data + writer->pos);
515
4.51k
        break;
516
0
    }
517
0
    default:
518
0
        Py_UNREACHABLE();
519
41.3M
    }
520
521
41.3M
    writer->pos += len;
522
41.3M
    return 0;
523
41.3M
}
524
525
526
int
527
PyUnicodeWriter_WriteASCII(PyUnicodeWriter *writer,
528
                           const char *str,
529
                           Py_ssize_t size)
530
738k
{
531
738k
    assert(writer != NULL);
532
738k
    _Py_AssertHoldsTstate();
533
534
738k
    _PyUnicodeWriter *priv_writer = (_PyUnicodeWriter*)writer;
535
738k
    return _PyUnicodeWriter_WriteASCIIString(priv_writer, str, size);
536
738k
}
537
538
539
int
540
PyUnicodeWriter_WriteUTF8(PyUnicodeWriter *writer,
541
                          const char *str,
542
                          Py_ssize_t size)
543
4
{
544
4
    if (size < 0) {
545
4
        size = strlen(str);
546
4
    }
547
548
4
    _PyUnicodeWriter *_writer = (_PyUnicodeWriter*)writer;
549
4
    Py_ssize_t old_pos = _writer->pos;
550
4
    int res = _PyUnicode_DecodeUTF8Writer(_writer, str, size,
551
4
                                          _Py_ERROR_STRICT, NULL, NULL);
552
4
    if (res < 0) {
553
0
        _writer->pos = old_pos;
554
0
    }
555
4
    return res;
556
4
}
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
56.0M
{
603
56.0M
    PyObject *str;
604
605
56.0M
    if (writer->pos == 0) {
606
882
        Py_CLEAR(writer->buffer);
607
882
        return _PyUnicode_GetEmpty();
608
882
    }
609
610
56.0M
    str = writer->buffer;
611
56.0M
    writer->buffer = NULL;
612
613
56.0M
    if (writer->readonly) {
614
94.4k
        assert(PyUnicode_GET_LENGTH(str) == writer->pos);
615
94.4k
        return str;
616
94.4k
    }
617
618
55.9M
    if (PyUnicode_GET_LENGTH(str) != writer->pos) {
619
50.4M
        PyObject *str2;
620
50.4M
        str2 = _PyUnicode_ResizeCompact(str, writer->pos);
621
50.4M
        if (str2 == NULL) {
622
0
            Py_DECREF(str);
623
0
            return NULL;
624
0
        }
625
50.4M
        str = str2;
626
50.4M
    }
627
628
55.9M
    assert(_PyUnicode_CheckConsistency(str, 1));
629
55.9M
    return _PyUnicode_Result(str);
630
55.9M
}
631
632
633
PyObject*
634
PyUnicodeWriter_Finish(PyUnicodeWriter *writer)
635
3.80M
{
636
3.80M
    PyObject *str = _PyUnicodeWriter_Finish((_PyUnicodeWriter*)writer);
637
3.80M
    assert(((_PyUnicodeWriter*)writer)->buffer == NULL);
638
3.80M
    _Py_FREELIST_FREE(unicode_writers, writer, PyMem_Free);
639
3.80M
    return str;
640
3.80M
}
641
642
643
void
644
_PyUnicodeWriter_Dealloc(_PyUnicodeWriter *writer)
645
3.30M
{
646
    Py_CLEAR(writer->buffer);
647
3.30M
}