if (!PyArg_ParseTuple(arg, "O:range", &m)) return (0);
if (PyInt_Check(m)) {
long mm = PyInt_AS_LONG(m);
- if (mm < 0)
- goto negative;
+ if (mm <= 0)
+ goto notpos;
if (mm <= 0xffffffff)
return (PyInt_FromLong(grand_range(GRAND_R(me), mm)));
}
if ((x = getmp(m)) == 0)
goto end;
- if (MP_NEGP(x))
- goto negative;
+ if (!MP_POSP(x))
+ goto notpos;
y = mprand_range(MP_NEW, x, GRAND_R(me), 0);
MP_DROP(x);
return (mp_pywrap(y));
-negative:
- TYERR("range must be nonnegative");
+notpos:
+ VALERR("range must be strictly positive");
end:
if (x) MP_DROP(x);
return (0);
static PyObject *grmeth_mp(PyObject *me, PyObject *arg, PyObject *kw)
{
size_t l;
- mpw o;
+ mpw o = 0;
char *kwlist[] = { "bits", "or", 0 };
if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&|O&:mp", kwlist,
convszt, &l, convmpw, &o))
goto end;
+ if (l < MPW_BITS && (o >> l)) VALERR("or mask too large");
return (mp_pywrap(mprand(MP_NEW, l, GRAND_R(me), o)));
end:
return (0);
METH (byte, "R.byte() -> BYTE")
METH (word, "R.word() -> WORD")
METH (block, "R.block(N) -> STRING")
- KWMETH(mp, "R.mp(bits, or = 0) -> MP")
+ KWMETH(mp, "R.mp(bits, [or = 0]) -> MP")
METH (range, "R.range(MAX) -> INT")
METH (mask, "R.mask(STR) -> STR")
METH (seedint, "R.seedint(I)")
typedef grand *gcrand_func(const void *, size_t sz);
typedef grand *gcirand_func(const void *, size_t sz, uint32);
+typedef grand *gcnrand_func(const void *, size_t sz, const void *);
typedef struct gccrand_info {
const char *name;
const octet *keysz;
unsigned f;
+ size_t noncesz;
gcrand_func *func;
} gccrand_info;
#define RNGF_INT 1u
+#define RNGF_NONCE 2u
typedef struct gccrand_pyobj {
PyHeapTypeObject ty;
} gccrand_pyobj;
#define GCCRAND_INFO(o) (((gccrand_pyobj *)(o))->info)
-#define GCCRAND_DEF(name, ksz, func, f) \
+#define GCCRAND_DEF(name, ksz, func, f, nsz) \
static const gccrand_info func##_info = \
- { name, ksz, f, (gcrand_func *)func };
+ { name, ksz, f, nsz, (gcrand_func *)func };
RNGS(GCCRAND_DEF)
static const gccrand_info *const gcrandtab[] = {
-#define GCCRAND_ENTRY(name, ksz, func, f) &func##_info,
+#define GCCRAND_ENTRY(name, ksz, func, f, nsz) &func##_info,
RNGS(GCCRAND_ENTRY)
0
};
return (0);
}
+static PyObject *gcnrand_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
+{
+ const gccrand_info *info = GCCRAND_INFO(ty);
+ static char *kwlist[] = { "key", "nonce", 0 };
+ char *k, *n;
+ int ksz, nsz;
+
+ if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#s#:new", kwlist,
+ &k, &ksz, &n, &nsz))
+ goto end;
+ if (keysz(ksz, info->keysz) != ksz) VALERR("bad key length");
+ if (nsz != info->noncesz) VALERR("bad nonce length");
+ return (grand_dopywrap(ty,
+ ((gcnrand_func *)info->func)(k, ksz, n),
+ f_freeme));
+end:
+ return (0);
+}
+
static PyObject *gccrand_pywrap(const gccrand_info *info)
{
gccrand_pyobj *g = newtype(gccrand_pytype, 0, info->name);
Py_TPFLAGS_HEAPTYPE);
g->ty.ht_type.tp_alloc = PyType_GenericAlloc;
g->ty.ht_type.tp_free = 0;
- if (info->f & RNGF_INT)
- g->ty.ht_type.tp_new = gcirand_pynew;
- else
- g->ty.ht_type.tp_new = gcrand_pynew;
+ if (info->f & RNGF_INT) g->ty.ht_type.tp_new = gcirand_pynew;
+ else if (info->f & RNGF_NONCE) g->ty.ht_type.tp_new = gcnrand_pynew;
+ else g->ty.ht_type.tp_new = gcrand_pynew;
typeready(&g->ty.ht_type);
return ((PyObject *)g);
}