X-Git-Url: https://git.distorted.org.uk/~mdw/catacomb-python/blobdiff_plain/b2687a0a4b3c5e45cad7c5815a6d3805bfc8d4f1..b4dbeed57af31ba6b03c3eda36168d36c26de954:/buffer.c diff --git a/buffer.c b/buffer.c index af4e1bf..d0df068 100644 --- a/buffer.c +++ b/buffer.c @@ -1,7 +1,5 @@ /* -*-c-*- * - * $Id$ - * * Reading and writing buffers of stuff * * (c) 2005 Straylight/Edgeware @@ -30,67 +28,55 @@ #include "catacomb-python.h" -/*----- Data structures ---------------------------------------------------*/ - -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 --------------------------------------------------------*/ - -static PyObject *buferr; - -#define BUFERR() do { PyErr_SetNone(buferr); goto end; } while (0) - /*----- Read buffers ------------------------------------------------------*/ +PyTypeObject *rbuf_pytype; + static PyObject *rbuf_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw) { - char *p, *q; - int n; + struct bin in; + void *q; buf_pyobj *me = 0; - static char *kwlist[] = { "data", 0 }; + static const char *const kwlist[] = { "data", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#:new", kwlist, &p, &n)) + if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&:new", KWLIST, convbin, &in)) goto end; - q = xmalloc(n); - memcpy(q, p, n); + q = xmalloc(in.sz); + memcpy(q, in.p, in.sz); me = (buf_pyobj *)ty->tp_alloc(ty, 0); - me->sub = 0; - buf_init(&me->b, q, n); + me->sub = 0; me->lk = 0; + buf_init(&me->b, q, in.sz); end: return ((PyObject *)me); } static void buf_pydealloc(PyObject *me) { - if (BUF_SUB(me)) - Py_DECREF(BUF_SUB(me)); - else - xfree(BBASE(BUF_B(me))); + assert(!BUF_LK(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) - { if (nn) *nn = BSZ(BUF_B(me)); return (1); } - -static int rbuf_pyreadbuf(PyObject *me, int 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) { size_t n; if (!PyArg_ParseTuple(arg, "O&:skip", convszt, &n)) goto end; - if (!buf_get(BUF_B(me), n)) BUFERR(); + if (!buf_get(BUF_B(me), n)) BUFERR("buffer exhausted"); RETURN_ME; end: return (0); @@ -102,31 +88,31 @@ static PyObject *rbmeth_get(PyObject *me, PyObject *arg) size_t n; if (!PyArg_ParseTuple(arg, "O&:get", convszt, &n)) goto end; - if ((p = buf_get(BUF_B(me), n)) == 0) BUFERR(); + if ((p = buf_get(BUF_B(me), n)) == 0) BUFERR("buffer exhausted"); return (bytestring_pywrap(p, n)); end: return (0); } #define RBMETH_GETU_(n, W, w) \ - static PyObject *rbmeth_getu##w(PyObject *me, PyObject *arg) \ + static PyObject *rbmeth_getu##w(PyObject *me) \ { \ uint##n x; \ - if (!PyArg_ParseTuple(arg, ":getu" #w)) goto end; \ - if (buf_getu##w(BUF_B(me), &x)) BUFERR(); \ - return (getulong(x)); \ + if (buf_getu##w(BUF_B(me), &x)) BUFERR("buffer exhausted"); \ + if (MASK##W <= ULONG_MAX) return (getulong(x)); \ + else { kludge64 y; ASSIGN64(y, x); return (getk64(y)); } \ end: \ return (0); \ } DOUINTCONV(RBMETH_GETU_) #define RBMETH_GETBLK_(n, W, w) \ - static PyObject *rbmeth_getblk##w(PyObject *me, PyObject *arg) \ + static PyObject *rbmeth_getblk##w(PyObject *me) \ { \ size_t sz; \ char *q; \ - if (!PyArg_ParseTuple(arg, ":getblk" #w)) goto end; \ - if ((q = buf_getmem##w(BUF_B(me), &sz)) == 0) BUFERR(); \ + if ((q = buf_getmem##w(BUF_B(me), &sz)) == 0) \ + BUFERR("buffer exhausted"); \ return (bytestring_pywrap(q, sz)); \ end: \ return (0); \ @@ -134,15 +120,15 @@ DOUINTCONV(RBMETH_GETU_) BUF_DOSUFFIXES(RBMETH_GETBLK_) #define RBMETH_GETBUF_(n, W, w) \ - static PyObject *rbmeth_getbuf##w(PyObject *me, PyObject *arg) \ + static PyObject *rbmeth_getbuf##w(PyObject *me) \ { \ buf_pyobj *b; \ buf bb; \ - if (!PyArg_ParseTuple(arg, ":getbuf" #w)) goto end; \ - if (buf_getbuf##w(BUF_B(me), &bb)) BUFERR(); \ + if (buf_getbuf##w(BUF_B(me), &bb)) BUFERR("buffer exhausted"); \ b = PyObject_NEW(buf_pyobj, rbuf_pytype); \ b->b = bb; \ b->sub = me; \ + b->lk = 0; \ Py_INCREF(me); \ return ((PyObject *)b); \ end: \ @@ -150,21 +136,19 @@ BUF_DOSUFFIXES(RBMETH_GETBLK_) } BUF_DOSUFFIXES(RBMETH_GETBUF_) -static PyObject *rbmeth_getmp(PyObject *me, PyObject *arg) +static PyObject *rbmeth_getmp(PyObject *me) { mp *x; - if (!PyArg_ParseTuple(arg, ":getmp")) goto end; - if ((x = buf_getmp(BUF_B(me))) == 0) BUFERR(); + if ((x = buf_getmp(BUF_B(me))) == 0) BUFERR("buffer exhausted"); return (mp_pywrap(x)); end: return (0); } -static PyObject *rbmeth_getgf(PyObject *me, PyObject *arg) +static PyObject *rbmeth_getgf(PyObject *me) { mp *x; - if (!PyArg_ParseTuple(arg, ":getgf")) goto end; - if ((x = buf_getmp(BUF_B(me))) == 0) BUFERR(); + if ((x = buf_getmp(BUF_B(me))) == 0) BUFERR("buffer exhausted"); return (gf_pywrap(x)); end: return (0); @@ -173,15 +157,15 @@ end: static PyObject *rbmeth_getecpt(PyObject *me, PyObject *arg, PyObject *kw) { PyObject *cobj = Py_None; - static char *kwlist[] = { "curve", 0 }; + static const char *const kwlist[] = { "curve", 0 }; ec pt = EC_INIT; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "|O:getecpt", kwlist, &cobj)) + if (!PyArg_ParseTupleAndKeywords(arg, kw, "|O:getecpt", KWLIST, &cobj)) goto end; if (cobj == Py_None) cobj = (PyObject *)ecpt_pytype; if (!PyType_Check(cobj) || !PyType_IsSubtype((PyTypeObject *)cobj, ecpt_pytype)) TYERR("expected elliptic curve type"); - if (buf_getec(BUF_B(me), &pt)) BUFERR(); + if (buf_getec(BUF_B(me), &pt)) BUFERR("buffer exhausted"); return (ecpt_pywrapout(cobj, &pt)); end: return (0); @@ -189,14 +173,31 @@ end: static PyObject *rbmeth_getecptraw(PyObject *me, PyObject *arg) { - PyTypeObject *cobj = ecpt_pytype; + PyObject *cobj; ec pt = EC_INIT; + PyObject *rc = 0; if (!PyArg_ParseTuple(arg, "O!:getecptraw", eccurve_pytype, &cobj)) goto end; - if (ec_getraw(ECCURVE_C(cobj), BUF_B(me), &pt)) BUFERR(); - return (ecpt_pywrapout(cobj, &pt)); + if (ec_getraw(ECCURVE_C(cobj), BUF_B(me), &pt)) BUFERR("buffer exhausted"); + rc = ecpt_pywrapout(cobj, &pt); end: - return (0); + 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) @@ -205,7 +206,7 @@ static PyObject *rbmeth_getge(PyObject *me, PyObject *arg) ge *x = 0; if (!PyArg_ParseTuple(arg, "O!:getge", group_pytype, &gobj)) goto end; x = G_CREATE(GROUP_G(gobj)); - if (G_FROMBUF(GROUP_G(gobj), BUF_B(me), x)) BUFERR(); + if (G_FROMBUF(GROUP_G(gobj), BUF_B(me), x)) BUFERR("buffer exhausted"); return (ge_pywrap(gobj, x)); end: if (x) G_DESTROY(GROUP_G(gobj), x); @@ -218,7 +219,7 @@ static PyObject *rbmeth_getgeraw(PyObject *me, PyObject *arg) ge *x = 0; if (!PyArg_ParseTuple(arg, "O!:getgeraw", group_pytype, &gobj)) goto end; x = G_CREATE(GROUP_G(gobj)); - if (G_FROMRAW(GROUP_G(gobj), BUF_B(me), x)) BUFERR(); + if (G_FROMRAW(GROUP_G(gobj), BUF_B(me), x)) BUFERR("buffer exhausted"); return (ge_pywrap(gobj, x)); end: if (x) G_DESTROY(GROUP_G(gobj), x); @@ -245,49 +246,55 @@ end: return (-1); } -static PyGetSetDef rbuf_pygetset[] = { +static const 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") + GET (size, "RBUF.size -> SIZE") + GET (left, "RBUF.left -> REMAINDER") + GET (endp, "RBUF.endp -> BOOL") + GETSET(offset, "RBUF.offset -> OFFSET") #undef GETSETNAME { 0 } }; -static PyMethodDef rbuf_pymethods[] = { +static const PyMethodDef rbuf_pymethods[] = { #define METHNAME(func) rbmeth_##func - METH (skip, "RBUF.skip(N)") - METH (get, "RBUF.get(N) -> BYTES") + METH (skip, "RBUF.skip(N)") + METH (get, "RBUF.get(N) -> BYTES") #define RBMETH_DECL_GETU_(n, W, w) \ - METH(getu##w, "RBUF.getu" #w "() -> INT") + NAMETH(getu##w, "RBUF.getu" #w "() -> INT") DOUINTCONV(RBMETH_DECL_GETU_) #define RBMETH_DECL_GETBLK_(n, W, w) \ - METH(getblk##w, "RBUF.getblk" #w "() -> INT") + NAMETH(getblk##w, "RBUF.getblk" #w "() -> BYTES") BUF_DOSUFFIXES(RBMETH_DECL_GETBLK_) #define RBMETH_DECL_GETBUF_(n, W, w) \ - METH(getbuf##w, "RBUF.getbuf" #w "() -> INT") + NAMETH(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") - METH (getecptraw, "RBUF.getecptraw(CURVE) -> P") - METH (getge, "RBUF.getge(GROUP) -> X") - METH (getgeraw, "RBUF.getgeraw(GROUP) -> X") + NAMETH(getmp, "RBUF.getmp() -> X") + 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 { 0 } }; -static PyBufferProcs rbuf_pybuffer = { +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 PyTypeObject rbuf_pytype_skel = { - PyObject_HEAD_INIT(0) 0, /* Header */ - "catacomb.ReadBuffer", /* @tp_name@ */ +static const PyTypeObject rbuf_pytype_skel = { + PyVarObject_HEAD_INIT(0, 0) /* Header */ + "ReadBuffer", /* @tp_name@ */ sizeof(buf_pyobj), /* @tp_basicsize@ */ 0, /* @tp_itemsize@ */ @@ -305,12 +312,12 @@ static PyTypeObject rbuf_pytype_skel = { 0, /* @tp_str@ */ 0, /* @tp_getattro@ */ 0, /* @tp_setattro@ */ - &rbuf_pybuffer, /* @tp_as_buffer@ */ + PYBUFFER(rbuf), /* @tp_as_buffer@ */ Py_TPFLAGS_DEFAULT | /* @tp_flags@ */ Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ - "A read buffer.", + "ReadBuffer(STR): a read buffer.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@ -318,9 +325,9 @@ static PyTypeObject rbuf_pytype_skel = { 0, /* @tp_weaklistoffset@ */ 0, /* @tp_iter@ */ 0, /* @tp_iternext@ */ - rbuf_pymethods, /* @tp_methods@ */ + PYMETHODS(rbuf), /* @tp_methods@ */ 0, /* @tp_members@ */ - rbuf_pygetset, /* @tp_getset@ */ + PYGETSET(rbuf), /* @tp_getset@ */ 0, /* @tp_base@ */ 0, /* @tp_dict@ */ 0, /* @tp_descr_get@ */ @@ -335,20 +342,29 @@ static PyTypeObject rbuf_pytype_skel = { /*----- Write buffers -----------------------------------------------------*/ -static void 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); + octet *p; + size_t want = BLEN(b) + n; - if (BLEFT(b) < n) { - size_t nn = BSZ(b); - octet *p; - size_t want = BLEFT(b) + n; + if (BLEFT(b) >= n) + return (0); + else if (BUF_LK(me)) + BUFERR("buffer locked"); + else { while (nn < want) nn <<= 1; p = xrealloc(BBASE(b), nn, BSZ(b)); BCUR(b) = p + BLEN(b); BLIM(b) = p + nn; BBASE(b) = p; + return (0); } +end: + return (-1); } static PyObject *wbuf_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw) @@ -356,31 +372,41 @@ static PyObject *wbuf_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw) char *p; size_t n = 64; buf_pyobj *me = 0; - static char *kwlist[] = { "size", 0 }; + static const char *const kwlist[] = { "size", 0 }; - if (!PyArg_ParseTupleAndKeywords(arg, kw, "|O&:new", kwlist, + if (!PyArg_ParseTupleAndKeywords(arg, kw, "|O&:new", KWLIST, convszt, &n)) goto end; me = (buf_pyobj *)ty->tp_alloc(ty, 0); p = xmalloc(n); - me->sub = 0; + me->sub = 0; me->lk = 0; buf_init(&me->b, p, n); end: return ((PyObject *)me); } -static int wbuf_pysegcount(PyObject *me, int *nn) - { if (nn) *nn = BLEN(BUF_B(me)); return (1); } - -static int wbuf_pyreadbuf(PyObject *me, int 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); - ensure(me, n); + 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; @@ -388,11 +414,10 @@ static PyObject *wbmeth_zero(PyObject *me, PyObject *arg) static PyObject *wbmeth_put(PyObject *me, PyObject *arg) { - void *p; - int 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))); + struct bin in; + if (!PyArg_ParseTuple(arg, "O&:put", convbin, &in)) 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; } @@ -401,22 +426,25 @@ static PyObject *wbmeth_put(PyObject *me, PyObject *arg) { \ uint##n i; \ if (!PyArg_ParseTuple(arg, "O&:putu" #w, convu##n, &i)) return (0); \ - ensure(me, SZ_##n); \ + if (ensurebuf(me, SZ_##n)) return (0); \ buf_putu##w(BUF_B(me), i); assert(BOK(BUF_B(me))); \ RETURN_ME; \ } 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); \ - ensure(me, sz + SZ_##n); \ - buf_putmem##w(BUF_B(me), p, sz); assert(BOK(BUF_B(me))); \ + 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 (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: \ + return (0); \ } BUF_DOSUFFIXES(WBMETH_PUTBLK_) @@ -424,7 +452,7 @@ static PyObject *wbmeth_putmp(PyObject *me, PyObject *arg) { mp *x = 0; if (!PyArg_ParseTuple(arg, "O&:putmp", convmp, &x)) return (0); - ensure(me, mp_octets(x) + 2); + if (ensurebuf(me, mp_octets(x) + 2)) return (0); buf_putmp(BUF_B(me), x); assert(BOK(BUF_B(me))); RETURN_ME; } @@ -433,7 +461,7 @@ static PyObject *wbmeth_putgf(PyObject *me, PyObject *arg) { mp *x = 0; if (!PyArg_ParseTuple(arg, "O&:putgf", convgf, &x)) return (0); - ensure(me, mp_octets(x) + 2); + 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; @@ -443,8 +471,9 @@ static PyObject *wbmeth_putecpt(PyObject *me, PyObject *arg) { ec pt = EC_INIT; if (!PyArg_ParseTuple(arg, "O&:putecpt", convecpt, &pt)) return (0); - if (EC_ATINF(&pt)) ensure(me, 2); - else ensure(me, 4 + 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); RETURN_ME; @@ -453,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)); - ensure(me, ECPT_C(ptobj)->f->noctets * 2 + 1); - 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); - ensure(me, GE_G(geobj)->noctets); + 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; } @@ -476,7 +526,7 @@ static PyObject *wbmeth_putgeraw(PyObject *me, PyObject *arg) { PyObject *geobj; if (!PyArg_ParseTuple(arg, "O!:putgeraw", ge_pytype, &geobj)) return (0); - ensure(me, GE_G(geobj)->noctets); + 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; } @@ -484,43 +534,53 @@ static PyObject *wbmeth_putgeraw(PyObject *me, PyObject *arg) static PyObject *wbget_size(PyObject *me, void *hunoz) { return (PyInt_FromLong(BLEN(BUF_B(me)))); } -static PyGetSetDef wbuf_pygetset[] = { +static PyObject *wbget_contents(PyObject *me, void *hunoz) + { return (bytestring_pywrap(BBASE(BUF_B(me)), BLEN(BUF_B(me)))); } + +static const PyGetSetDef wbuf_pygetset[] = { #define GETSETNAME(op, name) wb##op##_##name - GET (size, "WBUF.size -> SIZE") + GET (size, "WBUF.size -> SIZE") + GET (contents, "WBUF.contents -> STR") #undef GETSETNAME { 0 } }; -static PyMethodDef wbuf_pymethods[] = { +static const PyMethodDef wbuf_pymethods[] = { #define METHNAME(func) wbmeth_##func - METH (zero, "WBUF.skip(N)") - METH (put, "WBUF.put(BYTES)") + METH (zero, "WBUF.zero(N)") + METH (put, "WBUF.put(BYTES)") #define WBMETH_DECL_PUTU_(n, W, w) \ - METH(putu##w, "WBUF.putu" #w "(INT)") + METH(putu##w, "WBUF.putu" #w "(INT)") DOUINTCONV(WBMETH_DECL_PUTU_) #define WBMETH_DECL_PUTBLK_(n, W, w) \ - METH(putblk##w, "WBUF.putblk" #w "(BYTES)") + METH(putblk##w, "WBUF.putblk" #w "(BYTES)") BUF_DOSUFFIXES(WBMETH_DECL_PUTBLK_) - METH (putmp, "WBUF.putmp(X)") - METH (putgf, "WBUF.putgf(X)") - KWMETH(putecpt, "WBUF.putecpt(P)") - METH (putecptraw, "WBUF.putecptraw(P)") - METH (putge, "WBUF.putge(X)") - METH (putgeraw, "WBUF.putgeraw(X)") + METH (putmp, "WBUF.putmp(X)") + 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 { 0 } }; -static PyBufferProcs wbuf_pybuffer = { +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 PyTypeObject wbuf_pytype_skel = { - PyObject_HEAD_INIT(0) 0, /* Header */ - "catacomb.WriteBuffer", /* @tp_name@ */ +static const PyTypeObject wbuf_pytype_skel = { + PyVarObject_HEAD_INIT(0, 0) /* Header */ + "WriteBuffer", /* @tp_name@ */ sizeof(buf_pyobj), /* @tp_basicsize@ */ 0, /* @tp_itemsize@ */ @@ -538,12 +598,12 @@ static PyTypeObject wbuf_pytype_skel = { 0, /* @tp_str@ */ 0, /* @tp_getattro@ */ 0, /* @tp_setattro@ */ - &wbuf_pybuffer, /* @tp_as_buffer@ */ + PYBUFFER(wbuf), /* @tp_as_buffer@ */ Py_TPFLAGS_DEFAULT | /* @tp_flags@ */ Py_TPFLAGS_BASETYPE, /* @tp_doc@ */ - "A write buffer.", + "WriteBuffer([size = ?]): a write buffer.", 0, /* @tp_traverse@ */ 0, /* @tp_clear@ */ @@ -551,9 +611,9 @@ static PyTypeObject wbuf_pytype_skel = { 0, /* @tp_weaklistoffset@ */ 0, /* @tp_iter@ */ 0, /* @tp_iternext@ */ - wbuf_pymethods, /* @tp_methods@ */ + PYMETHODS(wbuf), /* @tp_methods@ */ 0, /* @tp_members@ */ - wbuf_pygetset, /* @tp_getset@ */ + PYGETSET(wbuf), /* @tp_getset@ */ 0, /* @tp_base@ */ 0, /* @tp_dict@ */ 0, /* @tp_descr_get@ */ @@ -568,6 +628,8 @@ static PyTypeObject wbuf_pytype_skel = { /*----- Initialization ----------------------------------------------------*/ +PyObject *buferr; + void buffer_pyinit(void) { INITTYPE(rbuf, root);