Buffer sharing and subbuffers.
authormdw <mdw>
Tue, 27 Sep 2005 11:27:03 +0000 (11:27 +0000)
committermdw <mdw>
Tue, 27 Sep 2005 11:27:03 +0000 (11:27 +0000)
buffer.c

index 8dc885a..ee0dd40 100644 (file)
--- a/buffer.c
+++ b/buffer.c
 typedef struct buf_pyobj {
   PyObject_HEAD
   buf b;
+  PyObject *sub;
 } buf_pyobj;
 
 static PyTypeObject *rbuf_pytype, *wbuf_pytype;
 #define RBUF_PYCHECK(o) PyObject_TypeCheck((o), rbuf_pytype)
 #define WBUF_PYCHECK(o) PyObject_TypeCheck((o), wbuf_pytype)
 #define BUF_B(o) (&((buf_pyobj *)(o))->b)
+#define BUF_SUB(o) (((buf_pyobj *)(o))->sub)
 
 /*----- Exceptions --------------------------------------------------------*/
 
@@ -59,16 +61,23 @@ static PyObject *rbuf_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
 
   if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#:new", kwlist, &p, &n))
     goto end;
-  me = (buf_pyobj *)ty->tp_alloc(ty, 0);
   q = xmalloc(n);
   memcpy(q, p, n);
+  me = (buf_pyobj *)ty->tp_alloc(ty, 0);
+  me->sub = 0;
   buf_init(&me->b, q, n);
 end:
   return ((PyObject *)me);
 }
 
 static void buf_pydealloc(PyObject *me)
-  { xfree(BBASE(BUF_B(me))); FREEOBJ(me); }
+{
+  if (BUF_SUB(me))
+    Py_DECREF(BUF_SUB(me));
+  else
+    xfree(BBASE(BUF_B(me)));
+  FREEOBJ(me);
+}
 
 static int rbuf_pysegcount(PyObject *me, int *nn)
   { if (nn) *nn = BSZ(BUF_B(me)); return (1); }
@@ -124,6 +133,23 @@ DOUINTCONV(RBMETH_GETU_)
   }
 BUF_DOSUFFIXES(RBMETH_GETBLK_)
 
+#define RBMETH_GETBUF_(n, W, w)                                                \
+  static PyObject *rbmeth_getbuf##w(PyObject *me, PyObject *arg)       \
+  {                                                                    \
+    buf_pyobj *b;                                                      \
+    buf bb;                                                            \
+    if (!PyArg_ParseTuple(arg, ":getbuf" #w)) goto end;                        \
+    if (buf_getbuf##w(BUF_B(me), &bb)) BUFERR();                       \
+    b = PyObject_NEW(buf_pyobj, rbuf_pytype);                          \
+    b->b = bb;                                                         \
+    b->sub = me;                                                       \
+    Py_INCREF(me);                                                     \
+    return ((PyObject *)b);                                            \
+  end:                                                                 \
+    return (0);                                                                \
+  }
+BUF_DOSUFFIXES(RBMETH_GETBUF_)
+
 static PyObject *rbmeth_getmp(PyObject *me, PyObject *arg)
 {
   mp *x;
@@ -205,12 +231,25 @@ static PyObject *rbget_left(PyObject *me, void *hunoz)
   { return (PyInt_FromLong(BLEFT(BUF_B(me)))); }
 static PyObject *rbget_endp(PyObject *me, void *hunoz)
   { return (getbool(!BLEFT(BUF_B(me)))); }
+static PyObject *rbget_offset(PyObject *me, void *hunoz)
+  { return (PyInt_FromLong(BLEN(BUF_B(me)))); }
+static int rbset_offset(PyObject *me, PyObject *x, void *hunoz)
+{
+  size_t n;
+  if (!convszt(x, &n)) goto end;
+  if (n > BSZ(BUF_B(me))) VALERR("out of range");
+  BCUR(BUF_B(me)) = BBASE(BUF_B(me)) + n;
+  return (0);
+end:
+  return (-1);
+}
 
 static PyGetSetDef rbuf_pygetset[] = {
 #define GETSETNAME(op, name) rb##op##_##name
   GET  (size,                  "RBUF.size -> SIZE")
   GET  (left,                  "RBUF.left -> REMAINDER")
   GET  (endp,                  "RBUF.endp -> BOOL")
+  GETSET(offset,               "RBUF.offset -> OFFSET")
 #undef GETSETNAME
   { 0 }
 };
@@ -225,6 +264,9 @@ static PyMethodDef rbuf_pymethods[] = {
 #define RBMETH_DECL_GETBLK_(n, W, w)                                   \
     METH(getblk##w, "RBUF.getblk" #w "() -> INT")
   BUF_DOSUFFIXES(RBMETH_DECL_GETBLK_)
+#define RBMETH_DECL_GETBUF_(n, W, w)                                   \
+    METH(getbuf##w, "RBUF.getbuf" #w "() -> INT")
+  BUF_DOSUFFIXES(RBMETH_DECL_GETBUF_)
   METH (getmp,                 "RBUF.getmp() -> X")
   METH (getgf,                 "RBUF.getgf() -> X")
   KWMETH(getecpt,              "RBUF.getecpt(curve = None) -> P")
@@ -320,6 +362,7 @@ static PyObject *wbuf_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
     goto end;
   me = (buf_pyobj *)ty->tp_alloc(ty, 0);
   p = xmalloc(n);
+  me->sub = 0;
   buf_init(&me->b, p, n);
 end:
   return ((PyObject *)me);