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