[Python-checkins] r46118 - in python/branches/blais-bytebuf: Modules/bytebufmodule.c setup.py
martin.blais
python-checkins at python.org
Tue May 23 18:19:50 CEST 2006
Author: martin.blais
Date: Tue May 23 18:19:49 2006
New Revision: 46118
Added:
python/branches/blais-bytebuf/Modules/bytebufmodule.c
- copied, changed from r46090, python/branches/blais-bytebuf/Objects/bufferobject.c
Modified:
python/branches/blais-bytebuf/setup.py
Log:
Basic byte buffer class skeleton for adding fast I/O functions.
Copied: python/branches/blais-bytebuf/Modules/bytebufmodule.c (from r46090, python/branches/blais-bytebuf/Objects/bufferobject.c)
==============================================================================
--- python/branches/blais-bytebuf/Objects/bufferobject.c (original)
+++ python/branches/blais-bytebuf/Modules/bytebufmodule.c Tue May 23 18:19:49 2006
@@ -1,657 +1,353 @@
-
-/* Buffer object implementation */
+/* Bytebuf object interface */
#include "Python.h"
+/* Note: the object's structure is private */
-typedef struct {
- PyObject_HEAD
- PyObject *b_base;
- void *b_ptr;
- Py_ssize_t b_size;
- Py_ssize_t b_offset;
- int b_readonly;
- long b_hash;
-} PyBufferObject;
+#ifndef Py_BYTEBUFOBJECT_H
+#define Py_BYTEBUFOBJECT_H
+#ifdef __cplusplus
+extern "C" {
+#endif
-static int
-get_buf(PyBufferObject *self, void **ptr, Py_ssize_t *size)
-{
- if (self->b_base == NULL) {
- assert (ptr != NULL);
- *ptr = self->b_ptr;
- *size = self->b_size;
- }
- else {
- Py_ssize_t count, offset;
- readbufferproc proc;
- PyBufferProcs *bp = self->b_base->ob_type->tp_as_buffer;
- if ((*bp->bf_getsegcount)(self->b_base, NULL) != 1) {
- PyErr_SetString(PyExc_TypeError,
- "single-segment buffer object expected");
- return 0;
- }
- if (self->b_readonly)
- proc = bp->bf_getreadbuffer;
- else
- proc = (readbufferproc)bp->bf_getwritebuffer;
- if ((count = (*proc)(self->b_base, 0, ptr)) < 0)
- return 0;
- /* apply constraints to the start/end */
- if (self->b_offset > count)
- offset = count;
- else
- offset = self->b_offset;
- *(char **)ptr = *(char **)ptr + offset;
- if (self->b_size == Py_END_OF_BUFFER)
- *size = count;
- else
- *size = self->b_size;
- if (offset + *size > count)
- *size = count - offset;
- }
- return 1;
-}
+PyAPI_DATA(PyTypeObject) PyBytebuf_Type;
+#define PyBytebuf_Check(op) ((op)->ob_type == &PyBytebuf_Type)
-static PyObject *
-buffer_from_memory(PyObject *base, Py_ssize_t size, Py_ssize_t offset, void *ptr,
- int readonly)
-{
- PyBufferObject * b;
+#define Py_END_OF_BYTEBUF (-1)
- if (size < 0 && size != Py_END_OF_BUFFER) {
- PyErr_SetString(PyExc_ValueError,
- "size must be zero or positive");
- return NULL;
- }
- if (offset < 0) {
- PyErr_SetString(PyExc_ValueError,
- "offset must be zero or positive");
- return NULL;
- }
-
- b = PyObject_NEW(PyBufferObject, &PyBuffer_Type);
- if ( b == NULL )
- return NULL;
-
- Py_XINCREF(base);
- b->b_base = base;
- b->b_ptr = ptr;
- b->b_size = size;
- b->b_offset = offset;
- b->b_readonly = readonly;
- b->b_hash = -1;
+PyAPI_FUNC(PyObject *) PyBytebuf_New(Py_ssize_t size);
- return (PyObject *) b;
+#ifdef __cplusplus
}
+#endif
+#endif /* !Py_BYTEBUFOBJECT_H */
-static PyObject *
-buffer_from_object(PyObject *base, Py_ssize_t size, Py_ssize_t offset, int readonly)
-{
- if (offset < 0) {
- PyErr_SetString(PyExc_ValueError,
- "offset must be zero or positive");
- return NULL;
- }
- if ( PyBuffer_Check(base) && (((PyBufferObject *)base)->b_base) ) {
- /* another buffer, refer to the base object */
- PyBufferObject *b = (PyBufferObject *)base;
- if (b->b_size != Py_END_OF_BUFFER) {
- Py_ssize_t base_size = b->b_size - offset;
- if (base_size < 0)
- base_size = 0;
- if (size == Py_END_OF_BUFFER || size > base_size)
- size = base_size;
- }
- offset += b->b_offset;
- base = b->b_base;
- }
- return buffer_from_memory(base, size, offset, NULL, readonly);
-}
+/* Byte Buffer object implementation */
-PyObject *
-PyBuffer_FromObject(PyObject *base, Py_ssize_t offset, Py_ssize_t size)
-{
- PyBufferProcs *pb = base->ob_type->tp_as_buffer;
+/*
+ * bytebuf object structure declaration.
+ */
+typedef struct {
+ PyObject_HEAD
- if ( pb == NULL ||
- pb->bf_getreadbuffer == NULL ||
- pb->bf_getsegcount == NULL )
- {
- PyErr_SetString(PyExc_TypeError, "buffer object expected");
- return NULL;
- }
+ /* Base pointer location */
+ void* b_ptr;
- return buffer_from_object(base, size, offset, 1);
-}
-
-PyObject *
-PyBuffer_FromReadWriteObject(PyObject *base, Py_ssize_t offset, Py_ssize_t size)
-{
- PyBufferProcs *pb = base->ob_type->tp_as_buffer;
+ /* Total size in bytes of the area that we can access. The allocated
+ memory must be at least as large as this size. */
+ Py_ssize_t b_size;
- if ( pb == NULL ||
- pb->bf_getwritebuffer == NULL ||
- pb->bf_getsegcount == NULL )
- {
- PyErr_SetString(PyExc_TypeError, "buffer object expected");
- return NULL;
- }
+} PyBytebufObject;
- return buffer_from_object(base, size, offset, 0);
-}
-PyObject *
-PyBuffer_FromMemory(void *ptr, Py_ssize_t size)
-{
- return buffer_from_memory(NULL, size, 0, ptr, 1);
-}
-
-PyObject *
-PyBuffer_FromReadWriteMemory(void *ptr, Py_ssize_t size)
+/*
+ * Given a bytebuf object, return the buffer memory (in 'ptr' and 'size') and
+ * true if there was no error.
+ */
+static int
+get_buf(PyBytebufObject *self, void **ptr, Py_ssize_t *size)
{
- return buffer_from_memory(NULL, size, 0, ptr, 0);
+ assert(ptr != NULL);
+ *ptr = self->b_ptr;
+ *size = self->b_size;
+ return 1;
}
+/*
+ * Create a new bytebuf where we allocate the memory ourselves.
+ */
PyObject *
-PyBuffer_New(Py_ssize_t size)
+PyBytebuf_New(Py_ssize_t size)
{
- PyObject *o;
- PyBufferObject * b;
+ PyObject *o;
+ PyBytebufObject * b;
- if (size < 0) {
- PyErr_SetString(PyExc_ValueError,
- "size must be zero or positive");
- return NULL;
- }
- /* XXX: check for overflow in multiply */
- /* Inline PyObject_New */
- o = (PyObject *)PyObject_MALLOC(sizeof(*b) + size);
- if ( o == NULL )
- return PyErr_NoMemory();
- b = (PyBufferObject *) PyObject_INIT(o, &PyBuffer_Type);
-
- b->b_base = NULL;
- b->b_ptr = (void *)(b + 1);
- b->b_size = size;
- b->b_offset = 0;
- b->b_readonly = 0;
- b->b_hash = -1;
+ if (size < 0) {
+ PyErr_SetString(PyExc_ValueError,
+ "size must be zero or positive");
+ return NULL;
+ }
+
+ /* FIXME: check for overflow in multiply */
+ o = (PyObject *)PyObject_MALLOC(sizeof(*b) + size);
+ if ( o == NULL )
+ return PyErr_NoMemory();
+ b = (PyBytebufObject *) PyObject_INIT(o, &PyBytebuf_Type);
+
+ /* We setup the memory buffer to be right after the object itself. */
+ b->b_ptr = (void *)(b + 1);
+ b->b_size = size;
- return o;
+ return o;
}
/* Methods */
+/*
+ * Constructor.
+ */
static PyObject *
-buffer_new(PyTypeObject *type, PyObject *args, PyObject *kw)
+bytebuf_new(PyTypeObject *type, PyObject *args, PyObject *kw)
{
- PyObject *ob;
- Py_ssize_t offset = 0;
- Py_ssize_t size = Py_END_OF_BUFFER;
+ Py_ssize_t size = -1;
- if (!_PyArg_NoKeywords("buffer()", kw))
- return NULL;
-
- if (!PyArg_ParseTuple(args, "O|nn:buffer", &ob, &offset, &size))
- return NULL;
- return PyBuffer_FromObject(ob, offset, size);
-}
+ if (!_PyArg_NoKeywords("bytebuf()", kw))
+ return NULL;
+
+ if (!PyArg_ParseTuple(args, "n:bytebuf", &size))
+ return NULL;
-PyDoc_STRVAR(buffer_doc,
-"buffer(object [, offset[, size]])\n\
-\n\
-Create a new buffer object which references the given object.\n\
-The buffer will reference a slice of the target object from the\n\
-start of the object (or at the specified offset). The slice will\n\
-extend to the end of the target object (or with the specified size).");
+ if ( size <= 0 ) {
+ PyErr_SetString(PyExc_TypeError,
+ "size must be greater than zero");
+ return NULL;
+ }
+ return PyBytebuf_New(size);
+}
+/*
+ * Destructor.
+ */
static void
-buffer_dealloc(PyBufferObject *self)
+bytebuf_dealloc(PyBytebufObject *self)
{
- Py_XDECREF(self->b_base);
- PyObject_DEL(self);
+ /* Note: by virtue of the memory buffer being allocated with the PyObject
+ itself, this frees the buffer as well. */
+ PyObject_DEL(self);
}
+/*
+ * Comparison.
+ */
static int
-buffer_compare(PyBufferObject *self, PyBufferObject *other)
+bytebuf_compare(PyBytebufObject *self, PyBytebufObject *other)
{
- void *p1, *p2;
- Py_ssize_t len_self, len_other, min_len;
- int cmp;
-
- if (!get_buf(self, &p1, &len_self))
- return -1;
- if (!get_buf(other, &p2, &len_other))
- return -1;
- min_len = (len_self < len_other) ? len_self : len_other;
- if (min_len > 0) {
- cmp = memcmp(p1, p2, min_len);
- if (cmp != 0)
- return cmp;
- }
- return (len_self < len_other) ? -1 : (len_self > len_other) ? 1 : 0;
+ void *p1, *p2;
+ Py_ssize_t len_self, len_other, min_len;
+ int cmp;
+
+ if (!get_buf(self, &p1, &len_self))
+ return -1;
+ if (!get_buf(other, &p2, &len_other))
+ return -1;
+ min_len = (len_self < len_other) ? len_self : len_other;
+ if (min_len > 0) {
+ cmp = memcmp(p1, p2, min_len);
+ if (cmp != 0)
+ return cmp;
+ }
+ return (len_self < len_other) ? -1 : (len_self > len_other) ? 1 : 0;
}
+
+/*
+ * Conversion to 'repr' string.
+ */
static PyObject *
-buffer_repr(PyBufferObject *self)
+bytebuf_repr(PyBytebufObject *self)
{
- const char *status = self->b_readonly ? "read-only" : "read-write";
-
- if ( self->b_base == NULL )
- return PyString_FromFormat("<%s buffer ptr %p, size %zd at %p>",
- status,
- self->b_ptr,
- self->b_size,
- self);
- else
- return PyString_FromFormat(
- "<%s buffer for %p, size %zd, offset %zd at %p>",
- status,
- self->b_base,
- self->b_size,
- self->b_offset,
- self);
-}
-
-static long
-buffer_hash(PyBufferObject *self)
-{
- void *ptr;
- Py_ssize_t size;
- register Py_ssize_t len;
- register unsigned char *p;
- register long x;
-
- if ( self->b_hash != -1 )
- return self->b_hash;
-
- /* XXX potential bugs here, a readonly buffer does not imply that the
- * underlying memory is immutable. b_readonly is a necessary but not
- * sufficient condition for a buffer to be hashable. Perhaps it would
- * be better to only allow hashing if the underlying object is known to
- * be immutable (e.g. PyString_Check() is true). Another idea would
- * be to call tp_hash on the underlying object and see if it raises
- * an error. */
- if ( !self->b_readonly )
- {
- PyErr_SetString(PyExc_TypeError,
- "writable buffers are not hashable");
- return -1;
- }
-
- if (!get_buf(self, &ptr, &size))
- return -1;
- p = (unsigned char *) ptr;
- len = size;
- x = *p << 7;
- while (--len >= 0)
- x = (1000003*x) ^ *p++;
- x ^= size;
- if (x == -1)
- x = -2;
- self->b_hash = x;
- return x;
+ return PyString_FromFormat("<bytebuf ptr %p, size %zd at %p>",
+ self->b_ptr,
+ self->b_size,
+ self);
}
+/*
+ * Conversion to string.
+ */
static PyObject *
-buffer_str(PyBufferObject *self)
+bytebuf_str(PyBytebufObject *self)
{
- void *ptr;
- Py_ssize_t size;
- if (!get_buf(self, &ptr, &size))
- return NULL;
- return PyString_FromStringAndSize((const char *)ptr, size);
+ void *ptr;
+ Py_ssize_t size;
+ if (!get_buf(self, &ptr, &size))
+ return NULL;
+ return PyString_FromStringAndSize((const char *)ptr, size);
}
-/* Sequence methods */
+/* Bytebuf methods */
+
+/*
+ * Returns the buffer for reading or writing.
+ */
static Py_ssize_t
-buffer_length(PyBufferObject *self)
+bytebuf_getwritebuf(PyBytebufObject *self, Py_ssize_t idx, void **pp)
{
- void *ptr;
- Py_ssize_t size;
- if (!get_buf(self, &ptr, &size))
- return -1;
- return size;
+ Py_ssize_t size;
+ if ( idx != 0 ) {
+ PyErr_SetString(PyExc_SystemError,
+ "accessing non-existent bytebuf segment");
+ return -1;
+ }
+ if (!get_buf(self, pp, &size))
+ return -1;
+ return size;
}
-static PyObject *
-buffer_concat(PyBufferObject *self, PyObject *other)
+static Py_ssize_t
+bytebuf_getsegcount(PyBytebufObject *self, Py_ssize_t *lenp)
{
- PyBufferProcs *pb = other->ob_type->tp_as_buffer;
- void *ptr1, *ptr2;
- char *p;
- PyObject *ob;
- Py_ssize_t size, count;
-
- if ( pb == NULL ||
- pb->bf_getreadbuffer == NULL ||
- pb->bf_getsegcount == NULL )
- {
- PyErr_BadArgument();
- return NULL;
- }
- if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
- {
- /* ### use a different exception type/message? */
- PyErr_SetString(PyExc_TypeError,
- "single-segment buffer object expected");
- return NULL;
- }
+ void *ptr;
+ Py_ssize_t size;
+ if (!get_buf(self, &ptr, &size))
+ return -1;
+ if (lenp)
+ *lenp = size;
+ return 1;
+}
- if (!get_buf(self, &ptr1, &size))
- return NULL;
-
- /* optimize special case */
- if ( size == 0 )
- {
- Py_INCREF(other);
- return other;
- }
-
- if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
- return NULL;
-
- ob = PyString_FromStringAndSize(NULL, size + count);
- if ( ob == NULL )
- return NULL;
- p = PyString_AS_STRING(ob);
- memcpy(p, ptr1, size);
- memcpy(p + size, ptr2, count);
+static Py_ssize_t
+bytebuf_getcharbuf(PyBytebufObject *self, Py_ssize_t idx, const char **pp)
+{
+ void *ptr;
+ Py_ssize_t size;
+ if ( idx != 0 ) {
+ PyErr_SetString(PyExc_SystemError,
+ "accessing non-existent bytebuf segment");
+ return -1;
+ }
+ if (!get_buf(self, &ptr, &size))
+ return -1;
+ *pp = (const char *)ptr;
+ return size;
+}
- /* there is an extra byte in the string object, so this is safe */
- p[size + count] = '\0';
- return ob;
-}
+PyDoc_STRVAR(module_doc,
+ "This module defines an object type which can represent a fixed size\n\
+buffer of bytes in momery, from which you can directly read and into\n\
+which you can directly write objects in various other types. This is\n\
+used to avoid buffer copies in network I/O as much as possible. For\n\
+example, socket recv() can directly fill a byte buffer's memory and\n\
+send() can read the data to be sent from one as well.\n\
+\n\
+In addition, a byte buffer has two pointers within it, that delimit\n\
+an active slice, the current \"position\" and the \"limit\". The\n\
+active region of a byte buffer is located within these boundaries.\n\
+\n\
+This class is heaviliy inspired from Java's NIO ByteBuffer class.\n\
+\n\
+The constructor is:\n\
+\n\
+bytebuf(nbytes) -- create a new bytebuf\n\
+");
-static PyObject *
-buffer_repeat(PyBufferObject *self, Py_ssize_t count)
-{
- PyObject *ob;
- register char *p;
- void *ptr;
- Py_ssize_t size;
-
- if ( count < 0 )
- count = 0;
- if (!get_buf(self, &ptr, &size))
- return NULL;
- ob = PyString_FromStringAndSize(NULL, size * count);
- if ( ob == NULL )
- return NULL;
-
- p = PyString_AS_STRING(ob);
- while ( count-- )
- {
- memcpy(p, ptr, size);
- p += size;
- }
- /* there is an extra byte in the string object, so this is safe */
- *p = '\0';
+/* FIXME: needs an update */
- return ob;
-}
+/* PyDoc_STRVAR(bytebuf_doc, */
+/* "bytebuf(object [, offset[, size]])\n\ */
+/* \n\ */
+/* Create a new bytebuf object which references the given object.\n\ */
+/* The bytebuf will reference a slice of the target object from the\n\ */
+/* start of the object (or at the specified offset). The slice will\n\ */
+/* extend to the end of the target object (or with the specified size)."); */
-static PyObject *
-buffer_item(PyBufferObject *self, Py_ssize_t idx)
-{
- void *ptr;
- Py_ssize_t size;
- if (!get_buf(self, &ptr, &size))
- return NULL;
- if ( idx < 0 || idx >= size ) {
- PyErr_SetString(PyExc_IndexError, "buffer index out of range");
- return NULL;
- }
- return PyString_FromStringAndSize((char *)ptr + idx, 1);
-}
+PyDoc_STRVAR(bytebuftype_doc,
+ "bytebuf(size) -> bytebuf\n\
+\n\
+Return a new bytebuf with a new buffer of fixed size 'size'.\n\
+\n\
+Methods:\n\
+\n\
+Attributes:\n\
+\n\
+");
-static PyObject *
-buffer_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right)
-{
- void *ptr;
- Py_ssize_t size;
- if (!get_buf(self, &ptr, &size))
- return NULL;
- if ( left < 0 )
- left = 0;
- if ( right < 0 )
- right = 0;
- if ( right > size )
- right = size;
- if ( right < left )
- right = left;
- return PyString_FromStringAndSize((char *)ptr + left,
- right - left);
-}
-static int
-buffer_ass_item(PyBufferObject *self, Py_ssize_t idx, PyObject *other)
-{
- PyBufferProcs *pb;
- void *ptr1, *ptr2;
- Py_ssize_t size;
- Py_ssize_t count;
-
- if ( self->b_readonly ) {
- PyErr_SetString(PyExc_TypeError,
- "buffer is read-only");
- return -1;
- }
-
- if (!get_buf(self, &ptr1, &size))
- return -1;
-
- if (idx < 0 || idx >= size) {
- PyErr_SetString(PyExc_IndexError,
- "buffer assignment index out of range");
- return -1;
- }
-
- pb = other ? other->ob_type->tp_as_buffer : NULL;
- if ( pb == NULL ||
- pb->bf_getreadbuffer == NULL ||
- pb->bf_getsegcount == NULL )
- {
- PyErr_BadArgument();
- return -1;
- }
- if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
- {
- /* ### use a different exception type/message? */
- PyErr_SetString(PyExc_TypeError,
- "single-segment buffer object expected");
- return -1;
- }
-
- if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
- return -1;
- if ( count != 1 ) {
- PyErr_SetString(PyExc_TypeError,
- "right operand must be a single byte");
- return -1;
- }
+static PyBufferProcs bytebuf_as_buffer = {
+ (readbufferproc)bytebuf_getwritebuf,
+ (writebufferproc)bytebuf_getwritebuf,
+ (segcountproc)bytebuf_getsegcount,
+ (charbufferproc)bytebuf_getcharbuf,
+};
- ((char *)ptr1)[idx] = *(char *)ptr2;
- return 0;
-}
+PyTypeObject PyBytebuf_Type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,
+ "bytebuf",
+ sizeof(PyBytebufObject),
+ 0,
+ (destructor)bytebuf_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ (cmpfunc)bytebuf_compare, /* tp_compare */
+ (reprfunc)bytebuf_repr, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ (reprfunc)bytebuf_str, /* tp_str */
+ PyObject_GenericGetAttr, /* tp_getattro */
+ 0, /* tp_setattro */
+ &bytebuf_as_buffer, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+ bytebuftype_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ bytebuf_new, /* tp_new */
+};
-static int
-buffer_ass_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right, PyObject *other)
-{
- PyBufferProcs *pb;
- void *ptr1, *ptr2;
- Py_ssize_t size;
- Py_ssize_t slice_len;
- Py_ssize_t count;
-
- if ( self->b_readonly ) {
- PyErr_SetString(PyExc_TypeError,
- "buffer is read-only");
- return -1;
- }
-
- pb = other ? other->ob_type->tp_as_buffer : NULL;
- if ( pb == NULL ||
- pb->bf_getreadbuffer == NULL ||
- pb->bf_getsegcount == NULL )
- {
- PyErr_BadArgument();
- return -1;
- }
- if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
- {
- /* ### use a different exception type/message? */
- PyErr_SetString(PyExc_TypeError,
- "single-segment buffer object expected");
- return -1;
- }
- if (!get_buf(self, &ptr1, &size))
- return -1;
- if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
- return -1;
-
- if ( left < 0 )
- left = 0;
- else if ( left > size )
- left = size;
- if ( right < left )
- right = left;
- else if ( right > size )
- right = size;
- slice_len = right - left;
-
- if ( count != slice_len ) {
- PyErr_SetString(
- PyExc_TypeError,
- "right operand length must match slice length");
- return -1;
- }
- if ( slice_len )
- memcpy((char *)ptr1 + left, ptr2, slice_len);
+/*********************** Install Module **************************/
- return 0;
-}
+/* No functions in array module. */
+static PyMethodDef a_methods[] = {
+ {NULL, NULL, 0, NULL} /* Sentinel */
+};
-/* Buffer methods */
-static Py_ssize_t
-buffer_getreadbuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
+PyMODINIT_FUNC
+initbytebuf(void)
{
- Py_ssize_t size;
- if ( idx != 0 ) {
- PyErr_SetString(PyExc_SystemError,
- "accessing non-existent buffer segment");
- return -1;
- }
- if (!get_buf(self, pp, &size))
- return -1;
- return size;
-}
+ PyObject *m;
-static Py_ssize_t
-buffer_getwritebuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
-{
- if ( self->b_readonly )
- {
- PyErr_SetString(PyExc_TypeError, "buffer is read-only");
- return -1;
- }
- return buffer_getreadbuf(self, idx, pp);
-}
+ PyBytebuf_Type.ob_type = &PyType_Type;
+ m = Py_InitModule3("bytebuf", a_methods, module_doc);
+ if (m == NULL)
+ return;
-static Py_ssize_t
-buffer_getsegcount(PyBufferObject *self, Py_ssize_t *lenp)
-{
- void *ptr;
- Py_ssize_t size;
- if (!get_buf(self, &ptr, &size))
- return -1;
- if (lenp)
- *lenp = size;
- return 1;
+ Py_INCREF((PyObject *)&PyBytebuf_Type);
+ PyModule_AddObject(m, "BytebufType", (PyObject *)&PyBytebuf_Type);
+ Py_INCREF((PyObject *)&PyBytebuf_Type);
+ PyModule_AddObject(m, "bytebuf", (PyObject *)&PyBytebuf_Type);
+ /* No need to check the error here, the caller will do that */
}
-static Py_ssize_t
-buffer_getcharbuf(PyBufferObject *self, Py_ssize_t idx, const char **pp)
-{
- void *ptr;
- Py_ssize_t size;
- if ( idx != 0 ) {
- PyErr_SetString(PyExc_SystemError,
- "accessing non-existent buffer segment");
- return -1;
- }
- if (!get_buf(self, &ptr, &size))
- return -1;
- *pp = (const char *)ptr;
- return size;
-}
-static PySequenceMethods buffer_as_sequence = {
- (lenfunc)buffer_length, /*sq_length*/
- (binaryfunc)buffer_concat, /*sq_concat*/
- (ssizeargfunc)buffer_repeat, /*sq_repeat*/
- (ssizeargfunc)buffer_item, /*sq_item*/
- (ssizessizeargfunc)buffer_slice, /*sq_slice*/
- (ssizeobjargproc)buffer_ass_item, /*sq_ass_item*/
- (ssizessizeobjargproc)buffer_ass_slice, /*sq_ass_slice*/
-};
+/*
+ TODO
+ ----
+ - Update doc.
+ - Add hash function
+ - Add support for sequence methods.
-static PyBufferProcs buffer_as_buffer = {
- (readbufferproc)buffer_getreadbuf,
- (writebufferproc)buffer_getwritebuf,
- (segcountproc)buffer_getsegcount,
- (charbufferproc)buffer_getcharbuf,
-};
-PyTypeObject PyBuffer_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0,
- "buffer",
- sizeof(PyBufferObject),
- 0,
- (destructor)buffer_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- (cmpfunc)buffer_compare, /* tp_compare */
- (reprfunc)buffer_repr, /* tp_repr */
- 0, /* tp_as_number */
- &buffer_as_sequence, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- (hashfunc)buffer_hash, /* tp_hash */
- 0, /* tp_call */
- (reprfunc)buffer_str, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- &buffer_as_buffer, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT, /* tp_flags */
- buffer_doc, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- 0, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- buffer_new, /* tp_new */
-};
+ Pending Issues
+ --------------
+ - Should we support weakrefs?
+
+*/
+
Modified: python/branches/blais-bytebuf/setup.py
==============================================================================
--- python/branches/blais-bytebuf/setup.py (original)
+++ python/branches/blais-bytebuf/setup.py Tue May 23 18:19:49 2006
@@ -334,6 +334,10 @@
# array objects
exts.append( Extension('array', ['arraymodule.c']) )
+
+ # array objects
+ exts.append( Extension('bytebuf', ['bytebufmodule.c']) )
+
# complex math library functions
exts.append( Extension('cmath', ['cmathmodule.c'],
libraries=math_libs) )
More information about the Python-checkins
mailing list