Coverage Report

Created: 2025-07-18 06:09

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