Coverage Report

Created: 2026-05-30 06:18

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