[Python-checkins] r46270 - in python/branches/blais-bytebuf: Lib/hotbuf.py Lib/test/test_hotbuf.py Modules/_hotbuf.c

martin.blais python-checkins at python.org
Fri May 26 03:24:34 CEST 2006


Author: martin.blais
Date: Fri May 26 03:24:33 2006
New Revision: 46270

Modified:
   python/branches/blais-bytebuf/Lib/hotbuf.py
   python/branches/blais-bytebuf/Lib/test/test_hotbuf.py
   python/branches/blais-bytebuf/Modules/_hotbuf.c
Log:
hotbufferola: Added support for pack_to() and fixed may bugs.

Modified: python/branches/blais-bytebuf/Lib/hotbuf.py
==============================================================================
--- python/branches/blais-bytebuf/Lib/hotbuf.py	(original)
+++ python/branches/blais-bytebuf/Lib/hotbuf.py	Fri May 26 03:24:33 2006
@@ -10,5 +10,20 @@
 _long = Struct('l')
 
 class hotbuf(_hotbuf):
-    pass
+
+    def pack( self, structobj, *values ):
+        """
+        Pack using the given Struct object 'structobj', the remaining arguments.
+        """
+        structobj.pack_to(self, 0, *values)
+        self.advance(structobj.size)
+
+    def unpack( self, structobj ):
+        """
+        Pack using the given Struct object 'structobj', the remaining arguments.
+        """
+        values = structobj.unpack_from(self, 0)
+        self.advance(structobj.size)
+        return values
+
 

Modified: python/branches/blais-bytebuf/Lib/test/test_hotbuf.py
==============================================================================
--- python/branches/blais-bytebuf/Lib/test/test_hotbuf.py	(original)
+++ python/branches/blais-bytebuf/Lib/test/test_hotbuf.py	Fri May 26 03:24:33 2006
@@ -94,6 +94,14 @@
         b.compact()
         self.assertEquals((b.position, b.limit, b.mark),
                           (100, CAPACITY, -1))
+        
+        # Compare the text that gets compacted.
+        b.clear()
+        b.setposition(100)
+        b.putstr(MSG)
+        b.setposition(100)
+        b.compact()
+        self.assertEquals(str(b), MSG)
 
     def test_byte( self ):
         b = hotbuf(256)
@@ -131,6 +139,13 @@
         # Test underflow.
         self.assertRaises(IndexError, b.getstr, 1000)
 
+        # Test getting the rest of the string.
+        b.clear()
+        b.putstr(MSG)
+        b.flip()
+        s = b.getstr()
+        self.assertEquals(s, MSG)
+        
     def test_conversion( self ):
         b = hotbuf(CAPACITY)
 
@@ -170,6 +185,12 @@
         b.flip()
         self.assertEquals(fmt.unpack_from(b), ARGS)
 
+    def test_zerolen( self ):
+        b = hotbuf(CAPACITY)
+        b.setlimit(0)
+        self.assertEquals(str(b), '')
+        self.assertEquals(b.getstr(), '')
+
 
 def test_main():
     test_support.run_unittest(HotbufTestCase)
@@ -177,3 +198,4 @@
 if __name__ == "__main__":
     test_main()
 
+

Modified: python/branches/blais-bytebuf/Modules/_hotbuf.c
==============================================================================
--- python/branches/blais-bytebuf/Modules/_hotbuf.c	(original)
+++ python/branches/blais-bytebuf/Modules/_hotbuf.c	Fri May 26 03:24:33 2006
@@ -9,11 +9,7 @@
 
 PyAPI_DATA(PyTypeObject) PyHotbuf_Type;
 
-#define PyHotbuf_Check(op) ((op)->ob_type == &PyHotbuf_Type)
-
-#define Py_END_OF_HOTBUF       (-1)
-
-PyAPI_FUNC(PyObject *) PyHotbuf_New(Py_ssize_t size);
+#define PyHotbuf_Check(op) PyObject_TypeCheck((op), &PyHotbuf_Type)
 
 
 
@@ -52,7 +48,7 @@
     PyObject_HEAD
 
     /* Base pointer location */
-    void*      b_ptr;
+    void* b_ptr;
 
     /* Total size in bytes of the area that we can access.  The allocated
        memory must be at least as large as this size. */
@@ -63,10 +59,10 @@
      */
 
     /* The current position in the buffer. */
