Coverage Report

Created: 2025-11-24 06:11

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