#include "Python.h"
#include "pycore_abstract.h"
#include "pycore_bytes_methods.h"
#include "pycore_bytesobject.h"
#include "pycore_object.h"
#include "pycore_strhex.h"
#include "pycore_long.h"
#include "bytesobject.h"
char _PyByteArray_empty_string[] = "";
static int
_getbytevalue(PyObject* arg, int *value)
{
int overflow;
long face_value = PyLong_AsLongAndOverflow(arg, &overflow);
if (face_value == -1 && PyErr_Occurred()) {
*value = -1;
return 0;
}
if (face_value < 0 || face_value >= 256) {
PyErr_SetString(PyExc_ValueError, "byte must be in range(0, 256)");
*value = -1;
return 0;
}
*value = face_value;
return 1;
}
static int
bytearray_getbuffer(PyByteArrayObject *obj, Py_buffer *view, int flags)
{
void *ptr;
if (view == NULL) {
PyErr_SetString(PyExc_BufferError,
"bytearray_getbuffer: view==NULL argument is obsolete");
return -1;
}
ptr = (void *) PyByteArray_AS_STRING(obj);
(void)PyBuffer_FillInfo(view, (PyObject*)obj, ptr, Py_SIZE(obj), 0, flags);
obj->ob_exports++;
return 0;
}
static void
bytearray_releasebuffer(PyByteArrayObject *obj, Py_buffer *view)
{
obj->ob_exports--;
assert(obj->ob_exports >= 0);
}
static int
_canresize(PyByteArrayObject *self)
{
if (self->ob_exports > 0) {
PyErr_SetString(PyExc_BufferError,
"Existing exports of data: object cannot be re-sized");
return 0;
}
return 1;
}
#include "clinic/bytearrayobject.c.h"
PyObject *
PyByteArray_FromObject(PyObject *input)
{
return PyObject_CallOneArg((PyObject *)&PyByteArray_Type, input);
}
static PyObject *
_PyByteArray_FromBufferObject(PyObject *obj)
{
PyObject *result;
Py_buffer view;
if (PyObject_GetBuffer(obj, &view, PyBUF_FULL_RO) < 0) {
return NULL;
}
result = PyByteArray_FromStringAndSize(NULL, view.len);
if (result != NULL &&
PyBuffer_ToContiguous(PyByteArray_AS_STRING(result),
&view, view.len, 'C') < 0)
{
Py_CLEAR(result);
}
PyBuffer_Release(&view);
return result;
}
PyObject *
PyByteArray_FromStringAndSize(const char *bytes, Py_ssize_t size)
{
PyByteArrayObject *new;
Py_ssize_t alloc;
if (size < 0) {
PyErr_SetString(PyExc_SystemError,
"Negative size passed to PyByteArray_FromStringAndSize");
return NULL;
}
if (size == PY_SSIZE_T_MAX) {
return PyErr_NoMemory();
}
new = PyObject_New(PyByteArrayObject, &PyByteArray_Type);
if (new == NULL)
return NULL;
if (size == 0) {
new->ob_bytes = NULL;
alloc = 0;
}
else {
alloc = size + 1;
new->ob_bytes = PyObject_Malloc(alloc);
if (new->ob_bytes == NULL) {
Py_DECREF(new);
return PyErr_NoMemory();
}
if (bytes != NULL && size > 0)
memcpy(new->ob_bytes, bytes, size);
new->ob_bytes[size] = '\0';
}
Py_SET_SIZE(new, size);
new->ob_alloc = alloc;
new->ob_start = new->ob_bytes;
new->ob_exports = 0;
return (PyObject *)new;
}
Py_ssize_t
PyByteArray_Size(PyObject *self)
{
assert(self != NULL);
assert(PyByteArray_Check(self));
return PyByteArray_GET_SIZE(self);
}
char *
PyByteArray_AsString(PyObject *self)
{
assert(self != NULL);
assert(PyByteArray_Check(self));
return PyByteArray_AS_STRING(self);
}
int
PyByteArray_Resize(PyObject *self, Py_ssize_t requested_size)
{
void *sval;
PyByteArrayObject *obj = ((PyByteArrayObject *)self);
size_t alloc = (size_t) obj->ob_alloc;
size_t logical_offset = (size_t) (obj->ob_start - obj->ob_bytes);
size_t size = (size_t) requested_size;
assert(self != NULL);
assert(PyByteArray_Check(self));
assert(logical_offset <= alloc);
assert(requested_size >= 0);
if (requested_size == Py_SIZE(self)) {
return 0;
}
if (!_canresize(obj)) {
return -1;
}
if (size + logical_offset + 1 <= alloc) {
if (size < alloc / 2) {
alloc = size + 1;
}
else {
Py_SET_SIZE(self, size);
PyByteArray_AS_STRING(self)[size] = '\0';
return 0;
}
}
else {
if (size <= alloc * 1.125) {
alloc = size + (size >> 3) + (size < 9 ? 3 : 6);
}
else {
alloc = size + 1;
}
}
if (alloc > PY_SSIZE_T_MAX) {
PyErr_NoMemory();
return -1;
}
if (logical_offset > 0) {
sval = PyObject_Malloc(alloc);
if (sval == NULL) {
PyErr_NoMemory();
return -1;
}
memcpy(sval, PyByteArray_AS_STRING(self),
Py_MIN((size_t)requested_size, (size_t)Py_SIZE(self)));
PyObject_Free(obj->ob_bytes);
}
else {
sval = PyObject_Realloc(obj->ob_bytes, alloc);
if (sval == NULL) {
PyErr_NoMemory();
return -1;
}
}
obj->ob_bytes = obj->ob_start = sval;
Py_SET_SIZE(self, size);
obj->ob_alloc = alloc;
obj->ob_bytes[size] = '\0';
return 0;
}
PyObject *
PyByteArray_Concat(PyObject *a, PyObject *b)
{
Py_buffer va, vb;
PyByteArrayObject *result = NULL;
va.len = -1;
vb.len = -1;
if (PyObject_GetBuffer(a, &va, PyBUF_SIMPLE) != 0 ||
PyObject_GetBuffer(b, &vb, PyBUF_SIMPLE) != 0) {
PyErr_Format(PyExc_TypeError, "can't concat %.100s to %.100s",
Py_TYPE(b)->tp_name, Py_TYPE(a)->tp_name);
goto done;
}
if (va.len > PY_SSIZE_T_MAX - vb.len) {
PyErr_NoMemory();
goto done;
}
result = (PyByteArrayObject *) \
PyByteArray_FromStringAndSize(NULL, va.len + vb.len);
if (result != NULL && result->ob_bytes != NULL) {
memcpy(result->ob_bytes, va.buf, va.len);
memcpy(result->ob_bytes + va.len, vb.buf, vb.len);
}
done:
if (va.len != -1)
PyBuffer_Release(&va);
if (vb.len != -1)
PyBuffer_Release(&vb);
return (PyObject *)result;
}
static Py_ssize_t
bytearray_length(PyByteArrayObject *self)
{
return Py_SIZE(self);
}
static PyObject *
bytearray_iconcat(PyByteArrayObject *self, PyObject *other)
{
Py_ssize_t size;
Py_buffer vo;
if (PyObject_GetBuffer(other, &vo, PyBUF_SIMPLE) != 0) {
PyErr_Format(PyExc_TypeError, "can't concat %.100s to %.100s",
Py_TYPE(other)->tp_name, Py_TYPE(self)->tp_name);
return NULL;
}
size = Py_SIZE(self);
if (size > PY_SSIZE_T_MAX - vo.len) {
PyBuffer_Release(&vo);
return PyErr_NoMemory();
}
if (PyByteArray_Resize((PyObject *)self, size + vo.len) < 0) {
PyBuffer_Release(&vo);
return NULL;
}
memcpy(PyByteArray_AS_STRING(self) + size, vo.buf, vo.len);
PyBuffer_Release(&vo);
return Py_NewRef(self);
}
static PyObject *
bytearray_repeat(PyByteArrayObject *self, Py_ssize_t count)
{
if (count < 0)
count = 0;
const Py_ssize_t mysize = Py_SIZE(self);
if (count > 0 && mysize > PY_SSIZE_T_MAX / count)
return PyErr_NoMemory();
Py_ssize_t size = mysize * count;
PyByteArrayObject* result = (PyByteArrayObject *)PyByteArray_FromStringAndSize(NULL, size);
const char* buf = PyByteArray_AS_STRING(self);
if (result != NULL && size != 0) {
_PyBytes_Repeat(result->ob_bytes, size, buf, mysize);
}
return (PyObject *)result;
}
static PyObject *
bytearray_irepeat(PyByteArrayObject *self, Py_ssize_t count)
{
if (count < 0)
count = 0;
else if (count == 1) {
return Py_NewRef(self);
}
const Py_ssize_t mysize = Py_SIZE(self);
if (count > 0 && mysize > PY_SSIZE_T_MAX / count)
return PyErr_NoMemory();
const Py_ssize_t size = mysize * count;
if (PyByteArray_Resize((PyObject *)self, size) < 0)
return NULL;
char* buf = PyByteArray_AS_STRING(self);
_PyBytes_Repeat(buf, size, buf, mysize);
return Py_NewRef(self);
}
static PyObject *
bytearray_getitem(PyByteArrayObject *self, Py_ssize_t i)
{
if (i < 0 || i >= Py_SIZE(self)) {
PyErr_SetString(PyExc_IndexError, "bytearray index out of range");
return NULL;
}
return _PyLong_FromUnsignedChar((unsigned char)(self->ob_start[i]));
}
static PyObject *
bytearray_subscript(PyByteArrayObject *self, PyObject *index)
{
if (_PyIndex_Check(index)) {
Py_ssize_t i = PyNumber_AsSsize_t(index, PyExc_IndexError);
if (i == -1 && PyErr_Occurred())
return NULL;
if (i < 0)
i += PyByteArray_GET_SIZE(self);
if (i < 0 || i >= Py_SIZE(self)) {
PyErr_SetString(PyExc_IndexError, "bytearray index out of range");
return NULL;
}
return _PyLong_FromUnsignedChar((unsigned char)(self->ob_start[i]));
}
else if (PySlice_Check(index)) {
Py_ssize_t start, stop, step, slicelength, i;
size_t cur;
if (PySlice_Unpack(index, &start, &stop, &step) < 0) {
return NULL;
}
slicelength = PySlice_AdjustIndices(PyByteArray_GET_SIZE(self),
&start, &stop, step);
if (slicelength <= 0)
return PyByteArray_FromStringAndSize("", 0);
else if (step == 1) {
return PyByteArray_FromStringAndSize(
PyByteArray_AS_STRING(self) + start, slicelength);
}
else {
char *source_buf = PyByteArray_AS_STRING(self);
char *result_buf;
PyObject *result;
result = PyByteArray_FromStringAndSize(NULL, slicelength);
if (result == NULL)
return NULL;
result_buf = PyByteArray_AS_STRING(result);
for (cur = start, i = 0; i < slicelength;
cur += step, i++) {
result_buf[i] = source_buf[cur];
}
return result;
}
}
else {
PyErr_Format(PyExc_TypeError,
"bytearray indices must be integers or slices, not %.200s",
Py_TYPE(index)->tp_name);
return NULL;
}
}
static int
bytearray_setslice_linear(PyByteArrayObject *self,
Py_ssize_t lo, Py_ssize_t hi,
char *bytes, Py_ssize_t bytes_len)
{
Py_ssize_t avail = hi - lo;
char *buf = PyByteArray_AS_STRING(self);
Py_ssize_t growth = bytes_len - avail;
int res = 0;
assert(avail >= 0);
if (growth < 0) {
if (!_canresize(self))
return -1;
if (lo == 0) {
self->ob_start -= growth;
}
else {
memmove(buf + lo + bytes_len, buf + hi,
Py_SIZE(self) - hi);
}
if (PyByteArray_Resize((PyObject *)self,
Py_SIZE(self) + growth) < 0) {
if (lo == 0) {
self->ob_start += growth;
return -1;
}
Py_SET_SIZE(self, Py_SIZE(self) + growth);
res = -1;
}
buf = PyByteArray_AS_STRING(self);
}
else if (growth > 0) {
if (Py_SIZE(self) > (Py_ssize_t)PY_SSIZE_T_MAX - growth) {
PyErr_NoMemory();
return -1;
}
if (PyByteArray_Resize((PyObject *)self,
Py_SIZE(self) + growth) < 0) {
return -1;
}
buf = PyByteArray_AS_STRING(self);
memmove(buf + lo + bytes_len, buf + hi,
Py_SIZE(self) - lo - bytes_len);
}
if (bytes_len > 0)
memcpy(buf + lo, bytes, bytes_len);
return res;
}
static int
bytearray_setslice(PyByteArrayObject *self, Py_ssize_t lo, Py_ssize_t hi,
PyObject *values)
{
Py_ssize_t needed;
void *bytes;
Py_buffer vbytes;
int res = 0;
vbytes.len = -1;
if (values == (PyObject *)self) {
int err;
values = PyByteArray_FromStringAndSize(PyByteArray_AS_STRING(values),
PyByteArray_GET_SIZE(values));
if (values == NULL)
return -1;
err = bytearray_setslice(self, lo, hi, values);
Py_DECREF(values);
return err;
}
if (values == NULL) {
bytes = NULL;
needed = 0;
}
else {
if (PyObject_GetBuffer(values, &vbytes, PyBUF_SIMPLE) != 0) {
PyErr_Format(PyExc_TypeError,
"can't set bytearray slice from %.100s",
Py_TYPE(values)->tp_name);
return -1;
}
needed = vbytes.len;
bytes = vbytes.buf;
}
if (lo < 0)
lo = 0;
if (hi < lo)
hi = lo;
if (hi > Py_SIZE(self))
hi = Py_SIZE(self);
res = bytearray_setslice_linear(self, lo, hi, bytes, needed);
if (vbytes.len != -1)
PyBuffer_Release(&vbytes);
return res;
}
static int
bytearray_setitem(PyByteArrayObject *self, Py_ssize_t i, PyObject *value)
{
int ival = -1;
if (value && !_getbytevalue(value, &ival)) {
return -1;
}
if (i < 0) {
i += Py_SIZE(self);
}
if (i < 0 || i >= Py_SIZE(self)) {
PyErr_SetString(PyExc_IndexError, "bytearray index out of range");
return -1;
}
if (value == NULL) {
return bytearray_setslice(self, i, i+1, NULL);
}
assert(0 <= ival && ival < 256);
PyByteArray_AS_STRING(self)[i] = ival;
return 0;
}
static int
bytearray_ass_subscript(PyByteArrayObject *self, PyObject *index, PyObject *values)
{
Py_ssize_t start, stop, step, slicelen, needed;
char *buf, *bytes;
buf = PyByteArray_AS_STRING(self);
if (_PyIndex_Check(index)) {
Py_ssize_t i = PyNumber_AsSsize_t(index, PyExc_IndexError);
if (i == -1 && PyErr_Occurred()) {
return -1;
}
int ival = -1;
if (values && !_getbytevalue(values, &ival)) {
return -1;
}
if (i < 0) {
i += PyByteArray_GET_SIZE(self);
}
if (i < 0 || i >= Py_SIZE(self)) {
PyErr_SetString(PyExc_IndexError, "bytearray index out of range");
return -1;
}
if (values == NULL) {
start = i;
stop = i + 1;
step = 1;
slicelen = 1;
}
else {
assert(0 <= ival && ival < 256);
buf[i] = (char)ival;
return 0;
}
}
else if (PySlice_Check(index)) {
if (PySlice_Unpack(index, &start, &stop, &step) < 0) {
return -1;
}
slicelen = PySlice_AdjustIndices(PyByteArray_GET_SIZE(self), &start,
&stop, step);
}
else {
PyErr_Format(PyExc_TypeError,
"bytearray indices must be integers or slices, not %.200s",
Py_TYPE(index)->tp_name);
return -1;
}
if (values == NULL) {
bytes = NULL;
needed = 0;
}
else if (values == (PyObject *)self || !PyByteArray_Check(values)) {
int err;
if (PyNumber_Check(values) || PyUnicode_Check(values)) {
PyErr_SetString(PyExc_TypeError,
"can assign only bytes, buffers, or iterables "
"of ints in range(0, 256)");
return -1;
}
values = PyByteArray_FromObject(values);
if (values == NULL)
return -1;
err = bytearray_ass_subscript(self, index, values);
Py_DECREF(values);
return err;
}
else {
assert(PyByteArray_Check(values));
bytes = PyByteArray_AS_STRING(values);
needed = Py_SIZE(values);
}
if ((step < 0 && start < stop) ||
(step > 0 && start > stop))
stop = start;
if (step == 1) {
return bytearray_setslice_linear(self, start, stop, bytes, needed);
}
else {
if (needed == 0) {
size_t cur;
Py_ssize_t i;
if (!_canresize(self))
return -1;
if (slicelen == 0)
return 0;
if (step < 0) {
stop = start + 1;
start = stop + step * (slicelen - 1) - 1;
step = -step;
}
for (cur = start, i = 0;
i < slicelen; cur += step, i++) {
Py_ssize_t lim = step - 1;
if (cur + step >= (size_t)PyByteArray_GET_SIZE(self))
lim = PyByteArray_GET_SIZE(self) - cur - 1;
memmove(buf + cur - i,
buf + cur + 1, lim);
}
cur = start + (size_t)slicelen*step;
if (cur < (size_t)PyByteArray_GET_SIZE(self)) {
memmove(buf + cur - slicelen,
buf + cur,
PyByteArray_GET_SIZE(self) - cur);
}
if (PyByteArray_Resize((PyObject *)self,
PyByteArray_GET_SIZE(self) - slicelen) < 0)
return -1;
return 0;
}
else {
Py_ssize_t i;
size_t cur;
if (needed != slicelen) {
PyErr_Format(PyExc_ValueError,
"attempt to assign bytes of size %zd "
"to extended slice of size %zd",
needed, slicelen);
return -1;
}
for (cur = start, i = 0; i < slicelen; cur += step, i++)
buf[cur] = bytes[i];
return 0;
}
}
}
static int
bytearray___init___impl(PyByteArrayObject *self, PyObject *arg,
const char *encoding, const char *errors)
{
Py_ssize_t count;
PyObject *it;
PyObject *(*iternext)(PyObject *);
if (Py_SIZE(self) != 0) {
if (PyByteArray_Resize((PyObject *)self, 0) < 0)
return -1;
}
if (arg == NULL) {
if (encoding != NULL || errors != NULL) {
PyErr_SetString(PyExc_TypeError,
encoding != NULL ?
"encoding without a string argument" :
"errors without a string argument");
return -1;
}
return 0;
}
if (PyUnicode_Check(arg)) {
PyObject *encoded, *new;
if (encoding == NULL) {
PyErr_SetString(PyExc_TypeError,
"string argument without an encoding");
return -1;
}
encoded = PyUnicode_AsEncodedString(arg, encoding, errors);
if (encoded == NULL)
return -1;
assert(PyBytes_Check(encoded));
new = bytearray_iconcat(self, encoded);
Py_DECREF(encoded);
if (new == NULL)
return -1;
Py_DECREF(new);
return 0;
}
if (encoding != NULL || errors != NULL) {
PyErr_SetString(PyExc_TypeError,
encoding != NULL ?
"encoding without a string argument" :
"errors without a string argument");
return -1;
}
if (_PyIndex_Check(arg)) {
count = PyNumber_AsSsize_t(arg, PyExc_OverflowError);
if (count == -1 && PyErr_Occurred()) {
if (!PyErr_ExceptionMatches(PyExc_TypeError))
return -1;
PyErr_Clear();
}
else {
if (count < 0) {
PyErr_SetString(PyExc_ValueError, "negative count");
return -1;
}
if (count > 0) {
if (PyByteArray_Resize((PyObject *)self, count))
return -1;
memset(PyByteArray_AS_STRING(self), 0, count);
}
return 0;
}
}
if (PyObject_CheckBuffer(arg)) {
Py_ssize_t size;
Py_buffer view;
if (PyObject_GetBuffer(arg, &view, PyBUF_FULL_RO) < 0)
return -1;
size = view.len;
if (PyByteArray_Resize((PyObject *)self, size) < 0) goto fail;
if (PyBuffer_ToContiguous(PyByteArray_AS_STRING(self),
&view, size, 'C') < 0)
goto fail;
PyBuffer_Release(&view);
return 0;
fail:
PyBuffer_Release(&view);
return -1;
}
if (PyList_CheckExact(arg) || PyTuple_CheckExact(arg)) {
Py_ssize_t size = PySequence_Fast_GET_SIZE(arg);
if (PyByteArray_Resize((PyObject *)self, size) < 0) {
return -1;
}
PyObject **items = PySequence_Fast_ITEMS(arg);
char *s = PyByteArray_AS_STRING(self);
for (Py_ssize_t i = 0; i < size; i++) {
int value;
if (!PyLong_CheckExact(items[i])) {
if (Py_SIZE(self) != 0) {
if (PyByteArray_Resize((PyObject *)self, 0) < 0) {
return -1;
}
}
goto slowpath;
}
int rc = _getbytevalue(items[i], &value);
if (!rc) {
return -1;
}
s[i] = value;
}
return 0;
}
slowpath:
it = PyObject_GetIter(arg);
if (it == NULL) {
if (PyErr_ExceptionMatches(PyExc_TypeError)) {
PyErr_Format(PyExc_TypeError,
"cannot convert '%.200s' object to bytearray",
Py_TYPE(arg)->tp_name);
}
return -1;
}
iternext = *Py_TYPE(it)->tp_iternext;
for (;;) {
PyObject *item;
int rc, value;
item = iternext(it);
if (item == NULL) {
if (PyErr_Occurred()) {
if (!PyErr_ExceptionMatches(PyExc_StopIteration))
goto error;
PyErr_Clear();
}
break;
}
rc = _getbytevalue(item, &value);
Py_DECREF(item);
if (!rc)
goto error;
if (Py_SIZE(self) + 1 < self->ob_alloc) {
Py_SET_SIZE(self, Py_SIZE(self) + 1);
PyByteArray_AS_STRING(self)[Py_SIZE(self)] = '\0';
}
else if (PyByteArray_Resize((PyObject *)self, Py_SIZE(self)+1) < 0)
goto error;
PyByteArray_AS_STRING(self)[Py_SIZE(self)-1] = value;
}
Py_DECREF(it);
return 0;
error:
Py_DECREF(it);
return -1;
}
static PyObject *
bytearray_repr(PyByteArrayObject *self)
{
const char *className = _PyType_Name(Py_TYPE(self));
const char *quote_prefix = "(b";
const char *quote_postfix = ")";
Py_ssize_t length = Py_SIZE(self);
Py_ssize_t newsize;
PyObject *v;
Py_ssize_t i;
char *bytes;
char c;
char *p;
int quote;
char *test, *start;
char *buffer;
newsize = strlen(className);
if (length > (PY_SSIZE_T_MAX - 6 - newsize) / 4) {
PyErr_SetString(PyExc_OverflowError,
"bytearray object is too large to make repr");
return NULL;
}
newsize += 6 + length * 4;
buffer = PyObject_Malloc(newsize);
if (buffer == NULL) {
PyErr_NoMemory();
return NULL;
}
quote = '\'';
start = PyByteArray_AS_STRING(self);
for (test = start; test < start+length; ++test) {
if (*test == '"') {
quote = '\'';
break;
}
else if (*test == '\'')
quote = '"';
}
p = buffer;
while (*className)
*p++ = *className++;
while (*quote_prefix)
*p++ = *quote_prefix++;
*p++ = quote;
bytes = PyByteArray_AS_STRING(self);
for (i = 0; i < length; i++) {
assert(newsize - (p - buffer) >= 5);
c = bytes[i];
if (c == '\'' || c == '\\')
*p++ = '\\', *p++ = c;
else if (c == '\t')
*p++ = '\\', *p++ = 't';
else if (c == '\n')
*p++ = '\\', *p++ = 'n';
else if (c == '\r')
*p++ = '\\', *p++ = 'r';
else if (c == 0)
*p++ = '\\', *p++ = 'x', *p++ = '0', *p++ = '0';
else if (c < ' ' || c >= 0x7f) {
*p++ = '\\';
*p++ = 'x';
*p++ = Py_hexdigits[(c & 0xf0) >> 4];
*p++ = Py_hexdigits[c & 0xf];
}
else
*p++ = c;
}
assert(newsize - (p - buffer) >= 1);
*p++ = quote;
while (*quote_postfix) {
*p++ = *quote_postfix++;
}
v = PyUnicode_FromStringAndSize(buffer, p - buffer);
PyObject_Free(buffer);
return v;
}
static PyObject *
bytearray_str(PyObject *op)
{
if (_Py_GetConfig()->bytes_warning) {
if (PyErr_WarnEx(PyExc_BytesWarning,
"str() on a bytearray instance", 1)) {
return NULL;
}
}
return bytearray_repr((PyByteArrayObject*)op);
}
static PyObject *
bytearray_richcompare(PyObject *self, PyObject *other, int op)
{
Py_ssize_t self_size, other_size;
Py_buffer self_bytes, other_bytes;
int cmp;
if (!PyObject_CheckBuffer(self) || !PyObject_CheckBuffer(other)) {
if (PyUnicode_Check(self) || PyUnicode_Check(other)) {
if (_Py_GetConfig()->bytes_warning && (op == Py_EQ || op == Py_NE)) {
if (PyErr_WarnEx(PyExc_BytesWarning,
"Comparison between bytearray and string", 1))
return NULL;
}
}
Py_RETURN_NOTIMPLEMENTED;
}
if (PyObject_GetBuffer(self, &self_bytes, PyBUF_SIMPLE) != 0) {
PyErr_Clear();
Py_RETURN_NOTIMPLEMENTED;
}
self_size = self_bytes.len;
if (PyObject_GetBuffer(other, &other_bytes, PyBUF_SIMPLE) != 0) {
PyErr_Clear();
PyBuffer_Release(&self_bytes);
Py_RETURN_NOTIMPLEMENTED;
}
other_size = other_bytes.len;
if (self_size != other_size && (op == Py_EQ || op == Py_NE)) {
PyBuffer_Release(&self_bytes);
PyBuffer_Release(&other_bytes);
return PyBool_FromLong((op == Py_NE));
}
else {
cmp = memcmp(self_bytes.buf, other_bytes.buf,
Py_MIN(self_size, other_size));
PyBuffer_Release(&self_bytes);
PyBuffer_Release(&other_bytes);
if (cmp != 0) {
Py_RETURN_RICHCOMPARE(cmp, 0, op);
}
Py_RETURN_RICHCOMPARE(self_size, other_size, op);
}
}
static void
bytearray_dealloc(PyByteArrayObject *self)
{
if (self->ob_exports > 0) {
PyErr_SetString(PyExc_SystemError,
"deallocated bytearray object has exported buffers");
PyErr_Print();
}
if (self->ob_bytes != 0) {
PyObject_Free(self->ob_bytes);
}
Py_TYPE(self)->tp_free((PyObject *)self);
}
#define STRINGLIB_IS_UNICODE 0
#define FASTSEARCH fastsearch
#define STRINGLIB(F) stringlib_##F
#define STRINGLIB_CHAR char
#define STRINGLIB_SIZEOF_CHAR 1
#define STRINGLIB_LEN PyByteArray_GET_SIZE
#define STRINGLIB_STR PyByteArray_AS_STRING
#define STRINGLIB_NEW PyByteArray_FromStringAndSize
#define STRINGLIB_ISSPACE Py_ISSPACE
#define STRINGLIB_ISLINEBREAK(x) ((x == '\n') || (x == '\r'))
#define STRINGLIB_CHECK_EXACT PyByteArray_CheckExact
#define STRINGLIB_FAST_MEMCHR memchr
#define STRINGLIB_MUTABLE 1
#include "stringlib/fastsearch.h"
#include "stringlib/count.h"
#include "stringlib/find.h"
#include "stringlib/join.h"
#include "stringlib/partition.h"
#include "stringlib/split.h"
#include "stringlib/ctype.h"
#include "stringlib/transmogrify.h"
static PyObject *
bytearray_find(PyByteArrayObject *self, PyObject *args)
{
return _Py_bytes_find(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), args);
}
static PyObject *
bytearray_count(PyByteArrayObject *self, PyObject *args)
{
return _Py_bytes_count(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), args);
}
static PyObject *
bytearray_clear_impl(PyByteArrayObject *self)
{
if (PyByteArray_Resize((PyObject *)self, 0) < 0)
return NULL;
Py_RETURN_NONE;
}
static PyObject *
bytearray_copy_impl(PyByteArrayObject *self)
{
return PyByteArray_FromStringAndSize(PyByteArray_AS_STRING((PyObject *)self),
PyByteArray_GET_SIZE(self));
}
static PyObject *
bytearray_index(PyByteArrayObject *self, PyObject *args)
{
return _Py_bytes_index(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), args);
}
static PyObject *
bytearray_rfind(PyByteArrayObject *self, PyObject *args)
{
return _Py_bytes_rfind(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), args);
}
static PyObject *
bytearray_rindex(PyByteArrayObject *self, PyObject *args)
{
return _Py_bytes_rindex(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), args);
}
static int
bytearray_contains(PyObject *self, PyObject *arg)
{
return _Py_bytes_contains(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), arg);
}
static PyObject *
bytearray_startswith(PyByteArrayObject *self, PyObject *args)
{
return _Py_bytes_startswith(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), args);
}
static PyObject *
bytearray_endswith(PyByteArrayObject *self, PyObject *args)
{
return _Py_bytes_endswith(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), args);
}
static PyObject *
bytearray_removeprefix_impl(PyByteArrayObject *self, Py_buffer *prefix)
{
const char *self_start = PyByteArray_AS_STRING(self);
Py_ssize_t self_len = PyByteArray_GET_SIZE(self);
const char *prefix_start = prefix->buf;
Py_ssize_t prefix_len = prefix->len;
if (self_len >= prefix_len
&& memcmp(self_start, prefix_start, prefix_len) == 0)
{
return PyByteArray_FromStringAndSize(self_start + prefix_len,
self_len - prefix_len);
}
return PyByteArray_FromStringAndSize(self_start, self_len);
}
static PyObject *
bytearray_removesuffix_impl(PyByteArrayObject *self, Py_buffer *suffix)
{
const char *self_start = PyByteArray_AS_STRING(self);
Py_ssize_t self_len = PyByteArray_GET_SIZE(self);
const char *suffix_start = suffix->buf;
Py_ssize_t suffix_len = suffix->len;
if (self_len >= suffix_len
&& memcmp(self_start + self_len - suffix_len,
suffix_start, suffix_len) == 0)
{
return PyByteArray_FromStringAndSize(self_start,
self_len - suffix_len);
}
return PyByteArray_FromStringAndSize(self_start, self_len);
}
static PyObject *
bytearray_translate_impl(PyByteArrayObject *self, PyObject *table,
PyObject *deletechars)
{
char *input, *output;
const char *table_chars;
Py_ssize_t i, c;
PyObject *input_obj = (PyObject*)self;
const char *output_start;
Py_ssize_t inlen;
PyObject *result = NULL;
int trans_table[256];
Py_buffer vtable, vdel;
if (table == Py_None) {
table_chars = NULL;
table = NULL;
} else if (PyObject_GetBuffer(table, &vtable, PyBUF_SIMPLE) != 0) {
return NULL;
} else {
if (vtable.len != 256) {
PyErr_SetString(PyExc_ValueError,
"translation table must be 256 characters long");
PyBuffer_Release(&vtable);
return NULL;
}
table_chars = (const char*)vtable.buf;
}
if (deletechars != NULL) {
if (PyObject_GetBuffer(deletechars, &vdel, PyBUF_SIMPLE) != 0) {
if (table != NULL)
PyBuffer_Release(&vtable);
return NULL;
}
}
else {
vdel.buf = NULL;
vdel.len = 0;
}
inlen = PyByteArray_GET_SIZE(input_obj);
result = PyByteArray_FromStringAndSize((char *)NULL, inlen);
if (result == NULL)
goto done;
output_start = output = PyByteArray_AS_STRING(result);
input = PyByteArray_AS_STRING(input_obj);
if (vdel.len == 0 && table_chars != NULL) {
for (i = inlen; --i >= 0; ) {
c = Py_CHARMASK(*input++);
*output++ = table_chars[c];
}
goto done;
}
if (table_chars == NULL) {
for (i = 0; i < 256; i++)
trans_table[i] = Py_CHARMASK(i);
} else {
for (i = 0; i < 256; i++)
trans_table[i] = Py_CHARMASK(table_chars[i]);
}
for (i = 0; i < vdel.len; i++)
trans_table[(int) Py_CHARMASK( ((unsigned char*)vdel.buf)[i] )] = -1;
for (i = inlen; --i >= 0; ) {
c = Py_CHARMASK(*input++);
if (trans_table[c] != -1)
*output++ = (char)trans_table[c];
}
if (inlen > 0)
if (PyByteArray_Resize(result, output - output_start) < 0) {
Py_CLEAR(result);
goto done;
}
done:
if (table != NULL)
PyBuffer_Release(&vtable);
if (deletechars != NULL)
PyBuffer_Release(&vdel);
return result;
}
static PyObject *
bytearray_maketrans_impl(Py_buffer *frm, Py_buffer *to)
{
return _Py_bytes_maketrans(frm, to);
}
static PyObject *
bytearray_replace_impl(PyByteArrayObject *self, Py_buffer *old,
Py_buffer *new, Py_ssize_t count)
{
return stringlib_replace((PyObject *)self,
(const char *)old->buf, old->len,
(const char *)new->buf, new->len, count);
}
static PyObject *
bytearray_split_impl(PyByteArrayObject *self, PyObject *sep,
Py_ssize_t maxsplit)
{
Py_ssize_t len = PyByteArray_GET_SIZE(self), n;
const char *s = PyByteArray_AS_STRING(self), *sub;
PyObject *list;
Py_buffer vsub;
if (maxsplit < 0)
maxsplit = PY_SSIZE_T_MAX;
if (sep == Py_None)
return stringlib_split_whitespace((PyObject*) self, s, len, maxsplit);
if (PyObject_GetBuffer(sep, &vsub, PyBUF_SIMPLE) != 0)
return NULL;
sub = vsub.buf;
n = vsub.len;
list = stringlib_split(
(PyObject*) self, s, len, sub, n, maxsplit
);
PyBuffer_Release(&vsub);
return list;
}
static PyObject *
bytearray_partition(PyByteArrayObject *self, PyObject *sep)
{
PyObject *bytesep, *result;
bytesep = _PyByteArray_FromBufferObject(sep);
if (! bytesep)
return NULL;
result = stringlib_partition(
(PyObject*) self,
PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self),
bytesep,
PyByteArray_AS_STRING(bytesep), PyByteArray_GET_SIZE(bytesep)
);
Py_DECREF(bytesep);
return result;
}
static PyObject *
bytearray_rpartition(PyByteArrayObject *self, PyObject *sep)
{
PyObject *bytesep, *result;
bytesep = _PyByteArray_FromBufferObject(sep);
if (! bytesep)
return NULL;
result = stringlib_rpartition(
(PyObject*) self,
PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self),
bytesep,
PyByteArray_AS_STRING(bytesep), PyByteArray_GET_SIZE(bytesep)
);
Py_DECREF(bytesep);
return result;
}
static PyObject *
bytearray_rsplit_impl(PyByteArrayObject *self, PyObject *sep,
Py_ssize_t maxsplit)
{
Py_ssize_t len = PyByteArray_GET_SIZE(self), n;
const char *s = PyByteArray_AS_STRING(self), *sub;
PyObject *list;
Py_buffer vsub;
if (maxsplit < 0)
maxsplit = PY_SSIZE_T_MAX;
if (sep == Py_None)
return stringlib_rsplit_whitespace((PyObject*) self, s, len, maxsplit);
if (PyObject_GetBuffer(sep, &vsub, PyBUF_SIMPLE) != 0)
return NULL;
sub = vsub.buf;
n = vsub.len;
list = stringlib_rsplit(
(PyObject*) self, s, len, sub, n, maxsplit
);
PyBuffer_Release(&vsub);
return list;
}
static PyObject *
bytearray_reverse_impl(PyByteArrayObject *self)
{
char swap, *head, *tail;
Py_ssize_t i, j, n = Py_SIZE(self);
j = n / 2;
head = PyByteArray_AS_STRING(self);
tail = head + n - 1;
for (i = 0; i < j; i++) {
swap = *head;
*head++ = *tail;
*tail-- = swap;
}
Py_RETURN_NONE;
}
static PyObject *
bytearray_insert_impl(PyByteArrayObject *self, Py_ssize_t index, int item)
{
Py_ssize_t n = Py_SIZE(self);
char *buf;
if (n == PY_SSIZE_T_MAX) {
PyErr_SetString(PyExc_OverflowError,
"cannot add more objects to bytearray");
return NULL;
}
if (PyByteArray_Resize((PyObject *)self, n + 1) < 0)
return NULL;
buf = PyByteArray_AS_STRING(self);
if (index < 0) {
index += n;
if (index < 0)
index = 0;
}
if (index > n)
index = n;
memmove(buf + index + 1, buf + index, n - index);
buf[index] = item;
Py_RETURN_NONE;
}
static PyObject *
bytearray_append_impl(PyByteArrayObject *self, int item)
{
Py_ssize_t n = Py_SIZE(self);
if (n == PY_SSIZE_T_MAX) {
PyErr_SetString(PyExc_OverflowError,
"cannot add more objects to bytearray");
return NULL;
}
if (PyByteArray_Resize((PyObject *)self, n + 1) < 0)
return NULL;
PyByteArray_AS_STRING(self)[n] = item;
Py_RETURN_NONE;
}
static PyObject *
bytearray_extend(PyByteArrayObject *self, PyObject *iterable_of_ints)
{
PyObject *it, *item, *bytearray_obj;
Py_ssize_t buf_size = 0, len = 0;
int value;
char *buf;
if (PyObject_CheckBuffer(iterable_of_ints)) {
if (bytearray_setslice(self, Py_SIZE(self), Py_SIZE(self), iterable_of_ints) == -1)
return NULL;
Py_RETURN_NONE;
}
it = PyObject_GetIter(iterable_of_ints);
if (it == NULL) {
if (PyErr_ExceptionMatches(PyExc_TypeError)) {
PyErr_Format(PyExc_TypeError,
"can't extend bytearray with %.100s",
Py_TYPE(iterable_of_ints)->tp_name);
}
return NULL;
}
buf_size = PyObject_LengthHint(iterable_of_ints, 32);
if (buf_size == -1) {
Py_DECREF(it);
return NULL;
}
bytearray_obj = PyByteArray_FromStringAndSize(NULL, buf_size);
if (bytearray_obj == NULL) {
Py_DECREF(it);
return NULL;
}
buf = PyByteArray_AS_STRING(bytearray_obj);
while ((item = PyIter_Next(it)) != NULL) {
if (! _getbytevalue(item, &value)) {
Py_DECREF(item);
Py_DECREF(it);
Py_DECREF(bytearray_obj);
return NULL;
}
buf[len++] = value;
Py_DECREF(item);
if (len >= buf_size) {
Py_ssize_t addition;
if (len == PY_SSIZE_T_MAX) {
Py_DECREF(it);
Py_DECREF(bytearray_obj);
return PyErr_NoMemory();
}
addition = len >> 1;
if (addition > PY_SSIZE_T_MAX - len - 1)
buf_size = PY_SSIZE_T_MAX;
else
buf_size = len + addition + 1;
if (PyByteArray_Resize((PyObject *)bytearray_obj, buf_size) < 0) {
Py_DECREF(it);
Py_DECREF(bytearray_obj);
return NULL;
}
buf = PyByteArray_AS_STRING(bytearray_obj);
}
}
Py_DECREF(it);
if (PyErr_Occurred()) {
Py_DECREF(bytearray_obj);
return NULL;
}
if (PyByteArray_Resize((PyObject *)bytearray_obj, len) < 0) {
Py_DECREF(bytearray_obj);
return NULL;
}
if (bytearray_setslice(self, Py_SIZE(self), Py_SIZE(self), bytearray_obj) == -1) {
Py_DECREF(bytearray_obj);
return NULL;
}
Py_DECREF(bytearray_obj);
assert(!PyErr_Occurred());
Py_RETURN_NONE;
}
static PyObject *
bytearray_pop_impl(PyByteArrayObject *self, Py_ssize_t index)
{
int value;
Py_ssize_t n = Py_SIZE(self);
char *buf;
if (n == 0) {
PyErr_SetString(PyExc_IndexError,
"pop from empty bytearray");
return NULL;
}
if (index < 0)
index += Py_SIZE(self);
if (index < 0 || index >= Py_SIZE(self)) {
PyErr_SetString(PyExc_IndexError, "pop index out of range");
return NULL;
}
if (!_canresize(self))
return NULL;
buf = PyByteArray_AS_STRING(self);
value = buf[index];
memmove(buf + index, buf + index + 1, n - index);
if (PyByteArray_Resize((PyObject *)self, n - 1) < 0)
return NULL;
return _PyLong_FromUnsignedChar((unsigned char)value);
}
static PyObject *
bytearray_remove_impl(PyByteArrayObject *self, int value)
{
Py_ssize_t where, n = Py_SIZE(self);
char *buf = PyByteArray_AS_STRING(self);
where = stringlib_find_char(buf, n, value);
if (where < 0) {
PyErr_SetString(PyExc_ValueError, "value not found in bytearray");
return NULL;
}
if (!_canresize(self))
return NULL;
memmove(buf + where, buf + where + 1, n - where);
if (PyByteArray_Resize((PyObject *)self, n - 1) < 0)
return NULL;
Py_RETURN_NONE;
}
#define LEFTSTRIP 0
#define RIGHTSTRIP 1
#define BOTHSTRIP 2
static PyObject*
bytearray_strip_impl_helper(PyByteArrayObject* self, PyObject* bytes, int striptype)
{
Py_ssize_t mysize, byteslen;
const char* myptr;
const char* bytesptr;
Py_buffer vbytes;
if (bytes == Py_None) {
bytesptr = "\t\n\r\f\v ";
byteslen = 6;
}
else {
if (PyObject_GetBuffer(bytes, &vbytes, PyBUF_SIMPLE) != 0)
return NULL;
bytesptr = (const char*)vbytes.buf;
byteslen = vbytes.len;
}
myptr = PyByteArray_AS_STRING(self);
mysize = Py_SIZE(self);
Py_ssize_t left = 0;
if (striptype != RIGHTSTRIP) {
while (left < mysize && memchr(bytesptr, (unsigned char)myptr[left], byteslen))
left++;
}
Py_ssize_t right = mysize;
if (striptype != LEFTSTRIP) {
do {
right--;
} while (right >= left && memchr(bytesptr, (unsigned char)myptr[right], byteslen));
right++;
}
if (bytes != Py_None)
PyBuffer_Release(&vbytes);
return PyByteArray_FromStringAndSize(myptr + left, right - left);
}
static PyObject *
bytearray_strip_impl(PyByteArrayObject *self, PyObject *bytes)
{
return bytearray_strip_impl_helper(self, bytes, BOTHSTRIP);
}
static PyObject *
bytearray_lstrip_impl(PyByteArrayObject *self, PyObject *bytes)
{
return bytearray_strip_impl_helper(self, bytes, LEFTSTRIP);
}
static PyObject *
bytearray_rstrip_impl(PyByteArrayObject *self, PyObject *bytes)
{
return bytearray_strip_impl_helper(self, bytes, RIGHTSTRIP);
}
static PyObject *
bytearray_decode_impl(PyByteArrayObject *self, const char *encoding,
const char *errors)
{
if (encoding == NULL)
encoding = PyUnicode_GetDefaultEncoding();
return PyUnicode_FromEncodedObject((PyObject*)self, encoding, errors);
}
PyDoc_STRVAR(alloc_doc,
"B.__alloc__() -> int\n\
\n\
Return the number of bytes actually allocated.");
static PyObject *
bytearray_alloc(PyByteArrayObject *self, PyObject *Py_UNUSED(ignored))
{
return PyLong_FromSsize_t(self->ob_alloc);
}
static PyObject *
bytearray_join(PyByteArrayObject *self, PyObject *iterable_of_bytes)
{
return stringlib_bytes_join((PyObject*)self, iterable_of_bytes);
}
static PyObject *
bytearray_splitlines_impl(PyByteArrayObject *self, int keepends)
{
return stringlib_splitlines(
(PyObject*) self, PyByteArray_AS_STRING(self),
PyByteArray_GET_SIZE(self), keepends
);
}
static PyObject *
bytearray_fromhex_impl(PyTypeObject *type, PyObject *string)
{
PyObject *result = _PyBytes_FromHex(string, type == &PyByteArray_Type);
if (type != &PyByteArray_Type && result != NULL) {
Py_SETREF(result, PyObject_CallOneArg((PyObject *)type, result));
}
return result;
}
static PyObject *
bytearray_hex_impl(PyByteArrayObject *self, PyObject *sep, int bytes_per_sep)
{
char* argbuf = PyByteArray_AS_STRING(self);
Py_ssize_t arglen = PyByteArray_GET_SIZE(self);
return _Py_strhex_with_sep(argbuf, arglen, sep, bytes_per_sep);
}
static PyObject *
_common_reduce(PyByteArrayObject *self, int proto)
{
PyObject *state;
const char *buf;
state = _PyObject_GetState((PyObject *)self);
if (state == NULL) {
return NULL;
}
if (!Py_SIZE(self)) {
return Py_BuildValue("(O()N)", Py_TYPE(self), state);
}
buf = PyByteArray_AS_STRING(self);
if (proto < 3) {
PyObject *latin1 = PyUnicode_DecodeLatin1(buf, Py_SIZE(self), NULL);
return Py_BuildValue("(O(Ns)N)", Py_TYPE(self), latin1, "latin-1", state);
}
else {
return Py_BuildValue("(O(y#)N)", Py_TYPE(self), buf, Py_SIZE(self), state);
}
}
static PyObject *
bytearray_reduce_impl(PyByteArrayObject *self)
{
return _common_reduce(self, 2);
}
static PyObject *
bytearray_reduce_ex_impl(PyByteArrayObject *self, int proto)
{
return _common_reduce(self, proto);
}
static PyObject *
bytearray_sizeof_impl(PyByteArrayObject *self)
{
size_t res = _PyObject_SIZE(Py_TYPE(self));
res += (size_t)self->ob_alloc * sizeof(char);
return PyLong_FromSize_t(res);
}
static PySequenceMethods bytearray_as_sequence = {
(lenfunc)bytearray_length,
(binaryfunc)PyByteArray_Concat,
(ssizeargfunc)bytearray_repeat,
(ssizeargfunc)bytearray_getitem,
0,
(ssizeobjargproc)bytearray_setitem,
0,
(objobjproc)bytearray_contains,
(binaryfunc)bytearray_iconcat,
(ssizeargfunc)bytearray_irepeat,
};
static PyMappingMethods bytearray_as_mapping = {
(lenfunc)bytearray_length,
(binaryfunc)bytearray_subscript,
(objobjargproc)bytearray_ass_subscript,
};
static PyBufferProcs bytearray_as_buffer = {
(getbufferproc)bytearray_getbuffer,
(releasebufferproc)bytearray_releasebuffer,
};
static PyMethodDef
bytearray_methods[] = {
{"__alloc__", (PyCFunction)bytearray_alloc, METH_NOARGS, alloc_doc},
BYTEARRAY_REDUCE_METHODDEF
BYTEARRAY_REDUCE_EX_METHODDEF
BYTEARRAY_SIZEOF_METHODDEF
BYTEARRAY_APPEND_METHODDEF
{"capitalize", stringlib_capitalize, METH_NOARGS,
_Py_capitalize__doc__},
STRINGLIB_CENTER_METHODDEF
BYTEARRAY_CLEAR_METHODDEF
BYTEARRAY_COPY_METHODDEF
{"count", (PyCFunction)bytearray_count, METH_VARARGS,
_Py_count__doc__},
BYTEARRAY_DECODE_METHODDEF
{"endswith", (PyCFunction)bytearray_endswith, METH_VARARGS,
_Py_endswith__doc__},
STRINGLIB_EXPANDTABS_METHODDEF
BYTEARRAY_EXTEND_METHODDEF
{"find", (PyCFunction)bytearray_find, METH_VARARGS,
_Py_find__doc__},
BYTEARRAY_FROMHEX_METHODDEF
BYTEARRAY_HEX_METHODDEF
{"index", (PyCFunction)bytearray_index, METH_VARARGS, _Py_index__doc__},
BYTEARRAY_INSERT_METHODDEF
{"isalnum", stringlib_isalnum, METH_NOARGS,
_Py_isalnum__doc__},
{"isalpha", stringlib_isalpha, METH_NOARGS,
_Py_isalpha__doc__},
{"isascii", stringlib_isascii, METH_NOARGS,
_Py_isascii__doc__},
{"isdigit", stringlib_isdigit, METH_NOARGS,
_Py_isdigit__doc__},
{"islower", stringlib_islower, METH_NOARGS,
_Py_islower__doc__},
{"isspace", stringlib_isspace, METH_NOARGS,
_Py_isspace__doc__},
{"istitle", stringlib_istitle, METH_NOARGS,
_Py_istitle__doc__},
{"isupper", stringlib_isupper, METH_NOARGS,
_Py_isupper__doc__},
BYTEARRAY_JOIN_METHODDEF
STRINGLIB_LJUST_METHODDEF
{"lower", stringlib_lower, METH_NOARGS, _Py_lower__doc__},
BYTEARRAY_LSTRIP_METHODDEF
BYTEARRAY_MAKETRANS_METHODDEF
BYTEARRAY_PARTITION_METHODDEF
BYTEARRAY_POP_METHODDEF
BYTEARRAY_REMOVE_METHODDEF
BYTEARRAY_REPLACE_METHODDEF
BYTEARRAY_REMOVEPREFIX_METHODDEF
BYTEARRAY_REMOVESUFFIX_METHODDEF
BYTEARRAY_REVERSE_METHODDEF
{"rfind", (PyCFunction)bytearray_rfind, METH_VARARGS, _Py_rfind__doc__},
{"rindex", (PyCFunction)bytearray_rindex, METH_VARARGS, _Py_rindex__doc__},
STRINGLIB_RJUST_METHODDEF
BYTEARRAY_RPARTITION_METHODDEF
BYTEARRAY_RSPLIT_METHODDEF
BYTEARRAY_RSTRIP_METHODDEF
BYTEARRAY_SPLIT_METHODDEF
BYTEARRAY_SPLITLINES_METHODDEF
{"startswith", (PyCFunction)bytearray_startswith, METH_VARARGS ,
_Py_startswith__doc__},
BYTEARRAY_STRIP_METHODDEF
{"swapcase", stringlib_swapcase, METH_NOARGS,
_Py_swapcase__doc__},
{"title", stringlib_title, METH_NOARGS, _Py_title__doc__},
BYTEARRAY_TRANSLATE_METHODDEF
{"upper", stringlib_upper, METH_NOARGS, _Py_upper__doc__},
STRINGLIB_ZFILL_METHODDEF
{NULL}
};
static PyObject *
bytearray_mod(PyObject *v, PyObject *w)
{
if (!PyByteArray_Check(v))
Py_RETURN_NOTIMPLEMENTED;
return _PyBytes_FormatEx(PyByteArray_AS_STRING(v), PyByteArray_GET_SIZE(v), w, 1);
}
static PyNumberMethods bytearray_as_number = {
0,
0,
0,
bytearray_mod,
};
PyDoc_STRVAR(bytearray_doc,
"bytearray(iterable_of_ints) -> bytearray\n\
bytearray(string, encoding[, errors]) -> bytearray\n\
bytearray(bytes_or_buffer) -> mutable copy of bytes_or_buffer\n\
bytearray(int) -> bytes array of size given by the parameter initialized with null bytes\n\
bytearray() -> empty bytes array\n\
\n\
Construct a mutable bytearray object from:\n\
- an iterable yielding integers in range(256)\n\
- a text string encoded using the specified encoding\n\
- a bytes or a buffer object\n\
- any object implementing the buffer API.\n\
- an integer");
static PyObject *bytearray_iter(PyObject *seq);
PyTypeObject PyByteArray_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
"bytearray",
sizeof(PyByteArrayObject),
0,
(destructor)bytearray_dealloc,
0,
0,
0,
0,
(reprfunc)bytearray_repr,
&bytearray_as_number,
&bytearray_as_sequence,
&bytearray_as_mapping,
0,
0,
bytearray_str,
PyObject_GenericGetAttr,
0,
&bytearray_as_buffer,
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
_Py_TPFLAGS_MATCH_SELF,
bytearray_doc,
0,
0,
(richcmpfunc)bytearray_richcompare,
0,
bytearray_iter,
0,
bytearray_methods,
0,
0,
0,
0,
0,
0,
0,
(initproc)bytearray___init__,
PyType_GenericAlloc,
PyType_GenericNew,
PyObject_Del,
};
typedef struct {
PyObject_HEAD
Py_ssize_t it_index;
PyByteArrayObject *it_seq;
} bytesiterobject;
static void
bytearrayiter_dealloc(bytesiterobject *it)
{
_PyObject_GC_UNTRACK(it);
Py_XDECREF(it->it_seq);
PyObject_GC_Del(it);
}
static int
bytearrayiter_traverse(bytesiterobject *it, visitproc visit, void *arg)
{
Py_VISIT(it->it_seq);
return 0;
}
static PyObject *
bytearrayiter_next(bytesiterobject *it)
{
PyByteArrayObject *seq;
assert(it != NULL);
seq = it->it_seq;
if (seq == NULL)
return NULL;
assert(PyByteArray_Check(seq));
if (it->it_index < PyByteArray_GET_SIZE(seq)) {
return _PyLong_FromUnsignedChar(
(unsigned char)PyByteArray_AS_STRING(seq)[it->it_index++]);
}
it->it_seq = NULL;
Py_DECREF(seq);
return NULL;
}
static PyObject *
bytearrayiter_length_hint(bytesiterobject *it, PyObject *Py_UNUSED(ignored))
{
Py_ssize_t len = 0;
if (it->it_seq) {
len = PyByteArray_GET_SIZE(it->it_seq) - it->it_index;
if (len < 0) {
len = 0;
}
}
return PyLong_FromSsize_t(len);
}
PyDoc_STRVAR(length_hint_doc,
"Private method returning an estimate of len(list(it)).");
static PyObject *
bytearrayiter_reduce(bytesiterobject *it, PyObject *Py_UNUSED(ignored))
{
PyObject *iter = _PyEval_GetBuiltin(&_Py_ID(iter));
if (it->it_seq != NULL) {
return Py_BuildValue("N(O)n", iter, it->it_seq, it->it_index);
} else {
return Py_BuildValue("N(())", iter);
}
}
static PyObject *
bytearrayiter_setstate(bytesiterobject *it, PyObject *state)
{
Py_ssize_t index = PyLong_AsSsize_t(state);
if (index == -1 && PyErr_Occurred())
return NULL;
if (it->it_seq != NULL) {
if (index < 0)
index = 0;
else if (index > PyByteArray_GET_SIZE(it->it_seq))
index = PyByteArray_GET_SIZE(it->it_seq);
it->it_index = index;
}
Py_RETURN_NONE;
}
PyDoc_STRVAR(setstate_doc, "Set state information for unpickling.");
static PyMethodDef bytearrayiter_methods[] = {
{"__length_hint__", (PyCFunction)bytearrayiter_length_hint, METH_NOARGS,
length_hint_doc},
{"__reduce__", (PyCFunction)bytearrayiter_reduce, METH_NOARGS,
bytearray_reduce__doc__},
{"__setstate__", (PyCFunction)bytearrayiter_setstate, METH_O,
setstate_doc},
{NULL, NULL}
};
PyTypeObject PyByteArrayIter_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
"bytearray_iterator",
sizeof(bytesiterobject),
0,
(destructor)bytearrayiter_dealloc,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
PyObject_GenericGetAttr,
0,
0,
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
0,
(traverseproc)bytearrayiter_traverse,
0,
0,
0,
PyObject_SelfIter,
(iternextfunc)bytearrayiter_next,
bytearrayiter_methods,
0,
};
static PyObject *
bytearray_iter(PyObject *seq)
{
bytesiterobject *it;
if (!PyByteArray_Check(seq)) {
PyErr_BadInternalCall();
return NULL;
}
it = PyObject_GC_New(bytesiterobject, &PyByteArrayIter_Type);
if (it == NULL)
return NULL;
it->it_index = 0;
it->it_seq = (PyByteArrayObject *)Py_NewRef(seq);
_PyObject_GC_TRACK(it);
return (PyObject *)it;
}