Coverage Report

Created: 2025-07-04 06:49

/src/cpython/Objects/bytearrayobject.c
Line
Count
Source (jump to first uncovered line)
1
/* PyByteArray (bytearray) implementation */
2
3
#include "Python.h"
4
#include "pycore_abstract.h"      // _PyIndex_Check()
5
#include "pycore_bytes_methods.h"
6
#include "pycore_bytesobject.h"
7
#include "pycore_ceval.h"         // _PyEval_GetBuiltin()
8
#include "pycore_critical_section.h"
9
#include "pycore_object.h"        // _PyObject_GC_UNTRACK()
10
#include "pycore_strhex.h"        // _Py_strhex_with_sep()
11
#include "pycore_long.h"          // _PyLong_FromUnsignedChar()
12
#include "pycore_pyatomic_ft_wrappers.h"
13
#include "bytesobject.h"
14
15
/*[clinic input]
16
class bytearray "PyByteArrayObject *" "&PyByteArray_Type"
17
[clinic start generated code]*/
18
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=5535b77c37a119e0]*/
19
20
/* For PyByteArray_AS_STRING(). */
21
char _PyByteArray_empty_string[] = "";
22
23
/* Helpers */
24
25
static int
26
_getbytevalue(PyObject* arg, int *value)
27
589k
{
28
589k
    int overflow;
29
589k
    long face_value = PyLong_AsLongAndOverflow(arg, &overflow);
30
31
589k
    if (face_value == -1 && PyErr_Occurred()) {
32
0
        *value = -1;
33
0
        return 0;
34
0
    }
35
589k
    if (face_value < 0 || face_value >= 256) {
36
        /* this includes an overflow in converting to C long */
37
0
        PyErr_SetString(PyExc_ValueError, "byte must be in range(0, 256)");
38
0
        *value = -1;
39
0
        return 0;
40
0
    }
41
42
589k
    *value = face_value;
43
589k
    return 1;
44
589k
}
45
46
static int
47
bytearray_getbuffer_lock_held(PyObject *self, Py_buffer *view, int flags)
48
936k
{
49
936k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(self);
50
936k
    PyByteArrayObject *obj = _PyByteArray_CAST(self);
51
936k
    if (view == NULL) {
52
0
        PyErr_SetString(PyExc_BufferError,
53
0
            "bytearray_getbuffer: view==NULL argument is obsolete");
54
0
        return -1;
55
0
    }
56
57
936k
    void *ptr = (void *) PyByteArray_AS_STRING(obj);
58
936k
    if (PyBuffer_FillInfo(view, (PyObject*)obj, ptr, Py_SIZE(obj), 0, flags) < 0) {
59
0
        return -1;
60
0
    }
61
936k
    obj->ob_exports++;
62
936k
    return 0;
63
936k
}
64
65
static int
66
bytearray_getbuffer(PyObject *self, Py_buffer *view, int flags)
67
936k
{
68
936k
    int ret;
69
936k
    Py_BEGIN_CRITICAL_SECTION(self);
70
936k
    ret = bytearray_getbuffer_lock_held(self, view, flags);
71
936k
    Py_END_CRITICAL_SECTION();
72
936k
    return ret;
73
936k
}
74
75
static void
76
bytearray_releasebuffer(PyObject *self, Py_buffer *view)
77
936k
{
78
936k
    Py_BEGIN_CRITICAL_SECTION(self);
79
936k
    PyByteArrayObject *obj = _PyByteArray_CAST(self);
80
936k
    obj->ob_exports--;
81
936k
    assert(obj->ob_exports >= 0);
82
936k
    Py_END_CRITICAL_SECTION();
83
936k
}
84
85
static int
86
_canresize(PyByteArrayObject *self)
87
5.62M
{
88
5.62M
    if (self->ob_exports > 0) {
89
0
        PyErr_SetString(PyExc_BufferError,
90
0
                "Existing exports of data: object cannot be re-sized");
91
0
        return 0;
92
0
    }
93
5.62M
    return 1;
94
5.62M
}
95
96
#include "clinic/bytearrayobject.c.h"
97
98
/* Direct API functions */
99
100
PyObject *
101
PyByteArray_FromObject(PyObject *input)
102
0
{
103
0
    return PyObject_CallOneArg((PyObject *)&PyByteArray_Type, input);
104
0
}
105
106
static PyObject *
107
_PyByteArray_FromBufferObject(PyObject *obj)
108
0
{
109
0
    PyObject *result;
110
0
    Py_buffer view;
111
112
0
    if (PyObject_GetBuffer(obj, &view, PyBUF_FULL_RO) < 0) {
113
0
        return NULL;
114
0
    }
115
0
    result = PyByteArray_FromStringAndSize(NULL, view.len);
116
0
    if (result != NULL &&
117
0
        PyBuffer_ToContiguous(PyByteArray_AS_STRING(result),
118
0
                              &view, view.len, 'C') < 0)
119
0
    {
120
0
        Py_CLEAR(result);
121
0
    }
122
0
    PyBuffer_Release(&view);
123
0
    return result;
124
0
}
125
126
PyObject *
127
PyByteArray_FromStringAndSize(const char *bytes, Py_ssize_t size)
128
1.37k
{
129
1.37k
    PyByteArrayObject *new;
130
1.37k
    Py_ssize_t alloc;
131
132
1.37k
    if (size < 0) {
133
0
        PyErr_SetString(PyExc_SystemError,
134
0
            "Negative size passed to PyByteArray_FromStringAndSize");
135
0
        return NULL;
136
0
    }
137
138
    /* Prevent buffer overflow when setting alloc to size+1. */
139
1.37k
    if (size == PY_SSIZE_T_MAX) {
140
0
        return PyErr_NoMemory();
141
0
    }
142
143
1.37k
    new = PyObject_New(PyByteArrayObject, &PyByteArray_Type);
144
1.37k
    if (new == NULL)
145
0
        return NULL;
146
147
1.37k
    if (size == 0) {
148
0
        new->ob_bytes = NULL;
149
0
        alloc = 0;
150
0
    }
151
1.37k
    else {
152
1.37k
        alloc = size + 1;
153
1.37k
        new->ob_bytes = PyMem_Malloc(alloc);
154
1.37k
        if (new->ob_bytes == NULL) {
155
0
            Py_DECREF(new);
156
0
            return PyErr_NoMemory();
157
0
        }
158
1.37k
        if (bytes != NULL && size > 0)
159
1.12k
            memcpy(new->ob_bytes, bytes, size);
160
1.37k
        new->ob_bytes[size] = '\0';  /* Trailing null byte */
161
1.37k
    }
162
1.37k
    Py_SET_SIZE(new, size);
163
1.37k
    new->ob_alloc = alloc;
164
1.37k
    new->ob_start = new->ob_bytes;
165
1.37k
    new->ob_exports = 0;
166
167
1.37k
    return (PyObject *)new;
168
1.37k
}
169
170
Py_ssize_t
171
PyByteArray_Size(PyObject *self)
172
0
{
173
0
    assert(self != NULL);
174
0
    assert(PyByteArray_Check(self));
175
176
0
    return PyByteArray_GET_SIZE(self);
177
0
}
178
179
char  *
180
PyByteArray_AsString(PyObject *self)
181
0
{
182
0
    assert(self != NULL);
183
0
    assert(PyByteArray_Check(self));
184
185
0
    return PyByteArray_AS_STRING(self);
186
0
}
187
188
static int
189
bytearray_resize_lock_held(PyObject *self, Py_ssize_t requested_size)
190
5.74M
{
191
5.74M
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(self);
192
5.74M
    void *sval;
193
5.74M
    PyByteArrayObject *obj = ((PyByteArrayObject *)self);
194
    /* All computations are done unsigned to avoid integer overflows
195
       (see issue #22335). */
196
5.74M
    size_t alloc = (size_t) obj->ob_alloc;
197
5.74M
    size_t logical_offset = (size_t) (obj->ob_start - obj->ob_bytes);
198
5.74M
    size_t size = (size_t) requested_size;
199
200
5.74M
    assert(self != NULL);
201
5.74M
    assert(PyByteArray_Check(self));
202
5.74M
    assert(logical_offset <= alloc);
203
204
5.74M
    if (requested_size < 0) {
205
0
        PyErr_Format(PyExc_ValueError,
206
0
            "Can only resize to positive sizes, got %zd", requested_size);
207
0
        return -1;
208
0
    }
209
210
5.74M
    if (requested_size == Py_SIZE(self)) {
211
116k
        return 0;
212
116k
    }
213
5.62M
    if (!_canresize(obj)) {
214
0
        return -1;
215
0
    }
216
217
5.62M
    if (size + logical_offset + 1 <= alloc) {
218
        /* Current buffer is large enough to host the requested size,
219
           decide on a strategy. */
220
4.01M
        if (size < alloc / 2) {
221
            /* Major downsize; resize down to exact size */
222
0
            alloc = size + 1;
223
0
        }
224
4.01M
        else {
225
            /* Minor downsize; quick exit */
226
4.01M
            Py_SET_SIZE(self, size);
227
4.01M
            PyByteArray_AS_STRING(self)[size] = '\0'; /* Trailing null */
228
4.01M
            return 0;
229
4.01M
        }
230
4.01M
    }
231
1.60M
    else {
232
        /* Need growing, decide on a strategy */
233
1.60M
        if (size <= alloc * 1.125) {
234
            /* Moderate upsize; overallocate similar to list_resize() */
235
643k
            alloc = size + (size >> 3) + (size < 9 ? 3 : 6);
236
643k
        }
237
965k
        else {
238
            /* Major upsize; resize up to exact size */
239
965k
            alloc = size + 1;
240
965k
        }
241
1.60M
    }
242
1.60M
    if (alloc > PY_SSIZE_T_MAX) {
243
0
        PyErr_NoMemory();
244
0
        return -1;
245
0
    }
246
247
1.60M
    if (logical_offset > 0) {
248
0
        sval = PyMem_Malloc(alloc);
249
0
        if (sval == NULL) {
250
0
            PyErr_NoMemory();
251
0
            return -1;
252
0
        }
253
0
        memcpy(sval, PyByteArray_AS_STRING(self),
254
0
               Py_MIN((size_t)requested_size, (size_t)Py_SIZE(self)));
255
0
        PyMem_Free(obj->ob_bytes);
256
0
    }
257
1.60M
    else {
258
1.60M
        sval = PyMem_Realloc(obj->ob_bytes, alloc);
259
1.60M
        if (sval == NULL) {
260
0
            PyErr_NoMemory();
261
0
            return -1;
262
0
        }
263
1.60M
    }
264
265
1.60M
    obj->ob_bytes = obj->ob_start = sval;
266
1.60M
    Py_SET_SIZE(self, size);
267
1.60M
    FT_ATOMIC_STORE_SSIZE_RELAXED(obj->ob_alloc, alloc);
268
1.60M
    obj->ob_bytes[size] = '\0'; /* Trailing null byte */
269
270
1.60M
    return 0;
271
1.60M
}
272
273
int
274
PyByteArray_Resize(PyObject *self, Py_ssize_t requested_size)
275
519k
{
276
519k
    int ret;
277
519k
    Py_BEGIN_CRITICAL_SECTION(self);
278
519k
    ret = bytearray_resize_lock_held(self, requested_size);
279
519k
    Py_END_CRITICAL_SECTION();
280
519k
    return ret;
281
519k
}
282
283
PyObject *
284
PyByteArray_Concat(PyObject *a, PyObject *b)
285
0
{
286
0
    Py_buffer va, vb;
287
0
    PyByteArrayObject *result = NULL;
288
289
0
    va.len = -1;
290
0
    vb.len = -1;
291
0
    if (PyObject_GetBuffer(a, &va, PyBUF_SIMPLE) != 0 ||
292
0
        PyObject_GetBuffer(b, &vb, PyBUF_SIMPLE) != 0) {
293
0
            PyErr_Format(PyExc_TypeError, "can't concat %.100s to %.100s",
294
0
                         Py_TYPE(b)->tp_name, Py_TYPE(a)->tp_name);
295
0
            goto done;
296
0
    }
297
298
0
    if (va.len > PY_SSIZE_T_MAX - vb.len) {
299
0
        PyErr_NoMemory();
300
0
        goto done;
301
0
    }
302
303
0
    result = (PyByteArrayObject *) \
304
0
        PyByteArray_FromStringAndSize(NULL, va.len + vb.len);
305
    // result->ob_bytes is NULL if result is an empty bytearray:
306
    // if va.len + vb.len equals zero.
307
0
    if (result != NULL && result->ob_bytes != NULL) {
308
0
        memcpy(result->ob_bytes, va.buf, va.len);
309
0
        memcpy(result->ob_bytes + va.len, vb.buf, vb.len);
310
0
    }
311
312
0
  done:
313
0
    if (va.len != -1)
314
0
        PyBuffer_Release(&va);
315
0
    if (vb.len != -1)
316
0
        PyBuffer_Release(&vb);
317
0
    return (PyObject *)result;
318
0
}
319
320
/* Functions stuffed into the type object */
321
322
static Py_ssize_t
323
bytearray_length(PyObject *op)
324
484
{
325
484
    return PyByteArray_GET_SIZE(op);
326
484
}
327
328
static PyObject *
329
bytearray_iconcat_lock_held(PyObject *op, PyObject *other)
330
20
{
331
20
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(op);
332
20
    PyByteArrayObject *self = _PyByteArray_CAST(op);
333
334
20
    Py_buffer vo;
335
20
    if (PyObject_GetBuffer(other, &vo, PyBUF_SIMPLE) != 0) {
336
0
        PyErr_Format(PyExc_TypeError, "can't concat %.100s to %.100s",
337
0
                     Py_TYPE(other)->tp_name, Py_TYPE(self)->tp_name);
338
0
        return NULL;
339
0
    }
340
341
20
    Py_ssize_t size = Py_SIZE(self);
342
20
    if (size > PY_SSIZE_T_MAX - vo.len) {
343
0
        PyBuffer_Release(&vo);
344
0
        return PyErr_NoMemory();
345
0
    }
346
347
20
    if (bytearray_resize_lock_held((PyObject *)self, size + vo.len) < 0) {
348
0
        PyBuffer_Release(&vo);
349
0
        return NULL;
350
0
    }
351
352
20
    memcpy(PyByteArray_AS_STRING(self) + size, vo.buf, vo.len);
353
20
    PyBuffer_Release(&vo);
354
20
    return Py_NewRef(self);
355
20
}
356
357
static PyObject *
358
bytearray_iconcat(PyObject *op, PyObject *other)
359
20
{
360
20
    PyObject *ret;
361
20
    Py_BEGIN_CRITICAL_SECTION(op);
362
20
    ret = bytearray_iconcat_lock_held(op, other);
363
20
    Py_END_CRITICAL_SECTION();
364
20
    return ret;
365
20
}
366
367
static PyObject *
368
bytearray_repeat_lock_held(PyObject *op, Py_ssize_t count)
369
0
{
370
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(op);
371
0
    PyByteArrayObject *self = _PyByteArray_CAST(op);
372
0
    if (count < 0) {
373
0
        count = 0;
374
0
    }
375
0
    const Py_ssize_t mysize = Py_SIZE(self);
376
0
    if (count > 0 && mysize > PY_SSIZE_T_MAX / count) {
377
0
        return PyErr_NoMemory();
378
0
    }
379
0
    Py_ssize_t size = mysize * count;
380
381
0
    PyByteArrayObject* result = (PyByteArrayObject *)PyByteArray_FromStringAndSize(NULL, size);
382
0
    const char* buf = PyByteArray_AS_STRING(self);
383
0
    if (result != NULL && size != 0) {
384
0
        _PyBytes_Repeat(result->ob_bytes, size, buf, mysize);
385
0
    }
386
0
    return (PyObject *)result;
387
0
}
388
389
static PyObject *
390
bytearray_repeat(PyObject *op, Py_ssize_t count)
391
0
{
392
0
    PyObject *ret;
393
0
    Py_BEGIN_CRITICAL_SECTION(op);
394
0
    ret = bytearray_repeat_lock_held(op, count);
395
0
    Py_END_CRITICAL_SECTION();
396
0
    return ret;
397
0
}
398
399
static PyObject *
400
bytearray_irepeat_lock_held(PyObject *op, Py_ssize_t count)
401
0
{
402
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(op);
403
0
    PyByteArrayObject *self = _PyByteArray_CAST(op);
404
0
    if (count < 0) {
405
0
        count = 0;
406
0
    }
407
0
    else if (count == 1) {
408
0
        return Py_NewRef(self);
409
0
    }
410
411
0
    const Py_ssize_t mysize = Py_SIZE(self);
412
0
    if (count > 0 && mysize > PY_SSIZE_T_MAX / count) {
413
0
        return PyErr_NoMemory();
414
0
    }
415
0
    const Py_ssize_t size = mysize * count;
416
0
    if (bytearray_resize_lock_held((PyObject *)self, size) < 0) {
417
0
        return NULL;
418
0
    }
419
420
0
    char* buf = PyByteArray_AS_STRING(self);
421
0
    _PyBytes_Repeat(buf, size, buf, mysize);
422
423
0
    return Py_NewRef(self);
424
0
}
425
426
static PyObject *
427
bytearray_irepeat(PyObject *op, Py_ssize_t count)
428
0
{
429
0
    PyObject *ret;
430
0
    Py_BEGIN_CRITICAL_SECTION(op);
431
0
    ret = bytearray_irepeat_lock_held(op, count);
432
0
    Py_END_CRITICAL_SECTION();
433
0
    return ret;
434
0
}
435
436
static PyObject *
437
bytearray_getitem_lock_held(PyObject *op, Py_ssize_t i)
438
0
{
439
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(op);
440
0
    PyByteArrayObject *self = _PyByteArray_CAST(op);
441
0
    if (i < 0 || i >= Py_SIZE(self)) {
442
0
        PyErr_SetString(PyExc_IndexError, "bytearray index out of range");
443
0
        return NULL;
444
0
    }
445
0
    return _PyLong_FromUnsignedChar((unsigned char)(self->ob_start[i]));
446
0
}
447
448
static PyObject *
449
bytearray_getitem(PyObject *op, Py_ssize_t i)
450
0
{
451
0
    PyObject *ret;
452
0
    Py_BEGIN_CRITICAL_SECTION(op);
453
0
    ret = bytearray_getitem_lock_held(op, i);
454
0
    Py_END_CRITICAL_SECTION();
455
0
    return ret;
456
0
}
457
458
static PyObject *
459
bytearray_subscript_lock_held(PyObject *op, PyObject *index)
460
1.24k
{
461
1.24k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(op);
462
1.24k
    PyByteArrayObject *self = _PyByteArray_CAST(op);
463
1.24k
    if (_PyIndex_Check(index)) {
464
0
        Py_ssize_t i = PyNumber_AsSsize_t(index, PyExc_IndexError);
465
466
0
        if (i == -1 && PyErr_Occurred())
467
0
            return NULL;
468
469
0
        if (i < 0)
470
0
            i += PyByteArray_GET_SIZE(self);
471
472
0
        if (i < 0 || i >= Py_SIZE(self)) {
473
0
            PyErr_SetString(PyExc_IndexError, "bytearray index out of range");
474
0
            return NULL;
475
0
        }
476
0
        return _PyLong_FromUnsignedChar((unsigned char)(self->ob_start[i]));
477
0
    }
478
1.24k
    else if (PySlice_Check(index)) {
479
1.24k
        Py_ssize_t start, stop, step, slicelength, i;
480
1.24k
        size_t cur;
481
1.24k
        if (PySlice_Unpack(index, &start, &stop, &step) < 0) {
482
0
            return NULL;
483
0
        }
484
1.24k
        slicelength = PySlice_AdjustIndices(PyByteArray_GET_SIZE(self),
485
1.24k
                                            &start, &stop, step);
486
487
1.24k
        if (slicelength <= 0)
488
0
            return PyByteArray_FromStringAndSize("", 0);
489
1.24k
        else if (step == 1) {
490
1.12k
            return PyByteArray_FromStringAndSize(
491
1.12k
                PyByteArray_AS_STRING(self) + start, slicelength);
492
1.12k
        }
493
128
        else {
494
128
            char *source_buf = PyByteArray_AS_STRING(self);
495
128
            char *result_buf;
496
128
            PyObject *result;
497
498
128
            result = PyByteArray_FromStringAndSize(NULL, slicelength);
499
128
            if (result == NULL)
500
0
                return NULL;
501
502
128
            result_buf = PyByteArray_AS_STRING(result);
503
35.9k
            for (cur = start, i = 0; i < slicelength;
504
35.8k
                 cur += step, i++) {
505
35.8k
                     result_buf[i] = source_buf[cur];
506
35.8k
            }
507
128
            return result;
508
128
        }
509
1.24k
    }
510
0
    else {
511
0
        PyErr_Format(PyExc_TypeError,
512
0
                     "bytearray indices must be integers or slices, not %.200s",
513
0
                     Py_TYPE(index)->tp_name);
514
0
        return NULL;
515
0
    }
516
1.24k
}
517
518
static PyObject *
519
bytearray_subscript(PyObject *op, PyObject *index)
520
1.24k
{
521
1.24k
    PyObject *ret;
522
1.24k
    Py_BEGIN_CRITICAL_SECTION(op);
523
1.24k
    ret = bytearray_subscript_lock_held(op, index);
524
1.24k
    Py_END_CRITICAL_SECTION();
525
1.24k
    return ret;
526
527
1.24k
}
528
529
static int
530
bytearray_setslice_linear(PyByteArrayObject *self,
531
                          Py_ssize_t lo, Py_ssize_t hi,
532
                          char *bytes, Py_ssize_t bytes_len)
