Coverage Report

Created: 2025-08-26 06:26

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