PageRenderTime 53ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 0ms

/xbmc/lib/libPython/Python/Objects/methodobject.c

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