Coverage Report

Created: 2026-01-09 06:26

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