533
8.66M
{
534
8.66M
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(self);
535
8.66M
    Py_ssize_t avail = hi - lo;
536
8.66M
    char *buf = PyByteArray_AS_STRING(self);
537
8.66M
    Py_ssize_t growth = bytes_len - avail;
538
8.66M
    int res = 0;
539
8.66M
    assert(avail >= 0);
540
541
8.66M
    if (growth < 0) {
542
0
        if (!_canresize(self))
543
0
            return -1;
544
545
0
        if (lo == 0) {
546
            /* Shrink the buffer by advancing its logical start */
547
0
            self->ob_start -= growth;
548
            /*
549
              0   lo               hi             old_size
550
              |   |<----avail----->|<-----tail------>|
551
              |      |<-bytes_len->|<-----tail------>|
552
              0    new_lo         new_hi          new_size
553
            */
554
0
        }
555
0
        else {
556
            /*
557
              0   lo               hi               old_size
558
              |   |<----avail----->|<-----tomove------>|
559
              |   |<-bytes_len->|<-----tomove------>|
560
              0   lo         new_hi              new_size
561
            */
562
0
            memmove(buf + lo + bytes_len, buf + hi,
563
0
                    Py_SIZE(self) - hi);
564
0
        }
565
0
        if (bytearray_resize_lock_held((PyObject *)self,
566
0
                               Py_SIZE(self) + growth) < 0) {
567
            /* Issue #19578: Handling the memory allocation failure here is
568
               tricky here because the bytearray object has already been
569
               modified. Depending on growth and lo, the behaviour is
570
               different.
571
572
               If growth < 0 and lo != 0, the operation is completed, but a
573
               MemoryError is still raised and the memory block is not
574
               shrunk. Otherwise, the bytearray is restored in its previous
575
               state and a MemoryError is raised. */
576
0
            if (lo == 0) {
577
0
                self->ob_start += growth;
578
0
                return -1;
579
0
            }
580
            /* memmove() removed bytes, the bytearray object cannot be
581
               restored in its previous state. */
582
0
            Py_SET_SIZE(self, Py_SIZE(self) + growth);
583
0
            res = -1;
584
0
        }
585
0
        buf = PyByteArray_AS_STRING(self);
586
0
    }
587
8.66M
    else if (growth > 0) {
588
4.64M
        if (Py_SIZE(self) > (Py_ssize_t)PY_SSIZE_T_MAX - growth) {
589
0
            PyErr_NoMemory();
590
0
            return -1;
591
0
        }
592
593
4.64M
        if (bytearray_resize_lock_held((PyObject *)self,
594
4.64M
                               Py_SIZE(self) + growth) < 0) {
595
0
            return -1;
596
0
        }
597
4.64M
        buf = PyByteArray_AS_STRING(self);
598
        /* Make the place for the additional bytes */
599
        /*
600
          0   lo        hi               old_size
601
          |   |<-avail->|<-----tomove------>|
602
          |   |<---bytes_len-->|<-----tomove------>|
603
          0   lo            new_hi              new_size
604
         */
605
4.64M
        memmove(buf + lo + bytes_len, buf + hi,
606
4.64M
                Py_SIZE(self) - lo - bytes_len);
607
4.64M
    }
608
609
8.66M
    if (bytes_len > 0)
610
4.64M
        memcpy(buf + lo, bytes, bytes_len);
611
8.66M
    return res;
612
8.66M
}
613
614
static int
615
bytearray_setslice(PyByteArrayObject *self, Py_ssize_t lo, Py_ssize_t hi,
616
               PyObject *values)
617
8.66M
{
618
8.66M
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(self);
619
8.66M
    Py_ssize_t needed;
620
8.66M
    void *bytes;
621
8.66M
    Py_buffer vbytes;
622
8.66M
    int res = 0;
623
624
8.66M
    vbytes.len = -1;
625
8.66M
    if (values == (PyObject *)self) {
626
        /* Make a copy and call this function recursively */
627
0
        int err;
628
0
        values = PyByteArray_FromStringAndSize(PyByteArray_AS_STRING(values),
629
0
                                               PyByteArray_GET_SIZE(values));
630
0
        if (values == NULL)
631
0
            return -1;
632
0
        err = bytearray_setslice(self, lo, hi, values);
633
0
        Py_DECREF(values);
634
0
        return err;
635
0
    }
636
8.66M
    if (values == NULL) {
637
        /* del b[lo:hi] */
638
0
        bytes = NULL;
639
0
        needed = 0;
640
0
    }
641
8.66M
    else {
642
8.66M
        if (PyObject_GetBuffer(values, &vbytes, PyBUF_SIMPLE) != 0) {
643
0
            PyErr_Format(PyExc_TypeError,
644
0
                         "can't set bytearray slice from %.100s",
645
0
                         Py_TYPE(values)->tp_name);
646
0
            return -1;
647
0
        }
648
8.66M
        needed = vbytes.len;
649
8.66M
        bytes = vbytes.buf;
650
8.66M
    }
651
652
8.66M
    if (lo < 0)
653
0
        lo = 0;
654
8.66M
    if (hi < lo)
655
0
        hi = lo;
656
8.66M
    if (hi > Py_SIZE(self))
657
0
        hi = Py_SIZE(self);
658
659
8.66M
    res = bytearray_setslice_linear(self, lo, hi, bytes, needed);
660
8.66M
    if (vbytes.len != -1)
661
8.66M
        PyBuffer_Release(&vbytes);
662
8.66M
    return res;
663
8.66M
}
664
665
static int
666
bytearray_setitem_lock_held(PyObject *op, Py_ssize_t i, PyObject *value)
667
0
{
668
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(op);
669
0
    PyByteArrayObject *self = _PyByteArray_CAST(op);
670
671
    // GH-91153: We need to do this *before* the size check, in case value has a
672
    // nasty __index__ method that changes the size of the bytearray:
673
0
    int ival = -1;
674
0
    if (value && !_getbytevalue(value, &ival)) {
675
0
        return -1;
676
0
    }
677
678
0
    if (i < 0) {
679
0
        i += Py_SIZE(self);
680
0
    }
681
682
0
    if (i < 0 || i >= Py_SIZE(self)) {
683
0
        PyErr_SetString(PyExc_IndexError, "bytearray index out of range");
684
0
        return -1;
685
0
    }
686
687
0
    if (value == NULL) {
688
0
        return bytearray_setslice(self, i, i+1, NULL);
689
0
    }
690
691
0
    assert(0 <= ival && ival < 256);
692
0
    PyByteArray_AS_STRING(self)[i] = ival;
693
0
    return 0;
694
0
}
695
696
static int
697
bytearray_setitem(PyObject *op, Py_ssize_t i, PyObject *value)
698
0
{
699
0
    int ret;
700
0
    Py_BEGIN_CRITICAL_SECTION(op);
701
0
    ret = bytearray_setitem_lock_held(op, i, value);
702
0
    Py_END_CRITICAL_SECTION();
703
0
    return ret;
704
0
}
705
706
static int
707
bytearray_ass_subscript_lock_held(PyObject *op, PyObject *index, PyObject *values)
708
8.67k
{
709
8.67k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(op);
710
8.67k
    PyByteArrayObject *self = _PyByteArray_CAST(op);
711
8.67k
    Py_ssize_t start, stop, step, slicelen;
712
8.67k
    char *buf = PyByteArray_AS_STRING(self);
713
714
8.67k
    if (_PyIndex_Check(index)) {
715
8.67k
        Py_ssize_t i = PyNumber_AsSsize_t(index, PyExc_IndexError);
716
717
8.67k
        if (i == -1 && PyErr_Occurred()) {
718
0
            return -1;
719
0
        }
720
721
8.67k
        int ival = -1;
722
723
        // GH-91153: We need to do this *before* the size check, in case values
724
        // has a nasty __index__ method that changes the size of the bytearray:
725
8.67k
        if (values && !_getbytevalue(values, &ival)) {
726
0
            return -1;
727
0
        }
728
729
8.67k
        if (i < 0) {
730
0
            i += PyByteArray_GET_SIZE(self);
731
0
        }
732
733
8.67k
        if (i < 0 || i >= Py_SIZE(self)) {
734
4
            PyErr_SetString(PyExc_IndexError, "bytearray index out of range");
735
4
            return -1;
736
4
        }
737
738
8.67k
        if (values == NULL) {
739
            /* Fall through to slice assignment */
740
0
            start = i;
741
0
            stop = i + 1;
742
0
            step = 1;
743
0
            slicelen = 1;
744
0
        }
745
8.67k
        else {
746
8.67k
            assert(0 <= ival && ival < 256);
747
8.67k
            buf[i] = (char)ival;
748
8.67k
            return 0;
749
8.67k
        }
750
8.67k
    }
751
0
    else if (PySlice_Check(index)) {
752
0
        if (PySlice_Unpack(index, &start, &stop, &step) < 0) {
753
0
            return -1;
754
0
        }
755
0
        slicelen = PySlice_AdjustIndices(PyByteArray_GET_SIZE(self), &start,
756
0
                                         &stop, step);
757
0
    }
758
0
    else {
759
0
        PyErr_Format(PyExc_TypeError,
760
0
                     "bytearray indices must be integers or slices, not %.200s",
761
0
                      Py_TYPE(index)->tp_name);
762
0
        return -1;
763
0
    }
764
765
0
    char *bytes;
766
0
    Py_ssize_t needed;
767
0
    if (values == NULL) {
768
0
        bytes = NULL;
769
0
        needed = 0;
770
0
    }
771
0
    else if (values == (PyObject *)self || !PyByteArray_Check(values)) {
772
0
        int err;
773
0
        if (PyNumber_Check(values) || PyUnicode_Check(values)) {
774
0
            PyErr_SetString(PyExc_TypeError,
775
0
                            "can assign only bytes, buffers, or iterables "
776
0
                            "of ints in range(0, 256)");
777
0
            return -1;
778
0
        }
779
        /* Make a copy and call this function recursively */
780
0
        values = PyByteArray_FromObject(values);
781
0
        if (values == NULL)
782
0
            return -1;
783
0
        err = bytearray_ass_subscript_lock_held((PyObject*)self, index, values);
784
0
        Py_DECREF(values);
785
0
        return err;
786
0
    }
787
0
    else {
788
0
        assert(PyByteArray_Check(values));
789
0
        bytes = PyByteArray_AS_STRING(values);
790
0
        needed = Py_SIZE(values);
791
0
    }
792
793
    /* Make sure b[5:2] = ... inserts before 5, not before 2. */
794
0
    if ((step < 0 && start < stop) ||
795
0
        (step > 0 && start > stop))
796
0
    {
797
0
        stop = start;
798
0
    }
799
800
0
    if (step == 1) {
801
0
        return bytearray_setslice_linear(self, start, stop, bytes, needed);
802
0
    }
803
0
    else {
804
0
        if (needed == 0) {
805
            /* Delete slice */
806
0
            size_t cur;
807
0
            Py_ssize_t i;
808
809
0
            if (!_canresize(self))
810
0
                return -1;
811
812
0
            if (slicelen == 0)
813
                /* Nothing to do here. */
814
0
                return 0;
815
816
0
            if (step < 0) {
817
0
                stop = start + 1;
818
0
                start = stop + step * (slicelen - 1) - 1;
819
0
                step = -step;
820
0
            }
821
0
            for (cur = start, i = 0;
822
0
                 i < slicelen; cur += step, i++) {
823
0
                Py_ssize_t lim = step - 1;
824
825
0
                if (cur + step >= (size_t)PyByteArray_GET_SIZE(self))
826
0
                    lim = PyByteArray_GET_SIZE(self) - cur - 1;
827
828
0
                memmove(buf + cur - i,
829
0
                        buf + cur + 1, lim);
830
0
            }
831
            /* Move the tail of the bytes, in one chunk */
832
0
            cur = start + (size_t)slicelen*step;
833
0
            if (cur < (size_t)PyByteArray_GET_SIZE(self)) {
834
0
                memmove(buf + cur - slicelen,
835
0
                        buf + cur,
836
0
                        PyByteArray_GET_SIZE(self) - cur);
837
0
            }
838
0
            if (bytearray_resize_lock_held((PyObject *)self,
839
0
                               PyByteArray_GET_SIZE(self) - slicelen) < 0)
840
0
                return -1;
841
842
0
            return 0;
843
0
        }
844
0
        else {
845
            /* Assign slice */
846
0
            Py_ssize_t i;
847
0
            size_t cur;
848
849
0
            if (needed != slicelen) {
850
0
                PyErr_Format(PyExc_ValueError,
851
0
                             "attempt to assign bytes of size %zd "
852
0
                             "to extended slice of size %zd",
853
0
                             needed, slicelen);
854
0
                return -1;
855
0
            }
856
0
            for (cur = start, i = 0; i < slicelen; cur += step, i++)
857
0
                buf[cur] = bytes[i];
858
0
            return 0;
859
0
        }
860
0
    }
861
0
}
862
863
static int
864
bytearray_ass_subscript(PyObject *op, PyObject *index, PyObject *values)
865
8.67k
{
866
8.67k
    int ret;
867
8.67k
    if (values != NULL && PyByteArray_Check(values)) {
868
0
        Py_BEGIN_CRITICAL_SECTION2(op, values);
869
0
        ret = bytearray_ass_subscript_lock_held(op, index, values);
870
0
        Py_END_CRITICAL_SECTION2();
871
0
    }
872
8.67k
    else {
873
8.67k
        Py_BEGIN_CRITICAL_SECTION(op);
874
8.67k
        ret = bytearray_ass_subscript_lock_held(op, index, values);
875
8.67k
        Py_END_CRITICAL_SECTION();
876
8.67k
    }
877
8.67k
    return ret;
878
8.67k
}
879
880
/*[clinic input]
881
bytearray.__init__
882
883
    source as arg: object = NULL
884
    encoding: str = NULL
885
    errors: str = NULL
886
887
[clinic start generated code]*/
888
889
static int
890
bytearray___init___impl(PyByteArrayObject *self, PyObject *arg,
891
                        const char *encoding, const char *errors)
