diff options
author | Guido van Rossum <guido@python.org> | 2006-05-05 15:15:40 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 2006-05-05 15:15:40 (GMT) |
commit | 2018831b2b2106499a43b37e49e24f7f14154d35 (patch) | |
tree | 1bc981556210e5090784002f7036a2d404856bfe /Objects | |
parent | a0867f79bbdd2b38add23fced8e5ae071ce09f70 (diff) | |
download | cpython-2018831b2b2106499a43b37e49e24f7f14154d35.zip cpython-2018831b2b2106499a43b37e49e24f7f14154d35.tar.gz cpython-2018831b2b2106499a43b37e49e24f7f14154d35.tar.bz2 |
Adding bytes.join() -- a class methods that concatenates an iterable of bytes.
The name and API are questionable, but the functionality isn't.
Diffstat (limited to 'Objects')
-rw-r--r-- | Objects/bytesobject.c | 67 |
1 files changed, 65 insertions, 2 deletions
diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c index d1ebc16..f335abe 100644 --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -48,7 +48,7 @@ PyBytes_Size(PyObject *self) assert(self != NULL); assert(PyBytes_Check(self)); - return ((PyBytesObject *)self)->ob_size; + return PyBytes_GET_SIZE(self); } char * @@ -57,7 +57,7 @@ PyBytes_AsString(PyObject *self) assert(self != NULL); assert(PyBytes_Check(self)); - return ((PyBytesObject *)self)->ob_bytes; + return PyBytes_AS_STRING(self); } int @@ -714,6 +714,68 @@ bytes_alloc(PyBytesObject *self) return PyInt_FromSsize_t(self->ob_alloc); } +PyDoc_STRVAR(join_doc, +"bytes.join(iterable_of_bytes) -> bytes\n\ +\n\ +Concatenates any number of bytes objects. Example:\n\ +bytes.join([bytes('ab'), bytes('pq'), bytes('rs')]) -> bytes('abpqrs')."); + +static PyObject * +bytes_join(PyObject *cls, PyObject *it) +{ + PyObject *seq; + Py_ssize_t i; + Py_ssize_t n; + PyObject **items; + Py_ssize_t totalsize = 0; + PyObject *result; + char *dest; + + seq = PySequence_Fast(it, "can only join an iterable"); + if (seq == NULL) + return NULL; + n = PySequence_Fast_GET_SIZE(seq); + items = PySequence_Fast_ITEMS(seq); + + /* Compute the total size, and check that they are all bytes */ + for (i = 0; i < n; i++) { + PyObject *obj = items[i]; + if (!PyBytes_Check(obj)) { + PyErr_Format(PyExc_TypeError, + "can only join an iterable of bytes " + "(item %d has type '%.100s')", + i, obj->ob_type->tp_name); + goto error; + } + totalsize += PyBytes_GET_SIZE(obj); + if (totalsize < 0) { + PyErr_NoMemory(); + goto error; + } + } + + /* Allocate the result, and copy the bytes */ + result = PyBytes_FromStringAndSize(NULL, totalsize); + if (result == NULL) + goto error; + dest = PyBytes_AS_STRING(result); + for (i = 0; i < n; i++) { + PyObject *obj = items[i]; + Py_ssize_t size = PyBytes_GET_SIZE(obj); + memcpy(dest, PyBytes_AS_STRING(obj), size); + dest += size; + } + + /* Done */ + Py_DECREF(seq); + return result; + + /* Error handling */ + error: + Py_DECREF(seq); + return NULL; +} + static PySequenceMethods bytes_as_sequence = { (lenfunc)bytes_length, /*sq_length*/ (binaryfunc)bytes_concat, /*sq_concat*/ @@ -746,6 +808,7 @@ static PyMethodDef bytes_methods[] = { {"decode", (PyCFunction)bytes_decode, METH_VARARGS, decode_doc}, {"__alloc__", (PyCFunction)bytes_alloc, METH_NOARGS, alloc_doc}, + {"join", (PyCFunction)bytes_join, METH_O|METH_CLASS, join_doc}, {NULL} }; |