@@@ py_buffer/freebin wip
[catacomb-python] / rand.c
diff --git a/rand.c b/rand.c
index 069c351..e72f450 100644 (file)
--- a/rand.c
+++ b/rand.c
@@ -102,16 +102,14 @@ 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;
-    if (mm <= 0xffffffff)
+    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)));
   }
-  if ((x = getmp(m)) == 0)
-    goto end;
-  if (!MP_POSP(x))
-    goto notpos;
+  if ((x = getmp(m)) == 0) goto end;
+  if (!MP_POSP(x)) goto notpos;
   y = mprand_range(MP_NEW, x, GRAND_R(me), 0);
   MP_DROP(x);
   return (mp_pywrap(y));
@@ -146,7 +144,7 @@ static PyObject *grmeth_block(PyObject *me, PyObject *arg)
   if (!PyArg_ParseTuple(arg, "O&:block", convulong, &n)) goto end;
   if (grand_check(me)) return (0);
   rc = bytestring_pywrap(0, n);
-  grand_fill(GRAND_R(me), PyString_AS_STRING(rc), n);
+  grand_fill(GRAND_R(me), BIN_PTR(rc), n);
 end:
   return (rc);
 }
@@ -239,7 +237,7 @@ static PyObject *grmeth_mask(PyObject *me, PyObject *arg)
   if (!PyArg_ParseTuple(arg, "O&:mask", convbin, &in)) return (0);
   if (grand_check(me)) return (0);
   rc = bytestring_pywrap(0, in.sz);
-  q = (octet *)PyString_AS_STRING(rc);
+  q = (octet *)BIN_PTR(rc);
   GR_FILL(r, q, in.sz);
   p = in.p; n = in.sz; while (n--) *q++ ^= *p++;
   return (rc);
@@ -253,7 +251,7 @@ static void grand_pydealloc(PyObject *me)
 }
 
 static PyObject *grget_name(PyObject *me, void *hunoz)
-  { return (grand_check(me) ? 0 : PyString_FromString(GRAND_R(me)->ops->name)); }
+  { return (grand_check(me) ? 0 : TEXT_FROMSTR(GRAND_R(me)->ops->name)); }
 
 static PyObject *grget_cryptop(PyObject *me, void *hunoz)
   { return (grand_check(me) ? 0 : getbool(GRAND_R(me)->ops->f & GRAND_CRYPTO)); }
@@ -644,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");
@@ -659,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");
@@ -731,7 +731,7 @@ static PyObject *gccrand_pywrap(const gccrand_info *info)
 }
 
 static PyObject *gccrget_name(PyObject *me, void *hunoz)
-  { return (PyString_FromString(GCCRAND_INFO(me)->name)); }
+  { return (TEXT_FROMSTR(GCCRAND_INFO(me)->name)); }
 static PyObject *gccrget_keysz(PyObject *me, void *hunoz)
   { return (keysz_pywrap(GCCRAND_INFO(me)->keysz)); }
 
@@ -1120,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);
 }
@@ -1135,13 +1141,36 @@ static PyObject *drget_seed(PyObject *me, void *hunoz)
   grand *r = GRAND_R(me);
   int n = r->ops->misc(r, DSARAND_SEEDSZ);
   PyObject *rc = bytestring_pywrap(0, n);
-  r->ops->misc(r, DSARAND_GETSEED, PyString_AS_STRING(rc));
+  r->ops->misc(r, DSARAND_GETSEED, BIN_PTR(rc));
+  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 }
 };