/Python/structmember.c

http://unladen-swallow.googlecode.com/ · C · 348 lines · 326 code · 13 blank · 9 comment · 103 complexity · 251600bf811a4b1fc817bf7063bd7e9e MD5 · raw file

  1. /* Map C struct members to Python object attributes */
  2. #include "Python.h"
  3. #include "structmember.h"
  4. static PyObject *
  5. listmembers(struct memberlist *mlist)
  6. {
  7. int i, n;
  8. PyObject *v;
  9. for (n = 0; mlist[n].name != NULL; n++)
  10. ;
  11. v = PyList_New(n);
  12. if (v != NULL) {
  13. for (i = 0; i < n; i++)
  14. PyList_SetItem(v, i,
  15. PyString_FromString(mlist[i].name));
  16. if (PyErr_Occurred()) {
  17. Py_DECREF(v);
  18. v = NULL;
  19. }
  20. else {
  21. PyList_Sort(v);
  22. }
  23. }
  24. return v;
  25. }
  26. PyObject *
  27. PyMember_Get(const char *addr, struct memberlist *mlist, const char *name)
  28. {
  29. struct memberlist *l;
  30. if (strcmp(name, "__members__") == 0)
  31. return listmembers(mlist);
  32. for (l = mlist; l->name != NULL; l++) {
  33. if (strcmp(l->name, name) == 0) {
  34. PyMemberDef copy;
  35. copy.name = l->name;
  36. copy.type = l->type;
  37. copy.offset = l->offset;
  38. copy.flags = l->flags;
  39. copy.doc = NULL;
  40. return PyMember_GetOne(addr, &copy);
  41. }
  42. }
  43. PyErr_SetString(PyExc_AttributeError, name);
  44. return NULL;
  45. }
  46. PyObject *
  47. PyMember_GetOne(const char *addr, PyMemberDef *l)
  48. {
  49. PyObject *v;
  50. if ((l->flags & READ_RESTRICTED) &&
  51. PyEval_GetRestricted()) {
  52. PyErr_SetString(PyExc_RuntimeError, "restricted attribute");
  53. return NULL;
  54. }
  55. addr += l->offset;
  56. switch (l->type) {
  57. case T_BOOL:
  58. v = PyBool_FromLong(*(char*)addr);
  59. break;
  60. case T_BYTE:
  61. v = PyInt_FromLong(*(char*)addr);
  62. break;
  63. case T_UBYTE:
  64. v = PyLong_FromUnsignedLong(*(unsigned char*)addr);
  65. break;
  66. case T_SHORT:
  67. v = PyInt_FromLong(*(short*)addr);
  68. break;
  69. case T_USHORT:
  70. v = PyLong_FromUnsignedLong(*(unsigned short*)addr);
  71. break;
  72. case T_INT:
  73. v = PyInt_FromLong(*(int*)addr);
  74. break;
  75. case T_UINT:
  76. v = PyLong_FromUnsignedLong(*(unsigned int*)addr);
  77. break;
  78. case T_LONG:
  79. v = PyInt_FromLong(*(long*)addr);
  80. break;
  81. case T_ULONG:
  82. v = PyLong_FromUnsignedLong(*(unsigned long*)addr);
  83. break;
  84. case T_PYSSIZET:
  85. v = PyInt_FromSsize_t(*(Py_ssize_t*)addr);
  86. break;
  87. case T_FLOAT:
  88. v = PyFloat_FromDouble((double)*(float*)addr);
  89. break;
  90. case T_DOUBLE:
  91. v = PyFloat_FromDouble(*(double*)addr);
  92. break;
  93. case T_STRING:
  94. if (*(char**)addr == NULL) {
  95. Py_INCREF(Py_None);
  96. v = Py_None;
  97. }
  98. else
  99. v = PyString_FromString(*(char**)addr);
  100. break;
  101. case T_STRING_INPLACE:
  102. v = PyString_FromString((char*)addr);
  103. break;
  104. case T_CHAR:
  105. v = PyString_FromStringAndSize((char*)addr, 1);
  106. break;
  107. case T_OBJECT:
  108. v = *(PyObject **)addr;
  109. if (v == NULL)
  110. v = Py_None;
  111. Py_INCREF(v);
  112. break;
  113. case T_OBJECT_EX:
  114. v = *(PyObject **)addr;
  115. if (v == NULL)
  116. PyErr_SetString(PyExc_AttributeError, l->name);
  117. Py_XINCREF(v);
  118. break;
  119. #ifdef HAVE_LONG_LONG
  120. case T_LONGLONG:
  121. v = PyLong_FromLongLong(*(PY_LONG_LONG *)addr);
  122. break;
  123. case T_ULONGLONG:
  124. v = PyLong_FromUnsignedLongLong(*(unsigned PY_LONG_LONG *)addr);
  125. break;
  126. #endif /* HAVE_LONG_LONG */
  127. default:
  128. PyErr_SetString(PyExc_SystemError, "bad memberdescr type");
  129. v = NULL;
  130. }
  131. return v;
  132. }
  133. int
  134. PyMember_Set(char *addr, struct memberlist *mlist, const char *name, PyObject *v)
  135. {
  136. struct memberlist *l;
  137. for (l = mlist; l->name != NULL; l++) {
  138. if (strcmp(l->name, name) == 0) {
  139. PyMemberDef copy;
  140. copy.name = l->name;
  141. copy.type = l->type;
  142. copy.offset = l->offset;
  143. copy.flags = l->flags;
  144. copy.doc = NULL;
  145. return PyMember_SetOne(addr, &copy, v);
  146. }
  147. }
  148. PyErr_SetString(PyExc_AttributeError, name);
  149. return -1;
  150. }
  151. #define WARN(msg) \
  152. do { \
  153. if (PyErr_Warn(PyExc_RuntimeWarning, msg) < 0) \
  154. return -1; \
  155. } while (0)
  156. int
  157. PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v)
  158. {
  159. PyObject *oldv;
  160. if ((l->flags & READONLY) || l->type == T_STRING)
  161. {
  162. PyErr_SetString(PyExc_TypeError, "readonly attribute");
  163. return -1;
  164. }
  165. if ((l->flags & PY_WRITE_RESTRICTED) && PyEval_GetRestricted()) {
  166. PyErr_SetString(PyExc_RuntimeError, "restricted attribute");
  167. return -1;
  168. }
  169. if (v == NULL && l->type != T_OBJECT_EX && l->type != T_OBJECT) {
  170. PyErr_SetString(PyExc_TypeError,
  171. "can't delete numeric/char attribute");
  172. return -1;
  173. }
  174. addr += l->offset;
  175. switch (l->type) {
  176. case T_BOOL:{
  177. if (!PyBool_Check(v)) {
  178. PyErr_SetString(PyExc_TypeError,
  179. "attribute value type must be bool");
  180. return -1;
  181. }
  182. if (v == Py_True)
  183. *(char*)addr = (char) 1;
  184. else
  185. *(char*)addr = (char) 0;
  186. break;
  187. }
  188. case T_BYTE:{
  189. long long_val = PyInt_AsLong(v);
  190. if ((long_val == -1) && PyErr_Occurred())
  191. return -1;
  192. *(char*)addr = (char)long_val;
  193. /* XXX: For compatibility, only warn about truncations
  194. for now. */
  195. if ((long_val > CHAR_MAX) || (long_val < CHAR_MIN))
  196. WARN("Truncation of value to char");
  197. break;
  198. }
  199. case T_UBYTE:{
  200. long long_val = PyInt_AsLong(v);
  201. if ((long_val == -1) && PyErr_Occurred())
  202. return -1;
  203. *(unsigned char*)addr = (unsigned char)long_val;
  204. if ((long_val > UCHAR_MAX) || (long_val < 0))
  205. WARN("Truncation of value to unsigned char");
  206. break;
  207. }
  208. case T_SHORT:{
  209. long long_val = PyInt_AsLong(v);
  210. if ((long_val == -1) && PyErr_Occurred())
  211. return -1;
  212. *(short*)addr = (short)long_val;
  213. if ((long_val > SHRT_MAX) || (long_val < SHRT_MIN))
  214. WARN("Truncation of value to short");
  215. break;
  216. }
  217. case T_USHORT:{
  218. long long_val = PyInt_AsLong(v);
  219. if ((long_val == -1) && PyErr_Occurred())
  220. return -1;
  221. *(unsigned short*)addr = (unsigned short)long_val;
  222. if ((long_val > USHRT_MAX) || (long_val < 0))
  223. WARN("Truncation of value to unsigned short");
  224. break;
  225. }
  226. case T_INT:{
  227. long long_val = PyInt_AsLong(v);
  228. if ((long_val == -1) && PyErr_Occurred())
  229. return -1;
  230. *(int *)addr = (int)long_val;
  231. if ((long_val > INT_MAX) || (long_val < INT_MIN))
  232. WARN("Truncation of value to int");
  233. break;
  234. }
  235. case T_UINT:{
  236. unsigned long ulong_val = PyLong_AsUnsignedLong(v);
  237. if ((ulong_val == (unsigned int)-1) && PyErr_Occurred()) {
  238. /* XXX: For compatibility, accept negative int values
  239. as well. */
  240. PyErr_Clear();
  241. ulong_val = PyLong_AsLong(v);
  242. if ((ulong_val == (unsigned int)-1) && PyErr_Occurred())
  243. return -1;
  244. *(unsigned int *)addr = (unsigned int)ulong_val;
  245. WARN("Writing negative value into unsigned field");
  246. } else
  247. *(unsigned int *)addr = (unsigned int)ulong_val;
  248. if (ulong_val > UINT_MAX)
  249. WARN("Truncation of value to unsigned int");
  250. break;
  251. }
  252. case T_LONG:{
  253. *(long*)addr = PyLong_AsLong(v);
  254. if ((*(long*)addr == -1) && PyErr_Occurred())
  255. return -1;
  256. break;
  257. }
  258. case T_ULONG:{
  259. *(unsigned long*)addr = PyLong_AsUnsignedLong(v);
  260. if ((*(unsigned long*)addr == (unsigned long)-1)
  261. && PyErr_Occurred()) {
  262. /* XXX: For compatibility, accept negative int values
  263. as well. */
  264. PyErr_Clear();
  265. *(unsigned long*)addr = PyLong_AsLong(v);
  266. if ((*(unsigned long*)addr == (unsigned int)-1)
  267. && PyErr_Occurred())
  268. return -1;
  269. WARN("Writing negative value into unsigned field");
  270. }
  271. break;
  272. }
  273. case T_PYSSIZET:{
  274. *(Py_ssize_t*)addr = PyInt_AsSsize_t(v);
  275. if ((*(Py_ssize_t*)addr == (Py_ssize_t)-1)
  276. && PyErr_Occurred())
  277. return -1;
  278. break;
  279. }
  280. case T_FLOAT:{
  281. double double_val = PyFloat_AsDouble(v);
  282. if ((double_val == -1) && PyErr_Occurred())
  283. return -1;
  284. *(float*)addr = (float)double_val;
  285. break;
  286. }
  287. case T_DOUBLE:
  288. *(double*)addr = PyFloat_AsDouble(v);
  289. if ((*(double*)addr == -1) && PyErr_Occurred())
  290. return -1;
  291. break;
  292. case T_OBJECT:
  293. case T_OBJECT_EX:
  294. Py_XINCREF(v);
  295. oldv = *(PyObject **)addr;
  296. *(PyObject **)addr = v;
  297. Py_XDECREF(oldv);
  298. break;
  299. case T_CHAR:
  300. if (PyString_Check(v) && PyString_Size(v) == 1) {
  301. *(char*)addr = PyString_AsString(v)[0];
  302. }
  303. else {
  304. PyErr_BadArgument();
  305. return -1;
  306. }
  307. break;
  308. #ifdef HAVE_LONG_LONG
  309. case T_LONGLONG:{
  310. PY_LONG_LONG value;
  311. *(PY_LONG_LONG*)addr = value = PyLong_AsLongLong(v);
  312. if ((value == -1) && PyErr_Occurred())
  313. return -1;
  314. break;
  315. }
  316. case T_ULONGLONG:{
  317. unsigned PY_LONG_LONG value;
  318. /* ??? PyLong_AsLongLong accepts an int, but PyLong_AsUnsignedLongLong
  319. doesn't ??? */
  320. if (PyLong_Check(v))
  321. *(unsigned PY_LONG_LONG*)addr = value = PyLong_AsUnsignedLongLong(v);
  322. else
  323. *(unsigned PY_LONG_LONG*)addr = value = PyInt_AsLong(v);
  324. if ((value == (unsigned PY_LONG_LONG)-1) && PyErr_Occurred())
  325. return -1;
  326. break;
  327. }
  328. #endif /* HAVE_LONG_LONG */
  329. default:
  330. PyErr_Format(PyExc_SystemError,
  331. "bad memberdescr type for %s", l->name);
  332. return -1;
  333. }
  334. return 0;
  335. }