X-Git-Url: https://git.distorted.org.uk/~mdw/pyke/blobdiff_plain/138563a571351c06c09fba7c6ed3d1f79fdd974d..4509276e7147042c753ec7180d1dd8e1f5923906:/pyke.h diff --git a/pyke.h b/pyke.h index e7a1ece..e6d465e 100644 --- a/pyke.h +++ b/pyke.h @@ -62,6 +62,18 @@ PRIVATE_SYMBOLS; +/*----- Python version compatibility hacks --------------------------------*/ + +/* The handy `Py_TYPE' and `Py_SIZE' macros turned up in 2.6. Define them if + * they're not already here. + */ +#ifndef Py_TYPE +# define Py_TYPE(obj) (((PyObject *)(obj))->ob_type) +#endif +#ifndef Py_SIZE +# define Py_SIZE(obj) (((PyVarObject *)(obj))->ob_size) +#endif + /*----- Utilities for returning values and exceptions ---------------------*/ /* Returning values. */ @@ -153,8 +165,7 @@ extern PyObject *getulong(unsigned long); /* any kind of unsigned integer */ /*----- Miscellaneous utilities -------------------------------------------*/ -#define FREEOBJ(obj) \ - (((PyObject *)(obj))->ob_type->tp_free((PyObject *)(obj))) +#define FREEOBJ(obj) (Py_TYPE(obj)->tp_free((PyObject *)(obj))) /* Actually free OBJ, e.g., in a deallocation function. */ extern PyObject *abstract_pynew(PyTypeObject *, PyObject *, PyObject *); @@ -208,11 +219,11 @@ extern void *newtype(PyTypeObject */*meta*/, extern void typeready(PyTypeObject *); /* The type object is now ready to be used. */ -extern PyTypeObject *inittype(PyTypeObject */*skel*/, +extern PyTypeObject *inittype(const PyTypeObject */*skel*/, + PyTypeObject */*base*/, PyTypeObject */*meta*/); /* All-in-one function to construct a working type from a type skeleton - * SKEL, with metaclass META. The caller is expected to have filled in the - * direct superclass in SKEL->tp_base. + * SKEL, with known base type BASE (null for `object') and metaclass. */ /* Alias for built-in types, to fit in with Pyke naming conventions. */ @@ -220,8 +231,7 @@ extern PyTypeObject *inittype(PyTypeObject */*skel*/, #define type_pytype &PyType_Type #define INITTYPE_META(ty, base, meta) do { \ - ty##_pytype_skel.tp_base = base##_pytype; \ - ty##_pytype = inittype(&ty##_pytype_skel, meta##_pytype); \ + ty##_pytype = inittype(&ty##_pytype_skel, base##_pytype, meta##_pytype); \ } while (0) #define INITTYPE(ty, base) INITTYPE_META(ty, base, type) /* Macros to initialize a type from its skeleton. */ @@ -271,15 +281,16 @@ extern PyTypeObject *inittype(PyTypeObject */*skel*/, #define GETSET(func, doc) \ { #func, GETSETNAME(get, func), GETSETNAME(set, func), doc }, -/* Convenience wrapper for filling in `PyMemberDef' tables. Define +/* Convenience wrappers for filling in `PyMemberDef' tables. Define * `MEMBERSTRUCT' locally as * * #define MEMBERSTRUCT foo_pyobj * * around the member table. */ -#define MEMBER(name, ty, f, doc) \ - { #name, ty, offsetof(MEMBERSTRUCT, name), f, doc }, +#define MEMRNM(name, ty, mem, f, doc) \ + { #name, ty, offsetof(MEMBERSTRUCT, mem), f, doc }, +#define MEMBER(name, ty, f, doc) MEMRNM(name, ty, name, f, doc) /* Wrappers for filling in pointers in a `PyTypeObject' structure, (a) * following Pyke naming convention, and (b) stripping `const' from the types @@ -321,6 +332,8 @@ extern PyObject *mkexc(PyObject */*mod*/, PyObject */*base*/, struct nameval { const char *name; unsigned f; unsigned long value; }; #define CF_SIGNED 1u extern void setconstants(PyObject *, const struct nameval *); +#define CONST(x) { #x, (x) >= 0 ? 0 : CF_SIGNED, x } +#define CONSTFLAG(f, x) { #x, f, x } #define INSEXC(name, var, base, meth) \ INSERT(name, var = mkexc(mod, base, name, meth)) @@ -369,6 +382,55 @@ extern PyMethodDef *donemethods(void); /*----- Generic mapping support -------------------------------------------*/ +/* Operations table. ME is the mapping object throughout. */ +typedef struct gmap_ops { + size_t isz; /* iterator size */ + + void *(*lookup)(PyObject *me, PyObject *key, unsigned *f); + /* Lookup the KEY. If it is found, return an entry pointer for it; if F + * is not null, set *F nonzero. Otherwise, if F is null, return a null + * pointer (without setting a pending exception); if F is not null, then + * set *F zero and return a fresh entry pointer. Return null on a Python + * exception (the caller will notice the difference.) + */ + + void (*iter_init)(PyObject *me, void *i); + /* Initialize an iterator at I. */ + + void *(*iter_next)(PyObject *me, void *i); + /* Return an entry pointer for a different item, or null if all have been + * visited. + */ + + PyObject *(*entry_key)(PyObject *me, void *e); + /* Return the key object for a mapping entry. */ + + PyObject *(*entry_value)(PyObject *me, void *e); + /* Return the value object for a mapping entry. */ + + int (*set_entry)(PyObject *me, void *e, PyObject *val); + /* Modify the entry by storing VAL in its place. Return 0 on success, + * or -1 on a Python error. + */ + + int (*del_entry)(PyObject *me, void *e); + /* Delete the entry. (It may be necessary to delete a freshly allocated + * entry, e.g., if `set_entry' failed.) Return 0 on success, or -1 on a + * Python error. + */ +} gmap_ops; + +/* The intrusion at the head of a mapping object. */ +#define GMAP_PYOBJ_HEAD \ + PyObject_HEAD \ + const gmap_ops *gmops; + +typedef struct gmap_pyobj { + GMAP_PYOBJ_HEAD +} gmap_pyobj; +#define GMAP_OPS(obj) (((gmap_pyobj *)(obj))->gmops) + /* Discover the operations from a mapping object. */ + /* Mapping methods. */ #define GMAP_METMNAME(func) gmapmeth_##func #define GMAP_METH(func, doc) STD_METHOD(GMAP_METMNAME, func, 0, doc) @@ -397,7 +459,7 @@ extern PyMethodDef *donemethods(void); KWMETH(setdefault, "D.setdefault(K, [default = None]) -> VALUE") \ KWMETH(pop, "D.pop(KEY, [default = ]) -> VALUE") \ NAMETH(popitem, "D.popitem() -> (KEY, VALUE)") \ - METH (update, "D.update(MAP)") + KWMETH(update, "D.update(MAP)") GMAP_DOMETHODS(GMAP_METHDECL, GMAP_KWMETHDECL, GMAP_NAMETHDECL) #define GMAP_ROMETHODS GMAP_DOROMETHODS(GMAP_METH, GMAP_KWMETH, GMAP_NAMETH) @@ -405,7 +467,12 @@ GMAP_DOMETHODS(GMAP_METHDECL, GMAP_KWMETHDECL, GMAP_NAMETHDECL) /* Mapping protocol implementation. */ extern Py_ssize_t gmap_pysize(PyObject *); /* for `mp_length' */ +extern PyObject *gmap_pyiter(PyObject *); /* for `tp_iter' */ +extern PyObject *gmap_pylookup(PyObject *, PyObject *); /* for `mp_subscript' */ +extern int gmap_pystore(PyObject *, PyObject *, PyObject *); /* for `mp_ass_subscript' */ +extern int gmap_pyhaskey(PyObject *, PyObject *); /* for `sq_contains' */ extern const PySequenceMethods gmap_pysequence; /* for `tp_as_sequence' */ +extern const PyMethodDef gmapro_pymethods[]; /* read-only methods */ extern const PyMethodDef gmap_pymethods[]; /* all the standard methods */ /*----- That's all, folks -------------------------------------------------*/