-    int b_position;
+    Py_ssize_t b_position;
 
     /* The limit position in the buffer. */
-    int b_limit;
+    Py_ssize_t b_limit;
 
     /* The mark. From the Java Buffer docs:
 
@@ -80,7 +76,7 @@
 
        The mark is set to -1 to indicate that the mark is unset.
     */
-    int b_mark;
+    Py_ssize_t b_mark;
 
 } PyHotbufObject;
 
@@ -90,73 +86,71 @@
  * true if there was no error.
  */
 
-/*
- * Create a new hotbuf where we allocate the memory ourselves.
- */
-PyObject *
-PyHotbuf_New(Py_ssize_t capacity)
-{
-    PyObject *o;
-    PyHotbufObject * b;
-
-    if (capacity < 0) {
-        PyErr_SetString(PyExc_ValueError,
-                        "capacity must be zero or positive");
-        return NULL;
-    }
-
-    /* FIXME: check for overflow in multiply */
-    o = (PyObject *)PyObject_MALLOC(sizeof(*b) + capacity);
-    if ( o == NULL )
-        return PyErr_NoMemory();
-    b = (PyHotbufObject *) PyObject_INIT(o, &PyHotbuf_Type);
-
-    /* We setup the memory buffer to be right after the object itself. */
-    b->b_ptr = (void *)(b + 1);
-    b->b_position = 0;
-    b->b_mark = -1;
-    b->b_limit = capacity;
-    b->b_capacity = capacity;
-
-    return o;
-}
 
 /* Methods */
 
 /*
- * Constructor.
+ * Constructor.  Note that we allocate the memory ourselves, unlike
+ * the buffer object.
  */
 static PyObject *
 hotbuf_new(PyTypeObject *type, PyObject *args, PyObject *kw)
 {
-    Py_ssize_t size = -1;
+    Py_ssize_t capacity = -1;
+    PyObject *ptr;
+    PyHotbufObject *new;
 
     if (!_PyArg_NoKeywords("hotbuf()", kw))
         return NULL;
 
-    if (!PyArg_ParseTuple(args, "n:hotbuf", &size))
+    if (!PyArg_ParseTuple(args, "n:hotbuf", &capacity))
         return NULL;
 
-    if ( size <= 0 ) {
+    if ( capacity <= 0 ) {
         PyErr_SetString(PyExc_ValueError,
-                        "size must be greater than zero");
+                        "capacity must be greater than zero");
         return NULL;
     }
 
-    return PyHotbuf_New(size);
+    /* Allocate the buffer of data */
+    ptr = (void*) PyObject_MALLOC(capacity);
+    if ( ptr == NULL ) {
+        return PyErr_NoMemory();
+    }
+    
+    /* Allocate the Python object itself. */
+    new = (PyHotbufObject *) type->tp_alloc(type, 0);
+    if (new == NULL) {
+        PyObject_FREE(ptr);
+        return NULL;
+    }
+
+    /* Initialize the members */
+    new->b_ptr = ptr;
+    new->b_position = 0;
+    new->b_mark = -1;
+    new->b_limit = capacity;
+    new->b_capacity = capacity;
+
+    return (PyObject*)new;
 }
 
+
 /*
  * Destructor.
  */
+
 static void
 hotbuf_dealloc(PyHotbufObject *self)
 {
     /* Note: by virtue of the memory buffer being allocated with the PyObject
        itself, this frees the buffer as well. */
-    PyObject_DEL(self);
+    PyObject_FREE(self->b_ptr);
+    self->b_ptr = NULL;
+    self->ob_type->tp_free(self);
 }
 
