summaryrefslogtreecommitdiffstats
path: root/Objects/bytesobject.c
diff options
context:
space:
mode:
Diffstat (limited to 'Objects/bytesobject.c')
-rw-r--r--Objects/bytesobject.c269
1 files changed, 105 insertions, 164 deletions
diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c
index 9dcb74e..614978b 100644
--- a/Objects/bytesobject.c
+++ b/Objects/bytesobject.c
@@ -10,9 +10,18 @@
static Py_ssize_t
_getbuffer(PyObject *obj, Py_buffer *view)
{
- PyBufferProcs *buffer = Py_TYPE(obj)->tp_as_buffer;
-
- if (buffer == NULL || buffer->bf_getbuffer == NULL)
+ PyBufferProcs *bufferprocs;
+ if (PyBytes_CheckExact(obj)) {
+ /* Fast path, e.g. for .join() of many bytes objects */
+ Py_INCREF(obj);
+ view->obj = obj;
+ view->buf = PyBytes_AS_STRING(obj);
+ view->len = PyBytes_GET_SIZE(obj);
+ return view->len;
+ }
+
+ bufferprocs = Py_TYPE(obj)->tp_as_buffer;
+ if (bufferprocs == NULL || bufferprocs->bf_getbuffer == NULL)
{
PyErr_Format(PyExc_TypeError,
"Type %.100s doesn't support the buffer API",
@@ -20,7 +29,7 @@ _getbuffer(PyObject *obj, Py_buffer *view)
return -1;
}
- if (buffer->bf_getbuffer(obj, view, PyBUF_SIMPLE) < 0)
+ if (bufferprocs->bf_getbuffer(obj, view, PyBUF_SIMPLE) < 0)
return -1;
return view->len;
}
@@ -65,7 +74,7 @@ static PyBytesObject *nullstring;
PyObject *
PyBytes_FromStringAndSize(const char *str, Py_ssize_t size)
{
- register PyBytesObject *op;
+ PyBytesObject *op;
if (size < 0) {
PyErr_SetString(PyExc_SystemError,
"Negative size passed to PyBytes_FromStringAndSize");
@@ -98,7 +107,7 @@ PyBytes_FromStringAndSize(const char *str, Py_ssize_t size)
op = (PyBytesObject *)PyObject_MALLOC(PyBytesObject_SIZE + size);
if (op == NULL)
return PyErr_NoMemory();
- PyObject_INIT_VAR(op, &PyBytes_Type, size);
+ (void)PyObject_INIT_VAR(op, &PyBytes_Type, size);
op->ob_shash = -1;
if (str != NULL)
Py_MEMCPY(op->ob_sval, str, size);
@@ -117,8 +126,8 @@ PyBytes_FromStringAndSize(const char *str, Py_ssize_t size)
PyObject *
PyBytes_FromString(const char *str)
{
- register size_t size;
- register PyBytesObject *op;
+ size_t size;
+ PyBytesObject *op;
assert(str != NULL);
size = strlen(str);
@@ -146,7 +155,7 @@ PyBytes_FromString(const char *str)
op = (PyBytesObject *)PyObject_MALLOC(PyBytesObject_SIZE + size);
if (op == NULL)
return PyErr_NoMemory();
- PyObject_INIT_VAR(op, &PyBytes_Type, size);
+ (void)PyObject_INIT_VAR(op, &PyBytes_Type, size);
op->ob_shash = -1;
Py_MEMCPY(op->ob_sval, str, size+1);
/* share short strings */
@@ -517,7 +526,7 @@ PyObject *PyBytes_DecodeEscape(const char *s,
/* object api */
Py_ssize_t
-PyBytes_Size(register PyObject *op)
+PyBytes_Size(PyObject *op)
{
if (!PyBytes_Check(op)) {
PyErr_Format(PyExc_TypeError,
@@ -528,7 +537,7 @@ PyBytes_Size(register PyObject *op)
}
char *
-PyBytes_AsString(register PyObject *op)
+PyBytes_AsString(PyObject *op)
{
if (!PyBytes_Check(op)) {
PyErr_Format(PyExc_TypeError,
@@ -539,9 +548,9 @@ PyBytes_AsString(register PyObject *op)
}
int
-PyBytes_AsStringAndSize(register PyObject *obj,
- register char **s,
- register Py_ssize_t *len)
+PyBytes_AsStringAndSize(PyObject *obj,
+ char **s,
+ Py_ssize_t *len)
{
if (s == NULL) {
PyErr_BadInternalCall();
@@ -573,6 +582,7 @@ PyBytes_AsStringAndSize(register PyObject *obj,
#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"
@@ -582,7 +592,7 @@ PyBytes_AsStringAndSize(register PyObject *obj,
PyObject *
PyBytes_Repr(PyObject *obj, int smartquotes)
{
- register PyBytesObject* op = (PyBytesObject*) obj;
+ PyBytesObject* op = (PyBytesObject*) obj;
Py_ssize_t i, length = Py_SIZE(op);
size_t newsize, squotes, dquotes;
PyObject *v;
@@ -721,12 +731,12 @@ bytes_concat(PyObject *a, PyObject *b)
}
static PyObject *
-bytes_repeat(register PyBytesObject *a, register Py_ssize_t n)
+bytes_repeat(PyBytesObject *a, Py_ssize_t n)
{
- register Py_ssize_t i;
- register Py_ssize_t j;
- register Py_ssize_t size;
- register PyBytesObject *op;
+ Py_ssize_t i;
+ Py_ssize_t j;
+ Py_ssize_t size;
+ PyBytesObject *op;
size_t nbytes;
if (n < 0)
n = 0;
@@ -752,7 +762,7 @@ bytes_repeat(register PyBytesObject *a, register Py_ssize_t n)
op = (PyBytesObject *)PyObject_MALLOC(PyBytesObject_SIZE + nbytes);
if (op == NULL)
return PyErr_NoMemory();
- PyObject_INIT_VAR(op, &PyBytes_Type, size);
+ (void)PyObject_INIT_VAR(op, &PyBytes_Type, size);
op->ob_shash = -1;
op->ob_sval[size] = '\0';
if (Py_SIZE(a) == 1 && n > 0) {
@@ -796,7 +806,7 @@ bytes_contains(PyObject *self, PyObject *arg)
}
static PyObject *
-bytes_item(PyBytesObject *a, register Py_ssize_t i)
+bytes_item(PyBytesObject *a, Py_ssize_t i)
{
if (i < 0 || i >= Py_SIZE(a)) {
PyErr_SetString(PyExc_IndexError, "index out of range");
@@ -805,6 +815,23 @@ bytes_item(PyBytesObject *a, register Py_ssize_t i)
return PyLong_FromLong((unsigned char)a->ob_sval[i]);
}
+Py_LOCAL(int)
+bytes_compare_eq(PyBytesObject *a, PyBytesObject *b)
+{
+ int cmp;
+ Py_ssize_t len;
+
+ len = Py_SIZE(a);
+ if (Py_SIZE(b) != len)
+ return 0;
+
+ if (a->ob_sval[0] != b->ob_sval[0])
+ return 0;
+
+ cmp = memcmp(a->ob_sval, b->ob_sval, len);
+ return (cmp == 0);
+}
+
static PyObject*
bytes_richcompare(PyBytesObject *a, PyBytesObject *b, int op)
{
@@ -825,53 +852,55 @@ bytes_richcompare(PyBytesObject *a, PyBytesObject *b, int op)
return NULL;
}
result = Py_NotImplemented;
- goto out;
}
- if (a == b) {
+ else if (a == b) {
switch (op) {
- case Py_EQ:case Py_LE:case Py_GE:
+ case Py_EQ:
+ case Py_LE:
+ case Py_GE:
+ /* a string is equal to itself */
result = Py_True;
- goto out;
- case Py_NE:case Py_LT:case Py_GT:
+ break;
+ case Py_NE:
+ case Py_LT:
+ case Py_GT:
result = Py_False;
- goto out;
+ break;
+ default:
+ PyErr_BadArgument();
+ return NULL;
}
}
- if (op == Py_EQ) {
- /* Supporting Py_NE here as well does not save
- much time, since Py_NE is rarely used. */
- if (Py_SIZE(a) == Py_SIZE(b)
- && (a->ob_sval[0] == b->ob_sval[0]
- && memcmp(a->ob_sval, b->ob_sval, Py_SIZE(a)) == 0)) {
- result = Py_True;
- } else {
- result = Py_False;
+ else if (op == Py_EQ || op == Py_NE) {
+ int eq = bytes_compare_eq(a, b);
+ eq ^= (op == Py_NE);
+ result = eq ? Py_True : Py_False;
+ }
+ else {
+ len_a = Py_SIZE(a);
+ len_b = Py_SIZE(b);
+ min_len = Py_MIN(len_a, len_b);
+ if (min_len > 0) {
+ c = Py_CHARMASK(*a->ob_sval) - Py_CHARMASK(*b->ob_sval);
+ if (c == 0)
+ c = memcmp(a->ob_sval, b->ob_sval, min_len);
}
- goto out;
- }
- len_a = Py_SIZE(a); len_b = Py_SIZE(b);
- min_len = (len_a < len_b) ? len_a : len_b;
- if (min_len > 0) {
- c = Py_CHARMASK(*a->ob_sval) - Py_CHARMASK(*b->ob_sval);
- if (c==0)
- c = memcmp(a->ob_sval, b->ob_sval, min_len);
- } else
- c = 0;
- if (c == 0)
- c = (len_a < len_b) ? -1 : (len_a > len_b) ? 1 : 0;
- switch (op) {
- case Py_LT: c = c < 0; break;
- case Py_LE: c = c <= 0; break;
- case Py_EQ: assert(0); break; /* unreachable */
- case Py_NE: c = c != 0; break;
- case Py_GT: c = c > 0; break;
- case Py_GE: c = c >= 0; break;
- default:
- result = Py_NotImplemented;
- goto out;
+ else
+ c = 0;
+ if (c == 0)
+ c = (len_a < len_b) ? -1 : (len_a > len_b) ? 1 : 0;
+ switch (op) {
+ case Py_LT: c = c < 0; break;
+ case Py_LE: c = c <= 0; break;
+ case Py_GT: c = c > 0; break;
+ case Py_GE: c = c >= 0; break;
+ default:
+ PyErr_BadArgument();
+ return NULL;
+ }
+ result = c ? Py_True : Py_False;
}
- result = c ? Py_True : Py_False;
- out:
+
Py_INCREF(result);
return result;
}
@@ -881,7 +910,7 @@ bytes_hash(PyBytesObject *a)
{
if (a->ob_shash == -1) {
/* Can't fail */
- a->ob_shash = _Py_HashBytes((unsigned char *) a->ob_sval, Py_SIZE(a));
+ a->ob_shash = _Py_HashBytes(a->ob_sval, Py_SIZE(a));
}
return a->ob_shash;
}
@@ -1125,94 +1154,9 @@ Concatenate any number of bytes objects, with B in between each pair.\n\
Example: b'.'.join([b'ab', b'pq', b'rs']) -> b'ab.pq.rs'.");
static PyObject *
-bytes_join(PyObject *self, PyObject *orig)
-{
- char *sep = PyBytes_AS_STRING(self);
- const Py_ssize_t seplen = PyBytes_GET_SIZE(self);
- PyObject *res = NULL;
- char *p;
- Py_ssize_t seqlen = 0;
- size_t sz = 0;
- Py_ssize_t i;
- PyObject *seq, *item;
-
- seq = PySequence_Fast(orig, "");
- if (seq == NULL) {
- return NULL;
- }
-
- seqlen = PySequence_Size(seq);
- if (seqlen == 0) {
- Py_DECREF(seq);
- return PyBytes_FromString("");
- }
- if (seqlen == 1) {
- item = PySequence_Fast_GET_ITEM(seq, 0);
- if (PyBytes_CheckExact(item)) {
- Py_INCREF(item);
- Py_DECREF(seq);
- return item;
- }
- }
-
- /* There are at least two things to join, or else we have a subclass
- * of the builtin types in the sequence.
- * Do a pre-pass to figure out the total amount of space we'll
- * need (sz), and see whether all argument are bytes.
- */
- /* XXX Shouldn't we use _getbuffer() on these items instead? */
- for (i = 0; i < seqlen; i++) {
- const size_t old_sz = sz;
- item = PySequence_Fast_GET_ITEM(seq, i);
- if (!PyBytes_Check(item) && !PyByteArray_Check(item)) {
- PyErr_Format(PyExc_TypeError,
- "sequence item %zd: expected bytes,"
- " %.80s found",
- i, Py_TYPE(item)->tp_name);
- Py_DECREF(seq);
- return NULL;
- }
- sz += Py_SIZE(item);
- if (i != 0)
- sz += seplen;
- if (sz < old_sz || sz > PY_SSIZE_T_MAX) {
- PyErr_SetString(PyExc_OverflowError,
- "join() result is too long for bytes");
- Py_DECREF(seq);
- return NULL;
- }
- }
-
- /* Allocate result space. */
- res = PyBytes_FromStringAndSize((char*)NULL, sz);
- if (res == NULL) {
- Py_DECREF(seq);
- return NULL;
- }
-
- /* Catenate everything. */
- /* I'm not worried about a PyByteArray item growing because there's
- nowhere in this function where we release the GIL. */
- p = PyBytes_AS_STRING(res);
- for (i = 0; i < seqlen; ++i) {
- size_t n;
- char *q;
- if (i) {
- Py_MEMCPY(p, sep, seplen);
- p += seplen;
- }
- item = PySequence_Fast_GET_ITEM(seq, i);
- n = Py_SIZE(item);
- if (PyBytes_Check(item))
- q = PyBytes_AS_STRING(item);
- else
- q = PyByteArray_AS_STRING(item);
- Py_MEMCPY(p, q, n);
- p += n;
- }
-
- Py_DECREF(seq);
- return res;
+bytes_join(PyObject *self, PyObject *iterable)
+{
+ return stringlib_bytes_join(self, iterable);
}
PyObject *
@@ -1435,7 +1379,7 @@ do_argstrip(PyBytesObject *self, int striptype, PyObject *args)
{
PyObject *sep = NULL;
- if (!PyArg_ParseTuple(args, (char *)stripformat[striptype], &sep))
+ if (!PyArg_ParseTuple(args, stripformat[striptype], &sep))
return NULL;
if (sep != NULL && sep != Py_None) {
@@ -1549,9 +1493,9 @@ table, which must be a bytes object of length 256.");
static PyObject *
bytes_translate(PyBytesObject *self, PyObject *args)
{
- register char *input, *output;
+ char *input, *output;
const char *table;
- register Py_ssize_t i, c, changed = 0;
+ Py_ssize_t i, c, changed = 0;
PyObject *input_obj = (PyObject*)self;
const char *output_start, *del_table=NULL;
Py_ssize_t inlen, tablen, dellen = 0;
@@ -2329,8 +2273,6 @@ bytes_decode(PyObject *self, PyObject *args, PyObject *kwargs)
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ss:decode", kwlist, &encoding, &errors))
return NULL;
- if (encoding == NULL)
- encoding = PyUnicode_GetDefaultEncoding();
return PyUnicode_FromEncodedObject(self, encoding, errors);
}
@@ -2460,7 +2402,7 @@ bytes_methods[] = {
{"decode", (PyCFunction)bytes_decode, METH_VARARGS | METH_KEYWORDS, decode__doc__},
{"endswith", (PyCFunction)bytes_endswith, METH_VARARGS,
endswith__doc__},
- {"expandtabs", (PyCFunction)stringlib_expandtabs, METH_VARARGS,
+ {"expandtabs", (PyCFunction)stringlib_expandtabs, METH_VARARGS | METH_KEYWORDS,
expandtabs__doc__},
{"find", (PyCFunction)bytes_find, METH_VARARGS, find__doc__},
{"fromhex", (PyCFunction)bytes_fromhex, METH_VARARGS|METH_CLASS,
@@ -2692,7 +2634,7 @@ PyBytes_FromObject(PyObject *x)
}
/* For iterator version, create a string object and resize as needed */
- size = _PyObject_LengthHint(x, 64);
+ size = PyObject_LengthHint(x, 64);
if (size == -1 && PyErr_Occurred())
return NULL;
/* Allocate an extra byte to prevent PyBytes_FromStringAndSize() from
@@ -2750,9 +2692,8 @@ PyBytes_FromObject(PyObject *x)
return new;
error:
- /* Error handling when new != NULL */
Py_XDECREF(it);
- Py_DECREF(new);
+ Py_XDECREF(new);
return NULL;
}
@@ -2838,9 +2779,9 @@ PyTypeObject PyBytes_Type = {
};
void
-PyBytes_Concat(register PyObject **pv, register PyObject *w)
+PyBytes_Concat(PyObject **pv, PyObject *w)
{
- register PyObject *v;
+ PyObject *v;
assert(pv != NULL);
if (*pv == NULL)
return;
@@ -2854,7 +2795,7 @@ PyBytes_Concat(register PyObject **pv, register PyObject *w)
}
void
-PyBytes_ConcatAndDel(register PyObject **pv, register PyObject *w)
+PyBytes_ConcatAndDel(PyObject **pv, PyObject *w)
{
PyBytes_Concat(pv, w);
Py_XDECREF(w);
@@ -2878,8 +2819,8 @@ PyBytes_ConcatAndDel(register PyObject **pv, register PyObject *w)
int
_PyBytes_Resize(PyObject **pv, Py_ssize_t newsize)
{
- register PyObject *v;
- register PyBytesObject *sv;
+ PyObject *v;
+ PyBytesObject *sv;
v = *pv;
if (!PyBytes_Check(v) || Py_REFCNT(v) != 1 || newsize < 0) {
*pv = 0;