No issues found
1 /* Method object implementation */
2
3 #include "Python.h"
4 #include "structmember.h"
5
6 /* Free list for method objects to safe malloc/free overhead
7 * The m_self element is used to chain the objects.
8 */
9 static PyCFunctionObject *free_list = NULL;
10 static int numfree = 0;
11 #ifndef PyCFunction_MAXFREELIST
12 #define PyCFunction_MAXFREELIST 256
13 #endif
14
15 PyObject *
16 PyCFunction_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module)
17 {
18 PyCFunctionObject *op;
19 op = free_list;
20 if (op != NULL) {
21 free_list = (PyCFunctionObject *)(op->m_self);
22 PyObject_INIT(op, &PyCFunction_Type);
23 numfree--;
24 }
25 else {
26 op = PyObject_GC_New(PyCFunctionObject, &PyCFunction_Type);
27 if (op == NULL)
28 return NULL;
29 }
30 op->m_ml = ml;
31 Py_XINCREF(self);
32 op->m_self = self;
33 Py_XINCREF(module);
34 op->m_module = module;
35 _PyObject_GC_TRACK(op);
36 return (PyObject *)op;
37 }
38
39 PyCFunction
40 PyCFunction_GetFunction(PyObject *op)
41 {
42 if (!PyCFunction_Check(op)) {
43 PyErr_BadInternalCall();
44 return NULL;
45 }
46 return ((PyCFunctionObject *)op) -> m_ml -> ml_meth;
47 }
48
49 PyObject *
50 PyCFunction_GetSelf(PyObject *op)
51 {
52 if (!PyCFunction_Check(op)) {
53 PyErr_BadInternalCall();
54 return NULL;
55 }
56 return ((PyCFunctionObject *)op) -> m_self;
57 }
58
59 int
60 PyCFunction_GetFlags(PyObject *op)
61 {
62 if (!PyCFunction_Check(op)) {
63 PyErr_BadInternalCall();
64 return -1;
65 }
66 return ((PyCFunctionObject *)op) -> m_ml -> ml_flags;
67 }
68
69 PyObject *
70 PyCFunction_Call(PyObject *func, PyObject *arg, PyObject *kw)
71 {
72 PyCFunctionObject* f = (PyCFunctionObject*)func;
73 PyCFunction meth = PyCFunction_GET_FUNCTION(func);
74 PyObject *self = PyCFunction_GET_SELF(func);
75 Py_ssize_t size;
76
77 switch (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST)) {
78 case METH_VARARGS:
79 if (kw == NULL || PyDict_Size(kw) == 0)
80 return (*meth)(self, arg);
81 break;
82 case METH_VARARGS | METH_KEYWORDS:
83 case METH_OLDARGS | METH_KEYWORDS:
84 return (*(PyCFunctionWithKeywords)meth)(self, arg, kw);
85 case METH_NOARGS:
86 if (kw == NULL || PyDict_Size(kw) == 0) {
87 size = PyTuple_GET_SIZE(arg);
88 if (size == 0)
89 return (*meth)(self, NULL);
90 PyErr_Format(PyExc_TypeError,
91 "%.200s() takes no arguments (%zd given)",
92 f->m_ml->ml_name, size);
93 return NULL;
94 }
95 break;
96 case METH_O:
97 if (kw == NULL || PyDict_Size(kw) == 0) {
98 size = PyTuple_GET_SIZE(arg);
99 if (size == 1)
100 return (*meth)(self, PyTuple_GET_ITEM(arg, 0));
101 PyErr_Format(PyExc_TypeError,
102 "%.200s() takes exactly one argument (%zd given)",
103 f->m_ml->ml_name, size);
104 return NULL;
105 }
106 break;
107 case METH_OLDARGS:
108 /* the really old style */
109 if (kw == NULL || PyDict_Size(kw) == 0) {
110 size = PyTuple_GET_SIZE(arg);
111 if (size == 1)
112 arg = PyTuple_GET_ITEM(arg, 0);
113 else if (size == 0)
114 arg = NULL;
115 return (*meth)(self, arg);
116 }
117 break;
118 default:
119 PyErr_BadInternalCall();
120 return NULL;
121 }
122 PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments",
123 f->m_ml->ml_name);
124 return NULL;
125 }
126
127 /* Methods (the standard built-in methods, that is) */
128
129 static void
130 meth_dealloc(PyCFunctionObject *m)
131 {
132 _PyObject_GC_UNTRACK(m);
133 Py_XDECREF(m->m_self);
134 Py_XDECREF(m->m_module);
135 if (numfree < PyCFunction_MAXFREELIST) {
136 m->m_self = (PyObject *)free_list;
137 free_list = m;
138 numfree++;
139 }
140 else {
141 PyObject_GC_Del(m);
142 }
143 }
144
145 static PyObject *
146 meth_get__doc__(PyCFunctionObject *m, void *closure)
147 {
148 const char *doc = m->m_ml->ml_doc;
149
150 if (doc != NULL)
151 return PyString_FromString(doc);
152 Py_INCREF(Py_None);
153 return Py_None;
154 }
155
156 static PyObject *
157 meth_get__name__(PyCFunctionObject *m, void *closure)
158 {
159 return PyString_FromString(m->m_ml->ml_name);
160 }
161
162 static int
163 meth_traverse(PyCFunctionObject *m, visitproc visit, void *arg)
164 {
165 Py_VISIT(m->m_self);
166 Py_VISIT(m->m_module);
167 return 0;
168 }
169
170 static PyObject *
171 meth_get__self__(PyCFunctionObject *m, void *closure)
172 {
173 PyObject *self;
174 if (PyEval_GetRestricted()) {
175 PyErr_SetString(PyExc_RuntimeError,
176 "method.__self__ not accessible in restricted mode");
177 return NULL;
178 }
179 self = m->m_self;
180 if (self == NULL)
181 self = Py_None;
182 Py_INCREF(self);
183 return self;
184 }
185
186 static PyGetSetDef meth_getsets [] = {
187 {"__doc__", (getter)meth_get__doc__, NULL, NULL},
188 {"__name__", (getter)meth_get__name__, NULL, NULL},
189 {"__self__", (getter)meth_get__self__, NULL, NULL},
190 {0}
191 };
192
193 #define OFF(x) offsetof(PyCFunctionObject, x)
194
195 static PyMemberDef meth_members[] = {
196 {"__module__", T_OBJECT, OFF(m_module), PY_WRITE_RESTRICTED},
197 {NULL}
198 };
199
200 static PyObject *
201 meth_repr(PyCFunctionObject *m)
202 {
203 if (m->m_self == NULL)
204 return PyString_FromFormat("<built-in function %s>",
205 m->m_ml->ml_name);
206 return PyString_FromFormat("<built-in method %s of %s object at %p>",
207 m->m_ml->ml_name,
208 m->m_self->ob_type->tp_name,
209 m->m_self);
210 }
211
212 static int
213 meth_compare(PyCFunctionObject *a, PyCFunctionObject *b)
214 {
215 if (a->m_self != b->m_self)
216 return (a->m_self < b->m_self) ? -1 : 1;
217 if (a->m_ml->ml_meth == b->m_ml->ml_meth)
218 return 0;
219 if (strcmp(a->m_ml->ml_name, b->m_ml->ml_name) < 0)
220 return -1;
221 else
222 return 1;
223 }
224
225 static PyObject *
226 meth_richcompare(PyObject *self, PyObject *other, int op)
227 {
228 PyCFunctionObject *a, *b;
229 PyObject *res;
230 int eq;
231
232 if (op != Py_EQ && op != Py_NE) {
233 /* Py3K warning if comparison isn't == or !=. */
234 if (PyErr_WarnPy3k("builtin_function_or_method order "
235 "comparisons not supported in 3.x", 1) < 0) {
236 return NULL;
237 }
238
239 Py_INCREF(Py_NotImplemented);
240 return Py_NotImplemented;
241 }
242 else if (!PyCFunction_Check(self) || !PyCFunction_Check(other)) {
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
259 static long
260 meth_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
280 PyTypeObject 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
317 static PyObject *
318 listmethodchain(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
350 PyObject *
351 Py_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
382 PyObject *
383 Py_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
393 int
394 PyCFunction_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
408 void
409 PyCFunction_Fini(void)
410 {
411 (void)PyCFunction_ClearFreeList();
412 }
413
414 /* Print summary info about the state of the optimized allocator */
415 void
416 _PyCFunction_DebugMallocStats(FILE *out)
417 {
418 _PyDebugAllocatorStats(out,
419 "free PyCFunction",
420 numfree, sizeof(PyCFunction));
421 }
422
423 /* PyCFunction_New() is now just a macro that calls PyCFunction_NewEx(),
424 but it's part of the API so we need to keep a function around that
425 existing C extensions can call.
426 */
427
428 #undef PyCFunction_New
429 PyAPI_FUNC(PyObject *) PyCFunction_New(PyMethodDef *, PyObject *);
430
431 PyObject *
432 PyCFunction_New(PyMethodDef *ml, PyObject *self)
433 {
434 return PyCFunction_NewEx(ml, self, NULL);
435 }