X-Git-Url: https://git.distorted.org.uk/~mdw/catacomb-python/blobdiff_plain/1e2e275eb4f02a53c28fc7617042dbe72a5ba413..ad70a954d0c71d5506143d57c63e58aa09d6a13f:/buffer.c diff --git a/buffer.c b/buffer.c index 5731c53..d0df068 100644 --- a/buffer.c +++ b/buffer.c @@ -28,30 +28,10 @@ #include "catacomb-python.h" -/*----- Data structures ---------------------------------------------------*/ - -typedef struct buf_pyobj { - PyObject_HEAD - buf b; - PyObject *sub; - unsigned lk; -} 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) -#define BUF_LK(o) (((buf_pyobj *)(o))->lk) - -/*----- Exceptions --------------------------------------------------------*/ - -static PyObject *buferr; - -#define BUFERR(str) do { PyErr_SetString(buferr, str); goto end; } while (0) - /*----- Read buffers ------------------------------------------------------*/ +PyTypeObject *rbuf_pytype; + static PyObject *rbuf_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw) { struct bin in; @@ -78,11 +58,18 @@ static void buf_pydealloc(PyObject *me) FREEOBJ(me); } -static Py_ssize_t rbuf_pysegcount(PyObject *me, Py_ssize_t *nn) - { if (nn) *nn = BSZ(BUF_B(me)); return (1); } - -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))); } +#ifdef PY3 + static int rbuf_pygetbuf(PyObject *me, Py_buffer *vw, int f) + { + buf *b = BUF_B(me); + return (PyBuffer_FillInfo(vw, me, BCUR(b), BLEFT(b), 1, f)); + } +#else + static Py_ssize_t rbuf_pysegcount(PyObject *me, Py_ssize_t *nn) + { if (nn) *nn = BSZ(BUF_B(me)); return (1); } + 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))); } +#endif static PyObject *rbmeth_skip(PyObject *me, PyObject *arg) { @@ -197,6 +184,22 @@ end: return (rc); } +static PyObject *rbmeth_os2ecp(PyObject *me, PyObject *arg, PyObject *kw) +{ + PyObject *cobj; + ec pt = EC_INIT; + unsigned f = EC_XONLY | EC_LSB | EC_SORT | EC_EXPLY; + PyObject *rc = 0; + static const char *const kwlist[] = { "curve", "flags", 0 }; + if (!PyArg_ParseTupleAndKeywords(arg, kw, "O!|O&:os2ecp", KWLIST, + eccurve_pytype, &cobj, convuint, &f)) + goto end; + if (ec_os2ecp(ECCURVE_C(cobj), f, BUF_B(me), &pt)) VALERR("bad point"); + rc = ecpt_pywrapout(cobj, &pt); +end: + return (rc); +} + static PyObject *rbmeth_getge(PyObject *me, PyObject *arg) { PyObject *gobj; @@ -270,6 +273,7 @@ static const PyMethodDef rbuf_pymethods[] = { NAMETH(getgf, "RBUF.getgf() -> X") KWMETH(getecpt, "RBUF.getecpt([curve = None]) -> P") METH (getecptraw, "RBUF.getecptraw(CURVE) -> P") + KWMETH(os2ecp, "RBUF.os2ecp(CURVE, [flags = ...]) -> P") METH (getge, "RBUF.getge(GROUP) -> X") METH (getgeraw, "RBUF.getgeraw(GROUP) -> X") #undef METHNAME @@ -277,10 +281,15 @@ static const PyMethodDef rbuf_pymethods[] = { }; static const PyBufferProcs rbuf_pybuffer = { +#ifdef PY3 + rbuf_pygetbuf, /* @bf_getbuffer@ */ + 0, /* @bf_releasebuffer@ */ +#else rbuf_pyreadbuf, /* @bf_getreadbuffer@ */ 0, /* @bf_getwritebuffer@ */ rbuf_pysegcount, /* @bf_getsegcount@ */ 0 /* @bf_getcharbuffer@ */ +#endif }; static const PyTypeObject rbuf_pytype_skel = { @@ -333,7 +342,9 @@ static const PyTypeObject rbuf_pytype_skel = { /*----- Write buffers -----------------------------------------------------*/ -static int ensure(PyObject *me, size_t n) +PyTypeObject *wbuf_pytype; + +int ensurebuf(PyObject *me, size_t n) { buf *b = BUF_B(me); size_t nn = BSZ(b); @@ -374,18 +385,28 @@ end: return ((PyObject *)me); } -static Py_ssize_t wbuf_pysegcount(PyObject *me, Py_ssize_t *nn) - { if (nn) *nn = BLEN(BUF_B(me)); return (1); } - -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))); } +#ifdef PY3 + static int wbuf_pygetbuf(PyObject *me, Py_buffer *vw, int f) + { + buf *b = BUF_B(me); + if (PyBuffer_FillInfo(vw, me, BBASE(b), BLEN(b), 0, f)) return (-1); + BUF_LK(me)++; return (0); + } + static void wbuf_pyrlsbuf(PyObject *me, Py_buffer *vw) + { BUF_LK(me)--; } +#else + static Py_ssize_t wbuf_pysegcount(PyObject *me, Py_ssize_t *nn) + { if (nn) *nn = BLEN(BUF_B(me)); return (1); } + 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))); } +#endif static PyObject *wbmeth_zero(PyObject *me, PyObject *arg) { void *p; size_t n; if (!PyArg_ParseTuple(arg, "O&:zero", convszt, &n)) return (0); - if (ensure(me, n)) return (0); + if (ensurebuf(me, n)) return (0); p = buf_get(BUF_B(me), n); assert(p && BOK(BUF_B(me))); memset(p, 0, n); RETURN_ME; @@ -395,7 +416,7 @@ static PyObject *wbmeth_put(PyObject *me, PyObject *arg) { struct bin in; if (!PyArg_ParseTuple(arg, "O&:put", convbin, &in)) return (0); - if (ensure(me, in.sz)) return (0); + if (ensurebuf(me, in.sz)) return (0); buf_put(BUF_B(me), in.p, in.sz); assert(BOK(BUF_B(me))); RETURN_ME; } @@ -405,7 +426,7 @@ static PyObject *wbmeth_put(PyObject *me, PyObject *arg) { \ uint##n i; \ if (!PyArg_ParseTuple(arg, "O&:putu" #w, convu##n, &i)) return (0); \ - if (ensure(me, SZ_##n)) return (0); \ + if (ensurebuf(me, SZ_##n)) return (0); \ buf_putu##w(BUF_B(me), i); assert(BOK(BUF_B(me))); \ RETURN_ME; \ } @@ -419,7 +440,7 @@ DOUINTCONV(WBMETH_PUTU_) struct bin in; \ if (!PyArg_ParseTuple(arg, "O&:putblk" #w, convbin, &in)) goto end; \ if (MASK##W && in.sz > MASK##W) VALERR("too large"); \ - if (ensure(me, in.sz + SZ_##n)) return (0); \ + if (ensurebuf(me, in.sz + SZ_##n)) return (0); \ buf_putmem##w(BUF_B(me), in.p, in.sz); assert(BOK(BUF_B(me))); \ RETURN_ME; \ end: \ @@ -431,7 +452,7 @@ static PyObject *wbmeth_putmp(PyObject *me, PyObject *arg) { mp *x = 0; if (!PyArg_ParseTuple(arg, "O&:putmp", convmp, &x)) return (0); - if (ensure(me, mp_octets(x) + 2)) return (0); + if (ensurebuf(me, mp_octets(x) + 2)) return (0); buf_putmp(BUF_B(me), x); assert(BOK(BUF_B(me))); RETURN_ME; } @@ -440,7 +461,7 @@ static PyObject *wbmeth_putgf(PyObject *me, PyObject *arg) { mp *x = 0; if (!PyArg_ParseTuple(arg, "O&:putgf", convgf, &x)) return (0); - if (ensure(me, mp_octets(x) + 2)) return (0); + if (ensurebuf(me, mp_octets(x) + 2)) return (0); buf_putmp(BUF_B(me), x); assert(BOK(BUF_B(me))); MP_DROP(x); RETURN_ME; @@ -450,7 +471,8 @@ static PyObject *wbmeth_putecpt(PyObject *me, PyObject *arg) { ec pt = EC_INIT; if (!PyArg_ParseTuple(arg, "O&:putecpt", convecpt, &pt)) return (0); - if (ensure(me, EC_ATINF(&pt) ? 2 : 6 + mp_octets(pt.x) + mp_octets(pt.y))) + if (ensurebuf(me, EC_ATINF(&pt) ? 2 : + 6 + mp_octets(pt.x) + mp_octets(pt.y))) return (0); buf_putec(BUF_B(me), &pt); assert(BOK(BUF_B(me))); EC_DESTROY(&pt); @@ -460,21 +482,42 @@ static PyObject *wbmeth_putecpt(PyObject *me, PyObject *arg) static PyObject *wbmeth_putecptraw(PyObject *me, PyObject *arg) { PyObject *ptobj; + ec_curve *cc; ec pt = EC_INIT; if (!PyArg_ParseTuple(arg, "O!:putecptraw", ecptcurve_pytype, &ptobj)) return (0); - EC_OUT(ECPT_C(ptobj), &pt, ECPT_P(ptobj)); - if (ensure(me, ECPT_C(ptobj)->f->noctets * 2 + 1)) return (0); - ec_putraw(ECPT_C(ptobj), BUF_B(me), &pt); assert(BOK(BUF_B(me))); + cc = ECPT_C(ptobj); + EC_OUT(cc, &pt, ECPT_P(ptobj)); + if (ensurebuf(me, 2*cc->f->noctets + 1)) return (0); + ec_putraw(cc, BUF_B(me), &pt); assert(BOK(BUF_B(me))); EC_DESTROY(&pt); RETURN_ME; } +static PyObject *wbmeth_ec2osp(PyObject *me, PyObject *arg, PyObject *kw) +{ + PyTypeObject *ptobj; + ec_curve *cc; + ec pt = EC_INIT; + unsigned f = EC_EXPLY; + static const char *const kwlist[] = { "point", "flags", 0 }; + if (!PyArg_ParseTupleAndKeywords(arg, kw, "O!|O&:os2ecp", KWLIST, + ecptcurve_pytype, &ptobj, convuint, &f)) + goto end; + cc = ECPT_C(ptobj); + EC_OUT(cc, &pt, ECPT_P(ptobj)); + if (ensurebuf(me, 2*cc->f->noctets + 1)) return (0); + if (ec_ec2osp(cc, f, BUF_B(me), &pt)) VALERR("invalid flags"); + RETURN_ME; +end: + return (0); +} + static PyObject *wbmeth_putge(PyObject *me, PyObject *arg) { PyObject *geobj; if (!PyArg_ParseTuple(arg, "O!:putge", ge_pytype, &geobj)) return (0); - if (ensure(me, GE_G(geobj)->noctets)) return (0); + if (ensurebuf(me, GE_G(geobj)->noctets)) return (0); G_TOBUF(GE_G(geobj), BUF_B(me), GE_X(geobj)); assert(BOK(BUF_B(me))); RETURN_ME; } @@ -483,7 +526,7 @@ static PyObject *wbmeth_putgeraw(PyObject *me, PyObject *arg) { PyObject *geobj; if (!PyArg_ParseTuple(arg, "O!:putgeraw", ge_pytype, &geobj)) return (0); - if (ensure(me, GE_G(geobj)->noctets)) return (0); + if (ensurebuf(me, GE_G(geobj)->noctets)) return (0); G_TORAW(GE_G(geobj), BUF_B(me), GE_X(geobj)); assert(BOK(BUF_B(me))); RETURN_ME; } @@ -516,6 +559,7 @@ static const PyMethodDef wbuf_pymethods[] = { METH (putgf, "WBUF.putgf(X)") METH (putecpt, "WBUF.putecpt(P)") METH (putecptraw, "WBUF.putecptraw(P)") + KWMETH(ec2osp, "WBUF.ec2osp(P, [flags = EC_EXPLY])") METH (putge, "WBUF.putge(X)") METH (putgeraw, "WBUF.putgeraw(X)") #undef METHNAME @@ -523,10 +567,15 @@ static const PyMethodDef wbuf_pymethods[] = { }; static const PyBufferProcs wbuf_pybuffer = { +#ifdef PY3 + wbuf_pygetbuf, /* @bf_getbuffer@ */ + wbuf_pyrlsbuf /* @bf_releasebuffer@ */ +#else wbuf_pyreadbuf, /* @bf_getreadbuffer@ */ 0, /* @bf_getwritebuffer@ */ wbuf_pysegcount, /* @bf_getsegcount@ */ 0 /* @bf_getcharbuffer@ */ +#endif }; static const PyTypeObject wbuf_pytype_skel = { @@ -579,6 +628,8 @@ static const PyTypeObject wbuf_pytype_skel = { /*----- Initialization ----------------------------------------------------*/ +PyObject *buferr; + void buffer_pyinit(void) { INITTYPE(rbuf, root);