added findmethodinchain and methodchain data types

This commit is contained in:
Guido van Rossum 1995-01-26 22:58:48 +00:00
parent 5279ec683a
commit 6978503235
3 changed files with 60 additions and 23 deletions

View file

@ -57,6 +57,14 @@ extern PyObject *PyCFunction_New
/* Flag passed to newmethodobject */ /* Flag passed to newmethodobject */
#define METH_VARARGS 0x0001 #define METH_VARARGS 0x0001
typedef struct PyMethodChain {
PyMethodDef *methods; /* Methods of this type */
struct PyMethodChain *link; /* NULL or base type */
} PyMethodChain;
extern PyObject *Py_FindMethodInChain
Py_PROTO((PyMethodChain *, PyObject *, char *));
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View file

@ -38,6 +38,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
/* typedef ANY *PyUnivPtr; */ /* typedef ANY *PyUnivPtr; */
#define methodlist PyMethodDef #define methodlist PyMethodDef
#define methodchain PyMethodChain
#define None Py_None #define None Py_None
#define False Py_False #define False Py_False
@ -290,6 +291,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#define newrangeobject PyRange_New #define newrangeobject PyRange_New
#define method PyCFunction #define method PyCFunction
#define findmethod Py_FindMethod #define findmethod Py_FindMethod
#define findmethodinchain Py_FindMethodInChain
#define getmethod PyCFunction_GetFunction #define getmethod PyCFunction_GetFunction
#define getself PyCFunction_GetSelf #define getself PyCFunction_GetSelf
#define getvarargs PyCFunction_IsVarArgs #define getvarargs PyCFunction_IsVarArgs

View file

@ -188,46 +188,73 @@ typeobject Methodtype = {
(hashfunc)meth_hash, /*tp_hash*/ (hashfunc)meth_hash, /*tp_hash*/
}; };
static object *listmethods PROTO((struct methodlist *)); /* Forward */ /* List all methods in a chain -- helper for findmethodinchain */
static object * static object *
listmethods(ml) listmethodchain(chain)
struct methodlist *ml; struct methodchain *chain;
{ {
struct methodchain *c;
struct methodlist *ml;
int i, n; int i, n;
object *v; object *v;
for (n = 0; ml[n].ml_name != NULL; n++)
; n = 0;
for (c = chain; c != NULL; c = c->link) {
for (ml = c->methods; ml->ml_name != NULL; ml++)
n++;
}
v = newlistobject(n); v = newlistobject(n);
if (v != NULL) { if (v == NULL)
for (i = 0; i < n; i++) return NULL;
setlistitem(v, i, newstringobject(ml[i].ml_name)); i = 0;
for (c = chain; c != NULL; c = c->link) {
for (ml = c->methods; ml->ml_name != NULL; ml++) {
setlistitem(v, i, newstringobject(ml->ml_name));
i++;
}
}
if (err_occurred()) { if (err_occurred()) {
DECREF(v); DECREF(v);
v = NULL; return NULL;
} }
else {
sortlist(v); sortlist(v);
}
}
return v; return v;
} }
/* Find a method in a module's method table. /* Find a method in a method chain */
Usually called from an object's getattr method. */
object * object *
findmethod(ml, op, name) findmethodinchain(chain, self, name)
struct methodlist *ml; struct methodchain *chain;
object *op; object *self;
char *name; char *name;
{ {
if (strcmp(name, "__methods__") == 0) if (strcmp(name, "__methods__") == 0)
return listmethods(ml); return listmethodchain(chain);
while (chain != NULL) {
struct methodlist *ml = chain->methods;
for (; ml->ml_name != NULL; ml++) { for (; ml->ml_name != NULL; ml++) {
if (strcmp(name, ml->ml_name) == 0) if (name[0] == ml->ml_name[0] &&
return newmethodobject(ml, op); strcmp(name+1, ml->ml_name+1) == 0)
return newmethodobject(ml, self);
}
chain = chain->link;
} }
err_setstr(AttributeError, name); err_setstr(AttributeError, name);
return NULL; return NULL;
} }
/* Find a method in a single method list */
object *
findmethod(methods, self, name)
struct methodlist *methods;
object *self;
char *name;
{
struct methodchain chain;
chain.methods = methods;
chain.link = NULL;
return findmethodinchain(&chain, self, name);
}