[Python-checkins] r46365 - in sandbox/trunk/hotbuffer: Modules Modules/_hotbuf.c README.txt test_hotbuf.py

martin.blais python-checkins at python.org
Fri May 26 19:25:28 CEST 2006


Author: martin.blais
Date: Fri May 26 19:25:28 2006
New Revision: 46365

Modified:
   sandbox/trunk/hotbuffer/   (props changed)
   sandbox/trunk/hotbuffer/Modules/   (props changed)
   sandbox/trunk/hotbuffer/Modules/_hotbuf.c
   sandbox/trunk/hotbuffer/README.txt
   sandbox/trunk/hotbuffer/test_hotbuf.py
Log:
Modified API of the hotbuffer.

Modified: sandbox/trunk/hotbuffer/Modules/_hotbuf.c
==============================================================================
--- sandbox/trunk/hotbuffer/Modules/_hotbuf.c	(original)
+++ sandbox/trunk/hotbuffer/Modules/_hotbuf.c	Fri May 26 19:25:28 2006
@@ -21,29 +21,30 @@
 /*
  * hotbuf object structure declaration.
 
-   From the Java Buffer docs:
+ From the Java Buffer docs:
 
-     A buffer is a linear, finite sequence of elements of a specific
-     primitive type. Aside from its content, the essential properties of a
-     buffer are its capacity, limit, and position:
+ A buffer is a linear, finite sequence of elements of a specific
+ primitive type. Aside from its content, the essential properties of a
+ buffer are its capacity, limit, and position:
 
-       A buffer's capacity is the number of elements it contains. The
-       capacity of a buffer is never negative and never changes.
+ A buffer's capacity is the number of elements it contains. The
+ capacity of a buffer is never negative and never changes.
 
-       A buffer's limit is the index of the first element that should not
-       be read or written. A buffer's limit is never negative and is never
-       greater than its capacity.
+ A buffer's limit is the index of the first element that should not
+ be read or written. A buffer's limit is never negative and is never
+ greater than its capacity.
 
-       A buffer's position is the index of the next element to be read or
-       written. A buffer's position is never negative and is never greater
-       than its limit.
+ A buffer's position is the index of the next element to be read or
+ written. A buffer's position is never negative and is never greater
+ than its limit.
 
-   The following invariant holds for the mark, position, limit, and
-   capacity values:
+ The following invariant holds for the position, limit, and
+ capacity values:
 
-      0 <= mark <= position <= limit <= capacity (length)
+ 0 <= position <= limit <= capacity
+ 0 <= mark_position <= mark_limit <= capacity
 
- */
+*/
 typedef struct {
     PyObject_HEAD
 
@@ -64,19 +65,12 @@
     /* The limit position in the buffer. */
     Py_ssize_t b_limit;
 
-    /* The mark. From the Java Buffer docs:
-
-         A buffer's mark is the index to which its position will be reset when
-         the reset method is invoked. The mark is not always defined, but when
-         it is defined it is never negative and is never greater than the
-         position. If the mark is defined then it is discarded when the
-         position or the limit is adjusted to a value smaller than the mark. If
-         the mark is not defined then invoking the reset method causes an
-         InvalidMarkException to be thrown.
-
-       The mark is set to -1 to indicate that the mark is unset.
+    /* The mark (position and limit), which save the current position and
+       limit on save(), to be reset later with restore().  The mark variables are
+       set to -1 to indicate that the mark is unset.
     */
-    Py_ssize_t b_mark;
+    Py_ssize_t b_mark_position;
+    Py_ssize_t b_mark_limit;
 
 } PyHotbufObject;
 
@@ -91,21 +85,17 @@
 static int
 hotbuf_advance_internal(PyHotbufObject *self, Py_ssize_t nbytes)
 {
-     Py_ssize_t newposition = self->b_position + nbytes;
-     if (newposition > self->b_limit) {
-         PyErr_SetString(PyExc_IndexError,
-                         "position must be smaller than limit");
-         return -1;
-     }
-
-     /* Set the new position */
-     self->b_position = newposition;
-
-     /* Discard the mark if it is beyond the new position */
-     if (self->b_mark > self->b_position)
-         self->b_mark = -1;
+    Py_ssize_t newposition = self->b_position + nbytes;
+    if (newposition > self->b_limit) {
+        PyErr_SetString(PyExc_IndexError,
+                        "position must be smaller than limit");
+        return -1;
+    }
 
-     return 0;
+    /* Set the new position */
+    self->b_position = newposition;
+
+    return 0;
 }
 
 
