algorithms.c (KECCAK.extract): Fix method name in keyword-args string.
[catacomb-python] / buffer.c
index 8dc885a..b15a245 100644 (file)
--- a/buffer.c
+++ b/buffer.c
@@ -1,13 +1,11 @@
 /* -*-c-*-
  *
- * $Id$
- *
  * Reading and writing buffers of stuff
  *
  * (c) 2005 Straylight/Edgeware
  */
 
-/*----- Licensing notice --------------------------------------------------* 
+/*----- Licensing notice --------------------------------------------------*
  *
  * This file is part of the Python interface to Catacomb.
  *
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
- * 
+ *
  * Catacomb/Python is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with Catacomb/Python; if not, write to the Free Software Foundation,
  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 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 --------------------------------------------------------*/
 
@@ -53,28 +53,35 @@ static PyObject *buferr;
 static PyObject *rbuf_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
 {
   char *p, *q;
-  int n;
+  Py_ssize_t n;
   buf_pyobj *me = 0;
   static char *kwlist[] = { "data", 0 };
 
   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)
+static Py_ssize_t rbuf_pysegcount(PyObject *me, Py_ssize_t *nn)
   { if (nn) *nn = BSZ(BUF_B(me)); return (1); }
 
-static int rbuf_pyreadbuf(PyObject *me, int seg, void **q)
-  { assert(seg == 0); *q = BBASE(BUF_B(me)); return (BSZ(BUF_B(me))); }
+static Py_ssize_t rbuf_pyreadbuf(PyObject *me, Py_ssize_t seg, void **q)
+  { assert(seg == 0); *q = BCUR(BUF_B(me)); return (BLEFT(BUF_B(me))); }
 
 static PyObject *rbmeth_skip(PyObject *me, PyObject *arg)
 {
@@ -105,7 +112,8 @@ end:
     uint##n x;                                                         \
     if (!PyArg_ParseTuple(arg, ":getu" #w)) goto end;                  \
     if (buf_getu##w(BUF_B(me), &x)) BUFERR();                          \
-    return (getu32(x));                                                        \
+    if (MASK##W <= ULONG_MAX) return (getulong(x));                    \
+    else { kludge64 y; ASSIGN64(y, x); return (getk64(y)); }           \
   end:                                                                 \
     return (0);                                                                \
   }
@@ -124,6 +132,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;
@@ -160,7 +185,7 @@ static PyObject *rbmeth_getecpt(PyObject *me, PyObject *arg, PyObject *kw)
 end:
   return (0);
 }
-    
+
 static PyObject *rbmeth_getecptraw(PyObject *me, PyObject *arg)
 {
   PyTypeObject *cobj = ecpt_pytype;
@@ -205,12 +230,26 @@ 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 (!x) NIERR("__del__");
+  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 }
 };
@@ -223,11 +262,14 @@ static PyMethodDef rbuf_pymethods[] = {
     METH(getu##w, "RBUF.getu" #w "() -> INT")
   DOUINTCONV(RBMETH_DECL_GETU_)
 #define RBMETH_DECL_GETBLK_(n, W, w)                                   \
-    METH(getblk##w, "RBUF.getblk" #w "() -> INT")
+    METH(getblk##w, "RBUF.getblk" #w "() -> BYTES")
   BUF_DOSUFFIXES(RBMETH_DECL_GETBLK_)
+#define RBMETH_DECL_GETBUF_(n, W, w)                                   \
+    METH(getbuf##w, "RBUF.getbuf" #w "() -> RBUF'")
+  BUF_DOSUFFIXES(RBMETH_DECL_GETBUF_)
   METH (getmp,                 "RBUF.getmp() -> X")
   METH (getgf,                 "RBUF.getgf() -> X")
-  KWMETH(getecpt,              "RBUF.getecpt(curve = None) -> P")
+  KWMETH(getecpt,              "RBUF.getecpt([curve = None]) -> P")
   METH (getecptraw,            "RBUF.getecptraw(CURVE) -> P")
   METH (getge,                 "RBUF.getge(GROUP) -> X")
   METH (getgeraw,              "RBUF.getgeraw(GROUP) -> X")
@@ -244,7 +286,7 @@ static PyBufferProcs rbuf_pybuffer = {
 
 static PyTypeObject rbuf_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.ReadBuffer",               /* @tp_name@ */
+  "ReadBuffer",                                /* @tp_name@ */
   sizeof(buf_pyobj),                   /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -274,7 +316,7 @@ static PyTypeObject rbuf_pytype_skel = {
   0,                                   /* @tp_richcompare@ */
   0,                                   /* @tp_weaklistoffset@ */
   0,                                   /* @tp_iter@ */
-  0,                                   /* @tp_iternexr@ */
+  0,                                   /* @tp_iternext@ */
   rbuf_pymethods,                      /* @tp_methods@ */
   0,                                   /* @tp_members@ */
   rbuf_pygetset,                       /* @tp_getset@ */
@@ -299,7 +341,7 @@ static void ensure(PyObject *me, size_t n)
   if (BLEFT(b) < n) {
     size_t nn = BSZ(b);
     octet *p;
-    size_t want = BLEFT(b) + n;
+    size_t want = BLEN(b) + n;
     while (nn < want) nn <<= 1;
     p = xrealloc(BBASE(b), nn, BSZ(b));
     BCUR(b) = p + BLEN(b);
@@ -320,15 +362,16 @@ 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);
 }
 
-static int wbuf_pysegcount(PyObject *me, int *nn)
+static Py_ssize_t wbuf_pysegcount(PyObject *me, Py_ssize_t *nn)
   { if (nn) *nn = BLEN(BUF_B(me)); return (1); }
 
-static int wbuf_pyreadbuf(PyObject *me, int seg, void **q)
+static Py_ssize_t wbuf_pyreadbuf(PyObject *me, Py_ssize_t seg, void **q)
   { assert(seg == 0); *q = BBASE(BUF_B(me)); return (BLEN(BUF_B(me))); }
 
 static PyObject *wbmeth_zero(PyObject *me, PyObject *arg)
@@ -345,10 +388,10 @@ static PyObject *wbmeth_zero(PyObject *me, PyObject *arg)
 static PyObject *wbmeth_put(PyObject *me, PyObject *arg)
 {
   void *p;
-  int n;
+  Py_ssize_t n;
   if (!PyArg_ParseTuple(arg, "s#:put", &p, &n)) return (0);
   ensure(me, n);
-  buf_put(BUF_B(me), p, n); assert(BOK(BUF_B(m)));
+  buf_put(BUF_B(me), p, n); assert(BOK(BUF_B(me)));
   RETURN_ME;
 }
 
@@ -363,16 +406,20 @@ static PyObject *wbmeth_put(PyObject *me, PyObject *arg)
   }
 DOUINTCONV(WBMETH_PUTU_)
 
+#define MASKz 0
 #define SZ_z 1
 #define WBMETH_PUTBLK_(n, W, w)                                                \
   static PyObject *wbmeth_putblk##w(PyObject *me, PyObject *arg)       \
   {                                                                    \
     char *p;                                                           \
-    int sz;                                                            \
-    if (!PyArg_ParseTuple(arg, "s#:putblk" #w, &p, &sz)) return (0);   \
+    Py_ssize_t sz;                                                     \
+    if (!PyArg_ParseTuple(arg, "s#:putblk" #w, &p, &sz)) goto end;     \
+    if (MASK##W && sz > MASK##W) VALERR("too large");                  \
     ensure(me, sz + SZ_##n);                                           \
     buf_putmem##w(BUF_B(me), p, sz); assert(BOK(BUF_B(me)));           \
     RETURN_ME;                                                         \
+  end:                                                                 \
+    return (0);                                                                \
   }
 BUF_DOSUFFIXES(WBMETH_PUTBLK_)
 
@@ -449,7 +496,7 @@ static PyGetSetDef wbuf_pygetset[] = {
 
 static PyMethodDef wbuf_pymethods[] = {
 #define METHNAME(func) wbmeth_##func
-  METH (zero,                  "WBUF.skip(N)")
+  METH (zero,                  "WBUF.zero(N)")
   METH (put,                   "WBUF.put(BYTES)")
 #define WBMETH_DECL_PUTU_(n, W, w)                                     \
     METH(putu##w, "WBUF.putu" #w "(INT)")
@@ -459,7 +506,7 @@ static PyMethodDef wbuf_pymethods[] = {
   BUF_DOSUFFIXES(WBMETH_DECL_PUTBLK_)
   METH (putmp,                 "WBUF.putmp(X)")
   METH (putgf,                 "WBUF.putgf(X)")
-  KWMETH(putecpt,              "WBUF.putecpt(P)")
+  METH (putecpt,               "WBUF.putecpt(P)")
   METH (putecptraw,            "WBUF.putecptraw(P)")
   METH (putge,                 "WBUF.putge(X)")
   METH (putgeraw,              "WBUF.putgeraw(X)")
@@ -476,7 +523,7 @@ static PyBufferProcs wbuf_pybuffer = {
 
 static PyTypeObject wbuf_pytype_skel = {
   PyObject_HEAD_INIT(0) 0,             /* Header */
-  "catacomb.WriteBuffer",              /* @tp_name@ */
+  "WriteBuffer",                       /* @tp_name@ */
   sizeof(buf_pyobj),                   /* @tp_basicsize@ */
   0,                                   /* @tp_itemsize@ */
 
@@ -506,7 +553,7 @@ static PyTypeObject wbuf_pytype_skel = {
   0,                                   /* @tp_richcompare@ */
   0,                                   /* @tp_weaklistoffset@ */
   0,                                   /* @tp_iter@ */
-  0,                                   /* @tp_iternexr@ */
+  0,                                   /* @tp_iternext@ */
   wbuf_pymethods,                      /* @tp_methods@ */
   0,                                   /* @tp_members@ */
   wbuf_pygetset,                       /* @tp_getset@ */