892
/*[clinic end generated code: output=4ce1304649c2f8b3 input=1141a7122eefd7b9]*/
893
936k
{
894
936k
    Py_ssize_t count;
895
936k
    PyObject *it;
896
936k
    PyObject *(*iternext)(PyObject *);
897
898
936k
    if (Py_SIZE(self) != 0) {
899
        /* Empty previous contents (yes, do this first of all!) */
900
0
        if (PyByteArray_Resize((PyObject *)self, 0) < 0)
901
0
            return -1;
902
0
    }
903
904
    /* Make a quick exit if no first argument */
905
936k
    if (arg == NULL) {
906
416k
        if (encoding != NULL || errors != NULL) {
907
0
            PyErr_SetString(PyExc_TypeError,
908
0
                            encoding != NULL ?
909
0
                            "encoding without a string argument" :
910
0
                            "errors without a string argument");
911
0
            return -1;
912
0
        }
913
416k
        return 0;
914
416k
    }
915
916
519k
    if (PyUnicode_Check(arg)) {
917
        /* Encode via the codec registry */
918
0
        PyObject *encoded, *new;
919
0
        if (encoding == NULL) {
920
0
            PyErr_SetString(PyExc_TypeError,
921
0
                            "string argument without an encoding");
922
0
            return -1;
923
0
        }
924
0
        encoded = PyUnicode_AsEncodedString(arg, encoding, errors);
925
0
        if (encoded == NULL)
926
0
            return -1;
927
0
        assert(PyBytes_Check(encoded));
928
0
        new = bytearray_iconcat((PyObject*)self, encoded);
929
0
        Py_DECREF(encoded);
930
0
        if (new == NULL)
931
0
            return -1;
932
0
        Py_DECREF(new);
933
0
        return 0;
934
0
    }
935
936
    /* If it's not unicode, there can't be encoding or errors */
937
519k
    if (encoding != NULL || errors != NULL) {
938
0
        PyErr_SetString(PyExc_TypeError,
939
0
                        encoding != NULL ?
940
0
                        "encoding without a string argument" :
941
0
                        "errors without a string argument");
942
0
        return -1;
943
0
    }
944
945
    /* Is it an int? */
946
519k
    if (_PyIndex_Check(arg)) {
947
374
        count = PyNumber_AsSsize_t(arg, PyExc_OverflowError);
948
374
        if (count == -1 && PyErr_Occurred()) {
949
0
            if (!PyErr_ExceptionMatches(PyExc_TypeError))
950
0
                return -1;
951
0
            PyErr_Clear();  /* fall through */
952
0
        }
953
374
        else {
954
374
            if (count < 0) {
955
0
                PyErr_SetString(PyExc_ValueError, "negative count");
956
0
                return -1;
957
0
            }
958
374
            if (count > 0) {
959
374
                if (PyByteArray_Resize((PyObject *)self, count))
960
0
                    return -1;
961
374
                memset(PyByteArray_AS_STRING(self), 0, count);
962
374
            }
963
374
            return 0;
964
374
        }
965
374
    }
966
967
    /* Use the buffer API */
968
519k
    if (PyObject_CheckBuffer(arg)) {
969
519k
        Py_ssize_t size;
970
519k
        Py_buffer view;
971
519k
        if (PyObject_GetBuffer(arg, &view, PyBUF_FULL_RO) < 0)
972
0
            return -1;
973
519k
        size = view.len;
974
519k
        if (PyByteArray_Resize((PyObject *)self, size) < 0) goto fail;
975
519k
        if (PyBuffer_ToContiguous(PyByteArray_AS_STRING(self),
976
519k
            &view, size, 'C') < 0)
977
0
            goto fail;
978
519k
        PyBuffer_Release(&view);
979
519k
        return 0;
980
0
    fail:
981
0
        PyBuffer_Release(&view);
982
0
        return -1;
983
519k
    }
984
985
0
    if (PyList_CheckExact(arg) || PyTuple_CheckExact(arg)) {
986
0
        Py_ssize_t size = PySequence_Fast_GET_SIZE(arg);
987
0
        if (PyByteArray_Resize((PyObject *)self, size) < 0) {
988
0
            return -1;
989
0
        }
990
0
        PyObject **items = PySequence_Fast_ITEMS(arg);
991
0
        char *s = PyByteArray_AS_STRING(self);
992
0
        for (Py_ssize_t i = 0; i < size; i++) {
993
0
            int value;
994
0
            if (!PyLong_CheckExact(items[i])) {
995
                /* Resize to 0 and go through slowpath */
996
0
                if (Py_SIZE(self) != 0) {
997
0
                   if (PyByteArray_Resize((PyObject *)self, 0) < 0) {
998
0
                       return -1;
999
0
                   }
1000
0
                }
1001
0
                goto slowpath;
1002
0
            }
1003
0
            int rc = _getbytevalue(items[i], &value);
1004
0
            if (!rc) {
1005
0
                return -1;
1006
0
            }
1007
0
            s[i] = value;
1008
0
        }
1009
0
        return 0;
1010
0
    }
1011
0
slowpath:
1012
    /* Get the iterator */
1013
0
    it = PyObject_GetIter(arg);
1014
0
    if (it == NULL) {
1015
0
        if (PyErr_ExceptionMatches(PyExc_TypeError)) {
1016
0
            PyErr_Format(PyExc_TypeError,
1017
0
                         "cannot convert '%.200s' object to bytearray",
1018
0
                         Py_TYPE(arg)->tp_name);
1019
0
        }
1020
0
        return -1;
1021
0
    }
1022
0
    iternext = *Py_TYPE(it)->tp_iternext;
1023
1024
    /* Run the iterator to exhaustion */
1025
0
    for (;;) {
1026
0
        PyObject *item;
1027
0
        int rc, value;
1028
1029
        /* Get the next item */
1030
0
        item = iternext(it);
1031
0
        if (item == NULL) {
1032
0
            if (PyErr_Occurred()) {
1033
0
                if (!PyErr_ExceptionMatches(PyExc_StopIteration))
1034
0
                    goto error;
1035
0
                PyErr_Clear();
1036
0
            }
1037
0
            break;
1038
0
        }
1039
1040
        /* Interpret it as an int (__index__) */
1041
0
        rc = _getbytevalue(item, &value);
1042
0
        Py_DECREF(item);
1043
0
        if (!rc)
1044
0
            goto error;
1045
1046
        /* Append the byte */
1047
0
        if (Py_SIZE(self) + 1 < self->ob_alloc) {
1048
0
            Py_SET_SIZE(self, Py_SIZE(self) + 1);
1049
0
            PyByteArray_AS_STRING(self)[Py_SIZE(self)] = '\0';
1050
0
        }
1051
0
        else if (PyByteArray_Resize((PyObject *)self, Py_SIZE(self)+1) < 0)
1052
0
            goto error;
1053
0
        PyByteArray_AS_STRING(self)[Py_SIZE(self)-1] = value;
1054
0
    }
1055
1056
    /* Clean up and return success */
1057
0
    Py_DECREF(it);
1058
0
    return 0;
1059
1060
0
 error:
1061
    /* Error handling when it != NULL */
1062
0
    Py_DECREF(it);
1063
0
    return -1;
1064
0
}
1065
1066
/* Mostly copied from string_repr, but without the
1067
   "smart quote" functionality. */
