PageRenderTime 35ms CodeModel.GetById 19ms app.highlight 13ms RepoModel.GetById 0ms app.codeStats 0ms

/src/utils/python/python26/Objects/methodobject.c

https://bitbucket.org/apexgames-ondemand/zombie-onslaught-source
C | 426 lines | 369 code | 41 blank | 16 comment | 98 complexity | ffe7c2d71e9a6f3ba8b8f784c502dc86 MD5 | raw file
  1
  2/* Method object implementation */
  3
  4#include "Python.h"
  5#include "structmember.h"
  6
  7/* Free list for method objects to safe malloc/free overhead
  8 * The m_self element is used to chain the objects.
  9 */
 10static PyCFunctionObject *free_list = NULL;
 11static int numfree = 0;
 12#ifndef PyCFunction_MAXFREELIST
 13#define PyCFunction_MAXFREELIST 256
 14#endif
 15
 16PyObject *
 17PyCFunction_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module)
 18{
 19	PyCFunctionObject *op;
 20	op = free_list;
 21	if (op != NULL) {
 22		free_list = (PyCFunctionObject *)(op->m_self);
 23		PyObject_INIT(op, &PyCFunction_Type);
 24		numfree--;
 25	}
 26	else {
 27		op = PyObject_GC_New(PyCFunctionObject, &PyCFunction_Type);
 28		if (op == NULL)
 29			return NULL;
 30	}
 31	op->m_ml = ml;
 32	Py_XINCREF(self);
 33	op->m_self = self;
 34	Py_XINCREF(module);
 35	op->m_module = module;
 36	_PyObject_GC_TRACK(op);
 37	return (PyObject *)op;
 38}
 39
 40PyCFunction
 41PyCFunction_GetFunction(PyObject *op)
 42{
 43	if (!PyCFunction_Check(op)) {
 44		PyErr_BadInternalCall();
 45		return NULL;
 46	}
 47	return ((PyCFunctionObject *)op) -> m_ml -> ml_meth;
 48}
 49
 50PyObject *
 51PyCFunction_GetSelf(PyObject *op)
 52{
 53	if (!PyCFunction_Check(op)) {
 54		PyErr_BadInternalCall();
 55		return NULL;
 56	}
 57	return ((PyCFunctionObject *)op) -> m_self;
 58}
 59
 60int
 61PyCFunction_GetFlags(PyObject *op)
 62{
 63	if (!PyCFunction_Check(op)) {
 64		PyErr_BadInternalCall();
 65		return -1;
 66	}
 67	return ((PyCFunctionObject *)op) -> m_ml -> ml_flags;
 68}
 69
 70PyObject *
 71PyCFunction_Call(PyObject *func, PyObject *arg, PyObject *kw)
 72{
 73	PyCFunctionObject* f = (PyCFunctionObject*)func;
 74	PyCFunction meth = PyCFunction_GET_FUNCTION(func);
 75	PyObject *self = PyCFunction_GET_SELF(func);
 76	Py_ssize_t size;
 77
 78	switch (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST)) {
 79	case METH_VARARGS:
 80		if (kw == NULL || PyDict_Size(kw) == 0)
 81			return (*meth)(self, arg);
 82		break;
 83	case METH_VARARGS | METH_KEYWORDS:
 84	case METH_OLDARGS | METH_KEYWORDS:
 85		return (*(PyCFunctionWithKeywords)meth)(self, arg, kw);
 86	case METH_NOARGS:
 87		if (kw == NULL || PyDict_Size(kw) == 0) {
 88			size = PyTuple_GET_SIZE(arg);
 89			if (size == 0)
 90				return (*meth)(self, NULL);
 91			PyErr_Format(PyExc_TypeError,
 92			    "%.200s() takes no arguments (%zd given)",
 93			    f->m_ml->ml_name, size);
 94			return NULL;
 95		}
 96		break;
 97	case METH_O:
 98		if (kw == NULL || PyDict_Size(kw) == 0) {
 99			size = PyTuple_GET_SIZE(arg);
100			if (size == 1)
101				return (*meth)(self, PyTuple_GET_ITEM(arg, 0));
102			PyErr_Format(PyExc_TypeError,
103			    "%.200s() takes exactly one argument (%zd given)",
104			    f->m_ml->ml_name, size);
105			return NULL;
106		}
107		break;
108	case METH_OLDARGS:
109		/* the really old style */
110		if (kw == NULL || PyDict_Size(kw) == 0) {
111			size = PyTuple_GET_SIZE(arg);
112			if (size == 1)
113				arg = PyTuple_GET_ITEM(arg, 0);
114			else if (size == 0)
115				arg = NULL;
116			return (*meth)(self, arg);
117		}
118		break;
119	default:
120		PyErr_BadInternalCall();
121		return NULL;
122	}
123	PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments",
124		     f->m_ml->ml_name);
125	return NULL;
126}
127
128/* Methods (the standard built-in methods, that is) */
129
130static void
131meth_dealloc(PyCFunctionObject *m)
132{
133	_PyObject_GC_UNTRACK(m);
134	Py_XDECREF(m->m_self);
135	Py_XDECREF(m->m_module);
136	if (numfree < PyCFunction_MAXFREELIST) {
137		m->m_self = (PyObject *)free_list;
138		free_list = m;
139		numfree++;
140	}
141	else {
142		PyObject_GC_Del(m);
143	}
144}
145
146static PyObject *
147meth_get__doc__(PyCFunctionObject *m, void *closure)
148{
149	const char *doc = m->m_ml->ml_doc;
150
151	if (doc != NULL)
152		return PyString_FromString(doc);
153	Py_INCREF(Py_None);
154	return Py_None;
155}
156
157static PyObject *
158meth_get__name__(PyCFunctionObject *m, void *closure)
159{
160	return PyString_FromString(m->m_ml->ml_name);
161}
162
163static int
164meth_traverse(PyCFunctionObject *m, visitproc visit, void *arg)
165{
166	Py_VISIT(m->m_self);
167	Py_VISIT(m->m_module);
168	return 0;
169}
170
171static PyObject *
172meth_get__self__(PyCFunctionObject *m, void *closure)
173{
174	PyObject *self;
175	if (PyEval_GetRestricted()) {
176		PyErr_SetString(PyExc_RuntimeError,
177			"method.__self__ not accessible in restricted mode");
178		return NULL;
179	}
180	self = m->m_self;
181	if (self == NULL)
182		self = Py_None;
183	Py_INCREF(self);
184	return self;
185}
186
187static PyGetSetDef meth_getsets [] = {
188	{"__doc__",  (getter)meth_get__doc__,  NULL, NULL},
189	{"__name__", (getter)meth_get__name__, NULL, NULL},
190	{"__self__", (getter)meth_get__self__, NULL, NULL},
191	{0}
192};
193
194#define OFF(x) offsetof(PyCFunctionObject, x)
195
196static PyMemberDef meth_members[] = {
197	{"__module__",    T_OBJECT,     OFF(m_module), PY_WRITE_RESTRICTED},
198	{NULL}
199};
200
201static PyObject *
202meth_repr(PyCFunctionObject *m)
203{
204	if (m->m_self == NULL)
205		return PyString_FromFormat("<built-in function %s>",
206					   m->m_ml->ml_name);
207	return PyString_FromFormat("<built-in method %s of %s object at %p>",
208				   m->m_ml->ml_name,
209				   m->m_self->ob_type->tp_name,
210				   m->m_self);
211}
212
213static int
214meth_compare(PyCFunctionObject *a, PyCFunctionObject *b)
215{
216	if (a->m_self != b->m_self)
217		return (a->m_self < b->m_self) ? -1 : 1;
218	if (a->m_ml->ml_meth == b->m_ml->ml_meth)
219		return 0;
220	if (strcmp(a->m_ml->ml_name, b->m_ml->ml_name) < 0)
221		return -1;
222	else
223		return 1;
224}
225
226static PyObject *
227meth_richcompare(PyObject *self, PyObject *other, int op)
228{
229	PyCFunctionObject *a, *b;
230	PyObject *res;
231	int eq;
232
233	if ((op != Py_EQ && op != Py_NE) ||
234	    !PyCFunction_Check(self) ||
235	    !PyCFunction_Check(other))
236	{
237		/* Py3K warning if types are not equal and comparison isn't == or !=  */
238		if (PyErr_WarnPy3k("builtin_function_or_method inequality "
239				   "comparisons not supported in 3.x", 1) < 0) {
240			return NULL;
241		}
242
243		Py_INCREF(Py_NotImplemented);
244		return Py_NotImplemented;
245	}
246	a = (PyCFunctionObject *)self;
247	b = (PyCFunctionObject *)other;
248	eq = a->m_self == b->m_self;
249	if (eq)
250		eq = a->m_ml->ml_meth == b->m_ml->ml_meth;
251	if (op == Py_EQ)
252		res = eq ? Py_True : Py_False;
253	else
254		res = eq ? Py_False : Py_True;
255	Py_INCREF(res);
256	return res;
257}
258
259static long
260meth_hash(PyCFunctionObject *a)
261{
262	long x,y;
263	if (a->m_self == NULL)
264		x = 0;
265	else {
266		x = PyObject_Hash(a->m_self);
267		if (x == -1)
268			return -1;
269	}
270	y = _Py_HashPointer((void*)(a->m_ml->ml_meth));
271	if (y == -1)
272		return -1;
273	x ^= y;
274	if (x == -1)
275		x = -2;
276	return x;
277}
278
279
280PyTypeObject PyCFunction_Type = {
281	PyVarObject_HEAD_INIT(&PyType_Type, 0)
282	"builtin_function_or_method",
283	sizeof(PyCFunctionObject),
284	0,
285	(destructor)meth_dealloc, 		/* tp_dealloc */
286	0,					/* tp_print */
287	0,					/* tp_getattr */
288	0,					/* tp_setattr */
289	(cmpfunc)meth_compare,			/* tp_compare */
290	(reprfunc)meth_repr,			/* tp_repr */
291	0,					/* tp_as_number */
292	0,					/* tp_as_sequence */
293	0,					/* tp_as_mapping */
294	(hashfunc)meth_hash,			/* tp_hash */
295	PyCFunction_Call,			/* tp_call */
296	0,					/* tp_str */
297	PyObject_GenericGetAttr,		/* tp_getattro */
298	0,					/* tp_setattro */
299	0,					/* tp_as_buffer */
300	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
301 	0,					/* tp_doc */
302 	(traverseproc)meth_traverse,		/* tp_traverse */
303	0,					/* tp_clear */
304	meth_richcompare,					/* tp_richcompare */
305	0,					/* tp_weaklistoffset */
306	0,					/* tp_iter */
307	0,					/* tp_iternext */
308	0,					/* tp_methods */
309	meth_members,				/* tp_members */
310	meth_getsets,				/* tp_getset */
311	0,					/* tp_base */
312	0,					/* tp_dict */
313};
314
315/* List all methods in a chain -- helper for findmethodinchain */
316
317static PyObject *
318listmethodchain(PyMethodChain *chain)
319{
320	PyMethodChain *c;
321	PyMethodDef *ml;
322	int i, n;
323	PyObject *v;
324
325	n = 0;
326	for (c = chain; c != NULL; c = c->link) {
327		for (ml = c->methods; ml->ml_name != NULL; ml++)
328			n++;
329	}
330	v = PyList_New(n);
331	if (v == NULL)
332		return NULL;
333	i = 0;
334	for (c = chain; c != NULL; c = c->link) {
335		for (ml = c->methods; ml->ml_name != NULL; ml++) {
336			PyList_SetItem(v, i, PyString_FromString(ml->ml_name));
337			i++;
338		}
339	}
340	if (PyErr_Occurred()) {
341		Py_DECREF(v);
342		return NULL;
343	}
344	PyList_Sort(v);
345	return v;
346}
347
348/* Find a method in a method chain */
349
350PyObject *
351Py_FindMethodInChain(PyMethodChain *chain, PyObject *self, const char *name)
352{
353	if (name[0] == '_' && name[1] == '_') {
354		if (strcmp(name, "__methods__") == 0) {
355			if (PyErr_WarnPy3k("__methods__ not supported in 3.x",
356					   1) < 0)
357				return NULL;
358			return listmethodchain(chain);
359		}
360		if (strcmp(name, "__doc__") == 0) {
361			const char *doc = self->ob_type->tp_doc;
362			if (doc != NULL)
363				return PyString_FromString(doc);
364		}
365	}
366	while (chain != NULL) {
367		PyMethodDef *ml = chain->methods;
368		for (; ml->ml_name != NULL; ml++) {
369			if (name[0] == ml->ml_name[0] &&
370			    strcmp(name+1, ml->ml_name+1) == 0)
371				/* XXX */
372				return PyCFunction_New(ml, self);
373		}
374		chain = chain->link;
375	}
376	PyErr_SetString(PyExc_AttributeError, name);
377	return NULL;
378}
379
380/* Find a method in a single method list */
381
382PyObject *
383Py_FindMethod(PyMethodDef *methods, PyObject *self, const char *name)
384{
385	PyMethodChain chain;
386	chain.methods = methods;
387	chain.link = NULL;
388	return Py_FindMethodInChain(&chain, self, name);
389}
390
391/* Clear out the free list */
392
393int
394PyCFunction_ClearFreeList(void)
395{
396	int freelist_size = numfree;
397	
398	while (free_list) {
399		PyCFunctionObject *v = free_list;
400		free_list = (PyCFunctionObject *)(v->m_self);
401		PyObject_GC_Del(v);
402		numfree--;
403	}
404	assert(numfree == 0);
405	return freelist_size;
406}
407
408void
409PyCFunction_Fini(void)
410{
411	(void)PyCFunction_ClearFreeList();
412}
413
414/* PyCFunction_New() is now just a macro that calls PyCFunction_NewEx(),
415   but it's part of the API so we need to keep a function around that
416   existing C extensions can call.
417*/
418
419#undef PyCFunction_New
420PyAPI_FUNC(PyObject *) PyCFunction_New(PyMethodDef *, PyObject *);
421
422PyObject *
423PyCFunction_New(PyMethodDef *ml, PyObject *self)
424{
425	return PyCFunction_NewEx(ml, self, NULL);
426}