LCOV - code coverage report
Current view: top level - libreoffice/workdir/unxlngi6.pro/UnpackedTarball/python3/Objects - bytearrayobject.c (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 30 1360 2.2 %
Date: 2012-12-17 Functions: 5 84 6.0 %
Legend: Lines: hit not hit

          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             : }

Generated by: LCOV version 1.10