1068
static PyObject *
1069
bytearray_repr_lock_held(PyObject *op)
1070
0
{
1071
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(op);
1072
0
    PyByteArrayObject *self = _PyByteArray_CAST(op);
1073
0
    const char *className = _PyType_Name(Py_TYPE(self));
1074
0
    const char *quote_prefix = "(b";
1075
0
    const char *quote_postfix = ")";
1076
0
    Py_ssize_t length = Py_SIZE(self);
1077
    /* 6 == strlen(quote_prefix) + 2 + strlen(quote_postfix) + 1 */
1078
0
    Py_ssize_t newsize;
1079
0
    PyObject *v;
1080
0
    Py_ssize_t i;
1081
0
    char *bytes;
1082
0
    char c;
1083
0
    char *p;
1084
0
    int quote;
1085
0
    char *test, *start;
1086
0
    char *buffer;
1087
1088
0
    newsize = strlen(className);
1089
0
    if (length > (PY_SSIZE_T_MAX - 6 - newsize) / 4) {
1090
0
        PyErr_SetString(PyExc_OverflowError,
1091
0
            "bytearray object is too large to make repr");
1092
0
        return NULL;
1093
0
    }
1094
1095
0
    newsize += 6 + length * 4;
1096
0
    buffer = PyMem_Malloc(newsize);
1097
0
    if (buffer == NULL) {
1098
0
        PyErr_NoMemory();
1099
0
        return NULL;
1100
0
    }
1101
1102
    /* Figure out which quote to use; single is preferred */
1103
0
    quote = '\'';
1104
0
    start = PyByteArray_AS_STRING(self);
1105
0
    for (test = start; test < start+length; ++test) {
1106
0
        if (*test == '"') {
1107
0
            quote = '\''; /* back to single */
1108
0
            break;
1109
0
        }
1110
0
        else if (*test == '\'')
1111
0
            quote = '"';
1112
0
    }
1113
1114
0
    p = buffer;
1115
0
    while (*className)
1116
0
        *p++ = *className++;
1117
0
    while (*quote_prefix)
1118
0
        *p++ = *quote_prefix++;
1119
0
    *p++ = quote;
1120
1121
0
    bytes = PyByteArray_AS_STRING(self);
1122
0
    for (i = 0; i < length; i++) {
1123
        /* There's at least enough room for a hex escape
1124
           and a closing quote. */
1125
0
        assert(newsize - (p - buffer) >= 5);
1126
0
        c = bytes[i];
1127
0
        if (c == '\'' || c == '\\')
1128
0
            *p++ = '\\', *p++ = c;
1129
0
        else if (c == '\t')
1130
0
            *p++ = '\\', *p++ = 't';
1131
0
        else if (c == '\n')
1132
0
            *p++ = '\\', *p++ = 'n';
1133
0
        else if (c == '\r')
1134
0
            *p++ = '\\', *p++ = 'r';
1135
0
        else if (c == 0)
1136
0
            *p++ = '\\', *p++ = 'x', *p++ = '0', *p++ = '0';
1137
0
        else if (c < ' ' || c >= 0x7f) {
1138
0
            *p++ = '\\';
1139
0
            *p++ = 'x';
1140
0
            *p++ = Py_hexdigits[(c & 0xf0) >> 4];
1141
0
            *p++ = Py_hexdigits[c & 0xf];
1142
0
        }
1143
0
        else
1144
0
            *p++ = c;
1145
0
    }
1146
0
    assert(newsize - (p - buffer) >= 1);
1147
0
    *p++ = quote;
1148
0
    while (*quote_postfix) {
1149
0
       *p++ = *quote_postfix++;
1150
0
    }
1151
1152
0
    v = PyUnicode_FromStringAndSize(buffer, p - buffer);
1153
0
    PyMem_Free(buffer);
1154
0
    return v;
1155
0
}
1156
1157
static PyObject *
1158
bytearray_repr(PyObject *op)
1159
0
{
1160
0
    PyObject *ret;
1161
0
    Py_BEGIN_CRITICAL_SECTION(op);
1162
0
    ret = bytearray_repr_lock_held(op);
1163
0
    Py_END_CRITICAL_SECTION();
1164
0
    return ret;
1165
0
}
1166
1167
static PyObject *
1168
bytearray_str(PyObject *op)
1169
0
{
1170
0
    if (_Py_GetConfig()->bytes_warning) {
1171
0
        if (PyErr_WarnEx(PyExc_BytesWarning,
1172
0
                         "str() on a bytearray instance", 1)) {
1173
0
                return NULL;
1174
0
        }
1175
0
    }
1176
0
    return bytearray_repr(op);
1177
0
}
1178
1179
static PyObject *
1180
bytearray_richcompare(PyObject *self, PyObject *other, int op)
1181
0
{
1182
0
    Py_ssize_t self_size, other_size;
1183
0
    Py_buffer self_bytes, other_bytes;
1184
0
    int cmp;
1185
1186
0
    if (!PyObject_CheckBuffer(self) || !PyObject_CheckBuffer(other)) {
1187
0
        if (PyUnicode_Check(self) || PyUnicode_Check(other)) {
1188
0
            if (_Py_GetConfig()->bytes_warning && (op == Py_EQ || op == Py_NE)) {
1189
0
                if (PyErr_WarnEx(PyExc_BytesWarning,
1190
0
                                "Comparison between bytearray and string", 1))
1191
0
                    return NULL;
1192
0
            }
1193
0
        }
1194
0
        Py_RETURN_NOTIMPLEMENTED;
1195
0
    }
1196
1197
    /* Bytearrays can be compared to anything that supports the buffer API. */
1198
0
    if (PyObject_GetBuffer(self, &self_bytes, PyBUF_SIMPLE) != 0) {
1199
0
        PyErr_Clear();
1200
0
        Py_RETURN_NOTIMPLEMENTED;
1201
0
    }
1202
0
    self_size = self_bytes.len;
1203
1204
0
    if (PyObject_GetBuffer(other, &other_bytes, PyBUF_SIMPLE) != 0) {
1205
0
        PyErr_Clear();
1206
0
        PyBuffer_Release(&self_bytes);
1207
0
        Py_RETURN_NOTIMPLEMENTED;
1208
0
    }
1209
0
    other_size = other_bytes.len;
1210
1211
0
    if (self_size != other_size && (op == Py_EQ || op == Py_NE)) {
1212
        /* Shortcut: if the lengths differ, the objects differ */
1213
0
        PyBuffer_Release(&self_bytes);
1214
0
        PyBuffer_Release(&other_bytes);
1215
0
        return PyBool_FromLong((op == Py_NE));
1216
0
    }
1217
0
    else {
1218
0
        cmp = memcmp(self_bytes.buf, other_bytes.buf,
1219
0
                     Py_MIN(self_size, other_size));
1220
        /* In ISO C, memcmp() guarantees to use unsigned bytes! */
1221
1222
0
        PyBuffer_Release(&self_bytes);
1223
0
        PyBuffer_Release(&other_bytes);
1224
1225
0
        if (cmp != 0) {
1226
0
            Py_RETURN_RICHCOMPARE(cmp, 0, op);
1227
0
        }
1228
1229
0
        Py_RETURN_RICHCOMPARE(self_size, other_size, op);
1230
0
    }
1231
1232
0
}
1233
1234
static void
1235
bytearray_dealloc(PyObject *op)
1236
937k
{
1237
937k
    PyByteArrayObject *self = _PyByteArray_CAST(op);
1238
937k
    if (self->ob_exports > 0) {
1239
0
        PyErr_SetString(PyExc_SystemError,
1240
0
                        "deallocated bytearray object has exported buffers");
1241
0
        PyErr_Print();
1242
0
    }
1243
937k
    if (self->ob_bytes != 0) {
1244
926k
        PyMem_Free(self->ob_bytes);
1245
926k
    }
1246
937k
    Py_TYPE(self)->tp_free((PyObject *)self);
1247
937k
}
1248
1249
1250
/* -------------------------------------------------------------------- */
1251
/* Methods */
1252
1253
#define STRINGLIB_IS_UNICODE 0
1254
0
#define FASTSEARCH fastsearch
1255
0
#define STRINGLIB(F) stringlib_##F
1256
0
#define STRINGLIB_CHAR char
1257
0
#define STRINGLIB_SIZEOF_CHAR 1
1258
0
#define STRINGLIB_LEN PyByteArray_GET_SIZE
1259
0
#define STRINGLIB_STR PyByteArray_AS_STRING
1260
0
#define STRINGLIB_NEW PyByteArray_FromStringAndSize
1261
0
#define STRINGLIB_ISSPACE Py_ISSPACE
1262
0
#define STRINGLIB_ISLINEBREAK(x) ((x == '\n') || (x == '\r'))
1263
#define STRINGLIB_CHECK_EXACT PyByteArray_CheckExact
1264
0
#define STRINGLIB_FAST_MEMCHR memchr
1265
#define STRINGLIB_MUTABLE 1
1266
1267
#include "stringlib/fastsearch.h"
1268
#include "stringlib/count.h"
1269
#include "stringlib/find.h"
1270
#include "stringlib/join.h"
1271
#include "stringlib/partition.h"
1272
#include "stringlib/split.h"
1273
#include "stringlib/ctype.h"
1274
#include "stringlib/transmogrify.h"
1275
1276
1277
/*[clinic input]
1278
@critical_section
1279
@text_signature "($self, sub[, start[, end]], /)"
1280
bytearray.find
1281
1282
    sub: object
1283
    start: slice_index(accept={int, NoneType}, c_default='0') = None
1284
         Optional start position. Default: start of the bytes.
1285
    end: slice_index(accept={int, NoneType}, c_default='PY_SSIZE_T_MAX') = None
1286
         Optional stop position. Default: end of the bytes.
1287
    /
1288
1289
Return the lowest index in B where subsection 'sub' is found, such that 'sub' is contained within B[start:end].
1290
1291
Return -1 on failure.
1292
[clinic start generated code]*/
1293
1294
static PyObject *
1295
bytearray_find_impl(PyByteArrayObject *self, PyObject *sub, Py_ssize_t start,
1296
                    Py_ssize_t end)
1297
/*[clinic end generated code: output=413e1cab2ae87da0 input=1de9f4558df68336]*/
1298
1.59k
{
1299
1.59k
    return _Py_bytes_find(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self),
1300
1.59k
                          sub, start, end);
1301
1.59k
}
1302
1303
/*[clinic input]
1304
@critical_section
1305
bytearray.count = bytearray.find
1306
1307
Return the number of non-overlapping occurrences of subsection 'sub' in bytes B[start:end].
1308
[clinic start generated code]*/
1309
1310
static PyObject *
1311
bytearray_count_impl(PyByteArrayObject *self, PyObject *sub,
1312
                     Py_ssize_t start, Py_ssize_t end)
1313
/*[clinic end generated code: output=a21ee2692e4f1233 input=2608c30644614724]*/
1314
0
{
1315
0
    return _Py_bytes_count(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self),
1316
0
                           sub, start, end);
1317
0
}
1318
1319
/*[clinic input]
1320
bytearray.clear
1321
1322
Remove all items from the bytearray.
1323
[clinic start generated code]*/
1324
1325
static PyObject *
1326
bytearray_clear_impl(PyByteArrayObject *self)
1327
/*[clinic end generated code: output=85c2fe6aede0956c input=ed6edae9de447ac4]*/
1328
0
{
1329
0
    if (PyByteArray_Resize((PyObject *)self, 0) < 0)
1330
0
        return NULL;
1331
0
    Py_RETURN_NONE;
1332
0
}
1333
1334
/*[clinic input]
1335
@critical_section
1336
bytearray.copy
1337
1338
Return a copy of B.
1339
[clinic start generated code]*/
1340
1341
static PyObject *
1342
bytearray_copy_impl(PyByteArrayObject *self)
1343
/*[clinic end generated code: output=68cfbcfed484c132 input=b96f8b01f73851ad]*/
1344
0
{
1345
0
    return PyByteArray_FromStringAndSize(PyByteArray_AS_STRING((PyObject *)self),
1346
0
                                         PyByteArray_GET_SIZE(self));
1347
0
}
1348
1349
/*[clinic input]
1350
@critical_section
1351
bytearray.index = bytearray.find
1352
1353
Return the lowest index in B where subsection 'sub' is found, such that 'sub' is contained within B[start:end].
1354
1355
Raise ValueError if the subsection is not found.
1356
[clinic start generated code]*/
1357
1358
static PyObject *
1359
bytearray_index_impl(PyByteArrayObject *self, PyObject *sub,
1360
                     Py_ssize_t start, Py_ssize_t end)
1361
/*[clinic end generated code: output=067a1e78efc672a7 input=0086ba0ab9bf44a5]*/
1362
0
{
1363
0
    return _Py_bytes_index(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self),
1364
0
                           sub, start, end);
1365
0
}
1366
1367
/*[clinic input]
1368
@critical_section
1369
bytearray.rfind = bytearray.find
1370
1371
Return the highest index in B where subsection 'sub' is found, such that 'sub' is contained within B[start:end].
1372
1373
Return -1 on failure.
1374
[clinic start generated code]*/
1375
1376
static PyObject *
1377
bytearray_rfind_impl(PyByteArrayObject *self, PyObject *sub,
1378
                     Py_ssize_t start, Py_ssize_t end)
1379
/*[clinic end generated code: output=51bf886f932b283c input=ac73593305d5c1d1]*/
1380
0
{
1381
0
    return _Py_bytes_rfind(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self),
1382
0
                           sub, start, end);
1383
0
}
1384
1385
/*[clinic input]
1386
@critical_section
1387
bytearray.rindex = bytearray.find
1388
1389
Return the highest index in B where subsection 'sub' is found, such that 'sub' is contained within B[start:end].
1390
1391
Raise ValueError if the subsection is not found.
1392
[clinic start generated code]*/
1393
1394
static PyObject *
1395
bytearray_rindex_impl(PyByteArrayObject *self, PyObject *sub,
1396
                      Py_ssize_t start, Py_ssize_t end)
1397
/*[clinic end generated code: output=38e1cf66bafb08b9 input=0cf331bf5ebe0e91]*/
1398
0
{
1399
0
    return _Py_bytes_rindex(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self),
1400
0
                            sub, start, end);
1401
0
}
1402
1403
static int
1404
bytearray_contains(PyObject *self, PyObject *arg)
1405
0
{
1406
0
    int ret;
1407
0
    Py_BEGIN_CRITICAL_SECTION(self);
1408
0
    ret = _Py_bytes_contains(PyByteArray_AS_STRING(self),
1409
0
                             PyByteArray_GET_SIZE(self),
1410
0
                             arg);
1411
0
    Py_END_CRITICAL_SECTION();
1412
0
    return ret;
1413
0
}
1414
1415
/*[clinic input]
1416
@critical_section
1417
@text_signature "($self, prefix[, start[, end]], /)"
1418
bytearray.startswith
1419
1420
    prefix as subobj: object
1421
        A bytes or a tuple of bytes to try.
1422
    start: slice_index(accept={int, NoneType}, c_default='0') = None
1423
        Optional start position. Default: start of the bytearray.
1424
    end: slice_index(accept={int, NoneType}, c_default='PY_SSIZE_T_MAX') = None
1425
        Optional stop position. Default: end of the bytearray.
1426
    /
1427
1428
Return True if the bytearray starts with the specified prefix, False otherwise.
1429
[clinic start generated code]*/
1430
1431
static PyObject *
1432
bytearray_startswith_impl(PyByteArrayObject *self, PyObject *subobj,
1433
                          Py_ssize_t start, Py_ssize_t end)
1434
/*[clinic end generated code: output=a3d9b6d44d3662a6 input=ea8d036d09df34b2]*/
1435
0
{
1436
0
    return _Py_bytes_startswith(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self),
1437
0
                                subobj, start, end);
1438
0
}
1439
1440
/*[clinic input]
1441
@critical_section
1442
@text_signature "($self, suffix[, start[, end]], /)"
1443
bytearray.endswith
1444
1445
    suffix as subobj: object
1446
        A bytes or a tuple of bytes to try.
1447
    start: slice_index(accept={int, NoneType}, c_default='0') = None
1448
         Optional start position. Default: start of the bytearray.
1449
    end: slice_index(accept={int, NoneType}, c_default='PY_SSIZE_T_MAX') = None
1450
         Optional stop position. Default: end of the bytearray.
1451
    /
1452
1453
Return True if the bytearray ends with the specified suffix, False otherwise.
1454
[clinic start generated code]*/
1455
1456
static PyObject *
1457
bytearray_endswith_impl(PyByteArrayObject *self, PyObject *subobj,
1458
                        Py_ssize_t start, Py_ssize_t end)
1459
/*[clinic end generated code: output=e75ea8c227954caa input=c61b90bb23a689ce]*/
1460
0
{
1461
0
    return _Py_bytes_endswith(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self),
1462
0
                              subobj, start, end);
1463
0
}
1464
1465
/*[clinic input]
1466
@critical_section
1467
bytearray.removeprefix as bytearray_removeprefix
1468
1469
    prefix: Py_buffer
1470
    /
1471
1472
Return a bytearray with the given prefix string removed if present.
1473
1474
If the bytearray starts with the prefix string, return
1475
bytearray[len(prefix):].  Otherwise, return a copy of the original
1476
bytearray.
1477
[clinic start generated code]*/
1478
1479
static PyObject *
1480
bytearray_removeprefix_impl(PyByteArrayObject *self, Py_buffer *prefix)
1481
/*[clinic end generated code: output=6cabc585e7f502e0 input=4323ba6d275fe7a8]*/
1482
0
{
1483
0
    const char *self_start = PyByteArray_AS_STRING(self);
1484
0
    Py_ssize_t self_len = PyByteArray_GET_SIZE(self);
1485
0
    const char *prefix_start = prefix->buf;
1486
0
    Py_ssize_t prefix_len = prefix->len;
1487
1488
0
    if (self_len >= prefix_len
1489
0
        && memcmp(self_start, prefix_start, prefix_len) == 0)
1490
0
    {
1491
0
        return PyByteArray_FromStringAndSize(self_start + prefix_len,
1492
0
                                             self_len - prefix_len);
1493
0
    }
1494
1495
0
    return PyByteArray_FromStringAndSize(self_start, self_len);
1496
0
}
1497
1498
/*[clinic input]
1499
@critical_section
1500
bytearray.removesuffix as bytearray_removesuffix
1501
1502
    suffix: Py_buffer
1503
    /
1504
1505
Return a bytearray with the given suffix string removed if present.
1506
1507
If the bytearray ends with the suffix string and that suffix is not
1508
empty, return bytearray[:-len(suffix)].  Otherwise, return a copy of
1509
the original bytearray.
1510
[clinic start generated code]*/
1511
1512
static PyObject *
1513
bytearray_removesuffix_impl(PyByteArrayObject *self, Py_buffer *suffix)
1514
/*[clinic end generated code: output=2bc8cfb79de793d3 input=f71ba2e1a40c47dd]*/
1515
0
{
1516
0
    const char *self_start = PyByteArray_AS_STRING(self);
1517
0
    Py_ssize_t self_len = PyByteArray_GET_SIZE(self);
1518
0
    const char *suffix_start = suffix->buf;
1519
0
    Py_ssize_t suffix_len = suffix->len;
1520
1521
0
    if (self_len >= suffix_len
1522
0
        && memcmp(self_start + self_len - suffix_len,
1523
0
                  suffix_start, suffix_len) == 0)
1524
0
    {
1525
0
        return PyByteArray_FromStringAndSize(self_start,
1526
0
                                             self_len - suffix_len);
1527
0
    }
1528
1529
0
    return PyByteArray_FromStringAndSize(self_start, self_len);
1530
0
}
1531
1532
1533
/*[clinic input]
1534
bytearray.resize
1535
    size: Py_ssize_t
1536
        New size to resize to..
1537
    /
1538
Resize the internal buffer of bytearray to len.
1539
[clinic start generated code]*/
1540
1541
static PyObject *
1542
bytearray_resize_impl(PyByteArrayObject *self, Py_ssize_t size)
1543
/*[clinic end generated code: output=f73524922990b2d9 input=75fd4d17c4aa47d3]*/
1544
0
{
1545
0
    Py_ssize_t start_size = PyByteArray_GET_SIZE(self);
1546
0
    int result = PyByteArray_Resize((PyObject *)self, size);
1547
0
    if (result < 0) {
1548
0
        return NULL;
1549
0
    }
1550
    // Set new bytes to null bytes
1551
0
    if (size > start_size) {
1552
0
        memset(PyByteArray_AS_STRING(self) + start_size, 0, size - start_size);
1553
0
    }
1554
0
    Py_RETURN_NONE;
1555
0
}
1556
1557
1558
/*[clinic input]
1559
@critical_section
1560
bytearray.translate
1561
1562
    table: object
1563
        Translation table, which must be a bytes object of length 256.
1564
    /
1565
    delete as deletechars: object(c_default="NULL") = b''
1566
1567
Return a copy with each character mapped by the given translation table.
1568
1569
All characters occurring in the optional argument delete are removed.
1570
The remaining characters are mapped through the given translation table.
1571
[clinic start generated code]*/
1572
1573
static PyObject *
1574
bytearray_translate_impl(PyByteArrayObject *self, PyObject *table,
1575
                         PyObject *deletechars)