+
 /*
  * Comparison.  We compare the active windows, not the entire allocated buffer
  * memory.
@@ -192,7 +186,7 @@
         "<hotbuf mark %zd, position %zd, limit %zd, capacity %zd, ptr %p, at %p>",
         self->b_mark,
         self->b_position,
-        self->b_limit, 
+        self->b_limit,
         self->b_capacity,
         self->b_ptr,
         self);
@@ -204,9 +198,7 @@
 static PyObject *
 hotbuf_str(PyHotbufObject *self)
 {
-    if ( self->b_position == self->b_limit ) {
-        return Py_None;
-    }
+    assert( self->b_position <= self->b_limit );
     return PyString_FromStringAndSize(
         (const char *)(self->b_ptr + self->b_position),
         self->b_limit - self->b_position);
@@ -228,7 +220,7 @@
 static PyObject*
 hotbuf_setposition(PyHotbufObject *self, PyObject* arg)
 {
-    int newposition;
+    Py_ssize_t newposition;
 
     newposition = PyInt_AsLong(arg);
     if (newposition == -1 && PyErr_Occurred())
@@ -247,7 +239,7 @@
     if ( self->b_mark > self->b_position )
         self->b_mark = -1;
 
-    return Py_None;
+    Py_RETURN_NONE;
 }
 
 
@@ -262,17 +254,17 @@
 static PyObject*
 hotbuf_advance(PyHotbufObject *self, PyObject* arg)
 {
-    int nbytes;
-    int newposition;
+    Py_ssize_t nbytes;
+    Py_ssize_t newposition;
 
     nbytes = PyInt_AsLong(arg);
     if (nbytes == -1 && PyErr_Occurred())
         return NULL;
 
     newposition = self->b_position + nbytes;
-    if ( newposition > self->b_capacity ) {
+    if ( newposition > self->b_limit ) {
         PyErr_SetString(PyExc_IndexError,
-                        "position must be smaller than capacity");
+                        "position must be smaller than limit");
         return NULL;
     }
 
@@ -283,7 +275,7 @@
     if ( self->b_mark > self->b_position )
         self->b_mark = -1;
 
-    return Py_None;
+    Py_RETURN_NONE;
 }
 
 
@@ -299,7 +291,7 @@
 static PyObject*
 hotbuf_setlimit(PyHotbufObject *self, PyObject* arg)
 {
-    int newlimit;
+    Py_ssize_t newlimit;
 
     newlimit = PyInt_AsLong(arg);
     if (newlimit == -1 && PyErr_Occurred())
@@ -323,7 +315,7 @@
     if ( self->b_mark > self->b_position )
         self->b_mark = -1;
 
-    return Py_None;
+    Py_RETURN_NONE;
 }
 
 
@@ -336,7 +328,7 @@
 hotbuf_setmark(PyHotbufObject *self)
 {
     self->b_mark = self->b_position;
-    return Py_None;
+    Py_RETURN_NONE;
 }
 
 
@@ -384,7 +376,7 @@
     self->b_position = 0;
     self->b_limit = self->b_capacity;
     self->b_mark = -1;
-    return Py_None;
+    Py_RETURN_NONE;
 }
 
 
@@ -413,7 +405,7 @@
     self->b_limit = self->b_position;
     self->b_position = 0;
     self->b_mark = -1;
-    return Py_None;
+    Py_RETURN_NONE;
 }
 
 
@@ -437,7 +429,7 @@
 {
     self->b_position = 0;
     self->b_mark = -1;
-    return Py_None;
+    Py_RETURN_NONE;
 }
 
 
@@ -456,9 +448,7 @@
 PyDoc_STRVAR(compact__doc__,
 "B.compact()\n\
 \n\
-public abstract ByteBuffer compact()\n\
-\n\
-Compacts this buffer  (optional operation).\n\
+Compacts this buffer.\n\
 \n\
 The bytes between the buffer's current position and its limit, if\n\
 any, are copied to the beginning of the buffer. That is, the byte\n\
@@ -489,7 +479,7 @@
 static PyObject*
 hotbuf_compact(PyHotbufObject *self)
 {
-    int length;
+    Py_ssize_t length;
 
     /* Calculate the number of bytes in the active window */
     length = self->b_limit - self->b_position;
@@ -504,7 +494,7 @@
     self->b_limit = self->b_capacity;
     self->b_mark = -1;
 
-    return Py_None;
+    Py_RETURN_NONE;
 }
 
 
@@ -568,28 +558,39 @@
     CHECK_LIMIT_ERROR(sizeof(byte));
     *(unsigned char*)(self->b_ptr + self->b_position) = byte;
     self->b_position += sizeof(byte);
