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