1576
/*[clinic end generated code: output=b6a8f01c2a74e446 input=cd6fa93ca04e05bc]*/
1577
128
{
1578
128
    char *input, *output;
1579
128
    const char *table_chars;
1580
128
    Py_ssize_t i, c;
1581
128
    PyObject *input_obj = (PyObject*)self;
1582
128
    const char *output_start;
1583
128
    Py_ssize_t inlen;
1584
128
    PyObject *result = NULL;
1585
128
    int trans_table[256];
1586
128
    Py_buffer vtable, vdel;
1587
1588
128
    if (table == Py_None) {
1589
0
        table_chars = NULL;
1590
0
        table = NULL;
1591
128
    } else if (PyObject_GetBuffer(table, &vtable, PyBUF_SIMPLE) != 0) {
1592
0
        return NULL;
1593
128
    } else {
1594
128
        if (vtable.len != 256) {
1595
0
            PyErr_SetString(PyExc_ValueError,
1596
0
                            "translation table must be 256 characters long");
1597
0
            PyBuffer_Release(&vtable);
1598
0
            return NULL;
1599
0
        }
1600
128
        table_chars = (const char*)vtable.buf;
1601
128
    }
1602
1603
128
    if (deletechars != NULL) {
1604
0
        if (PyObject_GetBuffer(deletechars, &vdel, PyBUF_SIMPLE) != 0) {
1605
0
            if (table != NULL)
1606
0
                PyBuffer_Release(&vtable);
1607
0
            return NULL;
1608
0
        }
1609
0
    }
1610
128
    else {
1611
128
        vdel.buf = NULL;
1612
128
        vdel.len = 0;
1613
128
    }
1614
1615
128
    inlen = PyByteArray_GET_SIZE(input_obj);
1616
128
    result = PyByteArray_FromStringAndSize((char *)NULL, inlen);
1617
128
    if (result == NULL)
1618
0
        goto done;
1619
128
    output_start = output = PyByteArray_AS_STRING(result);
1620
128
    input = PyByteArray_AS_STRING(input_obj);
1621
1622
128
    if (vdel.len == 0 && table_chars != NULL) {
1623
        /* If no deletions are required, use faster code */
1624
35.9k
        for (i = inlen; --i >= 0; ) {
1625
35.8k
            c = Py_CHARMASK(*input++);
1626
35.8k
            *output++ = table_chars[c];
1627
35.8k
        }
1628
128
        goto done;
1629
128
    }
1630
1631
0
    if (table_chars == NULL) {
1632
0
        for (i = 0; i < 256; i++)
1633
0
            trans_table[i] = Py_CHARMASK(i);
1634
0
    } else {
1635
0
        for (i = 0; i < 256; i++)
1636
0
            trans_table[i] = Py_CHARMASK(table_chars[i]);
1637
0
    }
1638
1639
0
    for (i = 0; i < vdel.len; i++)
1640
0
        trans_table[(int) Py_CHARMASK( ((unsigned char*)vdel.buf)[i] )] = -1;
1641
1642
0
    for (i = inlen; --i >= 0; ) {
1643
0
        c = Py_CHARMASK(*input++);
1644
0
        if (trans_table[c] != -1)
1645
0
            *output++ = (char)trans_table[c];
1646
0
    }
1647
    /* Fix the size of the resulting bytearray */
1648
0
    if (inlen > 0)
1649
0
        if (PyByteArray_Resize(result, output - output_start) < 0) {
1650
0
            Py_CLEAR(result);
1651
0
            goto done;
1652
0
        }
1653
1654
128
done:
1655
128
    if (table != NULL)
1656
128
        PyBuffer_Release(&vtable);
1657
128
    if (deletechars != NULL)
1658
0
        PyBuffer_Release(&vdel);
1659
128
    return result;
1660
0
}
1661
1662
1663
/*[clinic input]
1664
1665
@staticmethod
1666
bytearray.maketrans
1667
1668
    frm: Py_buffer
1669
    to: Py_buffer
1670
    /
1671
1672
Return a translation table usable for the bytes or bytearray translate method.
1673
1674
The returned table will be one where each byte in frm is mapped to the byte at
1675
the same position in to.
1676
1677
The bytes objects frm and to must be of the same length.
1678
[clinic start generated code]*/
1679
1680
static PyObject *
1681
bytearray_maketrans_impl(Py_buffer *frm, Py_buffer *to)
1682
/*[clinic end generated code: output=1df267d99f56b15e input=b10de38c85950a63]*/
1683
0
{
1684
0
    return _Py_bytes_maketrans(frm, to);
1685
0
}
1686
1687
1688
/*[clinic input]
1689
@critical_section
1690
bytearray.replace
1691
1692
    old: Py_buffer
1693
    new: Py_buffer
1694
    count: Py_ssize_t = -1
1695
        Maximum number of occurrences to replace.
1696
        -1 (the default value) means replace all occurrences.
1697
    /
1698
1699
Return a copy with all occurrences of substring old replaced by new.
1700
1701
If the optional argument count is given, only the first count occurrences are
1702
replaced.
1703
[clinic start generated code]*/
1704
1705
static PyObject *
1706
bytearray_replace_impl(PyByteArrayObject *self, Py_buffer *old,
1707
                       Py_buffer *new, Py_ssize_t count)
1708
/*[clinic end generated code: output=d39884c4dc59412a input=6992755672c8a807]*/
1709
0
{
1710
0
    return stringlib_replace((PyObject *)self,
1711
0
                             (const char *)old->buf, old->len,
1712
0
                             (const char *)new->buf, new->len, count);
1713
0
}
1714
1715
/*[clinic input]
1716
@critical_section
1717
bytearray.split
1718
1719
    sep: object = None
1720
        The delimiter according which to split the bytearray.
1721
        None (the default value) means split on ASCII whitespace characters
1722
        (space, tab, return, newline, formfeed, vertical tab).
1723
    maxsplit: Py_ssize_t = -1
1724
        Maximum number of splits to do.
1725
        -1 (the default value) means no limit.
1726
1727
Return a list of the sections in the bytearray, using sep as the delimiter.
1728
[clinic start generated code]*/
1729
1730
static PyObject *
1731
bytearray_split_impl(PyByteArrayObject *self, PyObject *sep,
1732
                     Py_ssize_t maxsplit)
1733
/*[clinic end generated code: output=833e2cf385d9a04d input=1c367486b9938909]*/
1734
0
{
1735
0
    Py_ssize_t len = PyByteArray_GET_SIZE(self), n;
1736
0
    const char *s = PyByteArray_AS_STRING(self), *sub;
1737
0
    PyObject *list;
1738
0
    Py_buffer vsub;
1739
1740
0
    if (maxsplit < 0)
1741
0
        maxsplit = PY_SSIZE_T_MAX;
1742
1743
0
    if (sep == Py_None)
1744
0
        return stringlib_split_whitespace((PyObject*) self, s, len, maxsplit);
1745
1746
0
    if (PyObject_GetBuffer(sep, &vsub, PyBUF_SIMPLE) != 0)
1747
0
        return NULL;
1748
0
    sub = vsub.buf;
1749
0
    n = vsub.len;
1750
1751
0
    list = stringlib_split(
1752
0
        (PyObject*) self, s, len, sub, n, maxsplit
1753
0
        );
1754
0
    PyBuffer_Release(&vsub);
1755
0
    return list;
1756
0
}
1757
1758
/*[clinic input]
1759
@critical_section
1760
bytearray.partition
1761
1762
    sep: object
1763
    /
1764
1765
Partition the bytearray into three parts using the given separator.
1766
1767
This will search for the separator sep in the bytearray. If the separator is
1768
found, returns a 3-tuple containing the part before the separator, the
1769
separator itself, and the part after it as new bytearray objects.
1770
1771
If the separator is not found, returns a 3-tuple containing the copy of the
1772
original bytearray object and two empty bytearray objects.
1773
[clinic start generated code]*/
1774
1775
static PyObject *
1776
bytearray_partition_impl(PyByteArrayObject *self, PyObject *sep)
1777
/*[clinic end generated code: output=b5fa1e03f10cfccb input=632855f986733f34]*/
1778
0
{
1779
0
    PyObject *bytesep, *result;
1780
1781
0
    bytesep = _PyByteArray_FromBufferObject(sep);
1782
0
    if (! bytesep)
1783
0
        return NULL;
1784
1785
0
    result = stringlib_partition(
1786
0
            (PyObject*) self,
1787
0
            PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self),
1788
0
            bytesep,
1789
0
            PyByteArray_AS_STRING(bytesep), PyByteArray_GET_SIZE(bytesep)
1790
0
            );
1791
1792
0
    Py_DECREF(bytesep);
1793
0
    return result;
1794
0
}
1795
1796
/*[clinic input]
1797
@critical_section
1798
bytearray.rpartition
1799
1800
    sep: object
1801
    /
1802
1803
Partition the bytearray into three parts using the given separator.
1804
1805
This will search for the separator sep in the bytearray, starting at the end.
1806
If the separator is found, returns a 3-tuple containing the part before the
1807
separator, the separator itself, and the part after it as new bytearray
1808
objects.
1809
1810
If the separator is not found, returns a 3-tuple containing two empty bytearray
1811
objects and the copy of the original bytearray object.
1812
[clinic start generated code]*/
1813
1814
static PyObject *
1815
bytearray_rpartition_impl(PyByteArrayObject *self, PyObject *sep)
1816
/*[clinic end generated code: output=0186ce7b1ef61289 input=4318e3d125497450]*/
1817
0
{
1818
0
    PyObject *bytesep, *result;
1819
1820
0
    bytesep = _PyByteArray_FromBufferObject(sep);
1821
0
    if (! bytesep)
1822
0
        return NULL;
1823
1824
0
    result = stringlib_rpartition(
1825
0
            (PyObject*) self,
1826
0
            PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self),
1827
0
            bytesep,
1828
0
            PyByteArray_AS_STRING(bytesep), PyByteArray_GET_SIZE(bytesep)
1829
0
            );
1830
1831
0
    Py_DECREF(bytesep);
1832
0
    return result;
1833
0
}
1834
1835
/*[clinic input]
1836
@critical_section
1837
bytearray.rsplit = bytearray.split
1838
1839
Return a list of the sections in the bytearray, using sep as the delimiter.
1840
1841
Splitting is done starting at the end of the bytearray and working to the front.
1842
[clinic start generated code]*/
1843
1844
static PyObject *
1845
bytearray_rsplit_impl(PyByteArrayObject *self, PyObject *sep,
1846
                      Py_ssize_t maxsplit)