-    return Py_None;
+    Py_RETURN_NONE;
 }
 
 
 PyDoc_STRVAR(getstr__doc__,
-"B.getstr(nbytes) -> data\n\
+"B.getstr([nbytes]) -> data\n\
 \n\
-Extract a string of 'nbytes' bytes from the buffer and advance the \n\
-position accordingly.\n\
+Extract a string of 'nbytes' bytes from the buffer and advance the\n\
+position accordingly.  If 'nbytes' is not specified, get the string\n\
+up to the limit.\n\
 An IndexError is raised if the position is at the end of the buffer.");
 
 static PyObject*
-hotbuf_getstr(PyHotbufObject *self, PyObject* arg)
+hotbuf_getstr(PyHotbufObject *self, PyObject* args)
 {
-    int len;
+    Py_ssize_t len = -1;
     PyObject* s;
 
     /* Extract the given number of bytes */
-    len = PyInt_AsLong(arg);
-    if (len == -1 && PyErr_Occurred())
+    if (!PyArg_ParseTuple(args, "|n:hotbuf", &len))
         return NULL;
-    
+
+    /* Validate positive */
+    if (len == -1) {
+        /* Using default value. */
+        len = self->b_limit - self->b_position;
+    }
+    else if (len < 0) {
+        PyErr_SetString(PyExc_ValueError,
+                        "length must be zero or positive");
+        return NULL;
+    }
+
     CHECK_LIMIT_ERROR(len);
 
     /* Extract the string object from the buffer */
@@ -619,7 +620,7 @@
 hotbuf_putstr(PyHotbufObject *self, PyObject* arg)
 {
     char *instring;
-    int len;
+    Py_ssize_t len;
 
     /* Check and extract input string */
     if ( arg == NULL || !PyString_Check(arg) ) {
@@ -633,12 +634,12 @@
     CHECK_LIMIT_ERROR(len);
 
     /* Copy the string into the buffer */
-    memcpy(self->b_ptr, instring, len);
+    memcpy(self->b_ptr + self->b_position, instring, len);
 
     /* Advance the position */
     self->b_position += len;
 
-    return Py_None;
+    Py_RETURN_NONE;
 }
 
 
@@ -649,7 +650,8 @@
  */
 
 /*
- * Returns the buffer for reading or writing.
+ * Returns the buffer for reading or writing.  Important!  We only
+ * deliver the portion in the active window.
  */
 static Py_ssize_t
 hotbuf_getwritebuf(PyHotbufObject *self, Py_ssize_t idx, void **pp)
@@ -660,8 +662,8 @@
         return -1;
     }
 
-    *pp = self->b_ptr;
-    return self->b_capacity;
+    *pp = self->b_ptr + self->b_position;
+    return self->b_limit - self->b_position;
 }
 
 static Py_ssize_t
@@ -675,14 +677,7 @@
 static Py_ssize_t
 hotbuf_getcharbuf(PyHotbufObject *self, Py_ssize_t idx, const char **pp)
 {
-    if ( idx != 0 ) {
-        PyErr_SetString(PyExc_SystemError,
-                        "accessing non-existent hotbuf segment");
-        return -1;
-    }
-
-    *pp = (const char *)self->b_ptr;
-    return self->b_capacity;
+    return hotbuf_getwritebuf(self, idx, (void**)pp);
 }
 
 
@@ -694,6 +689,7 @@
 static Py_ssize_t
 hotbuf_length(PyHotbufObject *self)
 {
+    /* Note: this is the same as 'remaining'. */
     assert(self->b_position <= self->b_limit);
     return self->b_limit - self->b_position;
 }
@@ -749,7 +745,7 @@
     {"compact", (PyCFunction)hotbuf_compact, METH_NOARGS, compact__doc__},
     {"getbyte", (PyCFunction)hotbuf_getbyte, METH_NOARGS, get__doc__},
     {"putbyte", (PyCFunction)hotbuf_putbyte, METH_O, put__doc__},
-    {"getstr", (PyCFunction)hotbuf_getstr, METH_O, getstr__doc__},
+    {"getstr", (PyCFunction)hotbuf_getstr, METH_VARARGS, getstr__doc__},
     {"putstr", (PyCFunction)hotbuf_putstr, METH_O, putstr__doc__},
     {NULL, NULL} /* sentinel */
 };
@@ -809,8 +805,9 @@
     0,                                          /* tp_descr_set */
     0,                                          /* tp_dictoffset */
     0,                                          /* tp_init */
-    0,                                          /* tp_alloc */
+    PyType_GenericAlloc,                        /* tp_alloc */
     hotbuf_new,                                 /* tp_new */
+    PyObject_Del,                               /* tp_free */
 };
 
 


More information about the Python-checkins mailing list