@@@ py_buffer/freebin wip
[catacomb-python] / rand.c
diff --git a/rand.c b/rand.c
index 6c6abdb..e72f450 100644 (file)
--- a/rand.c
+++ b/rand.c
@@ -102,8 +102,9 @@ static PyObject *grmeth_range(PyObject *me, PyObject *arg)
   if (!PyArg_ParseTuple(arg, "O:range", &m)) return (0);
   if (grand_check(me)) return (0);
   if (PyInt_Check(m)) {
-    long mm = PyInt_AS_LONG(m);
-    if (mm <= 0) goto notpos;
+    long mm = PyInt_AsLong(m);
+    if (mm == -1 && PyErr_Occurred()) PyErr_Clear();
+    else if (mm <= 0) goto notpos;
     else if (mm <= 0xffffffff)
       return (PyInt_FromLong(grand_range(GRAND_R(me), mm)));
   }
@@ -641,7 +642,7 @@ static PyObject *gcirand_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
   static const char *const kwlist[] = { "key", "i", 0 };
   struct bin k;
 
-  if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&:new", KWLIST,
+  if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&|O&:new", KWLIST,
                                   convbin, &k, convu32, &i))
     goto end;
   if (keysz(k.sz, info->keysz) != k.sz) VALERR("bad key length");
@@ -656,9 +657,11 @@ static PyObject *gcnrand_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
 {
   const gccrand_info *info = GCCRAND_INFO(ty);
   static const char *const kwlist[] = { "key", "nonce", 0 };
+  static const octet zn[24] = { 0 };
   struct bin k, n;
 
-  if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&:new", KWLIST,
+  n.p = zn; n.sz = info->noncesz; assert(info->noncesz <= sizeof(zn));
+  if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&|O&:new", KWLIST,
                                   convbin, &k, convbin, &n))
     goto end;
   if (keysz(k.sz, info->keysz) != k.sz) VALERR("bad key length");
@@ -1117,12 +1120,18 @@ static const PyTypeObject tlsprf_pytype_skel = {
 static PyObject *dsarand_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
 {
   struct bin in;
+  unsigned passes = 1;
+  grand *r;
   PyObject *rc = 0;
-  static const char *const kwlist[] = { "seed", 0 };
+  static const char *const kwlist[] = { "seed", "passes", 0 };
 
-  if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&:new", KWLIST, convbin, &in))
+  if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&|O&:new", KWLIST,
+                                  convbin, &in, convuint, &passes))
     goto end;
-  rc = grand_dopywrap(ty, dsarand_create(in.p, in.sz), f_freeme);
+  if (!passes) VALERR("must be positive");
+  r = dsarand_create(in.p, in.sz);
+  if (passes != 1) r->ops->misc(r, DSARAND_PASSES, passes);
+  rc = grand_dopywrap(ty, r, f_freeme);
 end:
   return (rc);
 }
@@ -1136,9 +1145,32 @@ static PyObject *drget_seed(PyObject *me, void *hunoz)
   return (rc);
 }
 
+static PyObject *drget_passes(PyObject *me, void *hunoz)
+{
+  grand *r = GRAND_R(me);
+  return (PyInt_FromLong(r->ops->misc(r, DSARAND_PASSES, 0)));
+}
+
+static int drset_passes(PyObject *me, PyObject *val, void *hunoz)
+{
+  grand *r = GRAND_R(me);
+  long n;
+  int rc = -1;
+
+  if (!val) NIERR("__del__");
+  n = PyInt_AsLong(val); if (n == -1 && PyErr_Occurred()) goto end;
+  if (n <= 0) VALERR("must be positive");
+  if (n > ULONG_MAX) VALERR("out of range");
+  r->ops->misc(r, DSARAND_PASSES, (unsigned)n);
+  rc = 0;
+end:
+  return (rc);
+}
+
 static const PyGetSetDef dsarand_pygetset[] = {
 #define GETSETNAME(op, name) dr##op##_##name
   GET  (seed,          "R.seed -> current generator seed")
+  GETSET(passes,       "R.passes -> number of passes to create output")
 #undef GETSETNAME
   { 0 }
 };