1847
/*[clinic end generated code: output=a55e0b5a03cb6190 input=3cd513c2b94a53c1]*/
1848
0
{
1849
0
    Py_ssize_t len = PyByteArray_GET_SIZE(self), n;
1850
0
    const char *s = PyByteArray_AS_STRING(self), *sub;
1851
0
    PyObject *list;
1852
0
    Py_buffer vsub;
1853
1854
0
    if (maxsplit < 0)
1855
0
        maxsplit = PY_SSIZE_T_MAX;
1856
1857
0
    if (sep == Py_None)
1858
0
        return stringlib_rsplit_whitespace((PyObject*) self, s, len, maxsplit);
1859
1860
0
    if (PyObject_GetBuffer(sep, &vsub, PyBUF_SIMPLE) != 0)
1861
0
        return NULL;
1862
0
    sub = vsub.buf;
1863
0
    n = vsub.len;
1864
1865
0
    list = stringlib_rsplit(
1866
0
        (PyObject*) self, s, len, sub, n, maxsplit
1867
0
        );
1868
0
    PyBuffer_Release(&vsub);
1869
0
    return list;
1870
0
}
1871
1872
/*[clinic input]
1873
@critical_section
1874
bytearray.reverse
1875
1876
Reverse the order of the values in B in place.
1877
[clinic start generated code]*/
1878
1879
static PyObject *
1880
bytearray_reverse_impl(PyByteArrayObject *self)
1881
/*[clinic end generated code: output=9f7616f29ab309d3 input=2f3d5ce3180ffc53]*/
1882
0
{
1883
0
    char swap, *head, *tail;
1884
0
    Py_ssize_t i, j, n = Py_SIZE(self);
1885
1886
0
    j = n / 2;
1887
0
    head = PyByteArray_AS_STRING(self);
1888
0
    tail = head + n - 1;
1889
0
    for (i = 0; i < j; i++) {
1890
0
        swap = *head;
1891
0
        *head++ = *tail;
1892
0
        *tail-- = swap;
1893
0
    }
1894
1895
0
    Py_RETURN_NONE;
1896
0
}
1897
1898
1899
/*[python input]
1900
class bytesvalue_converter(CConverter):
1901
    type = 'int'
1902
    converter = '_getbytevalue'
1903
[python start generated code]*/
1904
/*[python end generated code: output=da39a3ee5e6b4b0d input=29c2e7c26c212812]*/
1905
1906
1907
/*[clinic input]
1908
@critical_section
1909
bytearray.insert
1910
1911
    index: Py_ssize_t
1912
        The index where the value is to be inserted.
1913
    item: bytesvalue
1914
        The item to be inserted.
1915
    /
1916
1917
Insert a single item into the bytearray before the given index.
1918
[clinic start generated code]*/
1919
1920
static PyObject *
1921
bytearray_insert_impl(PyByteArrayObject *self, Py_ssize_t index, int item)
1922
/*[clinic end generated code: output=76c775a70e7b07b7 input=b3e14ede546dd8cc]*/
1923
0
{
1924
0
    Py_ssize_t n = Py_SIZE(self);
1925
0
    char *buf;
1926
1927
0
    if (n == PY_SSIZE_T_MAX) {
1928
0
        PyErr_SetString(PyExc_OverflowError,
1929
0
                        "cannot add more objects to bytearray");
1930
0
        return NULL;
1931
0
    }
1932
0
    if (bytearray_resize_lock_held((PyObject *)self, n + 1) < 0)
1933
0
        return NULL;
1934
0
    buf = PyByteArray_AS_STRING(self);
1935
1936
0
    if (index < 0) {
1937
0
        index += n;
1938
0
        if (index < 0)
1939
0
            index = 0;
1940
0
    }
1941
0
    if (index > n)
1942
0
        index = n;
1943
0
    memmove(buf + index + 1, buf + index, n - index);
1944
0
    buf[index] = item;
1945
1946
0
    Py_RETURN_NONE;
1947
0
}
1948
1949
static PyObject *
1950
bytearray_isalnum(PyObject *self, PyObject *Py_UNUSED(ignored))
1951
0
{
1952
0
    PyObject *ret;
1953
0
    Py_BEGIN_CRITICAL_SECTION(self);
1954
0
    ret = stringlib_isalnum(self, NULL);
1955
0
    Py_END_CRITICAL_SECTION();
1956
0
    return ret;
1957
0
}
1958
1959
static PyObject *
1960
bytearray_isalpha(PyObject *self, PyObject *Py_UNUSED(ignored))
1961
0
{
1962
0
    PyObject *ret;
1963
0
    Py_BEGIN_CRITICAL_SECTION(self);
1964
0
    ret = stringlib_isalpha(self, NULL);
1965
0
    Py_END_CRITICAL_SECTION();
1966
0
    return ret;
1967
0
}
1968
1969
static PyObject *
1970
bytearray_isascii(PyObject *self, PyObject *Py_UNUSED(ignored))
1971
0
{
1972
0
    PyObject *ret;
1973
0
    Py_BEGIN_CRITICAL_SECTION(self);
1974
0
    ret = stringlib_isascii(self, NULL);
1975
0
    Py_END_CRITICAL_SECTION();
1976
0
    return ret;
1977
0
}
1978
1979
static PyObject *
1980
bytearray_isdigit(PyObject *self, PyObject *Py_UNUSED(ignored))
1981
0
{
1982
0
    PyObject *ret;
1983
0
    Py_BEGIN_CRITICAL_SECTION(self);
1984
0
    ret = stringlib_isdigit(self, NULL);
1985
0
    Py_END_CRITICAL_SECTION();
1986
0
    return ret;
1987
0
}
1988
1989
static PyObject *
1990
bytearray_islower(PyObject *self, PyObject *Py_UNUSED(ignored))
1991
0
{
1992
0
    PyObject *ret;
1993
0
    Py_BEGIN_CRITICAL_SECTION(self);
1994
0
    ret = stringlib_islower(self, NULL);
1995
0
    Py_END_CRITICAL_SECTION();
1996
0
    return ret;
1997
0
}
1998
1999
static PyObject *
2000
bytearray_isspace(PyObject *self, PyObject *Py_UNUSED(ignored))
2001
0
{
2002
0
    PyObject *ret;
2003
0
    Py_BEGIN_CRITICAL_SECTION(self);
2004
0
    ret = stringlib_isspace(self, NULL);
2005
0
    Py_END_CRITICAL_SECTION();
2006
0
    return ret;
2007
0
}
2008
2009
static PyObject *
2010
bytearray_istitle(PyObject *self, PyObject *Py_UNUSED(ignored))
2011
0
{
2012
0
    PyObject *ret;
2013
0
    Py_BEGIN_CRITICAL_SECTION(self);
2014
0
    ret = stringlib_istitle(self, NULL);
2015
0
    Py_END_CRITICAL_SECTION();
2016
0
    return ret;
2017
0
}
2018
2019
static PyObject *
2020
bytearray_isupper(PyObject *self, PyObject *Py_UNUSED(ignored))
2021
0
{
2022
0
    PyObject *ret;
2023
0
    Py_BEGIN_CRITICAL_SECTION(self);
2024
0
    ret = stringlib_isupper(self, NULL);
2025
0
    Py_END_CRITICAL_SECTION();
2026
0
    return ret;
2027
0
}
2028
2029
/*[clinic input]
2030
@critical_section
2031
bytearray.append
2032
2033
    item: bytesvalue
2034
        The item to be appended.
2035
    /
2036
2037
Append a single item to the end of the bytearray.
2038
[clinic start generated code]*/
2039
2040
static PyObject *
2041
bytearray_append_impl(PyByteArrayObject *self, int item)
2042
/*[clinic end generated code: output=a154e19ed1886cb6 input=a874689bac8bd352]*/
2043
580k
{
2044
580k
    Py_ssize_t n = Py_SIZE(self);
2045
2046
580k
    if (n == PY_SSIZE_T_MAX) {
2047
0
        PyErr_SetString(PyExc_OverflowError,
2048
0
                        "cannot add more objects to bytearray");
2049
0
        return NULL;
2050
0
    }
2051
580k
    if (bytearray_resize_lock_held((PyObject *)self, n + 1) < 0)
2052
0
        return NULL;
2053
2054
580k
    PyByteArray_AS_STRING(self)[n] = item;
2055
2056
580k
    Py_RETURN_NONE;
2057
580k
}
2058
2059
static PyObject *
2060
bytearray_capitalize(PyObject *self, PyObject *Py_UNUSED(ignored))
2061
0
{
2062
0
    PyObject *ret;
2063
0
    Py_BEGIN_CRITICAL_SECTION(self);
2064
0
    ret = stringlib_capitalize(self, NULL);
2065
0
    Py_END_CRITICAL_SECTION();
2066
0
    return ret;
2067
0
}
2068
2069
static PyObject *
2070
bytearray_center(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
2071
0
{
2072
0
    PyObject *ret;
2073
0
    Py_BEGIN_CRITICAL_SECTION(self);
2074
0
    ret = stringlib_center(self, args, nargs);
2075
0
    Py_END_CRITICAL_SECTION();
2076
0
    return ret;
2077
0
}
2078
2079
static PyObject *
2080
bytearray_expandtabs(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
2081
0
{
2082
0
    PyObject *ret;
2083
0
    Py_BEGIN_CRITICAL_SECTION(self);
2084
0
    ret = stringlib_expandtabs(self, args, nargs, kwnames);
2085
0
    Py_END_CRITICAL_SECTION();
2086
0
    return ret;
2087
0
}
2088
2089
/*[clinic input]
2090
@critical_section
2091
bytearray.extend
2092
2093
    iterable_of_ints: object
2094
        The iterable of items to append.
2095
    /
2096
2097
Append all the items from the iterator or sequence to the end of the bytearray.
2098
[clinic start generated code]*/
2099
2100
static PyObject *
2101
bytearray_extend_impl(PyByteArrayObject *self, PyObject *iterable_of_ints)
2102
/*[clinic end generated code: output=2f25e0ce72b98748 input=86e65beaba444650]*/
2103
8.66M
{
2104
8.66M
    PyObject *it, *item, *bytearray_obj;
2105
8.66M
    Py_ssize_t buf_size = 0, len = 0;
2106
8.66M
    int value;
2107
8.66M
    char *buf;
2108
2109
    /* bytearray_setslice code only accepts something supporting PEP 3118. */
2110
8.66M
    if (PyObject_CheckBuffer(iterable_of_ints)) {
2111
8.66M
        if (bytearray_setslice(self, Py_SIZE(self), Py_SIZE(self), iterable_of_ints) == -1)
2112
0
            return NULL;
2113
2114
8.66M
        Py_RETURN_NONE;
2115
8.66M
    }
2116
2117
0
    it = PyObject_GetIter(iterable_of_ints);
2118
0
    if (it == NULL) {
2119
0
        if (PyErr_ExceptionMatches(PyExc_TypeError)) {
2120
0
            PyErr_Format(PyExc_TypeError,
2121
0
                         "can't extend bytearray with %.100s",
2122
0
                         Py_TYPE(iterable_of_ints)->tp_name);
2123
0
        }
2124
0
        return NULL;
2125
0
    }
2126
2127
    /* Try to determine the length of the argument. 32 is arbitrary. */
2128
0
    buf_size = PyObject_LengthHint(iterable_of_ints, 32);
2129
0
    if (buf_size == -1) {
2130
0
        Py_DECREF(it);
2131
0
        return NULL;
2132
0
    }
2133
2134
0
    bytearray_obj = PyByteArray_FromStringAndSize(NULL, buf_size);
2135
0
    if (bytearray_obj == NULL) {
2136
0
        Py_DECREF(it);
2137
0
        return NULL;
2138
0
    }
2139
0
    buf = PyByteArray_AS_STRING(bytearray_obj);
2140
2141
0
    while ((item = PyIter_Next(it)) != NULL) {
2142
0
        if (! _getbytevalue(item, &value)) {
2143
0
            if (PyErr_ExceptionMatches(PyExc_TypeError) && PyUnicode_Check(iterable_of_ints)) {
2144
0
                PyErr_Format(PyExc_TypeError,
2145
0
                             "expected iterable of integers; got: 'str'");
2146
0
            }
2147
0
            Py_DECREF(item);
2148
0
            Py_DECREF(it);
2149
0
            Py_DECREF(bytearray_obj);
2150
0
            return NULL;
2151
0
        }
2152
0
        buf[len++] = value;
2153
0
        Py_DECREF(item);
2154
2155
0
        if (len >= buf_size) {
2156
0
            Py_ssize_t addition;
2157
0
            if (len == PY_SSIZE_T_MAX) {
2158
0
                Py_DECREF(it);
2159
0
                Py_DECREF(bytearray_obj);
2160
0
                return PyErr_NoMemory();
2161
0
            }
2162
0
            addition = len >> 1;
2163
0
            if (addition > PY_SSIZE_T_MAX - len - 1)
2164
0
                buf_size = PY_SSIZE_T_MAX;
2165
0
            else
2166
0
                buf_size = len + addition + 1;
2167
0
            if (bytearray_resize_lock_held((PyObject *)bytearray_obj, buf_size) < 0) {
2168
0
                Py_DECREF(it);
2169
0
                Py_DECREF(bytearray_obj);
2170
0
                return NULL;
2171
0
            }
2172
            /* Recompute the `buf' pointer, since the resizing operation may
2173
               have invalidated it. */
2174
0
            buf = PyByteArray_AS_STRING(bytearray_obj);
2175
0
        }
2176
0
    }
2177
0
    Py_DECREF(it);
2178
2179
0
    if (PyErr_Occurred()) {
2180
0
        Py_DECREF(bytearray_obj);
2181
0
        return NULL;
2182
0
    }
2183
2184
    /* Resize down to exact size. */
2185
0
    if (bytearray_resize_lock_held((PyObject *)bytearray_obj, len) < 0) {
2186
0
        Py_DECREF(bytearray_obj);
2187
0
        return NULL;
2188
0
    }
2189
2190
0
    if (bytearray_setslice(self, Py_SIZE(self), Py_SIZE(self), bytearray_obj) == -1) {
2191
0
        Py_DECREF(bytearray_obj);
2192
0
        return NULL;
2193
0
    }
2194
0
    Py_DECREF(bytearray_obj);
2195
2196
0
    assert(!PyErr_Occurred());
2197
0
    Py_RETURN_NONE;
2198
0
}
2199
2200
/*[clinic input]
2201
@critical_section
2202
bytearray.pop
2203
2204
    index: Py_ssize_t = -1
2205
        The index from where to remove the item.
2206
        -1 (the default value) means remove the last item.
2207
    /
2208
2209
Remove and return a single item from B.
2210
2211
If no index argument is given, will pop the last item.
2212
[clinic start generated code]*/
2213
2214
static PyObject *
2215
bytearray_pop_impl(PyByteArrayObject *self, Py_ssize_t index)
2216
/*[clinic end generated code: output=e0ccd401f8021da8 input=fc0fd8de4f97661c]*/
2217
0
{
2218
0
    int value;
2219
0
    Py_ssize_t n = Py_SIZE(self);
2220
0
    char *buf;
2221
2222
0
    if (n == 0) {
2223
0
        PyErr_SetString(PyExc_IndexError,
2224
0
                        "pop from empty bytearray");
2225
0
        return NULL;
2226
0
    }
2227
0
    if (index < 0)
2228
0
        index += Py_SIZE(self);
2229
0
    if (index < 0 || index >= Py_SIZE(self)) {
2230
0
        PyErr_SetString(PyExc_IndexError, "pop index out of range");
2231
0
        return NULL;
2232
0
    }
2233
0
    if (!_canresize(self))
2234
0
        return NULL;
2235
2236
0
    buf = PyByteArray_AS_STRING(self);
2237
0
    value = buf[index];
2238
0
    memmove(buf + index, buf + index + 1, n - index);
2239
0
    if (bytearray_resize_lock_held((PyObject *)self, n - 1) < 0)
2240
0
        return NULL;
2241
2242
0
    return _PyLong_FromUnsignedChar((unsigned char)value);
2243
0
}
2244
2245
/*[clinic input]
2246
@critical_section
2247
bytearray.remove
2248
2249
    value: bytesvalue
2250
        The value to remove.
2251
    /
2252
2253
Remove the first occurrence of a value in the bytearray.
2254
[clinic start generated code]*/
2255
2256
static PyObject *
2257
bytearray_remove_impl(PyByteArrayObject *self, int value)
2258
/*[clinic end generated code: output=d659e37866709c13 input=797588bc77f86afb]*/
2259
0
{
2260
0
    Py_ssize_t where, n = Py_SIZE(self);
2261
0
    char *buf = PyByteArray_AS_STRING(self);
2262
2263
0
    where = stringlib_find_char(buf, n, value);
2264
0
    if (where < 0) {
2265
0
        PyErr_SetString(PyExc_ValueError, "value not found in bytearray");
2266
0
        return NULL;
2267
0
    }
2268
0
    if (!_canresize(self))
2269
0
        return NULL;
2270
2271
0
    memmove(buf + where, buf + where + 1, n - where);
2272
0
    if (bytearray_resize_lock_held((PyObject *)self, n - 1) < 0)
2273
0
        return NULL;
2274
2275
0
    Py_RETURN_NONE;
2276
0
}
2277
2278
0
#define LEFTSTRIP 0
2279
0
#define RIGHTSTRIP 1
2280
0
#define BOTHSTRIP 2
2281
2282
static PyObject*
2283
bytearray_strip_impl_helper(PyByteArrayObject* self, PyObject* bytes, int striptype)
2284
0
{
2285
0
    Py_ssize_t mysize, byteslen;
2286
0
    const char* myptr;
2287
0
    const char* bytesptr;
2288
0
    Py_buffer vbytes;
2289
2290
0
    if (bytes == Py_None) {
2291
0
        bytesptr = "\t\n\r\f\v ";
2292
0
        byteslen = 6;
2293
0
    }
2294
0
    else {
2295
0
        if (PyObject_GetBuffer(bytes, &vbytes, PyBUF_SIMPLE) != 0)
2296
0
            return NULL;
2297
0
        bytesptr = (const char*)vbytes.buf;
2298
0
        byteslen = vbytes.len;
2299
0
    }
2300
0
    myptr = PyByteArray_AS_STRING(self);
2301
0
    mysize = Py_SIZE(self);
2302
2303
0
    Py_ssize_t left = 0;
2304
0
    if (striptype != RIGHTSTRIP) {
2305
0
        while (left < mysize && memchr(bytesptr, (unsigned char)myptr[left], byteslen))
2306
0
            left++;
2307
0
    }
2308
0
    Py_ssize_t right = mysize;
2309
0
    if (striptype != LEFTSTRIP) {
2310
0
        do {
2311
0
            right--;
2312
0
        } while (right >= left && memchr(bytesptr, (unsigned char)myptr[right], byteslen));
2313
0
        right++;
2314
0
    }
2315
0
    if (bytes != Py_None)
2316
0
        PyBuffer_Release(&vbytes);
2317
0
    return PyByteArray_FromStringAndSize(myptr + left, right - left);
2318
0
}
2319
2320
/*[clinic input]
2321
@critical_section
2322
bytearray.strip
2323
2324
    bytes: object = None
2325
    /
2326
2327
Strip leading and trailing bytes contained in the argument.
2328
2329
If the argument is omitted or None, strip leading and trailing ASCII whitespace.
2330
[clinic start generated code]*/
2331
2332
static PyObject *
2333
bytearray_strip_impl(PyByteArrayObject *self, PyObject *bytes)
2334
/*[clinic end generated code: output=760412661a34ad5a input=1f9026e5ad35388a]*/
2335
0
{
2336
0
    return bytearray_strip_impl_helper(self, bytes, BOTHSTRIP);
2337
0
}
2338
2339
static PyObject *
2340
bytearray_swapcase(PyObject *self, PyObject *Py_UNUSED(ignored))
2341
0
{
2342
0
    PyObject *ret;
2343
0
    Py_BEGIN_CRITICAL_SECTION(self);
2344
0
    ret = stringlib_swapcase(self, NULL);
2345
0
    Py_END_CRITICAL_SECTION();
2346
0
    return ret;
2347
0
}
2348
2349
static PyObject *
2350
bytearray_title(PyObject *self, PyObject *Py_UNUSED(ignored))
2351
0
{
2352
0
    PyObject *ret;
2353
0
    Py_BEGIN_CRITICAL_SECTION(self);
2354
0
    ret = stringlib_title(self, NULL);
2355
0
    Py_END_CRITICAL_SECTION();
2356
0
    return ret;
2357
0
}
2358
2359
static PyObject *
2360
bytearray_upper(PyObject *self, PyObject *Py_UNUSED(ignored))
2361
0
{
2362
0
    PyObject *ret;
2363
0
    Py_BEGIN_CRITICAL_SECTION(self);
2364
0
    ret = stringlib_upper(self, NULL);
2365
0
    Py_END_CRITICAL_SECTION();
2366
0
    return ret;
2367
0
}
2368
2369
static PyObject *
2370
bytearray_lower(PyObject *self, PyObject *Py_UNUSED(ignored))
2371
0
{
2372
0
    PyObject *ret;
2373
0
    Py_BEGIN_CRITICAL_SECTION(self);
2374
0
    ret = stringlib_lower(self, NULL);
2375
0
    Py_END_CRITICAL_SECTION();
2376
0
    return ret;
2377
0
}
2378
2379
static PyObject *
2380
bytearray_zfill(PyObject *self, PyObject *arg)
2381
0
{
2382
0
    PyObject *ret;
2383
0
    Py_BEGIN_CRITICAL_SECTION(self);
2384
0
    ret = stringlib_zfill(self, arg);
2385
0
    Py_END_CRITICAL_SECTION();
2386
0
    return ret;
2387
0
}
2388
2389
/*[clinic input]
2390
@critical_section
2391
bytearray.lstrip
2392
2393
    bytes: object = None
2394
    /
2395
2396
Strip leading bytes contained in the argument.
2397
2398
If the argument is omitted or None, strip leading ASCII whitespace.
2399
[clinic start generated code]*/
2400
2401
static PyObject *
2402
bytearray_lstrip_impl(PyByteArrayObject *self, PyObject *bytes)
2403
/*[clinic end generated code: output=d005c9d0ab909e66 input=ed86e00eb2023625]*/
2404
0
{
2405
0
    return bytearray_strip_impl_helper(self, bytes, LEFTSTRIP);
2406
0
}
2407
2408
/*[clinic input]
2409
@critical_section
2410
bytearray.rstrip
2411
2412
    bytes: object = None
2413
    /
2414
2415
Strip trailing bytes contained in the argument.
2416
2417
If the argument is omitted or None, strip trailing ASCII whitespace.
2418
[clinic start generated code]*/
2419
2420
static PyObject *
2421
bytearray_rstrip_impl(PyByteArrayObject *self, PyObject *bytes)
2422
/*[clinic end generated code: output=030e2fbd2f7276bd input=d9ca66cf20fe7649]*/
2423
0
{
2424
0
    return bytearray_strip_impl_helper(self, bytes, RIGHTSTRIP);
2425
0
}
2426
2427
/*[clinic input]
2428
@critical_section
2429
bytearray.decode
2430
2431
    encoding: str(c_default="NULL") = 'utf-8'
2432
        The encoding with which to decode the bytearray.
2433
    errors: str(c_default="NULL") = 'strict'
2434
        The error handling scheme to use for the handling of decoding errors.
2435
        The default is 'strict' meaning that decoding errors raise a
2436
        UnicodeDecodeError. Other possible values are 'ignore' and 'replace'
2437
        as well as any other name registered with codecs.register_error that
2438
        can handle UnicodeDecodeErrors.
2439
2440
Decode the bytearray using the codec registered for encoding.
2441
[clinic start generated code]*/
2442
2443
static PyObject *
2444
bytearray_decode_impl(PyByteArrayObject *self, const char *encoding,
2445
                      const char *errors)
2446
/*[clinic end generated code: output=f57d43f4a00b42c5 input=86c303ee376b8453]*/
2447
485k
{
2448
485k
    if (encoding == NULL)
2449
0
        encoding = PyUnicode_GetDefaultEncoding();
2450
485k
    return PyUnicode_FromEncodedObject((PyObject*)self, encoding, errors);
2451
485k
}
2452
2453
PyDoc_STRVAR(alloc_doc,
2454
"B.__alloc__() -> int\n\
2455
\n\
2456
Return the number of bytes actually allocated.");
2457
2458
static PyObject *
2459
bytearray_alloc(PyObject *op, PyObject *Py_UNUSED(ignored))
2460
0
{
2461
0
    PyByteArrayObject *self = _PyByteArray_CAST(op);
2462
0
    return PyLong_FromSsize_t(FT_ATOMIC_LOAD_SSIZE_RELAXED(self->ob_alloc));
2463
0
}
2464
2465
/*[clinic input]
2466
@critical_section
2467
bytearray.join
2468
2469
    iterable_of_bytes: object
2470
    /
2471
2472
Concatenate any number of bytes/bytearray objects.
2473
2474
The bytearray whose method is called is inserted in between each pair.
2475
2476
The result is returned as a new bytearray object.
2477
[clinic start generated code]*/
2478
2479
static PyObject *
2480
bytearray_join_impl(PyByteArrayObject *self, PyObject *iterable_of_bytes)
2481
/*[clinic end generated code: output=0ced382b5846a7ee input=49627e07ca31ca26]*/
2482
0
{
2483
0
    PyObject *ret;
2484
0
    self->ob_exports++; // this protects `self` from being cleared/resized if `iterable_of_bytes` is a custom iterator
2485
0
    ret = stringlib_bytes_join((PyObject*)self, iterable_of_bytes);
2486
0
    self->ob_exports--; // unexport `self`
2487
0
    return ret;
2488
0
}
2489
2490
static PyObject *
2491
bytearray_ljust(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
2492
0
{
2493
0
    PyObject *ret;
2494
0
    Py_BEGIN_CRITICAL_SECTION(self);
2495
0
    ret = stringlib_ljust(self, args, nargs);
2496
0
    Py_END_CRITICAL_SECTION();
2497
0
    return ret;
2498
0
}
2499
2500
static PyObject *
2501
bytearray_rjust(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
2502
0
{
2503
0
    PyObject *ret;
2504
0
    Py_BEGIN_CRITICAL_SECTION(self);
2505
0
    ret = stringlib_rjust(self, args, nargs);
2506
0
    Py_END_CRITICAL_SECTION();
2507
0
    return ret;
2508
0
}
2509
2510
/*[clinic input]
2511
@critical_section
2512
bytearray.splitlines
2513
2514
    keepends: bool = False
2515
2516
Return a list of the lines in the bytearray, breaking at line boundaries.
2517
2518
Line breaks are not included in the resulting list unless keepends is given and
2519
true.
2520
[clinic start generated code]*/
2521
2522
static PyObject *
2523
bytearray_splitlines_impl(PyByteArrayObject *self, int keepends)
2524
/*[clinic end generated code: output=4223c94b895f6ad9 input=874cd662866a66a1]*/
2525
0
{
2526
0
    return stringlib_splitlines(
2527
0
        (PyObject*) self, PyByteArray_AS_STRING(self),
2528
0
        PyByteArray_GET_SIZE(self), keepends
2529
0
        );
2530
0
}
2531
2532
/*[clinic input]
2533
@classmethod
2534
bytearray.fromhex
2535
2536
    string: object
2537
    /
2538
2539
Create a bytearray object from a string of hexadecimal numbers.
2540
2541
Spaces between two numbers are accepted.
2542
Example: bytearray.fromhex('B9 01EF') -> bytearray(b'\\xb9\\x01\\xef')
2543
[clinic start generated code]*/
2544
2545
static PyObject *
2546
bytearray_fromhex_impl(PyTypeObject *type, PyObject *string)
2547
/*[clinic end generated code: output=8f0f0b6d30fb3ba0 input=7e314e5b2d7ab484]*/
2548
0
{
2549
0
    PyObject *result = _PyBytes_FromHex(string, type == &PyByteArray_Type);
2550
0
    if (type != &PyByteArray_Type && result != NULL) {
2551
0
        Py_SETREF(result, PyObject_CallOneArg((PyObject *)type, result));
2552
0
    }
2553
0
    return result;
2554
0
}
2555
2556
/*[clinic input]
2557
@critical_section
2558
bytearray.hex
2559
2560
    sep: object = NULL
2561
        An optional single character or byte to separate hex bytes.
2562
    bytes_per_sep: int = 1
2563
        How many bytes between separators.  Positive values count from the
2564
        right, negative values count from the left.
2565
2566
Create a string of hexadecimal numbers from a bytearray object.
2567
2568
Example:
2569
>>> value = bytearray([0xb9, 0x01, 0xef])
2570
>>> value.hex()
2571
'b901ef'
2572
>>> value.hex(':')
2573
'b9:01:ef'
2574
>>> value.hex(':', 2)
2575
'b9:01ef'
2576
>>> value.hex(':', -2)
2577
'b901:ef'
2578
[clinic start generated code]*/
2579
2580
static PyObject *
2581
bytearray_hex_impl(PyByteArrayObject *self, PyObject *sep, int bytes_per_sep)
2582
/*[clinic end generated code: output=29c4e5ef72c565a0 input=7784107de7048873]*/
2583
0
{
2584
0
    char* argbuf = PyByteArray_AS_STRING(self);
2585
0
    Py_ssize_t arglen = PyByteArray_GET_SIZE(self);
2586
0
    return _Py_strhex_with_sep(argbuf, arglen, sep, bytes_per_sep);
2587
0
}
2588
2589
static PyObject *
2590
_common_reduce(PyByteArrayObject *self, int proto)
2591
0
{
2592
0
    PyObject *state;
2593
0
    const char *buf;
2594
2595
0
    state = _PyObject_GetState((PyObject *)self);
2596
0
    if (state == NULL) {
2597
0
        return NULL;
2598
0
    }
2599
2600
0
    if (!Py_SIZE(self)) {
2601
0
        return Py_BuildValue("(O()N)", Py_TYPE(self), state);
2602
0
    }
2603
0
    buf = PyByteArray_AS_STRING(self);
2604
0
    if (proto < 3) {
2605
        /* use str based reduction for backwards compatibility with Python 2.x */
2606
0
        PyObject *latin1 = PyUnicode_DecodeLatin1(buf, Py_SIZE(self), NULL);
2607
0
        return Py_BuildValue("(O(Ns)N)", Py_TYPE(self), latin1, "latin-1", state);
2608
0
    }
2609
0
    else {
2610
        /* use more efficient byte based reduction */
2611
0
        return Py_BuildValue("(O(y#)N)", Py_TYPE(self), buf, Py_SIZE(self), state);
2612
0
    }
2613
0
}
2614
2615
/*[clinic input]
2616
@critical_section
2617
bytearray.__reduce__ as bytearray_reduce
2618
2619
Return state information for pickling.
2620
[clinic start generated code]*/
2621
2622
static PyObject *
2623
bytearray_reduce_impl(PyByteArrayObject *self)
2624
/*[clinic end generated code: output=52bf304086464cab input=0fac78e4b7d84dd2]*/
2625
0
{
2626
0
    return _common_reduce(self, 2);
2627
0
}
2628
2629
/*[clinic input]
2630
@critical_section
2631
bytearray.__reduce_ex__ as bytearray_reduce_ex
2632
2633
    proto: int = 0
2634
    /
2635
2636
Return state information for pickling.
2637
[clinic start generated code]*/
2638
2639
static PyObject *
2640
bytearray_reduce_ex_impl(PyByteArrayObject *self, int proto)
2641
/*[clinic end generated code: output=52eac33377197520 input=751718f477033a29]*/
2642
0
{
2643
0
    return _common_reduce(self, proto);
2644
0
}
2645
2646
/*[clinic input]
2647
bytearray.__sizeof__ as bytearray_sizeof
2648
2649
Returns the size of the bytearray object in memory, in bytes.
2650
[clinic start generated code]*/
2651
2652
static PyObject *
2653
bytearray_sizeof_impl(PyByteArrayObject *self)
2654
/*[clinic end generated code: output=738abdd17951c427 input=e27320fd98a4bc5a]*/
2655
0
{
2656
0
    size_t res = _PyObject_SIZE(Py_TYPE(self));
2657
0
    res += (size_t)FT_ATOMIC_LOAD_SSIZE_RELAXED(self->ob_alloc) * sizeof(char);
2658
0
    return PyLong_FromSize_t(res);
2659
0
}
2660
2661
static PySequenceMethods bytearray_as_sequence = {
2662
    bytearray_length,                       /* sq_length */
2663
    PyByteArray_Concat,                     /* sq_concat */
2664
    bytearray_repeat,                       /* sq_repeat */
2665
    bytearray_getitem,                      /* sq_item */
2666
    0,                                      /* sq_slice */
2667
    bytearray_setitem,                      /* sq_ass_item */
2668
    0,                                      /* sq_ass_slice */
2669
    bytearray_contains,                     /* sq_contains */
2670
    bytearray_iconcat,                      /* sq_inplace_concat */
2671
    bytearray_irepeat,                      /* sq_inplace_repeat */
2672
};
2673
2674
static PyMappingMethods bytearray_as_mapping = {
2675
    bytearray_length,
2676
    bytearray_subscript,
2677
    bytearray_ass_subscript,
2678
};
2679
2680
static PyBufferProcs bytearray_as_buffer = {
2681
    bytearray_getbuffer,
2682
    bytearray_releasebuffer,
2683
};
2684
2685
static PyMethodDef bytearray_methods[] = {
2686
    {"__alloc__", bytearray_alloc, METH_NOARGS, alloc_doc},
2687
    BYTEARRAY_REDUCE_METHODDEF
2688
    BYTEARRAY_REDUCE_EX_METHODDEF
2689
    BYTEARRAY_SIZEOF_METHODDEF
2690
    BYTEARRAY_APPEND_METHODDEF
2691
    {"capitalize", bytearray_capitalize, METH_NOARGS, _Py_capitalize__doc__},
2692
    {"center", _PyCFunction_CAST(bytearray_center), METH_FASTCALL,
2693
    stringlib_center__doc__},
2694
    BYTEARRAY_CLEAR_METHODDEF
2695
    BYTEARRAY_COPY_METHODDEF
2696
    BYTEARRAY_COUNT_METHODDEF
2697
    BYTEARRAY_DECODE_METHODDEF
2698
    BYTEARRAY_ENDSWITH_METHODDEF
2699
    {"expandtabs", _PyCFunction_CAST(bytearray_expandtabs),
2700
    METH_FASTCALL|METH_KEYWORDS, stringlib_expandtabs__doc__},
2701
    BYTEARRAY_EXTEND_METHODDEF
2702
    BYTEARRAY_FIND_METHODDEF
2703
    BYTEARRAY_FROMHEX_METHODDEF
2704
    BYTEARRAY_HEX_METHODDEF
2705
    BYTEARRAY_INDEX_METHODDEF
2706
    BYTEARRAY_INSERT_METHODDEF
2707
    {"isalnum", bytearray_isalnum, METH_NOARGS, _Py_isalnum__doc__},
2708
    {"isalpha", bytearray_isalpha, METH_NOARGS, _Py_isalpha__doc__},
2709
    {"isascii", bytearray_isascii, METH_NOARGS, _Py_isascii__doc__},
2710
    {"isdigit", bytearray_isdigit, METH_NOARGS, _Py_isdigit__doc__},
2711
    {"islower", bytearray_islower, METH_NOARGS, _Py_islower__doc__},
2712
    {"isspace", bytearray_isspace, METH_NOARGS, _Py_isspace__doc__},
2713
    {"istitle", bytearray_istitle, METH_NOARGS, _Py_istitle__doc__},
2714
    {"isupper", bytearray_isupper, METH_NOARGS, _Py_isupper__doc__},
2715
    BYTEARRAY_JOIN_METHODDEF
2716
    {"ljust", _PyCFunction_CAST(bytearray_ljust), METH_FASTCALL,
2717
    stringlib_ljust__doc__},
2718
    {"lower", bytearray_lower, METH_NOARGS, _Py_lower__doc__},
2719
    BYTEARRAY_LSTRIP_METHODDEF
2720
    BYTEARRAY_MAKETRANS_METHODDEF
2721
    BYTEARRAY_PARTITION_METHODDEF
2722
    BYTEARRAY_POP_METHODDEF
2723
    BYTEARRAY_REMOVE_METHODDEF
2724
    BYTEARRAY_REPLACE_METHODDEF
2725
    BYTEARRAY_REMOVEPREFIX_METHODDEF
2726
    BYTEARRAY_REMOVESUFFIX_METHODDEF
2727
    BYTEARRAY_RESIZE_METHODDEF
2728
    BYTEARRAY_REVERSE_METHODDEF
2729
    BYTEARRAY_RFIND_METHODDEF
2730
    BYTEARRAY_RINDEX_METHODDEF
2731
    {"rjust", _PyCFunction_CAST(bytearray_rjust), METH_FASTCALL,
2732
    stringlib_rjust__doc__},
2733
    BYTEARRAY_RPARTITION_METHODDEF
2734
    BYTEARRAY_RSPLIT_METHODDEF
2735
    BYTEARRAY_RSTRIP_METHODDEF
2736
    BYTEARRAY_SPLIT_METHODDEF
2737
    BYTEARRAY_SPLITLINES_METHODDEF
2738
    BYTEARRAY_STARTSWITH_METHODDEF
2739
    BYTEARRAY_STRIP_METHODDEF
2740
    {"swapcase", bytearray_swapcase, METH_NOARGS, _Py_swapcase__doc__},
2741
    {"title", bytearray_title, METH_NOARGS, _Py_title__doc__},
2742
    BYTEARRAY_TRANSLATE_METHODDEF
2743
    {"upper", bytearray_upper, METH_NOARGS, _Py_upper__doc__},
2744
    {"zfill", bytearray_zfill, METH_O, stringlib_zfill__doc__},
2745
    {NULL}
2746
};
2747
2748
static PyObject *
2749
bytearray_mod_lock_held(PyObject *v, PyObject *w)
2750
0
{
2751
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(v);
2752
0
    if (!PyByteArray_Check(v))
2753
0
        Py_RETURN_NOTIMPLEMENTED;
2754
0
    return _PyBytes_FormatEx(PyByteArray_AS_STRING(v), PyByteArray_GET_SIZE(v), w, 1);
2755
0
}
2756
2757
static PyObject *
2758
bytearray_mod(PyObject *v, PyObject *w)
2759
0
{
2760
0
    PyObject *ret;
2761
0
    if (PyByteArray_Check(w)) {
2762
0
        Py_BEGIN_CRITICAL_SECTION2(v, w);
2763
0
        ret = bytearray_mod_lock_held(v, w);
2764
0
        Py_END_CRITICAL_SECTION2();
2765
0
    }
2766
0
    else {
2767
0
        Py_BEGIN_CRITICAL_SECTION(v);
2768
0
        ret = bytearray_mod_lock_held(v, w);
2769
0
        Py_END_CRITICAL_SECTION();
2770
0
    }
2771
0
    return ret;
2772
0
}
2773
2774
static PyNumberMethods bytearray_as_number = {
2775
    0,              /*nb_add*/
2776
    0,              /*nb_subtract*/
2777
    0,              /*nb_multiply*/
2778
    bytearray_mod,  /*nb_remainder*/
2779
};
2780
2781
PyDoc_STRVAR(bytearray_doc,
2782
"bytearray(iterable_of_ints) -> bytearray\n\
2783
bytearray(string, encoding[, errors]) -> bytearray\n\
2784
bytearray(bytes_or_buffer) -> mutable copy of bytes_or_buffer\n\
2785
bytearray(int) -> bytes array of size given by the parameter initialized with null bytes\n\
2786
bytearray() -> empty bytes array\n\
2787
\n\
2788
Construct a mutable bytearray object from:\n\
2789
  - an iterable yielding integers in range(256)\n\
2790
  - a text string encoded using the specified encoding\n\
2791
  - a bytes or a buffer object\n\
2792
  - any object implementing the buffer API.\n\
2793
  - an integer");
2794
2795
2796
static PyObject *bytearray_iter(PyObject *seq);
2797
2798
PyTypeObject PyByteArray_Type = {
2799
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
2800
    "bytearray",
2801
    sizeof(PyByteArrayObject),
2802
    0,
2803
    bytearray_dealloc,                  /* tp_dealloc */
2804
    0,                                  /* tp_vectorcall_offset */
2805
    0,                                  /* tp_getattr */
2806
    0,                                  /* tp_setattr */
2807
    0,                                  /* tp_as_async */
2808
    bytearray_repr,                     /* tp_repr */
2809
    &bytearray_as_number,               /* tp_as_number */
2810
    &bytearray_as_sequence,             /* tp_as_sequence */
2811
    &bytearray_as_mapping,              /* tp_as_mapping */
2812
    0,                                  /* tp_hash */
2813
    0,                                  /* tp_call */
2814
    bytearray_str,                      /* tp_str */
2815
    PyObject_GenericGetAttr,            /* tp_getattro */
2816
    0,                                  /* tp_setattro */
2817
    &bytearray_as_buffer,               /* tp_as_buffer */
2818
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
2819
        _Py_TPFLAGS_MATCH_SELF,       /* tp_flags */
2820
    bytearray_doc,                      /* tp_doc */
2821
    0,                                  /* tp_traverse */
2822
    0,                                  /* tp_clear */
2823
    bytearray_richcompare,              /* tp_richcompare */
2824
    0,                                  /* tp_weaklistoffset */
2825
    bytearray_iter,                     /* tp_iter */
2826
    0,                                  /* tp_iternext */
2827
    bytearray_methods,                  /* tp_methods */
2828
    0,                                  /* tp_members */
2829
    0,                                  /* tp_getset */
2830
    0,                                  /* tp_base */
2831
    0,                                  /* tp_dict */
2832
    0,                                  /* tp_descr_get */
2833
    0,                                  /* tp_descr_set */
2834
    0,                                  /* tp_dictoffset */
2835
    bytearray___init__,                 /* tp_init */
2836
    PyType_GenericAlloc,                /* tp_alloc */
2837
    PyType_GenericNew,                  /* tp_new */
2838
    PyObject_Free,                      /* tp_free */
2839
    .tp_version_tag = _Py_TYPE_VERSION_BYTEARRAY,
2840
};
2841
2842
/*********************** Bytearray Iterator ****************************/
2843
2844
typedef struct {
2845
    PyObject_HEAD
2846
    Py_ssize_t it_index;
2847
    PyByteArrayObject *it_seq; /* Set to NULL when iterator is exhausted */
2848
} bytesiterobject;
2849
2850
16
#define _bytesiterobject_CAST(op)   ((bytesiterobject *)(op))
2851
2852
static void
2853
bytearrayiter_dealloc(PyObject *self)
2854
16
{
2855
16
    bytesiterobject *it = _bytesiterobject_CAST(self);
2856
16
    _PyObject_GC_UNTRACK(it);
2857
16
    Py_XDECREF(it->it_seq);
2858
16
    PyObject_GC_Del(it);
2859
16
}
2860
2861
static int
2862
bytearrayiter_traverse(PyObject *self, visitproc visit, void *arg)
2863
0
{
2864
0
    bytesiterobject *it = _bytesiterobject_CAST(self);
2865
0
    Py_VISIT(it->it_seq);
2866
0
    return 0;
2867
0
}
2868
2869
static PyObject *
2870
bytearrayiter_next(PyObject *self)
2871
0
{
2872
0
    bytesiterobject *it = _bytesiterobject_CAST(self);
2873
0
    int val;
2874
2875
0
    assert(it != NULL);
2876
0
    Py_ssize_t index = FT_ATOMIC_LOAD_SSIZE_RELAXED(it->it_index);
2877
0
    if (index < 0) {
2878
0
        return NULL;
2879
0
    }
2880
0
    PyByteArrayObject *seq = it->it_seq;
2881
0
    assert(PyByteArray_Check(seq));
2882
2883
0
    Py_BEGIN_CRITICAL_SECTION(seq);
2884
0
    if (index < Py_SIZE(seq)) {
2885
0
        val = (unsigned char)PyByteArray_AS_STRING(seq)[index];
2886
0
    }
2887
0
    else {
2888
0
        val = -1;
2889
0
    }
2890
0
    Py_END_CRITICAL_SECTION();
2891
2892
0
    if (val == -1) {
2893
0
        FT_ATOMIC_STORE_SSIZE_RELAXED(it->it_index, -1);
2894
0
#ifndef Py_GIL_DISABLED
2895
0
        Py_CLEAR(it->it_seq);
2896
0
#endif
2897
0
        return NULL;
2898
0
    }
2899
0
    FT_ATOMIC_STORE_SSIZE_RELAXED(it->it_index, index + 1);
2900
0
    return _PyLong_FromUnsignedChar((unsigned char)val);
2901
0
}
2902
2903
static PyObject *
2904
bytearrayiter_length_hint(PyObject *self, PyObject *Py_UNUSED(ignored))
2905
0
{
2906
0
    bytesiterobject *it = _bytesiterobject_CAST(self);
2907
0
    Py_ssize_t len = 0;
2908
0
    Py_ssize_t index = FT_ATOMIC_LOAD_SSIZE_RELAXED(it->it_index);
2909
0
    if (index >= 0) {
2910
0
        len = PyByteArray_GET_SIZE(it->it_seq) - index;
2911
0
        if (len < 0) {
2912
0
            len = 0;
2913
0
        }
2914
0
    }
2915
0
    return PyLong_FromSsize_t(len);
2916
0
}
2917
2918
PyDoc_STRVAR(length_hint_doc,
2919
    "Private method returning an estimate of len(list(it)).");
2920
2921
static PyObject *
2922
bytearrayiter_reduce(PyObject *self, PyObject *Py_UNUSED(ignored))
2923
0
{
2924
0
    PyObject *iter = _PyEval_GetBuiltin(&_Py_ID(iter));
2925
2926
    /* _PyEval_GetBuiltin can invoke arbitrary code,
2927
     * call must be before access of iterator pointers.
2928
     * see issue #101765 */
2929
0
    bytesiterobject *it = _bytesiterobject_CAST(self);
2930
0
    Py_ssize_t index = FT_ATOMIC_LOAD_SSIZE_RELAXED(it->it_index);
2931
0
    if (index >= 0) {
2932
0
        return Py_BuildValue("N(O)n", iter, it->it_seq, index);
2933
0
    }
2934
0
    return Py_BuildValue("N(())", iter);
2935
0
}
2936
2937
static PyObject *
2938
bytearrayiter_setstate(PyObject *self, PyObject *state)
2939
0
{
2940
0
    Py_ssize_t index = PyLong_AsSsize_t(state);
2941
0
    if (index == -1 && PyErr_Occurred()) {
2942
0
        return NULL;
2943
0
    }
2944
2945
0
    bytesiterobject *it = _bytesiterobject_CAST(self);
2946
0
    if (FT_ATOMIC_LOAD_SSIZE_RELAXED(it->it_index) >= 0) {
2947
0
        if (index < -1) {
2948
0
            index = -1;
2949
0
        }
2950
0
        else {
2951
0
            Py_ssize_t size = PyByteArray_GET_SIZE(it->it_seq);
2952
0
            if (index > size) {
2953
0
                index = size; /* iterator at end */
2954
0
            }
2955
0
        }
2956
0
        FT_ATOMIC_STORE_SSIZE_RELAXED(it->it_index, index);
2957
0
    }
2958
0
    Py_RETURN_NONE;
2959
0
}
2960
2961
PyDoc_STRVAR(setstate_doc, "Set state information for unpickling.");
2962
2963
static PyMethodDef bytearrayiter_methods[] = {
2964
    {"__length_hint__", bytearrayiter_length_hint, METH_NOARGS,
2965
     length_hint_doc},
2966
     {"__reduce__",     bytearrayiter_reduce, METH_NOARGS,
2967
     bytearray_reduce__doc__},
2968
    {"__setstate__",    bytearrayiter_setstate, METH_O,
2969
     setstate_doc},
2970
    {NULL, NULL} /* sentinel */
2971
};
2972
2973
PyTypeObject PyByteArrayIter_Type = {
2974
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
2975
    "bytearray_iterator",              /* tp_name */
2976
    sizeof(bytesiterobject),           /* tp_basicsize */
2977
    0,                                 /* tp_itemsize */
2978
    /* methods */
2979
    bytearrayiter_dealloc,             /* tp_dealloc */
2980
    0,                                 /* tp_vectorcall_offset */
2981
    0,                                 /* tp_getattr */
2982
    0,                                 /* tp_setattr */
2983
    0,                                 /* tp_as_async */
2984
    0,                                 /* tp_repr */
2985
    0,                                 /* tp_as_number */
2986
    0,                                 /* tp_as_sequence */
2987
    0,                                 /* tp_as_mapping */
2988
    0,                                 /* tp_hash */
2989
    0,                                 /* tp_call */
2990
    0,                                 /* tp_str */
2991
    PyObject_GenericGetAttr,           /* tp_getattro */
2992
    0,                                 /* tp_setattro */
2993
    0,                                 /* tp_as_buffer */
2994
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
2995
    0,                                 /* tp_doc */
2996
    bytearrayiter_traverse,            /* tp_traverse */
2997
    0,                                 /* tp_clear */
2998
    0,                                 /* tp_richcompare */
2999
    0,                                 /* tp_weaklistoffset */
3000
    PyObject_SelfIter,                 /* tp_iter */
3001
    bytearrayiter_next,                /* tp_iternext */
3002
    bytearrayiter_methods,             /* tp_methods */
3003
    0,
3004
};
3005
3006
static PyObject *
3007
bytearray_iter(PyObject *seq)
3008
16
{
3009
16
    bytesiterobject *it;
3010
3011
16
    if (!PyByteArray_Check(seq)) {
3012
0
        PyErr_BadInternalCall();
3013
0
        return NULL;
3014
0
    }
3015
16
    it = PyObject_GC_New(bytesiterobject, &PyByteArrayIter_Type);
3016
16
    if (it == NULL)
3017
0
        return NULL;
3018
16
    it->it_index = 0;  // -1 indicates exhausted
3019
16
    it->it_seq = (PyByteArrayObject *)Py_NewRef(seq);
3020
16
    _PyObject_GC_TRACK(it);
3021
16
    return (PyObject *)it;
3022
16
}