You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

363 lines
10 KiB

  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. addr += l->offset;
  161. if ((l->flags & READONLY))
  162. {
  163. PyErr_SetString(PyExc_TypeError, "readonly attribute");
  164. return -1;
  165. }
  166. if ((l->flags & PY_WRITE_RESTRICTED) && PyEval_GetRestricted()) {
  167. PyErr_SetString(PyExc_RuntimeError, "restricted attribute");
  168. return -1;
  169. }
  170. if (v == NULL) {
  171. if (l->type == T_OBJECT_EX) {
  172. /* Check if the attribute is set. */
  173. if (*(PyObject **)addr == NULL) {
  174. PyErr_SetString(PyExc_AttributeError, l->name);
  175. return -1;
  176. }
  177. }
  178. else if (l->type != T_OBJECT) {
  179. PyErr_SetString(PyExc_TypeError,
  180. "can't delete numeric/char attribute");
  181. return -1;
  182. }
  183. }
  184. switch (l->type) {
  185. case T_BOOL:{
  186. if (!PyBool_Check(v)) {
  187. PyErr_SetString(PyExc_TypeError,
  188. "attribute value type must be bool");
  189. return -1;
  190. }
  191. if (v == Py_True)
  192. *(char*)addr = (char) 1;
  193. else
  194. *(char*)addr = (char) 0;
  195. break;
  196. }
  197. case T_BYTE:{
  198. long long_val = PyInt_AsLong(v);
  199. if ((long_val == -1) && PyErr_Occurred())
  200. return -1;
  201. *(char*)addr = (char)long_val;
  202. /* XXX: For compatibility, only warn about truncations
  203. for now. */
  204. if ((long_val > CHAR_MAX) || (long_val < CHAR_MIN))
  205. WARN("Truncation of value to char");
  206. break;
  207. }
  208. case T_UBYTE:{
  209. long long_val = PyInt_AsLong(v);
  210. if ((long_val == -1) && PyErr_Occurred())
  211. return -1;
  212. *(unsigned char*)addr = (unsigned char)long_val;
  213. if ((long_val > UCHAR_MAX) || (long_val < 0))
  214. WARN("Truncation of value to unsigned char");
  215. break;
  216. }
  217. case T_SHORT:{
  218. long long_val = PyInt_AsLong(v);
  219. if ((long_val == -1) && PyErr_Occurred())
  220. return -1;
  221. *(short*)addr = (short)long_val;
  222. if ((long_val > SHRT_MAX) || (long_val < SHRT_MIN))
  223. WARN("Truncation of value to short");
  224. break;
  225. }
  226. case T_USHORT:{
  227. long long_val = PyInt_AsLong(v);
  228. if ((long_val == -1) && PyErr_Occurred())
  229. return -1;
  230. *(unsigned short*)addr = (unsigned short)long_val;
  231. if ((long_val > USHRT_MAX) || (long_val < 0))
  232. WARN("Truncation of value to unsigned short");
  233. break;
  234. }
  235. case T_INT:{
  236. long long_val = PyInt_AsLong(v);
  237. if ((long_val == -1) && PyErr_Occurred())
  238. return -1;
  239. *(int *)addr = (int)long_val;
  240. if ((long_val > INT_MAX) || (long_val < INT_MIN))
  241. WARN("Truncation of value to int");
  242. break;
  243. }
  244. case T_UINT:{
  245. unsigned long ulong_val = PyLong_AsUnsignedLong(v);
  246. if ((ulong_val == (unsigned long)-1) && PyErr_Occurred()) {
  247. /* XXX: For compatibility, accept negative int values
  248. as well. */
  249. PyErr_Clear();
  250. ulong_val = PyLong_AsLong(v);
  251. if ((ulong_val == (unsigned long)-1) &&
  252. PyErr_Occurred())
  253. return -1;
  254. *(unsigned int *)addr = (unsigned int)ulong_val;
  255. WARN("Writing negative value into unsigned field");
  256. } else
  257. *(unsigned int *)addr = (unsigned int)ulong_val;
  258. if (ulong_val > UINT_MAX)
  259. WARN("Truncation of value to unsigned int");
  260. break;
  261. }
  262. case T_LONG:{
  263. *(long*)addr = PyLong_AsLong(v);
  264. if ((*(long*)addr == -1) && PyErr_Occurred())
  265. return -1;
  266. break;
  267. }
  268. case T_ULONG:{
  269. *(unsigned long*)addr = PyLong_AsUnsignedLong(v);
  270. if ((*(unsigned long*)addr == (unsigned long)-1)
  271. && PyErr_Occurred()) {
  272. /* XXX: For compatibility, accept negative int values
  273. as well. */
  274. PyErr_Clear();
  275. *(unsigned long*)addr = PyLong_AsLong(v);
  276. if ((*(unsigned long*)addr == (unsigned long)-1)
  277. && PyErr_Occurred())
  278. return -1;
  279. WARN("Writing negative value into unsigned field");
  280. }
  281. break;
  282. }
  283. case T_PYSSIZET:{
  284. *(Py_ssize_t*)addr = PyInt_AsSsize_t(v);
  285. if ((*(Py_ssize_t*)addr == (Py_ssize_t)-1)
  286. && PyErr_Occurred())
  287. return -1;
  288. break;
  289. }
  290. case T_FLOAT:{
  291. double double_val = PyFloat_AsDouble(v);
  292. if ((double_val == -1) && PyErr_Occurred())
  293. return -1;
  294. *(float*)addr = (float)double_val;
  295. break;
  296. }
  297. case T_DOUBLE:
  298. *(double*)addr = PyFloat_AsDouble(v);
  299. if ((*(double*)addr == -1) && PyErr_Occurred())
  300. return -1;
  301. break;
  302. case T_OBJECT:
  303. case T_OBJECT_EX:
  304. Py_XINCREF(v);
  305. oldv = *(PyObject **)addr;
  306. *(PyObject **)addr = v;
  307. Py_XDECREF(oldv);
  308. break;
  309. case T_CHAR:
  310. if (PyString_Check(v) && PyString_Size(v) == 1) {
  311. *(char*)addr = PyString_AsString(v)[0];
  312. }
  313. else {
  314. PyErr_BadArgument();
  315. return -1;
  316. }
  317. break;
  318. case T_STRING:
  319. case T_STRING_INPLACE:
  320. PyErr_SetString(PyExc_TypeError, "readonly attribute");
  321. return -1;
  322. #ifdef HAVE_LONG_LONG
  323. case T_LONGLONG:{
  324. PY_LONG_LONG value;
  325. *(PY_LONG_LONG*)addr = value = PyLong_AsLongLong(v);
  326. if ((value == -1) && PyErr_Occurred())
  327. return -1;
  328. break;
  329. }
  330. case T_ULONGLONG:{
  331. unsigned PY_LONG_LONG value;
  332. /* ??? PyLong_AsLongLong accepts an int, but PyLong_AsUnsignedLongLong
  333. doesn't ??? */
  334. if (PyLong_Check(v))
  335. *(unsigned PY_LONG_LONG*)addr = value = PyLong_AsUnsignedLongLong(v);
  336. else
  337. *(unsigned PY_LONG_LONG*)addr = value = PyInt_AsLong(v);
  338. if ((value == (unsigned PY_LONG_LONG)-1) && PyErr_Occurred())
  339. return -1;
  340. break;
  341. }
  342. #endif /* HAVE_LONG_LONG */
  343. default:
  344. PyErr_Format(PyExc_SystemError,
  345. "bad memberdescr type for %s", l->name);
  346. return -1;
  347. }
  348. return 0;
  349. }