From 68ec53f32a22b0c38e3b7b53e03edf747c49e416 Mon Sep 17 00:00:00 2001 From: Mark Wooding Date: Sat, 28 Jan 2006 18:46:07 +0000 Subject: [PATCH] Reorganization: split out utilities; mapping methods * Move non-project-specific Python utilities into a separate file. They might conceivably find their way into a new project some day. * Implement the standard mapping methods generically (i.e., in terms of basic Python mapping operations). * Use the mapping methods for the various key-object-related mappings. * Start fixing setter functions for null values. --- catacomb-python.h | 102 ++++++--- catacomb.c | 255 ++------------------- util.c | 651 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 748 insertions(+), 260 deletions(-) create mode 100644 util.c diff --git a/catacomb-python.h b/catacomb-python.h index d71caa9..286dd9e 100644 --- a/catacomb-python.h +++ b/catacomb-python.h @@ -130,6 +130,7 @@ #define ZDIVERR(str) EXCERR(PyExc_ZeroDivisionError, str) #define SYNERR(str) EXCERR(PyExc_SyntaxError, str) #define SYSERR(str) EXCERR(PyExc_SystemError, str) +#define NIERR(str) EXCERR(PyExc_NotImplementedError, str) #define INDEXERR(idx) do { \ PyErr_SetObject(PyExc_KeyError, idx); \ goto end; \ @@ -200,6 +201,82 @@ MODULES(DO) #define FREEOBJ(obj) \ (((PyObject *)(obj))->ob_type->tp_free((PyObject *)(obj))) +#define GEN(func, base) \ + static PyObject *func(void) \ + { \ + PyObject *d = PyDict_New(); \ + PyObject *o; \ + int i; \ + \ + for (i = 0; g##base##tab[i]; i++) { \ + o = gc##base##_pywrap((/*unconst*/ gc##base *)g##base##tab[i]); \ + PyDict_SetItemString(d, \ + (/*unconst*/ char *)g##base##tab[i]->name, \ + o); \ + Py_DECREF(o); \ + } \ + return (d); \ + } + +struct nameval { const char *name; unsigned long value; }; +extern void setconstants(PyObject *, const struct nameval *); + +extern PyObject *mexp_common(PyObject *, PyObject *, size_t, + PyObject *(*id)(PyObject *), + int (*fill)(void *, PyObject *, + PyObject *, PyObject *), + PyObject *(*exp)(PyObject *, void *, int), + void (*drop)(void *)); + +extern int convulong(PyObject *, void *); +#define DECL_CONVU_(n) extern int convu##n(PyObject *, void *); +DOUINTSZ(DECL_CONVU_) +extern int convmpw(PyObject *, void *); +extern int convuint(PyObject *, void *); +extern int convszt(PyObject *, void *); +extern int convbool(PyObject *, void *); +extern PyObject *abstract_pynew(PyTypeObject *, PyObject *, PyObject *); +extern PyObject *getbool(int); +#define DECL_GETU_(n) extern PyObject *getu##n(uint##n); +DOUINTSZ(DECL_GETU_) +extern void *newtype(PyTypeObject *, const PyTypeObject *, const char *); + +extern PyObject * mkexc(PyObject *, PyObject *, const char *, PyMethodDef *); +extern PyTypeObject *inittype(PyTypeObject *); +extern void addmethods(const PyMethodDef *); +extern PyMethodDef *donemethods(void); + +/*----- Mapping methods ---------------------------------------------------*/ + +#define GMAP_METH(func, doc) { #func, gmapmeth_##func, METH_VARARGS, doc }, +#define GMAP_KWMETH(func, doc) \ + { #func, (PyCFunction)gmapmeth_##func, METH_VARARGS|METH_KEYWORDS, doc }, +#define GMAP_METHDECL(func, doc) \ + extern PyObject *gmapmeth_##func(PyObject *, PyObject *); +#define GMAP_KWMETHDECL(func, doc) \ + extern PyObject *gmapmeth_##func(PyObject *, PyObject *, PyObject *); + +#define GMAP_DOMETHODS(METH, KWMETH) \ + METH (has_key, "D.has_key(KEY) -> BOOL") \ + METH (keys, "D.keys() -> LIST") \ + METH (values, "D.values() -> LIST") \ + METH (items, "D.items() -> LIST") \ + METH (iterkeys, "D.iterkeys() -> ITER") \ + METH (itervalues, "D.itervalues() -> ITER") \ + METH (iteritems, "D.iteritems() -> ITER") \ + METH (clear, "D.clear()") \ + KWMETH(get, "D.get(KEY, [default = None]) -> VALUE") \ + KWMETH(setdefault, "D.setdefault(K, [default = None]) -> VALUE") \ + KWMETH(pop, "D.pop(KEY, [default = ]) -> VALUE") \ + METH (popitem, "D.popitem() -> (KEY, VALUE)") \ + METH (update, "D.update(MAP)") + +GMAP_DOMETHODS(GMAP_METHDECL, GMAP_KWMETHDECL) +#define GMAP_METHODS GMAP_DOMETHODS(GMAP_METH, GMAP_KWMETH) +extern int gmap_pysize(PyObject *); +extern PySequenceMethods gmap_pysequence; +extern PyMethodDef gmap_pymethods[]; + /*----- Bytestrings -------------------------------------------------------*/ PyTypeObject *bytestring_pyobj; @@ -502,31 +579,6 @@ extern int convpgev(PyObject *, void *); extern void droppgev(pgev *); extern void pgenerr(void); -/*----- Core utility functions --------------------------------------------*/ - -extern PyObject *mexp_common(PyObject *, PyObject *, size_t, - PyObject *(*id)(PyObject *), - int (*fill)(void *, PyObject *, - PyObject *, PyObject *), - PyObject *(*exp)(PyObject *, void *, int), - void (*drop)(void *)); - -extern int convulong(PyObject *, void *); -#define DECL_CONVU_(n) extern int convu##n(PyObject *, void *); -DOUINTSZ(DECL_CONVU_) -extern int convmpw(PyObject *, void *); -extern int convuint(PyObject *, void *); -extern int convszt(PyObject *, void *); -extern int convbool(PyObject *, void *); -extern PyObject *abstract_pynew(PyTypeObject *, PyObject *, PyObject *); -extern PyObject *getbool(int); -#define DECL_GETU_(n) extern PyObject *getu##n(uint##n); -DOUINTSZ(DECL_GETU_) -extern PyObject * mkexc(PyObject *, PyObject *, const char *, PyMethodDef *); -extern void *newtype(PyTypeObject *, const PyTypeObject *, const char *); -extern PyTypeObject *inittype(PyTypeObject *); -extern void addmethods(const PyMethodDef *); - /*----- That's all, folks -------------------------------------------------*/ #ifdef __cplusplus diff --git a/catacomb.c b/catacomb.c index 47a94dd..65d3985 100644 --- a/catacomb.c +++ b/catacomb.c @@ -32,142 +32,26 @@ /*----- Main code ---------------------------------------------------------*/ -static void setconstants(PyObject *mod) -{ - static const struct { const char *name; unsigned long value; } consts[] = { +static const struct nameval consts[] = { #define C(x) { #x, x } - C(FTY_PRIME), C(FTY_BINARY), - C(PGEN_PASS), C(PGEN_FAIL), C(PGEN_BEGIN), C(PGEN_TRY), C(PGEN_DONE), - C(PGEN_ABORT), - C(MPW_MAX), - C(PMODE_READ), C(PMODE_VERIFY), - C(KOPEN_READ), C(KOPEN_WRITE), C(KOPEN_NOFILE), - C(KEXP_FOREVER), C(KEXP_EXPIRE), - C(KF_ENCMASK), C(KENC_BINARY), C(KENC_MP), C(KENC_STRUCT), - C(KENC_ENCRYPT), C(KENC_STRING), C(KENC_EC), - C(KF_CATMASK), C(KCAT_SYMM), C(KCAT_PRIV), C(KCAT_PUB), C(KCAT_SHARE), - C(KF_NONSECRET), - C(KF_BURN), C(KF_OPT), + C(FTY_PRIME), C(FTY_BINARY), + C(PGEN_PASS), C(PGEN_FAIL), C(PGEN_BEGIN), C(PGEN_TRY), C(PGEN_DONE), + C(PGEN_ABORT), + C(MPW_MAX), + C(PMODE_READ), C(PMODE_VERIFY), + C(KOPEN_READ), C(KOPEN_WRITE), C(KOPEN_NOFILE), + C(KEXP_FOREVER), C(KEXP_EXPIRE), + C(KF_ENCMASK), C(KENC_BINARY), C(KENC_MP), C(KENC_STRUCT), + C(KENC_ENCRYPT), C(KENC_STRING), C(KENC_EC), + C(KF_CATMASK), C(KCAT_SYMM), C(KCAT_PRIV), C(KCAT_PUB), C(KCAT_SHARE), + C(KF_NONSECRET), + C(KF_BURN), C(KF_OPT), #define ENTRY(tag, val, str) C(KERR_##tag), - KEY_ERRORS(ENTRY) + KEY_ERRORS(ENTRY) #undef ENTRY #undef C - { 0 } - }; - int i; - PyObject *x; - - for (i = 0; consts[i].name; i++) { - if (consts[i].value > LONG_MAX) - x = PyLong_FromUnsignedLong(consts[i].value); - else - x = PyInt_FromLong(consts[i].value); - PyModule_AddObject(mod, (/*unconst*/ char *)consts[i].name, x); - } -} - -#define GETU_(n) \ - PyObject *getu##n(uint##n w) \ - { \ - if (w <= MASK##n) \ - return (PyInt_FromLong(w)); \ - else \ - return (PyLong_FromUnsignedLong(w)); \ - } -DOUINTSZ(GETU_) - -PyObject *getbool(int b) -{ - if (b) RETURN_TRUE; - else RETURN_FALSE; -} - -PyObject *abstract_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw) -{ - PyErr_SetString(PyExc_TypeError, "can't instantiate this class"); - return (0); -} - -int convulong(PyObject *o, void *pp) -{ - long i; - unsigned long *p = pp; - PyObject *t; - - if (PyInt_Check(o)) { - i = PyInt_AS_LONG(o); - if (i < 0) TYERR("must be nonnegative"); - *p = i; - } else { - if ((t = PyNumber_Long(o)) == 0) goto end; - *p = PyLong_AsUnsignedLong(t); - Py_DECREF(t); - if (PyErr_Occurred()) goto end; - } - return (1); -end: - return (0); -} - -#define CONVU_(n) \ - int convu##n(PyObject *o, void *pp) \ - { \ - unsigned long u; \ - uint##n *p = pp; \ - \ - if (!convulong(o, &u)) goto end; \ - if (u > MASK##n) TYERR("out of range"); \ - *p = u; \ - return (1); \ - end: \ - return (0); \ - } -DOUINTSZ(CONVU_) - -int convuint(PyObject *o, void *pp) -{ - unsigned long u; - unsigned *p = pp; - - if (!convulong(o, &u)) goto end; - if (u > UINT_MAX) TYERR("out of range"); - *p = u; - return (1); -end: - return (0); -} - -int convmpw(PyObject *o, void *pp) -{ - unsigned long u; - unsigned *p = pp; - - if (!convulong(o, &u)) goto end; - if (u > MPW_MAX) TYERR("out of range"); - *p = u; - return (1); -end: - return (0); -} - -int convszt(PyObject *o, void *pp) -{ - unsigned long u; - size_t *p = pp; - - if (!convulong(o, &u)) goto end; - if (u > ~(size_t)0) TYERR("out of range"); - *p = u; - return (1); -end: - return (0); -} - -int convbool(PyObject *o, void *pp) -{ - *(int *)pp = PyObject_IsTrue(o); - return (1); -} + { 0 } +}; PyObject *mexp_common(PyObject *me, PyObject *arg, size_t efsz, @@ -235,96 +119,6 @@ end: return (z); } -PyObject * mkexc(PyObject *mod, PyObject *base, - const char *name, PyMethodDef *mm) -{ - PyObject *nameobj = 0; - PyObject *dict = 0; - PyObject *exc = 0; - PyObject *func = 0; - PyObject *meth = 0; - - if ((nameobj = PyString_FromFormat("%s.%s", - PyModule_GetName(mod), - name)) == 0 || - (dict = PyDict_New()) == 0 || - (exc = PyErr_NewException(PyString_AS_STRING(nameobj), - base, dict)) == 0) - goto fail; - - if (mm) { - while (mm->ml_name) { - if ((func = PyCFunction_NewEx(mm, 0, mod)) == 0 || - (meth = PyMethod_New(func, 0, exc)) == 0 || - PyDict_SetItemString(dict, mm->ml_name, meth)) - goto fail; - Py_DECREF(func); func = 0; - Py_DECREF(meth); meth = 0; - mm++; - } - } - -done: - Py_XDECREF(nameobj); - Py_XDECREF(dict); - return (exc); - -fail: - Py_XDECREF(exc); - Py_XDECREF(func); - Py_XDECREF(meth); - exc = 0; - goto done; -} - -DA_DECL(method_v, PyMethodDef); -static method_v global_pymethods = DA_INIT; -void addmethods(const PyMethodDef *m) -{ - size_t n; - - for (n = 0; m[n].ml_name; n++); - DA_ENSURE(&global_pymethods, n); - memcpy(DA(&global_pymethods) + DA_LEN(&global_pymethods), - m, n * sizeof(*m)); - DA_EXTEND(&global_pymethods, n); -} - -static const PyTypeObject emptytype = { 0 }; - -void *newtype(PyTypeObject *metaty, - const PyTypeObject *skel, - const char *name) -{ - PyHeapTypeObject *ty = - (PyHeapTypeObject *)_PyObject_GC_Malloc(_PyObject_VAR_SIZE(metaty, 0)); - if (!skel) skel = &emptytype; - memcpy(ty, skel, sizeof(*skel)); - if (ty->type.tp_base) Py_INCREF(ty->type.tp_base); -#define COPY(blah) do { \ - if (ty->type.tp_as_##blah) { \ - memcpy(&ty->as_##blah, \ - ty->type.tp_as_##blah, \ - sizeof(ty->as_##blah)); \ - ty->type.tp_as_##blah = &ty->as_##blah; \ - } \ - } while (0) - COPY(number); - COPY(sequence); - COPY(mapping); - COPY(buffer); -#undef COPY - if (name) - ty->name = PyString_FromString(name); - else if (ty->type.tp_name) - ty->name = PyString_FromString(ty->type.tp_name); - if (ty->name) - ty->type.tp_name = PyString_AS_STRING(ty->name); - PyObject_INIT(&ty->type, metaty); - Py_INCREF(metaty); - return (ty); -} - static PyObject *smallprimes(void) { PyObject *v = PyList_New(NPRIME); @@ -335,14 +129,6 @@ static PyObject *smallprimes(void) return (v); } -PyTypeObject *inittype(PyTypeObject *tyskel) -{ - PyTypeObject *ty = newtype(&PyType_Type, tyskel, 0); - ty->tp_flags |= Py_TPFLAGS_HEAPTYPE; - PyType_Ready(ty); - return (ty); -} - static PyObject *meth__ego(PyObject *me, PyObject *arg) { char *argv0; @@ -360,16 +146,15 @@ static PyMethodDef methods[] = { { 0 } }; -void init_base(void) { - static const PyMethodDef mzero = { 0 }; +void init_base(void) +{ PyObject *mod; addmethods(methods); INIT_MODULES; - DA_PUSH(&global_pymethods, mzero); - mod = Py_InitModule("catacomb._base", DA(&global_pymethods)); + mod = Py_InitModule("catacomb._base", donemethods()); INSERT_MODULES; INSERT("smallprimes", smallprimes()); - setconstants(mod); + setconstants(mod, consts); } /*----- That's all, folks -------------------------------------------------*/ diff --git a/util.c b/util.c new file mode 100644 index 0000000..86b7aba --- /dev/null +++ b/util.c @@ -0,0 +1,651 @@ +/* -*-c-*- + * + * $Id$ + * + * Miscellaneous utilities (not Catacomb-specific) + * + * (c) 2005 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of the Python interface to Catacomb. + * + * Catacomb/Python is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Catacomb/Python is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Catacomb/Python; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "catacomb-python.h" + +/*----- Conversions -------------------------------------------------------*/ + +#define GETU_(n) \ + PyObject *getu##n(uint##n w) \ + { \ + if (w <= MASK##n) \ + return (PyInt_FromLong(w)); \ + else \ + return (PyLong_FromUnsignedLong(w)); \ + } +DOUINTSZ(GETU_) + +PyObject *getbool(int b) +{ + if (b) RETURN_TRUE; + else RETURN_FALSE; +} + +PyObject *abstract_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw) +{ + PyErr_SetString(PyExc_TypeError, "can't instantiate this class"); + return (0); +} + +int convulong(PyObject *o, void *pp) +{ + long i; + unsigned long *p = pp; + PyObject *t; + + if (PyInt_Check(o)) { + i = PyInt_AS_LONG(o); + if (i < 0) TYERR("must be nonnegative"); + *p = i; + } else { + if ((t = PyNumber_Long(o)) == 0) goto end; + *p = PyLong_AsUnsignedLong(t); + Py_DECREF(t); + if (PyErr_Occurred()) goto end; + } + return (1); +end: + return (0); +} + +#define CONVU_(n) \ + int convu##n(PyObject *o, void *pp) \ + { \ + unsigned long u; \ + uint##n *p = pp; \ + \ + if (!convulong(o, &u)) goto end; \ + if (u > MASK##n) TYERR("out of range"); \ + *p = u; \ + return (1); \ + end: \ + return (0); \ + } +DOUINTSZ(CONVU_) + +int convuint(PyObject *o, void *pp) +{ + unsigned long u; + unsigned *p = pp; + + if (!convulong(o, &u)) goto end; + if (u > UINT_MAX) TYERR("out of range"); + *p = u; + return (1); +end: + return (0); +} + +int convmpw(PyObject *o, void *pp) +{ + unsigned long u; + unsigned *p = pp; + + if (!convulong(o, &u)) goto end; + if (u > MPW_MAX) TYERR("out of range"); + *p = u; + return (1); +end: + return (0); +} + +int convszt(PyObject *o, void *pp) +{ + unsigned long u; + size_t *p = pp; + + if (!convulong(o, &u)) goto end; + if (u > ~(size_t)0) TYERR("out of range"); + *p = u; + return (1); +end: + return (0); +} + +int convbool(PyObject *o, void *pp) +{ + *(int *)pp = PyObject_IsTrue(o); + return (1); +} + +/*----- Type messing ------------------------------------------------------*/ + +static const PyTypeObject emptytype = { 0 }; + +void *newtype(PyTypeObject *metaty, + const PyTypeObject *skel, + const char *name) +{ + PyHeapTypeObject *ty = + (PyHeapTypeObject *)_PyObject_GC_Malloc(_PyObject_VAR_SIZE(metaty, 0)); + if (!skel) skel = &emptytype; + memcpy(ty, skel, sizeof(*skel)); + if (ty->type.tp_base) Py_INCREF(ty->type.tp_base); +#define COPY(blah) do { \ + if (ty->type.tp_as_##blah) { \ + memcpy(&ty->as_##blah, \ + ty->type.tp_as_##blah, \ + sizeof(ty->as_##blah)); \ + ty->type.tp_as_##blah = &ty->as_##blah; \ + } \ + } while (0) + COPY(number); + COPY(sequence); + COPY(mapping); + COPY(buffer); +#undef COPY + if (name) + ty->name = PyString_FromString(name); + else if (ty->type.tp_name) + ty->name = PyString_FromString(ty->type.tp_name); + if (ty->name) + ty->type.tp_name = PyString_AS_STRING(ty->name); + PyObject_INIT(&ty->type, metaty); + Py_INCREF(metaty); + return (ty); +} + +PyTypeObject *inittype(PyTypeObject *tyskel) +{ + PyTypeObject *ty = newtype(&PyType_Type, tyskel, 0); + ty->tp_flags |= Py_TPFLAGS_HEAPTYPE; + PyType_Ready(ty); + return (ty); +} + +/*----- Constants ---------------------------------------------------------*/ + +void setconstants(PyObject *mod, const struct nameval *c) +{ + PyObject *x; + + while (c->name) { + if (c->value > LONG_MAX) + x = PyLong_FromUnsignedLong(c->value); + else + x = PyInt_FromLong(c->value); + PyModule_AddObject(mod, (/*unconst*/ char *)c->name, x); + c++; + } +} + +/*----- Building method tables --------------------------------------------*/ + +DA_DECL(method_v, PyMethodDef); +static method_v global_pymethods = DA_INIT; +void addmethods(const PyMethodDef *m) +{ + size_t n; + + for (n = 0; m[n].ml_name; n++); + DA_ENSURE(&global_pymethods, n); + memcpy(DA(&global_pymethods) + DA_LEN(&global_pymethods), + m, n * sizeof(*m)); + DA_EXTEND(&global_pymethods, n); +} + +PyMethodDef *donemethods(void) +{ + static const PyMethodDef mzero = { 0 }; + DA_PUSH(&global_pymethods, mzero); + return (DA(&global_pymethods)); +} + +/*----- Exceptions --------------------------------------------------------*/ + +PyObject * mkexc(PyObject *mod, PyObject *base, + const char *name, PyMethodDef *mm) +{ + PyObject *nameobj = 0; + PyObject *dict = 0; + PyObject *exc = 0; + PyObject *func = 0; + PyObject *meth = 0; + + if ((nameobj = PyString_FromFormat("%s.%s", + PyModule_GetName(mod), + name)) == 0 || + (dict = PyDict_New()) == 0 || + (exc = PyErr_NewException(PyString_AS_STRING(nameobj), + base, dict)) == 0) + goto fail; + + if (mm) { + while (mm->ml_name) { + if ((func = PyCFunction_NewEx(mm, 0, mod)) == 0 || + (meth = PyMethod_New(func, 0, exc)) == 0 || + PyDict_SetItemString(dict, mm->ml_name, meth)) + goto fail; + Py_DECREF(func); func = 0; + Py_DECREF(meth); meth = 0; + mm++; + } + } + +done: + Py_XDECREF(nameobj); + Py_XDECREF(dict); + return (exc); + +fail: + Py_XDECREF(exc); + Py_XDECREF(func); + Py_XDECREF(meth); + exc = 0; + goto done; +} + +/*----- Generic dictionary methods ----------------------------------------*/ + +static PyTypeObject *itemiter_pytype, *valiter_pytype; + +typedef struct iter_pyobj { + PyObject_HEAD + PyObject *map; + PyObject *i; +} iter_pyobj; +#define ITER_MAP(o) (((iter_pyobj *)(o))->map) +#define ITER_I(o) (((iter_pyobj *)(o))->i) + +static void iter_pydealloc(PyObject *me) + { Py_DECREF(ITER_MAP(me)); Py_DECREF(ITER_I(me)); FREEOBJ(me); } + +static PyObject *itemiter_pynext(PyObject *me) +{ + PyObject *k = 0, *v = 0, *rc = 0; + + if ((k = PyIter_Next(ITER_I(me))) != 0 && + (v = PyObject_GetItem(ITER_MAP(me), k)) != 0) + rc = Py_BuildValue("(OO)", k, v); + Py_XDECREF(k); Py_XDECREF(v); + return (rc); +} + +static PyTypeObject itemiter_pytype_skel = { + PyObject_HEAD_INIT(0) 0, /* Header */ + "ItemIter", /* @tp_name@ */ + sizeof(iter_pyobj), /* @tp_basicsize@ */ + 0, /* @tp_itemsize@ */ + + iter_pydealloc, /* @tp_dealloc@ */ + 0, /* @tp_print@ */ + 0, /* @tp_getattr@ */ + 0, /* @tp_setattr@ */ + 0, /* @tp_compare@ */ + 0, /* @tp_repr@ */ + 0, /* @tp_as_number@ */ + 0, /* @tp_as_sequence@ */ + 0, /* @tp_as_mapping@ */ + 0, /* @tp_hash@ */ + 0, /* @tp_call@ */ + 0, /* @tp_str@ */ + 0, /* @tp_getattro@ */ + 0, /* @tp_setattro@ */ + 0, /* @tp_as_buffer@ */ + Py_TPFLAGS_DEFAULT | /* @tp_flags@ */ + Py_TPFLAGS_BASETYPE, + + /* @tp_doc@ */ +"Iterates over the items of a mapping.", + + 0, /* @tp_traverse@ */ + 0, /* @tp_clear@ */ + 0, /* @tp_richcompare@ */ + 0, /* @tp_weaklistoffset@ */ + PyObject_SelfIter, /* @tp_iter@ */ + itemiter_pynext, /* @tp_iternext@ */ + 0, /* @tp_methods@ */ + 0, /* @tp_members@ */ + 0, /* @tp_getset@ */ + 0, /* @tp_base@ */ + 0, /* @tp_dict@ */ + 0, /* @tp_descr_get@ */ + 0, /* @tp_descr_set@ */ + 0, /* @tp_dictoffset@ */ + 0, /* @tp_init@ */ + PyType_GenericAlloc, /* @tp_alloc@ */ + abstract_pynew, /* @tp_new@ */ + 0, /* @tp_free@ */ + 0 /* @tp_is_gc@ */ +}; + +static PyObject *valiter_pynext(PyObject *me) +{ + PyObject *k = 0, *rc = 0; + + if ((k = PyIter_Next(ITER_I(me))) != 0) + rc = PyObject_GetItem(ITER_MAP(me), k); + Py_XDECREF(k); + return (rc); +} + +static PyTypeObject valiter_pytype_skel = { + PyObject_HEAD_INIT(0) 0, /* Header */ + "ValueIter", /* @tp_name@ */ + sizeof(iter_pyobj), /* @tp_basicsize@ */ + 0, /* @tp_itemsize@ */ + + iter_pydealloc, /* @tp_dealloc@ */ + 0, /* @tp_print@ */ + 0, /* @tp_getattr@ */ + 0, /* @tp_setattr@ */ + 0, /* @tp_compare@ */ + 0, /* @tp_repr@ */ + 0, /* @tp_as_number@ */ + 0, /* @tp_as_sequence@ */ + 0, /* @tp_as_mapping@ */ + 0, /* @tp_hash@ */ + 0, /* @tp_call@ */ + 0, /* @tp_str@ */ + 0, /* @tp_getattro@ */ + 0, /* @tp_setattro@ */ + 0, /* @tp_as_buffer@ */ + Py_TPFLAGS_DEFAULT | /* @tp_flags@ */ + Py_TPFLAGS_BASETYPE, + + /* @tp_doc@ */ +"Iterates over the items of a mapping.", + + 0, /* @tp_traverse@ */ + 0, /* @tp_clear@ */ + 0, /* @tp_richcompare@ */ + 0, /* @tp_weaklistoffset@ */ + PyObject_SelfIter, /* @tp_iter@ */ + valiter_pynext, /* @tp_iternext@ */ + 0, /* @tp_methods@ */ + 0, /* @tp_members@ */ + 0, /* @tp_getset@ */ + 0, /* @tp_base@ */ + 0, /* @tp_dict@ */ + 0, /* @tp_descr_get@ */ + 0, /* @tp_descr_set@ */ + 0, /* @tp_dictoffset@ */ + 0, /* @tp_init@ */ + PyType_GenericAlloc, /* @tp_alloc@ */ + abstract_pynew, /* @tp_new@ */ + 0, /* @tp_free@ */ + 0 /* @tp_is_gc@ */ +}; + +PySequenceMethods gmap_pysequence = { + 0, /* @sq_length@ */ + 0, /* @sq_concat@ */ + 0, /* @sq_repeat@ */ + 0, /* @sq_item@ */ + 0, /* @sq_slice@ */ + 0, /* @sq_ass_item@ */ + 0, /* @sq_ass_slice@ */ + PyMapping_HasKey, /* @sq_contains@ */ + 0, /* @sq_inplace_concat@ */ + 0 /* @sq_inplace_repeat@ */ +}; + +int gmap_pysize(PyObject *me) +{ + PyObject *i = 0, *x = 0; + int rc = -1; + int n = 0; + + if ((i = PyObject_GetIter(me)) == 0) goto done; + while ((x = PyIter_Next(i)) != 0) { n++; Py_DECREF(x); x = 0; } + if (PyErr_Occurred()) goto done; + rc = n; +done: + Py_XDECREF(i); Py_XDECREF(x); + return (rc); +} + +PyObject *gmapmeth_has_key(PyObject *me, PyObject *arg) +{ + PyObject *k; + if (!PyArg_ParseTuple(arg, "O:has_key", &k)) return (0); + return (getbool(PyMapping_HasKey(me, k))); +} + +PyObject *gmapmeth_keys(PyObject *me, PyObject *arg) +{ + PyObject *l = 0, *i = 0, *k, *rc = 0; + int err; + + if (!PyArg_ParseTuple(arg, ":keys") || + (l = PyList_New(0)) == 0 || + (i = PyObject_GetIter(me)) == 0) + goto done; + while ((k = PyIter_Next(i)) != 0) + { err = PyList_Append(l, k); Py_DECREF(k); if (err) goto done; } + if (PyErr_Occurred()) goto done; + rc = l; l = 0; +done: + Py_XDECREF(l); Py_XDECREF(i); + return (rc); +} + +PyObject *gmapmeth_values(PyObject *me, PyObject *arg) +{ + PyObject *l = 0, *i = 0, *k, *v, *rc = 0; + int err = 0; + + if (!PyArg_ParseTuple(arg, ":values") || + (l = PyList_New(0)) == 0 || + (i = PyObject_GetIter(me)) == 0) + goto done; + while ((k = PyIter_Next(i)) != 0) { + if ((v = PyObject_GetItem(me, k)) == 0 || + PyList_Append(l, v)) + err = -1; + Py_DECREF(k); Py_XDECREF(v); + if (err) goto done; + } + if (PyErr_Occurred()) goto done; + rc = l; l = 0; +done: + Py_XDECREF(l); Py_XDECREF(i); + return (rc); +} + +PyObject *gmapmeth_items(PyObject *me, PyObject *arg) +{ + PyObject *l = 0, *i = 0, *k, *v, *z, *rc = 0; + int err = 0; + + if (!PyArg_ParseTuple(arg, ":items") || + (l = PyList_New(0)) == 0 || + (i = PyObject_GetIter(me)) == 0) + goto done; + while ((k = PyIter_Next(i)) != 0) { + z = 0; + if ((v = PyObject_GetItem(me, k)) == 0 || + (z = Py_BuildValue("(OO)", k, v)) == 0 || + PyList_Append(l, z)) + err = -1; + Py_DECREF(k); Py_XDECREF(v); Py_XDECREF(z); + if (err) goto done; + } + if (PyErr_Occurred()) goto done; + rc = l; l = 0; +done: + Py_XDECREF(l); Py_XDECREF(i); + return (rc); +} + +PyObject *gmapmeth_iterkeys(PyObject *me, PyObject *arg) +{ + if (!PyArg_ParseTuple(arg, ":iterkeys")) return (0); + return (PyObject_GetIter(me)); +} + +PyObject *gmapmeth_itervalues(PyObject *me, PyObject *arg) +{ + PyObject *i; + iter_pyobj *ii; + + if (!PyArg_ParseTuple(arg, ":itervalues") || + (i = PyObject_GetIter(me)) == 0) + return (0); + ii = PyObject_NEW(iter_pyobj, valiter_pytype); + ii->map = me; Py_INCREF(me); + ii->i = i; + return ((PyObject *)ii); +} + +PyObject *gmapmeth_iteritems(PyObject *me, PyObject *arg) +{ + PyObject *i; + iter_pyobj *ii; + + if (!PyArg_ParseTuple(arg, ":iteritems") || + (i = PyObject_GetIter(me)) == 0) + return (0); + ii = PyObject_NEW(iter_pyobj, itemiter_pytype); + ii->map = me; Py_INCREF(me); + ii->i = i; + return ((PyObject *)ii); +} + +PyObject *gmapmeth_clear(PyObject *me, PyObject *arg) +{ + PyObject *i = 0, *k = 0, *rc = 0; + + if (!PyArg_ParseTuple(arg, ":clear") || + (i = PyObject_GetIter(me)) == 0) + goto end; + while ((k = PyIter_Next(i)) != 0) { + PyObject_DelItem(me, k); + Py_DECREF(k); + } + if (PyErr_Occurred()) goto end; + rc = me; Py_INCREF(me); +end: + Py_XDECREF(i); + return (rc); +} + +static char *def_kwlist[] = { "key", "default", 0 }; + +PyObject *gmapmeth_get(PyObject *me, PyObject *arg, PyObject *kw) +{ + PyObject *k, *def = Py_None, *v; + + if (!PyArg_ParseTupleAndKeywords(arg, kw, "OO:get", def_kwlist, &k, &def)) + return (0); + if ((v = PyObject_GetItem(me, k)) != 0) return (v); + PyErr_Clear(); + RETURN_OBJ(def); +} + +PyObject *gmapmeth_setdefault(PyObject *me, PyObject *arg, PyObject *kw) +{ + PyObject *k, *def = Py_None, *v; + + if (!PyArg_ParseTupleAndKeywords(arg, kw, "OO:setdefault", + def_kwlist, &k, &def)) + return (0); + if ((v = PyObject_GetItem(me, k)) != 0) return (v); + PyErr_Clear(); + if (PyObject_SetItem(me, k, def)) return (0); + RETURN_OBJ(def); +} + +PyObject *gmapmeth_pop(PyObject *me, PyObject *arg, PyObject *kw) +{ + PyObject *k, *def = 0, *v; + + if (!PyArg_ParseTupleAndKeywords(arg, kw, "OO:pop", def_kwlist, &k, &def)) + return (0); + if ((v = PyObject_GetItem(me, k)) != 0) { + PyObject_DelItem(me, k); + return (v); + } + PyErr_Clear(); + RETURN_OBJ(def); +} + +PyObject *gmapmeth_update(PyObject *me, PyObject *arg) +{ + PyObject *map, *i = 0, *k, *v, *rc = 0; + int err = 0; + + if (!PyArg_ParseTuple(arg, "O:update", &map) || + (i = PyObject_GetIter(map)) == 0) + goto end; + while ((k = PyIter_Next(i)) != 0) { + if ((v = PyObject_GetItem(map, k)) == 0 || + PyObject_SetItem(me, k, v)) + err = -1; + Py_DECREF(k); Py_XDECREF(v); + if (err) goto end; + } + if (PyErr_Occurred()) goto end; + rc = me; Py_INCREF(me); +end: + Py_XDECREF(i); + return (rc); +} + +PyObject *gmapmeth_popitem(PyObject *me, PyObject *arg) +{ + PyObject *i = 0, *k = 0, *v = 0, *rc = 0; + + if (!PyArg_ParseTuple(arg, ":popitem") || + (i = PyObject_GetIter(me))) + goto end; + if ((k = PyIter_Next(i)) == 0) { + if (!PyErr_Occurred()) VALERR("popitem(): mapping is empty"); + goto end; + } + if ((v = PyObject_GetItem(me, k)) == 0 || + PyObject_DelItem(me, k)) + goto end; + rc = Py_BuildValue("(OO)", k, v); +end: + Py_XDECREF(i); Py_XDECREF(k); Py_XDECREF(v); + return (rc); +} + +PyMethodDef gmap_pymethods[] = { + GMAP_METHODS + { 0 } +}; + +/*----- Initialization ----------------------------------------------------*/ + +void util_init(void) +{ + INITTYPE(itemiter, root); + INITTYPE(valiter, root); +} + +void util_insert(PyObject *mod) +{ + INSERT("ItemIter", itemiter_pytype); + INSERT("ValueIter", valiter_pytype); +} + +/*----- That's all, folks -------------------------------------------------*/ -- 2.11.0