[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