@@ -150,8 +140,9 @@
     /* Initialize the members */
     new->b_ptr = ptr;
     new->b_position = 0;
-    new->b_mark = -1;
     new->b_limit = capacity;
+    new->b_mark_position = -1;
+    new->b_mark_limit = -1;
     new->b_capacity = capacity;
 
     return (PyObject*)new;
@@ -205,11 +196,12 @@
 hotbuf_repr(PyHotbufObject *self)
 {
     return PyString_FromFormat(
-        "<hotbuf mark %zd, position %zd, limit %zd, capacity %zd, ptr %p, at %p>",
-        self->b_mark,
+        "<hotbuf position %zd, limit %zd, capacity %zd, mark %zd %zd, ptr %p, at %p>",
         self->b_position,
         self->b_limit,
         self->b_capacity,
+        self->b_mark_position,
+        self->b_mark_limit,
         self->b_ptr,
         self);
 }
@@ -233,10 +225,9 @@
  */
 
 PyDoc_STRVAR(setposition__doc__,
-"B.setposition(int)\n\
+             "B.setposition(int)\n\
 \n\
-Sets this buffer's position. If the mark is defined and larger than\n\
-the new position then it is discarded.  If the given position is\n\
+Sets this buffer's position. If the given position is\n\
 larger than the limit an exception is raised.");
 
 static PyObject*
@@ -257,21 +248,16 @@
     /* Set the new position */
     self->b_position = newposition;
 
-    /* Discard the mark if it is beyond the new position */
-    if ( self->b_mark > self->b_position )
-        self->b_mark = -1;
-
     Py_RETURN_NONE;
 }
 
 
 PyDoc_STRVAR(advance__doc__,
-"B.advance(int)\n\
+             "B.advance(int)\n\
 \n\
 Advance this buffer's position by the given number of bytes. \n\
-If the mark is defined and larger than\n\
-the new position then it is discarded.  If the given position is\n\
-larger than the limit an exception is raised.");
+If the given position is larger than the limit an exception \n\
+is raised.");
 
 static PyObject*
 hotbuf_advance(PyHotbufObject *self, PyObject* arg)
@@ -290,11 +276,10 @@
 
 
 PyDoc_STRVAR(setlimit__doc__,
-"B.setlimit(int)\n\
+             "B.setlimit(int)\n\
 \n\
 Sets this buffer's limit. If the position is larger than the new limit\n\
-then it is set to the new limit. If the mark is defined and larger\n\
-than the new limit then it is discarded.");
+then it is set to the new limit.");
 
 static PyObject*
 hotbuf_setlimit(PyHotbufObject *self, PyObject* arg)
@@ -319,51 +304,105 @@
     if ( self->b_position > self->b_limit )
         self->b_position = newlimit;
 
-    /* Discard the mark if it is beyond the new limit */
-    if ( self->b_mark > self->b_position )
-        self->b_mark = -1;
+    Py_RETURN_NONE;
+}
+
+
+PyDoc_STRVAR(setwindow__doc__,
+             "B.setwindow(int)\n\
+\n\
+Sets this buffer's limit to be beyond position by the given\n\
+number number of bytes. If the limit is larger than the \n\
+capacity an IndexError is raised.");
+
+static PyObject*
+hotbuf_setwindow(PyHotbufObject *self, PyObject* arg)
+{
+    Py_ssize_t window;
+    Py_ssize_t newlimit;
+
+    window = PyInt_AsLong(arg);
+    if (window == -1 && PyErr_Occurred())
+        return NULL;
+
+    newlimit = self->b_position + window;
+    if ( newlimit > self->b_capacity ) {
+        PyErr_SetString(PyExc_IndexError,
+                        "limit must be smaller than capacity");
+        return NULL;
+    }
+
+    /* Set the new limit. */
+    self->b_limit = newlimit;
 
     Py_RETURN_NONE;
 }
 
 
-PyDoc_STRVAR(setmark__doc__,
-"B.setmark()\n\
+PyDoc_STRVAR(save__doc__,
+             "B.save()\n\
 \n\
-Sets this buffer's mark at its position.");
+Save this buffer's position and limit for later.");
 
 static PyObject*
-hotbuf_setmark(PyHotbufObject *self)
+hotbuf_save(PyHotbufObject *self)
 {
-    self->b_mark = self->b_position;
+    self->b_mark_position = self->b_position;
+    self->b_mark_limit = self->b_limit;
     Py_RETURN_NONE;
 }
 
 
-PyDoc_STRVAR(reset__doc__,
-"B.reset() -> int\n\
+PyDoc_STRVAR(restore__doc__,
+             "B.restore([advbytes]) -> int\n\
 \n\
-Resets this buffer's position to the previously-marked position.\n\
-Invoking this method neither changes nor discards the mark's value.\n\
-An IndexError is raised if the mark has not been set.\n\
-This method returns the new position's value.");
+Resets this buffer's position to the previously-marked\n\
+position and limit.  Invoking this method neither changes nor\n\
+discards the mark's value.  An IndexError is raised if the\n\
+mark has not been set.  This method returns the new\n\
+position's value.  If you specify a number of bytes via \n\
+'advbytes', the method advances the position by that many bytes.");
 
 static PyObject*
-hotbuf_reset(PyHotbufObject *self)
+hotbuf_restore(PyHotbufObject *self, PyObject* args)
 {
-    if ( self->b_mark == -1 ) {
+    Py_ssize_t advbytes = 0;
+    Py_ssize_t newposition = -1;
+
+    /* Validate that the mark is set. */
+    if ( self->b_mark_position == -1 || self->b_mark_limit == -1 ) {
         PyErr_SetString(PyExc_IndexError,
                         "mark has not been yet set");
         return NULL;
     }
 
-    self->b_position = self->b_mark;
-    return PyInt_FromLong(self->b_position);
+    /* Extract and validate advbytes */
+    if (!PyArg_ParseTuple(args, "|n:hotbuf", &advbytes))
+        return NULL;
+
+    if (advbytes < 0) {
+        PyErr_SetString(PyExc_ValueError,
+                        "advbytes must be a positive number");
+        return NULL;
+    }
+
+    /* Validate the new position, if specified */
+    newposition = self->b_mark_position + advbytes;
+    if (newposition > self->b_limit) {
+        PyErr_SetString(PyExc_IndexError,
+                        "new position must be smaller than limit");
+        return NULL;
+    }
+
+    self->b_position = newposition;
+    self->b_limit = self->b_mark_limit;
+
+    return PyInt_FromLong(newposition);
 }
 
 
 PyDoc_STRVAR(clear__doc__,
-"B.clear()\n\
+             "B.clear()\n\
 \n\
 Clears this buffer. The position is set to zero, the limit is set to\n\
 the capacity, and the mark is discarded.\n\
@@ -383,13 +422,13 @@
 {
     self->b_position = 0;
     self->b_limit = self->b_capacity;
-    self->b_mark = -1;
+    self->b_mark_position = self->b_mark_limit = -1;
     Py_RETURN_NONE;
 }
 
 
 PyDoc_STRVAR(flip__doc__,
-"B.flip()\n\
+             "B.flip()\n\
 \n\
 Flips this buffer. The limit is set to the current position and then\n\
 the position is set to zero. If the mark is defined then it is\n\
@@ -412,16 +451,15 @@
 {
     self->b_limit = self->b_position;
     self->b_position = 0;
-    self->b_mark = -1;
+    self->b_mark_position = self->b_mark_limit = -1;
     Py_RETURN_NONE;
 }
 
 
 PyDoc_STRVAR(rewind__doc__,
-"B.rewind()\n\
+             "B.rewind()\n\
 \n\
-Rewinds this buffer. The position is set to zero and the mark is\n\
-discarded.\n\
+Rewinds this buffer. The position is set to zero.\n\
 \n\
 Invoke this method before a sequence of channel-write or get\n\
 operations, assuming that the limit has already been set\n\
@@ -436,13 +474,12 @@
 hotbuf_rewind(PyHotbufObject *self)
 {
     self->b_position = 0;
-    self->b_mark = -1;
     Py_RETURN_NONE;
 }
 
 
 PyDoc_STRVAR(remaining__doc__,
-"B.remaining() -> int\n\
+             "B.remaining() -> int\n\
 \n\
 Returns the number of bytes between the current position and the limit.");
 
@@ -454,7 +491,7 @@
 
 
 PyDoc_STRVAR(compact__doc__,
-"B.compact()\n\
+             "B.compact()\n\
 \n\
 Compacts this buffer.\n\
 \n\
@@ -500,7 +537,7 @@
 
     self->b_position = length;
     self->b_limit = self->b_capacity;
-    self->b_mark = -1;
+    self->b_mark_position = self->b_mark_limit = -1;
 
     Py_RETURN_NONE;
 }
@@ -512,7 +549,7 @@
  */
 
 PyDoc_STRVAR(get__doc__,
-"B.get*() -> data\n\
+             "B.get*() -> data\n\
 \n\
 Relative get methods. \n\
 Reads something at this buffer's current position, \n\
@@ -520,7 +557,7 @@
 An IndexError is raised if the position is at the end of the buffer.");
 
 PyDoc_STRVAR(put__doc__,
-"B.put*(data)\n\
+             "B.put*(data)\n\
 \n\
 Relative put methods. \n\
 Writes the given byte into this buffer at the current position,\n\
@@ -571,7 +608,7 @@
 
 
 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.  If 'nbytes' is not specified, get the string\n\
@@ -608,17 +645,13 @@
     /* Advance to the new position */
     self->b_position += len;
 
-    /* Discard the mark if it is beyond the new position */
-    if ( self->b_mark > self->b_position )
-        self->b_mark = -1;
-
     /* Return the new string */
     return s;
 }
 
 
 PyDoc_STRVAR(putstr__doc__,
-"B.putstr(str)\n\
+             "B.putstr(str)\n\
 \n\
 Write a string of 'nbytes' bytes from the buffer and advance the \n\
 position accordingly.\n\
@@ -651,7 +684,7 @@
 }
 
 PyDoc_STRVAR(unpack__doc__,
-"B.unpack(structobj) -> v1, v2, ...\n\
+             "B.unpack(structobj) -> v1, v2, ...\n\
 \n\
 Unpack the given structure directly from this buffer and advance\n\
 the position accordingly.");
@@ -694,7 +727,8 @@
         PyErr_SetString(PyExc_TypeError,
                         "unpack requires a single struct argument");
     
-    result = PyObject_CallMethodObjArgs(structobj, str_unpack_from, self, NULL);
+    result = PyObject_CallMethodObjArgs(structobj, 
+                                        str_unpack_from, self, NULL);
     
     if (result == NULL)
         return NULL;
@@ -765,7 +799,7 @@
 
 
 PyDoc_STRVAR(hotbuf_doc,
-"hotbuf(capacity) -> hotbuf\n\
+             "hotbuf(capacity) -> hotbuf\n\
 \n\
 Return a new hotbuf with a buffer of fixed size 'capacity'.\n\
 \n\
@@ -789,8 +823,10 @@
      "buffer's position"},
     {"limit", T_INT, OFF(b_limit), RO,
      "buffer's limit"},
-    {"mark", T_INT, OFF(b_mark), RO,
-     "buffer's mark, -1 if not set"},
+    {"mark_position", T_INT, OFF(b_mark_position), RO,
+     "buffer's mark position, -1 if not set"},
+    {"mark_limit", T_INT, OFF(b_mark_limit), RO,
+     "buffer's mark limit, -1 if not set"},
     {NULL} /* Sentinel */
 };
 
@@ -800,8 +836,9 @@
     {"setposition", (PyCFunction)hotbuf_setposition, METH_O, setposition__doc__},
     {"advance", (PyCFunction)hotbuf_advance, METH_O, advance__doc__},
     {"setlimit", (PyCFunction)hotbuf_setlimit, METH_O, setlimit__doc__},
-    {"setmark", (PyCFunction)hotbuf_setmark, METH_NOARGS, setmark__doc__},
-    {"reset", (PyCFunction)hotbuf_reset, METH_NOARGS, reset__doc__},
+    {"setwindow", (PyCFunction)hotbuf_setwindow, METH_O, setwindow__doc__},
+    {"save", (PyCFunction)hotbuf_save, METH_NOARGS, save__doc__},
+    {"restore", (PyCFunction)hotbuf_restore, METH_VARARGS, restore__doc__},
     {"flip", (PyCFunction)hotbuf_flip, METH_NOARGS, flip__doc__},
     {"rewind", (PyCFunction)hotbuf_rewind, METH_NOARGS, rewind__doc__},
     {"remaining", (PyCFunction)hotbuf_remaining, METH_NOARGS, remaining__doc__},
@@ -916,8 +953,8 @@
     if (m == NULL)
         return;
 
-	if (PyType_Ready(&PyHotbuf_Type) < 0)
-		return;
+    if (PyType_Ready(&PyHotbuf_Type) < 0)
+        return;
 
     Py_INCREF((PyObject *)&PyHotbuf_Type);
     PyModule_AddObject(m, "HotbufType", (PyObject *)&PyHotbuf_Type);

Modified: sandbox/trunk/hotbuffer/README.txt
==============================================================================
--- sandbox/trunk/hotbuffer/README.txt	(original)
+++ sandbox/trunk/hotbuffer/README.txt	Fri May 26 19:25:28 2006
@@ -36,6 +36,10 @@
 Features
 --------
 
+* Use descriptors rather than function calls to set the limit, etc.
+
+* Add restore() to the tests.
+
 * Change the mark, this will make the loop easier to understand
 
   * setmark() to save both the position and limit
@@ -55,6 +59,8 @@
 
 - Should we support weakrefs?
 
+* Add with protocol for guards
+
 
 Document
 --------

Modified: sandbox/trunk/hotbuffer/test_hotbuf.py
==============================================================================
--- sandbox/trunk/hotbuffer/test_hotbuf.py	(original)
+++ sandbox/trunk/hotbuffer/test_hotbuf.py	Fri May 26 19:25:28 2006
@@ -48,30 +48,30 @@
         # Play with the mark
         b.setposition(10)
         b.setlimit(100)
-        b.setmark()
+        b.save()
         b.setposition(15)
-        self.assertEquals(b.mark, 10)
+        self.assertEquals(b.mark_position, 10)
 
         # Play with clear
         b.clear()
-        self.assertEquals((b.position, b.limit, b.mark),
+        self.assertEquals((b.position, b.limit, b.mark_position),
                           (0, CAPACITY, -1))
 
         # Play with flip.
         b.setposition(42)
         b.setlimit(104)
-        b.setmark()
+        b.save()
         b.flip()
-        self.assertEquals((b.position, b.limit, b.mark),
+        self.assertEquals((b.position, b.limit, b.mark_position),
                           (0, 42, -1))
 
         # Play with rewind.
         b.setposition(42)
         b.setlimit(104)
-        b.setmark()
+        b.save()
         b.rewind()
-        self.assertEquals((b.position, b.limit, b.mark),
-                          (0, 104, -1))
+        self.assertEquals((b.position, b.limit, b.mark_position),
+                          (0, 104, 42))
 
         # Play with remaining.
         self.assertEquals(b.remaining(), 104)
@@ -85,14 +85,22 @@
 
         self.assertRaises(IndexError, b.advance, CAPACITY)
 
+        # Play with setwindow()
+        b.clear()
+        b.setwindow(12)
+        self.assertEquals((b.position, b.limit), (0, 12))
+        b.advance(3)
+        b.setwindow(12)
+        self.assertEquals((b.position, b.limit), (3, 15))
+
     def test_compact( self ):
         b = hotbuf(CAPACITY)
 
         b.setposition(100)
         b.setlimit(200)
-        m = b.mark
+        m = b.mark_position
         b.compact()
-        self.assertEquals((b.position, b.limit, b.mark),
+        self.assertEquals((b.position, b.limit, b.mark_position),
                           (100, CAPACITY, -1))
         
         # Compare the text that gets compacted.
@@ -227,3 +235,5 @@
     test_main()
 
 
+
+## FIXME TODO add  restore() in test.


More information about the Python-checkins mailing list